This commit is contained in:
Igor Pavlov
2005-05-30 00:00:00 +00:00
committed by Kornel Lesiński
parent 8c1b5c7b7e
commit 3c510ba80b
926 changed files with 40559 additions and 23519 deletions

View File

@@ -8,11 +8,10 @@
#include "Windows/PropVariant.h"
#include "Windows/FileFind.h"
#include "../Common/OpenArchive.h"
#include "../Common/DefaultName.h"
#include "../Common/ArchiveExtractCallback.h"
#include "Agent.h"
#include "ArchiveExtractCallback.h"
#ifdef FORMAT_7Z
#include "../../Archive/7z/7zHandler.h"
@@ -62,8 +61,7 @@ STDMETHODIMP CAgentFolder::GetProperty(UINT32 itemIndex, PROPID propID, PROPVARI
break;
default:
if (item.IsLeaf)
return _agentSpec->_archive->GetProperty(item.Index,
propID, value);
return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value);
}
}
else
@@ -79,7 +77,7 @@ STDMETHODIMP CAgentFolder::GetProperty(UINT32 itemIndex, PROPID propID, PROPVARI
propVariant = item.Name;
break;
default:
return _agentSpec->_archive->GetProperty(item.Index,
return _agentSpec->GetArchive()->GetProperty(item.Index,
propID, value);
}
}
@@ -140,7 +138,7 @@ struct CArchiveItemPropertyTemp
STDMETHODIMP CAgentFolder::GetNumberOfProperties(UINT32 *numProperties)
{
COM_TRY_BEGIN
return _agentSpec->_archive->GetNumberOfProperties(numProperties);
return _agentSpec->GetArchive()->GetNumberOfProperties(numProperties);
COM_TRY_END
}
@@ -148,7 +146,7 @@ STDMETHODIMP CAgentFolder::GetPropertyInfo(UINT32 index,
BSTR *name, PROPID *propID, VARTYPE *varType)
{
COM_TRY_BEGIN
RINOK(_agentSpec->_archive->GetPropertyInfo(index, name, propID, varType));
RINOK(_agentSpec->GetArchive()->GetPropertyInfo(index, name, propID, varType));
if (*propID == kpidPath)
*propID = kpidName;
return S_OK;
@@ -200,8 +198,8 @@ STDMETHODIMP CAgentFolder::GetPath(BSTR *path)
STDMETHODIMP CAgentFolder::Extract(const UINT32 *indices,
UINT32 numItems,
NExtractionMode::NPath::EEnum pathMode,
NExtractionMode::NOverwrite::EEnum overwriteMode,
NExtract::NPathMode::EEnum pathMode,
NExtract::NOverwriteMode::EEnum overwriteMode,
const wchar_t *path,
INT32 testMode,
IFolderArchiveExtractCallback *extractCallback2)
@@ -216,8 +214,9 @@ STDMETHODIMP CAgentFolder::Extract(const UINT32 *indices,
pathParts.Insert(0, currentProxyFolder->Name);
currentProxyFolder = currentProxyFolder->Parent;
}
extractCallbackSpec->Init(_agentSpec->_archive,
extractCallbackSpec->Init(_agentSpec->GetArchive(),
extractCallback2,
false,
path,
pathMode,
overwriteMode,
@@ -229,7 +228,7 @@ STDMETHODIMP CAgentFolder::Extract(const UINT32 *indices,
);
CUIntVector realIndices;
_proxyFolderItem->GetRealIndices(indices, numItems, realIndices);
return _agentSpec->_archive->Extract(&realIndices.Front(),
return _agentSpec->GetArchive()->Extract(&realIndices.Front(),
realIndices.Size(), testMode, extractCallback);
COM_TRY_END
}
@@ -262,23 +261,19 @@ STDMETHODIMP CAgent::Open(
return ::GetLastError();
if (fileInfo.IsDirectory())
return E_FAIL;
CArchiverInfo archiverInfo;
int subExtIndex;
HRESULT res = OpenArchive(_archiveFilePath,
#ifndef EXCLUDE_COM
&_library,
#endif
&_archive, archiverInfo, subExtIndex, openArchiveCallback);
CArchiverInfo archiverInfo0, archiverInfo1;
HRESULT res = OpenArchive(_archiveFilePath, _archiveLink, openArchiveCallback);
// _archive = _archiveLink.GetArchive();
DefaultName = _archiveLink.GetDefaultItemName();
const CArchiverInfo &ai = _archiveLink.GetArchiverInfo();
RINOK(res);
DefaultName = GetDefaultName(_archiveFilePath,
archiverInfo.Extensions[subExtIndex].Extension,
archiverInfo.Extensions[subExtIndex].AddExtension);
DefaultTime = fileInfo.LastWriteTime;
DefaultAttributes = fileInfo.Attributes;
ArchiveType = archiverInfo.Name;
ArchiveType = ai.Name;
if (archiveType != 0)
{
CMyComBSTR name = archiverInfo.Name;
CMyComBSTR name = ArchiveType;
*archiveType = name.Detach();
}
return S_OK;
@@ -295,7 +290,7 @@ STDMETHODIMP CAgent::ReOpen(
delete _proxyArchive;
_proxyArchive = NULL;
}
RINOK(ReOpenArchive(_archive, _archiveFilePath));
RINOK(ReOpenArchive(_archiveLink, _archiveFilePath));
return ReadItems();
COM_TRY_END
}
@@ -303,7 +298,13 @@ STDMETHODIMP CAgent::ReOpen(
STDMETHODIMP CAgent::Close()
{
COM_TRY_BEGIN
return _archive->Close();
RINOK(_archiveLink.Close());
if (_archiveLink.GetNumLevels() > 1)
{
// return S_OK;
}
// _archive->Close();
return S_OK;
COM_TRY_END
}
@@ -319,7 +320,7 @@ HRESULT CAgent::ReadItems()
if (_proxyArchive != NULL)
return S_OK;
_proxyArchive = new CProxyArchive();
return _proxyArchive->Load(_archive,
return _proxyArchive->Load(GetArchive(),
DefaultName,
// _defaultTime,
// _defaultAttributes,
@@ -340,8 +341,8 @@ STDMETHODIMP CAgent::BindToRootFolder(IFolderFolder **resultFolder)
STDMETHODIMP CAgent::Extract(
NExtractionMode::NPath::EEnum pathMode,
NExtractionMode::NOverwrite::EEnum overwriteMode,
NExtract::NPathMode::EEnum pathMode,
NExtract::NOverwriteMode::EEnum overwriteMode,
const wchar_t *path,
INT32 testMode,
IFolderArchiveExtractCallback *extractCallback2)
@@ -349,8 +350,9 @@ STDMETHODIMP CAgent::Extract(
COM_TRY_BEGIN
CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
extractCallbackSpec->Init(_archive,
extractCallbackSpec->Init(GetArchive(),
extractCallback2,
false,
path,
pathMode,
overwriteMode,
@@ -360,14 +362,14 @@ STDMETHODIMP CAgent::Extract(
DefaultAttributes
// ,_srcDirectoryPrefix
);
return _archive->Extract(0, -1, testMode, extractCallback);
return GetArchive()->Extract(0, -1, testMode, extractCallback);
COM_TRY_END
}
STDMETHODIMP CAgent::GetNumberOfProperties(UINT32 *numProperties)
{
COM_TRY_BEGIN
return _archive->GetNumberOfProperties(numProperties);
return GetArchive()->GetNumberOfProperties(numProperties);
COM_TRY_END
}
@@ -375,7 +377,7 @@ STDMETHODIMP CAgent::GetPropertyInfo(UINT32 index,
BSTR *name, PROPID *propID, VARTYPE *varType)
{
COM_TRY_BEGIN
RINOK(_archive->GetPropertyInfo(index, name, propID, varType));
RINOK(GetArchive()->GetPropertyInfo(index, name, propID, varType));
if (*propID == kpidPath)
*propID = kpidName;
return S_OK;
@@ -385,14 +387,14 @@ STDMETHODIMP CAgent::GetPropertyInfo(UINT32 index,
STDMETHODIMP CAgent::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
return _archive->GetArchiveProperty(propID, value);
return GetArchive()->GetArchiveProperty(propID, value);
COM_TRY_END
}
STDMETHODIMP CAgent::GetNumberOfArchiveProperties(UINT32 *numProperties)
{
COM_TRY_BEGIN
return _archive->GetNumberOfArchiveProperties(numProperties);
return GetArchive()->GetNumberOfArchiveProperties(numProperties);
COM_TRY_END
}
@@ -400,7 +402,7 @@ STDMETHODIMP CAgent::GetArchivePropertyInfo(UINT32 index,
BSTR *name, PROPID *propID, VARTYPE *varType)
{
COM_TRY_BEGIN
return _archive->GetArchivePropertyInfo(index,
return GetArchive()->GetArchivePropertyInfo(index,
name, propID, varType);
COM_TRY_END
}

View File

@@ -1,15 +1,16 @@
// Agent/Agent.h
#pragma once
#ifndef __AGENT_AGENT_H
#define __AGENT_AGENT_H
#include "Windows/PropVariant.h"
#include <vector>
#include "Common/MyCom.h"
#include "Windows/PropVariant.h"
#include "../Common/UpdateAction.h"
#include "../Common/ArchiverInfo.h"
#include "../Common/OpenArchive.h"
#include "IFolderArchive.h"
#include "AgentProxy.h"
@@ -74,8 +75,8 @@ public:
// IArchiveFolder
STDMETHOD(Extract)(const UINT32 *indices, UINT32 numItems,
NExtractionMode::NPath::EEnum pathMode,
NExtractionMode::NOverwrite::EEnum overwriteMode,
NExtract::NPathMode::EEnum pathMode,
NExtract::NOverwriteMode::EEnum overwriteMode,
const wchar_t *path,
INT32 testMode,
IFolderArchiveExtractCallback *extractCallback);
@@ -137,6 +138,7 @@ public:
CMyComPtr<IFolderFolder> _parentFolder;
CMyComPtr<IInFolderArchive> _agent;
CAgent *_agentSpec;
private:
};
// {23170F69-40C1-278A-1000-000100030000}
@@ -189,8 +191,8 @@ public:
BSTR *name, PROPID *propID, VARTYPE *varType);
STDMETHOD(BindToRootFolder)(IFolderFolder **resultFolder);
STDMETHOD(Extract)(
NExtractionMode::NPath::EEnum pathMode,
NExtractionMode::NOverwrite::EEnum overwriteMode,
NExtract::NPathMode::EEnum pathMode,
NExtract::NOverwriteMode::EEnum overwriteMode,
const wchar_t *path,
INT32 testMode,
IFolderArchiveExtractCallback *extractCallback2);
@@ -204,11 +206,12 @@ public:
const wchar_t *filePath,
const CLSID *clsID,
const wchar_t *newArchiveName,
const BYTE *stateActions,
const Byte *stateActions,
const wchar_t *sfxModule,
IFolderArchiveUpdateCallback *updateCallback);
HRESULT CommonUpdate(const wchar_t *newArchiveName,
HRESULT CommonUpdate(
const wchar_t *newArchiveName,
int numUpdateItems,
IArchiveUpdateCallback *updateCallback);
@@ -224,7 +227,7 @@ public:
IFolderArchiveUpdateCallback *updateCallback100);
// ISetProperties
STDMETHOD(SetProperties)(const BSTR *names, const PROPVARIANT *values, INT32 numProperties);
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, INT32 numProperties);
#endif
CAgent();
@@ -234,16 +237,14 @@ private:
public:
CProxyArchive *_proxyArchive;
#ifndef EXCLUDE_COM
NWindows::NDLL::CLibrary _library;
#endif
CMyComPtr<IInArchive> _archive;
CArchiveLink _archiveLink;
// IInArchive *_archive2;
// CLSID _CLSID;
// CMyComPtr<IArchiveFolder> m_RootFolder;
UString DefaultName;
FILETIME DefaultTime;
UINT32 DefaultAttributes;
@@ -258,9 +259,12 @@ public:
UString _archiveFilePath;
#ifndef EXTRACT_ONLY
CObjectVector<CMyComBSTR> m_PropNames;
CObjectVector<UString> m_PropNames;
std::vector<NWindows::NCOM::CPropVariant> m_PropValues;
#endif
IInArchive *GetArchive() { return _archiveLink.GetArchive(); }
bool CanUpdate() const { return _archiveLink.GetNumLevels() <= 1; }
};
#ifdef NEW_FOLDER_INTERFACE

View File

@@ -1,26 +1,26 @@
// Zip/Handler.cpp
// AgentOutcpp
#include "StdAfx.h"
#include "../Common/UpdatePair.h"
#include "../Common/EnumDirItems.h"
#include "../Common/HandlerLoader.h"
// #include "../Common/UpdatePairAction.h"
// #include "../Common/CompressEngineCommon.h"
// #include "../Common/UpdateProducer.h"
#include "../../Compress/Copy/CopyCoder.h"
#include "Common/StringConvert.h"
#include "Common/IntToString.h"
#include "Windows/Defs.h"
#include "Windows/PropVariant.h"
#include "Windows/PropVariantConversions.h"
#include "Windows/FileDir.h"
#include "../../Compress/Copy/CopyCoder.h"
#include "../../Common/FileStreams.h"
#include "../Common/UpdatePair.h"
#include "../Common/EnumDirItems.h"
#include "../Common/HandlerLoader.h"
#include "../Common/UpdateCallback.h"
#include "../Common/OpenArchive.h"
#include "Agent.h"
#include "ArchiveUpdateCallback.h"
#include "UpdateCallbackAgent.h"
using namespace NWindows;
using namespace NCOM;
@@ -90,7 +90,7 @@ STDMETHODIMP CAgent::SetFiles(const wchar_t *folderPrefix,
static HRESULT GetFileTime(CAgent *agent, UINT32 itemIndex, FILETIME &fileTime)
{
CPropVariant property;
RINOK(agent->_archive->GetProperty(itemIndex, kpidLastWriteTime, &property));
RINOK(agent->GetArchive()->GetProperty(itemIndex, kpidLastWriteTime, &property));
if (property.vt == VT_FILETIME)
fileTime = property.filetime;
else if (property.vt == VT_EMPTY)
@@ -114,9 +114,9 @@ static HRESULT EnumerateArchiveItems(CAgent *agent,
RINOK(::GetFileTime(agent, fileItem.Index, archiveItem.LastWriteTime));
CPropVariant property;
agent->_archive->GetProperty(fileItem.Index, kpidSize, &property);
agent->GetArchive()->GetProperty(fileItem.Index, kpidSize, &property);
if (archiveItem.SizeIsDefined = (property.vt != VT_EMPTY))
archiveItem.Size = ConvertPropVariantToUINT64(property);
archiveItem.Size = ConvertPropVariantToUInt64(property);
archiveItem.IsDirectory = false;
archiveItem.Name = prefix + fileItem.Name;
archiveItem.Censored = true; // test it
@@ -147,10 +147,12 @@ STDMETHODIMP CAgent::DoOperation(
const wchar_t *filePath,
const CLSID *clsID,
const wchar_t *newArchiveName,
const BYTE *stateActions,
const Byte *stateActions,
const wchar_t *sfxModule,
IFolderArchiveUpdateCallback *updateCallback100)
{
if (!CanUpdate())
return E_NOTIMPL;
NUpdateArchive::CActionSet actionSet;
for (int i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
actionSet.StateActions[i] = (NUpdateArchive::NPairAction::EEnum)stateActions[i];
@@ -159,18 +161,20 @@ STDMETHODIMP CAgent::DoOperation(
UString folderPrefix = _folderPrefix;
NFile::NName::NormalizeDirPathPrefix(folderPrefix);
::EnumerateDirItems(folderPrefix, _names, _archiveNamePrefix, dirItems);
RINOK(::EnumerateDirItems(folderPrefix, _names, _archiveNamePrefix, dirItems));
NWindows::NDLL::CLibrary library;
CMyComPtr<IOutArchive> outArchive;
if (_archive)
if (GetArchive())
{
RINOK(_archive.QueryInterface(IID_IOutArchive, &outArchive));
RINOK(GetArchive()->QueryInterface(IID_IOutArchive, (void **)&outArchive));
}
else
{
CHandlerLoader loader;
RINOK(loader.CreateHandler(filePath, *clsID, (void **)&outArchive, true));
_library.Attach(loader.Detach());
library.Attach(loader.Detach());
}
NFileTimeType::EEnum fileTimeType;
@@ -191,7 +195,7 @@ STDMETHODIMP CAgent::DoOperation(
CObjectVector<CUpdatePair> updatePairs;
CObjectVector<CArchiveItem> archiveItems;
if (_archive)
if (GetArchive())
{
RINOK(ReadItems());
EnumerateArchiveItems(this, _proxyArchive->RootFolder, L"", archiveItems);
@@ -199,16 +203,22 @@ STDMETHODIMP CAgent::DoOperation(
GetUpdatePairInfoList(dirItems, archiveItems, fileTimeType, updatePairs);
CObjectVector<CUpdatePair2> operationChain;
CObjectVector<CUpdatePair2> updatePairs2;
UpdateProduce(dirItems, archiveItems, updatePairs, actionSet,
operationChain);
updatePairs2);
CUpdateCallbackAgent updateCallbackAgent;
updateCallbackAgent.Callback = updateCallback100;
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec );
updateCallbackSpec->Init(folderPrefix,&dirItems, &archiveItems,
&operationChain, NULL, updateCallback100);
updateCallbackSpec->DirPrefix = folderPrefix;
updateCallbackSpec->DirItems = &dirItems;
updateCallbackSpec->ArchiveItems = &archiveItems;
updateCallbackSpec->UpdatePairs = &updatePairs2;
updateCallbackSpec->Archive = GetArchive();
updateCallbackSpec->Callback = &updateCallbackAgent;
COutFileStream *outStreamSpec = new COutFileStream;
CMyComPtr<IOutStream> outStream(outStreamSpec);
UString archiveName = newArchiveName;
@@ -219,7 +229,7 @@ STDMETHODIMP CAgent::DoOperation(
throw 141716;
NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));
}
if (!outStreamSpec->Open(archiveName))
if (!outStreamSpec->Create(archiveName, true))
{
// ShowLastErrorMessage();
return E_FAIL;
@@ -234,11 +244,12 @@ STDMETHODIMP CAgent::DoOperation(
}
else
{
std::vector<BSTR> names;
CRecordVector<const wchar_t *> names;
for(i = 0; i < m_PropNames.Size(); i++)
names.push_back(m_PropNames[i]);
RINOK(setProperties->SetProperties(&names.front(),
&m_PropValues.front(), names.size()));
names.Add((const wchar_t *)m_PropNames[i]);
RINOK(setProperties->SetProperties(&names.Front(),
&m_PropValues.front(), names.Size()));
}
}
m_PropNames.Clear();
@@ -253,20 +264,24 @@ STDMETHODIMP CAgent::DoOperation(
RINOK(CopyBlock(sfxStream, outStream));
}
return outArchive->UpdateItems(outStream, operationChain.Size(),
return outArchive->UpdateItems(outStream, updatePairs2.Size(),
updateCallback);
}
HRESULT CAgent::CommonUpdate(const wchar_t *newArchiveName,
HRESULT CAgent::CommonUpdate(
const wchar_t *newArchiveName,
int numUpdateItems,
IArchiveUpdateCallback *updateCallback)
{
if (!CanUpdate())
return E_NOTIMPL;
CMyComPtr<IOutArchive> outArchive;
RINOK(_archive.QueryInterface(IID_IOutArchive, &outArchive));
RINOK(GetArchive()->QueryInterface(IID_IOutArchive, (void **)&outArchive));
COutFileStream *outStreamSpec = new COutFileStream;
CMyComPtr<IOutStream> outStream(outStreamSpec);
UString archiveName = newArchiveName;
{
UString resultPath;
@@ -275,7 +290,30 @@ HRESULT CAgent::CommonUpdate(const wchar_t *newArchiveName,
throw 141716;
NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));
}
if (!outStreamSpec->Open(archiveName))
/*
bool isOK = false;
for (int i = 0; i < (1 << 16); i++)
{
resultName = newArchiveName;
if (i > 0)
{
wchar_t s[32];
ConvertUInt64ToString(i, s);
resultName += s;
}
if (outStreamSpec->Open(realPath))
{
isOK = true;
break;
}
if (::GetLastError() != ERROR_FILE_EXISTS)
return ::GetLastError();
}
if (!isOK)
return ::GetLastError();
*/
if (!outStreamSpec->Create(archiveName, true))
{
// ShowLastErrorMessage();
return E_FAIL;
@@ -290,6 +328,10 @@ STDMETHODIMP CAgent::DeleteItems(
const UINT32 *indices, UINT32 numItems,
IFolderArchiveUpdateCallback *updateCallback100)
{
if (!CanUpdate())
return E_NOTIMPL;
CUpdateCallbackAgent updateCallbackAgent;
updateCallbackAgent.Callback = updateCallback100;
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
@@ -298,7 +340,7 @@ STDMETHODIMP CAgent::DeleteItems(
CObjectVector<CUpdatePair2> updatePairs;
int curIndex = 0;
UINT32 numItemsInArchive;
RINOK(_archive->GetNumberOfItems(&numItemsInArchive));
RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive));
for (int i = 0; i < numItemsInArchive; i++)
{
if (curIndex < realIndices.Size())
@@ -311,11 +353,13 @@ STDMETHODIMP CAgent::DeleteItems(
updatePair.NewData = updatePair.NewProperties = false;
updatePair.ExistInArchive = true;
updatePair.ExistOnDisk = false;
updatePair.IsAnti = false;
updatePair.IsAnti = false; // check it. Maybe it can be undefined
updatePair.ArchiveItemIndex = i;
updatePairs.Add(updatePair);
}
updateCallbackSpec->Init(L"", NULL, NULL, &updatePairs, NULL, updateCallback100);
updateCallbackSpec->UpdatePairs = &updatePairs;
updateCallbackSpec->Archive = GetArchive();
updateCallbackSpec->Callback = &updateCallbackAgent;
return CommonUpdate(newArchiveName, updatePairs.Size(), updateCallback);
}
@@ -324,19 +368,23 @@ HRESULT CAgent::CreateFolder(
const wchar_t *folderName,
IFolderArchiveUpdateCallback *updateCallback100)
{
if (!CanUpdate())
return E_NOTIMPL;
CUpdateCallbackAgent updateCallbackAgent;
updateCallbackAgent.Callback = updateCallback100;
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
CObjectVector<CUpdatePair2> updatePairs;
UINT32 numItemsInArchive;
RINOK(_archive->GetNumberOfItems(&numItemsInArchive));
RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive));
for (int i = 0; i < numItemsInArchive; i++)
{
CUpdatePair2 updatePair;
updatePair.NewData = updatePair.NewProperties = false;
updatePair.ExistInArchive = true;
updatePair.ExistOnDisk = false;
updatePair.IsAnti = false;
updatePair.IsAnti = false; // check it.
updatePair.ArchiveItemIndex = i;
updatePairs.Add(updatePair);
}
@@ -366,7 +414,10 @@ HRESULT CAgent::CreateFolder(
dirItems.Add(dirItem);
updateCallbackSpec->Init(L"", &dirItems, NULL, &updatePairs, NULL, updateCallback100);
updateCallbackSpec->Callback = &updateCallbackAgent;
updateCallbackSpec->DirItems = &dirItems;
updateCallbackSpec->UpdatePairs = &updatePairs;
updateCallbackSpec->Archive = GetArchive();
return CommonUpdate(newArchiveName, updatePairs.Size(), updateCallback);
}
@@ -377,8 +428,12 @@ HRESULT CAgent::RenameItem(
const wchar_t *newItemName,
IFolderArchiveUpdateCallback *updateCallback100)
{
if (!CanUpdate())
return E_NOTIMPL;
if (numItems != 1)
return E_INVALIDARG;
CUpdateCallbackAgent updateCallbackAgent;
updateCallbackAgent.Callback = updateCallback100;
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
@@ -393,7 +448,7 @@ HRESULT CAgent::RenameItem(
CObjectVector<CUpdatePair2> updatePairs;
int curIndex = 0;
UINT32 numItemsInArchive;
RINOK(_archive->GetNumberOfItems(&numItemsInArchive));
RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive));
for (int i = 0; i < numItemsInArchive; i++)
{
if (curIndex < realIndices.Size())
@@ -404,37 +459,19 @@ HRESULT CAgent::RenameItem(
updatePair.NewProperties = true;
updatePair.ExistInArchive = true;
updatePair.ExistOnDisk = false;
updatePair.IsAnti = false; // ?
RINOK(IsArchiveItemAnti(GetArchive(), i, updatePair.IsAnti));
updatePair.ArchiveItemIndex = i;
updatePair.NewNameIsDefined = true;
updatePair.NewName = newItemName;
UString oldFullPath;
{
NCOM::CPropVariant propVariant;
RINOK(_archive->GetProperty(
updatePair.ArchiveItemIndex, kpidPath, &propVariant));
if (propVariant.vt != VT_BSTR)
return E_INVALIDARG;
oldFullPath = propVariant.bstrVal;
}
RINOK(GetArchiveItemPath(GetArchive(), i, DefaultName, oldFullPath));
if (oldItemPath.CollateNoCase(oldFullPath.Left(oldItemPath.Length())) != 0)
return E_INVALIDARG;
{
NCOM::CPropVariant propVariant;
RINOK(_archive->GetProperty(i, kpidIsAnti, &propVariant));
if (propVariant.vt == VT_EMPTY)
updatePair.IsAnti = false;
else if (propVariant.vt != VT_BOOL)
return E_INVALIDARG;
else
updatePair.IsAnti = (propVariant.boolVal != VARIANT_FALSE);
}
updatePair.NewName = newItemPath + oldFullPath.Mid(oldItemPath.Length());
updatePairs.Add(updatePair);
curIndex++;
continue;
@@ -447,13 +484,13 @@ HRESULT CAgent::RenameItem(
updatePair.ArchiveItemIndex = i;
updatePairs.Add(updatePair);
}
updateCallbackSpec->Init(L"", NULL, NULL, &updatePairs, _archive, updateCallback100);
updateCallbackSpec->Callback = &updateCallbackAgent;
updateCallbackSpec->UpdatePairs = &updatePairs;
updateCallbackSpec->Archive = GetArchive();
return CommonUpdate(newArchiveName, updatePairs.Size(), updateCallback);
}
STDMETHODIMP CAgent::SetProperties(const BSTR *names,
STDMETHODIMP CAgent::SetProperties(const wchar_t **names,
const PROPVARIANT *values, INT32 numProperties)
{
m_PropNames.Clear();

View File

@@ -7,6 +7,7 @@
#include "Common/MyCom.h"
#include "Windows/PropVariant.h"
#include "Windows/Defs.h"
#include "../Common/OpenArchive.h"
using namespace NWindows;
@@ -184,11 +185,9 @@ HRESULT CProxyArchive::ReadObjects(IInArchive *archiveHandler, IProgress *progre
}
NCOM::CPropVariant propVariantIsFolder;
RINOK(archiveHandler->GetProperty(i,
kpidIsFolder, &propVariantIsFolder));
if(propVariantIsFolder.vt != VT_BOOL)
return E_FAIL;
if(VARIANT_BOOLToBool(propVariantIsFolder.boolVal))
bool isFolder;
RINOK(IsArchiveItemFolder(archiveHandler, i, isFolder));
if(isFolder)
currentItem->AddDirSubItem(i, true, fileName);
else
currentItem->AddFileSubItem(i, fileName);

View File

@@ -1,7 +1,5 @@
// AgentProxy.h
#pragma once
#ifndef __AGENT_PROXY_H
#define __AGENT_PROXY_H

View File

@@ -12,9 +12,9 @@
#include "../../Common/FileStreams.h"
#include "../Common/UpdatePair.h"
#include "../Common/ArchiveExtractCallback.h"
#include "Agent.h"
#include "ArchiveExtractCallback.h"
using namespace NWindows;
using namespace NCOM;
@@ -41,11 +41,12 @@ STDMETHODIMP CAgentFolder::CopyTo(const UINT32 *indices, UINT32 numItems,
IID_IFolderArchiveExtractCallback, &extractCallback2));
}
extractCallbackSpec->Init(_agentSpec->_archive,
extractCallbackSpec->Init(_agentSpec->GetArchive(),
extractCallback2,
false,
path,
NExtractionMode::NPath::kCurrentPathnames,
NExtractionMode::NOverwrite::kAskBefore,
NExtract::NPathMode::kCurrentPathnames,
NExtract::NOverwriteMode::kAskBefore,
pathParts,
_agentSpec->DefaultName,
_agentSpec->DefaultTime,
@@ -54,7 +55,7 @@ STDMETHODIMP CAgentFolder::CopyTo(const UINT32 *indices, UINT32 numItems,
);
CUIntVector realIndices;
_proxyFolderItem->GetRealIndices(indices, numItems, realIndices);
return _agentSpec->_archive->Extract(&realIndices.Front(),
return _agentSpec->GetArchive()->Extract(&realIndices.Front(),
realIndices.Size(), BoolToInt(false), extractCallback);
COM_TRY_END
}

View File

@@ -8,7 +8,7 @@
#include "../Common/OpenArchive.h"
static const UINT64 kMaxCheckStartPosition = 1 << 20;
static const UInt64 kMaxCheckStartPosition = 1 << 20;
static inline UINT GetCurrentFileCodePage()
{ return AreFileApisANSI() ? CP_ACP : CP_OEMCP; }

View File

@@ -85,7 +85,7 @@ HRESULT CAgentFolder::CommonUpdateOperation(
}
else
{
BYTE actionSetByte[NUpdateArchive::NPairState::kNumValues];
Byte actionSetByte[NUpdateArchive::NPairState::kNumValues];
for (int i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
actionSetByte[i] = actionSet->StateActions[i];
result = _agentSpec->DoOperation(NULL, NULL,

View File

@@ -1,229 +0,0 @@
// ArchiveUpdateCallback.h
#include "StdAfx.h"
#include "ArchiveUpdateCallback.h"
#include "Common/StringConvert.h"
#include "Common/Defs.h"
#include "Windows/FileName.h"
#include "Windows/PropVariant.h"
#include "../../Common/FileStreams.h"
#include "Windows/Defs.h"
using namespace NWindows;
void CArchiveUpdateCallback::Init(const UString &baseFolderPrefix,
const CObjectVector<CDirItem> *dirItems,
const CObjectVector<CArchiveItem> *archiveItems, // test CItemInfoExList
CObjectVector<CUpdatePair2> *updatePairs,
IInArchive *inArchive,
IFolderArchiveUpdateCallback *updateCallback)
{
m_BaseFolderPrefix = baseFolderPrefix;
NFile::NName::NormalizeDirPathPrefix(m_BaseFolderPrefix);
m_DirItems = dirItems;
m_ArchiveItems = archiveItems;
m_UpdatePairs = updatePairs;
m_UpdateCallback = updateCallback;
m_CodePage = ::AreFileApisANSI() ? CP_ACP : CP_OEMCP;
_inArchive = inArchive;;
}
STDMETHODIMP CArchiveUpdateCallback::SetTotal(UINT64 size)
{
if (m_UpdateCallback)
return m_UpdateCallback->SetTotal(size);
return S_OK;
}
STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UINT64 *completeValue)
{
if (m_UpdateCallback)
return m_UpdateCallback->SetCompleted(completeValue);
return S_OK;
}
/*
STATPROPSTG kProperties[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsFolder, VT_BOOL},
{ NULL, kpidSize, VT_UI8},
{ NULL, kpidLastAccessTime, VT_FILETIME},
{ NULL, kpidCreationTime, VT_FILETIME},
{ NULL, kpidLastWriteTime, VT_FILETIME},
{ NULL, kpidAttributes, VT_UI4},
{ NULL, kpidIsAnti, VT_BOOL}
};
STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **enumerator)
{
return CStatPropEnumerator::CreateEnumerator(kProperties,
sizeof(kProperties) / sizeof(kProperties[0]), enumerator);
}
*/
STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UINT32 index,
INT32 *newData, INT32 *newProperties, UINT32 *indexInArchive)
{
const CUpdatePair2 &updatePair = (*m_UpdatePairs)[index];
if(newData != NULL)
*newData = BoolToInt(updatePair.NewData);
if(newProperties != NULL)
*newProperties = BoolToInt(updatePair.NewProperties);
if(indexInArchive != NULL)
{
if (updatePair.ExistInArchive)
{
if (m_ArchiveItems == 0)
*indexInArchive = updatePair.ArchiveItemIndex;
else
*indexInArchive = (*m_ArchiveItems)[updatePair.ArchiveItemIndex].IndexInServer;
}
else
*indexInArchive = UINT32(-1);
}
return S_OK;
}
STDMETHODIMP CArchiveUpdateCallback::GetProperty(UINT32 index, PROPID propID, PROPVARIANT *value)
{
const CUpdatePair2 &updatePair = (*m_UpdatePairs)[index];
NWindows::NCOM::CPropVariant propVariant;
if (propID == kpidIsAnti)
{
propVariant = updatePair.IsAnti;
propVariant.Detach(value);
return S_OK;
}
if (updatePair.IsAnti)
{
switch(propID)
{
case kpidIsFolder:
case kpidPath:
break;
case kpidSize:
propVariant = (UINT64)0;
propVariant.Detach(value);
return S_OK;
default:
propVariant.Detach(value);
return S_OK;
}
}
if(updatePair.ExistOnDisk)
{
const CDirItem &dirItem = (*m_DirItems)[updatePair.DirItemIndex];
switch(propID)
{
case kpidPath:
propVariant = dirItem.Name;
break;
case kpidIsFolder:
propVariant = dirItem.IsDirectory();
break;
case kpidSize:
propVariant = dirItem.Size;
break;
case kpidAttributes:
propVariant = dirItem.Attributes;
break;
case kpidLastAccessTime:
propVariant = dirItem.LastAccessTime;
break;
case kpidCreationTime:
propVariant = dirItem.CreationTime;
break;
case kpidLastWriteTime:
propVariant = dirItem.LastWriteTime;
break;
}
}
else
{
if (propID == kpidPath)
{
if (updatePair.NewNameIsDefined)
{
propVariant = updatePair.NewName;
propVariant.Detach(value);
return S_OK;
}
}
if (updatePair.ExistInArchive && _inArchive)
{
UINT32 indexInArchive;
if (m_ArchiveItems == 0)
indexInArchive = updatePair.ArchiveItemIndex;
else
indexInArchive = (*m_ArchiveItems)[updatePair.ArchiveItemIndex].IndexInServer;
return _inArchive->GetProperty(indexInArchive, propID, value);
}
}
propVariant.Detach(value);
return S_OK;
}
STDMETHODIMP CArchiveUpdateCallback::GetStream(UINT32 index,
IInStream **inStream)
{
const CUpdatePair2 &updatePair = (*m_UpdatePairs)[index];
if(!updatePair.NewData)
return E_FAIL;
const CDirItem &dirItem = (*m_DirItems)[updatePair.DirItemIndex];
/*
m_PercentPrinter.PrintString("Compressing ");
m_PercentCanBePrint = true;
m_PercentPrinter.PrintString(UnicodeStringToMultiByte(dirItem.Name, CP_OEMCP));
m_PercentPrinter.PreparePrint();
m_PercentPrinter.RePrintRatio();
*/
if (m_UpdateCallback)
{
RINOK(m_UpdateCallback->CompressOperation(
GetUnicodeString(dirItem.FullPath, m_CodePage)));
}
if(dirItem.IsDirectory())
return S_OK;
CInFileStream *inStreamSpec = new CInFileStream;
CMyComPtr<IInStream> inStreamLoc(inStreamSpec);
if(!inStreamSpec->Open(m_BaseFolderPrefix + dirItem.FullPath))
return ::GetLastError();
*inStream = inStreamLoc.Detach();
return S_OK;
}
STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(INT32 operationResult)
{
if (m_UpdateCallback)
return m_UpdateCallback->OperationResult(operationResult);
return S_OK;
}
STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(INT32 *passwordIsDefined, BSTR *password)
{
*passwordIsDefined = BoolToInt(false);
if (!_cryptoGetTextPassword)
{
if (!m_UpdateCallback)
return S_OK;
HRESULT result = m_UpdateCallback.QueryInterface(
IID_ICryptoGetTextPassword2, &_cryptoGetTextPassword);
if (result != S_OK)
return S_OK;
}
return _cryptoGetTextPassword->CryptoGetTextPassword2(passwordIsDefined, password);
}

View File

@@ -1,71 +0,0 @@
// ArchiveUpdateCallback.h
#pragma once
#ifndef __ARCHIVEUPDATECALLBACK_H
#define __ARCHIVEUPDATECALLBACK_H
#include "../../Archive/IArchive.h"
#include "../../IPassword.h"
#include "IFolderArchive.h"
#include "Common/String.h"
#include "Common/MyCom.h"
#include "../Common/UpdateProduce.h"
// #include "Interface/CryptoInterface.h"
// #include "Interface/MyCom.h"
class CArchiveUpdateCallback:
public IArchiveUpdateCallback,
public ICryptoGetTextPassword2,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP1(ICryptoGetTextPassword2)
// IProgress
STDMETHOD(SetTotal)(UINT64 size);
STDMETHOD(SetCompleted)(const UINT64 *completeValue);
// IArchiveUpdateCallback
// STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator);
STDMETHOD(GetUpdateItemInfo)(UINT32 index,
INT32 *newData, // 1 - new data, 0 - old data
INT32 *newProperties, // 1 - new properties, 0 - old properties
UINT32 *indexInArchive// set if existInArchive == true
);
STDMETHOD(GetProperty)(UINT32 index, PROPID propID, PROPVARIANT *value);
STDMETHOD(GetStream)(UINT32 index, IInStream **anInStream);
STDMETHOD(SetOperationResult)(INT32 operationResult);
STDMETHOD(CryptoGetTextPassword2)(INT32 *passwordIsDefined, BSTR *password);
private:
UString m_BaseFolderPrefix;
const CObjectVector<CDirItem> *m_DirItems;
const CObjectVector<CArchiveItem> *m_ArchiveItems;
const CObjectVector<CUpdatePair2> *m_UpdatePairs;
CMyComPtr<IFolderArchiveUpdateCallback> m_UpdateCallback;
CMyComPtr<ICryptoGetTextPassword2> _cryptoGetTextPassword;
UINT m_CodePage;
CMyComPtr<IInArchive> _inArchive;
public:
void Init(const UString &baseFolderPrefix,
const CObjectVector<CDirItem> *dirItems,
const CObjectVector<CArchiveItem> *archiveItems, // test CItemInfoExList
CObjectVector<CUpdatePair2> *updatePairs,
// UINT codePage,
IInArchive *inArchive,
IFolderArchiveUpdateCallback *updateCallback);
};
#endif

View File

@@ -1,65 +1,13 @@
// IFolderArchive.h
#pragma once
#ifndef __IFOLDERARCHIVE_H
#define __IFOLDERARCHIVE_H
#ifndef __IFOLDER_ARCHIVE_H
#define __IFOLDER_ARCHIVE_H
#include "../../Archive/IArchive.h"
// #include "../Format/Common/ArchiveInterface.h"
#include "../../FileManager/IFolder.h"
namespace NExtractionMode {
namespace NPath
{
enum EEnum
{
kFullPathnames,
kCurrentPathnames,
kNoPathnames
};
}
namespace NOverwrite
{
enum EEnum
{
kAskBefore,
kWithoutPrompt,
kSkipExisting,
kAutoRename
};
}
}
namespace NOverwriteAnswer
{
enum EEnum
{
kYes,
kYesToAll,
kNo,
kNoToAll,
kAutoRename,
kCancel,
};
}
// {23170F69-40C1-278A-0000-000100070000}
DEFINE_GUID(IID_IFolderArchiveExtractCallback,
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00);
MIDL_INTERFACE("23170F69-40C1-278A-0000-000100070000")
IFolderArchiveExtractCallback: public IProgress
{
public:
STDMETHOD(AskOverwrite)(
const wchar_t *existName, const FILETIME *existTime, const UINT64 *existSize,
const wchar_t *newName, const FILETIME *newTime, const UINT64 *newSize,
INT32 *answer);
STDMETHOD(PrepareOperation)(const wchar_t *name, INT32 askExtractMode) PURE;
STDMETHOD(MessageError)(const wchar_t *message) PURE;
STDMETHOD(SetOperationResult)(INT32 operationResult) PURE;
};
#include "../Common/IFileExtractCallback.h"
#include "../Common/ExtractMode.h"
// {23170F69-40C1-278A-0000-000100050000}
DEFINE_GUID(IID_IArchiveFolder,
@@ -69,8 +17,8 @@ IArchiveFolder: public IUnknown
{
public:
STDMETHOD(Extract)(const UINT32 *indices, UINT32 numItems,
NExtractionMode::NPath::EEnum pathMode,
NExtractionMode::NOverwrite::EEnum overwriteMode,
NExtract::NPathMode::EEnum pathMode,
NExtract::NOverwriteMode::EEnum overwriteMode,
const wchar_t *path,
INT32 testMode,
IFolderArchiveExtractCallback *extractCallback2) PURE;
@@ -100,8 +48,8 @@ public:
BSTR *name, PROPID *propID, VARTYPE *varType) PURE;
STDMETHOD(BindToRootFolder)(IFolderFolder **resultFolder) PURE;
STDMETHOD(Extract)(
NExtractionMode::NPath::EEnum pathMode,
NExtractionMode::NOverwrite::EEnum overwriteMode,
NExtract::NPathMode::EEnum pathMode,
NExtract::NOverwriteMode::EEnum overwriteMode,
const wchar_t *path,
INT32 testMode,
IFolderArchiveExtractCallback *extractCallback2) PURE;
@@ -117,6 +65,7 @@ public:
STDMETHOD(CompressOperation)(const wchar_t *name) PURE;
STDMETHOD(DeleteOperation)(const wchar_t *name) PURE;
STDMETHOD(OperationResult)(INT32 operationResult) PURE;
STDMETHOD(UpdateErrorMessage)(const wchar_t *message) PURE;
};
// {23170F69-40C1-278A-0000-0001000A0000}
@@ -133,7 +82,7 @@ IOutFolderArchive: public IUnknown
const wchar_t *filePath,
const CLSID *clsID,
const wchar_t *newArchiveName,
const BYTE *stateActions,
const Byte *stateActions,
const wchar_t *sfxModule,
IFolderArchiveUpdateCallback *updateCallback) PURE;
};

View File

@@ -0,0 +1,80 @@
// UpdateCallbackAgent.h
#include "StdAfx.h"
#include "Windows/Error.h"
#include "UpdateCallbackAgent.h"
using namespace NWindows;
HRESULT CUpdateCallbackAgent::SetTotal(UINT64 size)
{
if (Callback)
return Callback->SetTotal(size);
return S_OK;
}
HRESULT CUpdateCallbackAgent::SetCompleted(const UINT64 *completeValue)
{
if (Callback)
return Callback->SetCompleted(completeValue);
return S_OK;
}
HRESULT CUpdateCallbackAgent::CheckBreak()
{
return S_OK;
}
HRESULT CUpdateCallbackAgent::Finilize()
{
return S_OK;
}
HRESULT CUpdateCallbackAgent::OpenFileError(const wchar_t *name, DWORD systemError)
{
// if (systemError == ERROR_SHARING_VIOLATION)
{
if (Callback)
{
RINOK(Callback->UpdateErrorMessage(
UString(L"WARNING: ") +
NError::MyFormatMessageW(systemError) +
UString(L": ") +
UString(name)));
return S_FALSE;
}
}
// FailedFiles.Add(name);
return systemError;
}
HRESULT CUpdateCallbackAgent::GetStream(const wchar_t *name, bool isAnti)
{
if (Callback)
return Callback->CompressOperation(name);
return S_OK;
}
HRESULT CUpdateCallbackAgent::SetOperationResult(INT32 operationResult)
{
if (Callback)
return Callback->OperationResult(operationResult);
return S_OK;
}
HRESULT CUpdateCallbackAgent::CryptoGetTextPassword2(INT32 *passwordIsDefined, BSTR *password)
{
*passwordIsDefined = BoolToInt(false);
if (!_cryptoGetTextPassword)
{
if (!Callback)
return S_OK;
HRESULT result = Callback.QueryInterface(
IID_ICryptoGetTextPassword2, &_cryptoGetTextPassword);
if (result != S_OK)
return S_OK;
}
return _cryptoGetTextPassword->CryptoGetTextPassword2(passwordIsDefined, password);
}

View File

@@ -0,0 +1,24 @@
// UpdateCallbackAgent.h
#ifndef __UPDATECALLBACKAGENT_H
#define __UPDATECALLBACKAGENT_H
#include "../Common/UpdateCallback.h"
#include "IFolderArchive.h"
class CUpdateCallbackAgent: public IUpdateCallbackUI
{
virtual HRESULT SetTotal(UINT64 size);
virtual HRESULT SetCompleted(const UINT64 *completeValue);
virtual HRESULT CheckBreak();
virtual HRESULT Finilize();
virtual HRESULT GetStream(const wchar_t *name, bool isAnti);
virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError);
virtual HRESULT SetOperationResult(INT32 operationResult);
virtual HRESULT CryptoGetTextPassword2(INT32 *passwordIsDefined, BSTR *password);
CMyComPtr<ICryptoGetTextPassword2> _cryptoGetTextPassword;
public:
CMyComPtr<IFolderArchiveUpdateCallback> Callback;
};
#endif

View File

@@ -1,6 +1,6 @@
// Client7z.cpp : Defines the entry point for the console application.
// Client7z.cpp
#include "stdafx.h"
#include "StdAfx.h"
#include <initguid.h>
@@ -59,9 +59,9 @@ int main(int argc, char* argv[])
}
if (archive->Open(file, 0, 0) != S_OK)
return 0;
UINT32 numItems = 0;
UInt32 numItems = 0;
archive->GetNumberOfItems(&numItems);
for (UINT32 i = 0; i < numItems; i++)
for (UInt32 i = 0; i < numItems; i++)
{
NWindows::NCOM::CPropVariant propVariant;
archive->GetProperty(i, kpidPath, &propVariant);

View File

@@ -81,35 +81,19 @@ LINK32=link.exe
# Name "Client7z - Win32 Release"
# Name "Client7z - Win32 Debug"
# Begin Group "Source Files"
# Begin Group "Spec"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\Client7z.cpp
# End Source File
# Begin Source File
SOURCE=.\StdAfx.cpp
# ADD CPP /Yc"stdafx.h"
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\StdAfx.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# Begin Group "SDK"
# PROP Default_Filter ""
# End Group
# Begin Group "Windows"
# PROP Default_Filter ""
@@ -186,5 +170,9 @@ SOURCE=..\..\Common\FileStreams.cpp
SOURCE=..\..\Common\FileStreams.h
# End Source File
# End Group
# Begin Source File
SOURCE=.\Client7z.cpp
# End Source File
# End Target
# End Project

View File

@@ -1,8 +1,3 @@
// stdafx.cpp : source file that includes just the standard includes
// Client7z.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
// StdAfx.cpp
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file
#include "StdAfx.h"

View File

@@ -1,6 +1,4 @@
// stdafx.h
#pragma once
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
@@ -9,4 +7,3 @@
#include <stdio.h>
#endif

View File

@@ -0,0 +1,830 @@
// ArchiveCommandLine.cpp
#include "StdAfx.h"
#include <io.h>
#include <stdio.h>
#include "Common/ListFileUtils.h"
#include "Common/StringConvert.h"
#include "Common/StringToInt.h"
#include "Windows/FileName.h"
#include "Windows/FileDir.h"
#ifdef _WIN32
#include "Windows/FileMapping.h"
#include "Windows/Synchronization.h"
#endif
#include "ArchiveCommandLine.h"
#include "UpdateAction.h"
#include "Update.h"
#include "ArchiverInfo.h"
#include "SortUtils.h"
#include "EnumDirItems.h"
using namespace NCommandLineParser;
using namespace NWindows;
using namespace NFile;
static const int kNumSwitches = 24;
namespace NKey {
enum Enum
{
kHelp1 = 0,
kHelp2,
kDisableHeaders,
kDisablePercents,
kArchiveType,
kYes,
kPassword,
kProperty,
kOutputDir,
kWorkingDir,
kInclude,
kExclude,
kArInclude,
kArExclude,
kNoArName,
kUpdate,
kVolume,
kRecursed,
kSfx,
kStdIn,
kStdOut,
kOverwrite,
kEmail,
kShowDialog
};
}
static const wchar_t kRecursedIDChar = 'R';
static const wchar_t *kRecursedPostCharSet = L"0-";
static const wchar_t *kDefaultArchiveType = L"7z";
static const wchar_t *kSFXExtension = L"exe";
namespace NRecursedPostCharIndex {
enum EEnum
{
kWildCardRecursionOnly = 0,
kNoRecursion = 1
};
}
static const char kImmediateNameID = '!';
static const char kMapNameID = '#';
static const char kFileListID = '@';
static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be
static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be
static const wchar_t *kOverwritePostCharSet = L"asut";
NExtract::NOverwriteMode::EEnum k_OverwriteModes[] =
{
NExtract::NOverwriteMode::kWithoutPrompt,
NExtract::NOverwriteMode::kSkipExisting,
NExtract::NOverwriteMode::kAutoRename,
NExtract::NOverwriteMode::kAutoRenameExisting
};
static const CSwitchForm kSwitchForms[kNumSwitches] =
{
{ L"?", NSwitchType::kSimple, false },
{ L"H", NSwitchType::kSimple, false },
{ L"BA", NSwitchType::kSimple, false },
{ L"BD", NSwitchType::kSimple, false },
{ L"T", NSwitchType::kUnLimitedPostString, false, 1 },
{ L"Y", NSwitchType::kSimple, false },
{ L"P", NSwitchType::kUnLimitedPostString, false, 0 },
{ L"M", NSwitchType::kUnLimitedPostString, true, 1 },
{ L"O", NSwitchType::kUnLimitedPostString, false, 1 },
{ L"W", NSwitchType::kUnLimitedPostString, false, 0 },
{ L"I", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},
{ L"X", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},
{ L"AI", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},
{ L"AX", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSize},
{ L"AN", NSwitchType::kSimple, false },
{ L"U", NSwitchType::kUnLimitedPostString, true, 1},
{ L"V", NSwitchType::kUnLimitedPostString, true, 1},
{ L"R", NSwitchType::kPostChar, false, 0, 0, kRecursedPostCharSet },
{ L"SFX", NSwitchType::kUnLimitedPostString, false, 0 },
{ L"SI", NSwitchType::kUnLimitedPostString, false, 0 },
{ L"SO", NSwitchType::kSimple, false, 0 },
{ L"AO", NSwitchType::kPostChar, false, 1, 1, kOverwritePostCharSet},
{ L"SEML", NSwitchType::kUnLimitedPostString, false, 0},
{ L"AD", NSwitchType::kSimple, false }
};
static const int kNumCommandForms = 7;
static const CCommandForm g_CommandForms[kNumCommandForms] =
{
{ L"A", false },
{ L"U", false },
{ L"D", false },
{ L"T", false },
{ L"E", false },
{ L"X", false },
{ L"L", false }
};
static const int kMaxCmdLineSize = 1000;
static const wchar_t *kUniversalWildcard = L"*";
static const int kMinNonSwitchWords = 1;
static const int kCommandIndex = 0;
// ---------------------------
// exception messages
static const char *kUserErrorMessage = "Incorrect command line";
static const char *kIncorrectListFile = "Incorrect wildcard in listfile";
static const char *kIncorrectWildCardInListFile = "Incorrect wildcard in listfile";
static const char *kIncorrectWildCardInCommandLine = "Incorrect wildcard in command line";
static const char *kTerminalOutError = "I won't write compressed data to a terminal";
// ---------------------------
bool CArchiveCommand::IsFromExtractGroup() const
{
switch(CommandType)
{
case NCommandType::kTest:
case NCommandType::kExtract:
case NCommandType::kFullExtract:
return true;
default:
return false;
}
}
NExtract::NPathMode::EEnum CArchiveCommand::GetPathMode() const
{
switch(CommandType)
{
case NCommandType::kTest:
case NCommandType::kFullExtract:
return NExtract::NPathMode::kFullPathnames;
default:
return NExtract::NPathMode::kNoPathnames;
}
}
bool CArchiveCommand::IsFromUpdateGroup() const
{
return (CommandType == NCommandType::kAdd ||
CommandType == NCommandType::kUpdate ||
CommandType == NCommandType::kDelete);
}
static NRecursedType::EEnum GetRecursedTypeFromIndex(int index)
{
switch (index)
{
case NRecursedPostCharIndex::kWildCardRecursionOnly:
return NRecursedType::kWildCardOnlyRecursed;
case NRecursedPostCharIndex::kNoRecursion:
return NRecursedType::kNonRecursed;
default:
return NRecursedType::kRecursed;
}
}
static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command)
{
UString commandStringUpper = commandString;
commandStringUpper.MakeUpper();
UString postString;
int commandIndex = ParseCommand(kNumCommandForms, g_CommandForms, commandStringUpper,
postString) ;
if (commandIndex < 0)
return false;
command.CommandType = (NCommandType::EEnum)commandIndex;
return true;
}
// ------------------------------------------------------------------
// filenames functions
static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor,
const UString &name, bool include, NRecursedType::EEnum type)
{
bool isWildCard = DoesNameContainWildCard(name);
bool recursed;
switch (type)
{
case NRecursedType::kWildCardOnlyRecursed:
recursed = isWildCard;
break;
case NRecursedType::kRecursed:
recursed = true;
break;
case NRecursedType::kNonRecursed:
recursed = false;
break;
}
wildcardCensor.AddItem(name, include, recursed);
return true;
}
static inline UINT GetCurrentCodePage()
{ return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }
static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor,
LPCWSTR fileName, bool include, NRecursedType::EEnum type)
{
UStringVector names;
if (!ReadNamesFromListFile(GetSystemString(fileName,
GetCurrentCodePage()), names))
throw kIncorrectListFile;
for (int i = 0; i < names.Size(); i++)
if (!AddNameToCensor(wildcardCensor, names[i], include, type))
throw kIncorrectWildCardInListFile;
}
static void AddCommandLineWildCardToCensr(NWildcard::CCensor &wildcardCensor,
const UString &name, bool include, NRecursedType::EEnum recursedType)
{
if (!AddNameToCensor(wildcardCensor, name, include, recursedType))
throw kIncorrectWildCardInCommandLine;
}
static void AddToCensorFromNonSwitchesStrings(
int startIndex,
NWildcard::CCensor &wildcardCensor,
const UStringVector &nonSwitchStrings, NRecursedType::EEnum type,
bool thereAreSwitchIncludes)
{
if(nonSwitchStrings.Size() == startIndex && (!thereAreSwitchIncludes))
AddCommandLineWildCardToCensr(wildcardCensor, kUniversalWildcard, true, type);
for(int i = startIndex; i < nonSwitchStrings.Size(); i++)
{
const UString &s = nonSwitchStrings[i];
if (s[0] == kFileListID)
AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type);
else
AddCommandLineWildCardToCensr(wildcardCensor, s, true, type);
}
}
#ifdef _WIN32
static void ParseMapWithPaths(NWildcard::CCensor &wildcardCensor,
const UString &switchParam, bool include,
NRecursedType::EEnum commonRecursedType)
{
int splitPos = switchParam.Find(L':');
if (splitPos < 0)
throw kUserErrorMessage;
UString mappingName = switchParam.Left(splitPos);
UString switchParam2 = switchParam.Mid(splitPos + 1);
splitPos = switchParam2.Find(L':');
if (splitPos < 0)
throw kUserErrorMessage;
UString mappingSize = switchParam2.Left(splitPos);
UString eventName = switchParam2.Mid(splitPos + 1);
UInt64 dataSize64 = ConvertStringToUInt64(mappingSize, NULL);
UInt32 dataSize = (UInt32)dataSize64;
{
CFileMapping fileMapping;
if (!fileMapping.Open(FILE_MAP_READ, false, GetSystemString(mappingName)))
throw L"Can not open mapping";
LPVOID data = fileMapping.MapViewOfFile(FILE_MAP_READ, 0, dataSize);
if (data == NULL)
throw L"MapViewOfFile error";
try
{
const wchar_t *curData = (const wchar_t *)data;
if (*curData != 0)
throw L"Incorrect mapping data";
UInt32 numChars = dataSize / sizeof(wchar_t);
UString name;
for (UInt32 i = 1; i < numChars; i++)
{
wchar_t c = curData[i];
if (c == L'\0')
{
AddCommandLineWildCardToCensr(wildcardCensor,
name, include, commonRecursedType);
name.Empty();
}
else
name += c;
}
if (!name.IsEmpty())
throw L"data error";
}
catch(...)
{
UnmapViewOfFile(data);
throw;
}
UnmapViewOfFile(data);
}
{
NSynchronization::CEvent event;
event.Open(EVENT_MODIFY_STATE, false, GetSystemString(eventName));
event.Set();
}
}
#endif
static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor,
const UStringVector &strings, bool include,
NRecursedType::EEnum commonRecursedType)
{
for(int i = 0; i < strings.Size(); i++)
{
const UString &name = strings[i];
NRecursedType::EEnum recursedType;
int pos = 0;
if (name.Length() < kSomeCludePostStringMinSize)
throw kUserErrorMessage;
if (::MyCharUpper(name[pos]) == kRecursedIDChar)
{
pos++;
int index = UString(kRecursedPostCharSet).Find(name[pos]);
recursedType = GetRecursedTypeFromIndex(index);
if (index >= 0)
pos++;
}
else
recursedType = commonRecursedType;
if (name.Length() < pos + kSomeCludeAfterRecursedPostStringMinSize)
throw kUserErrorMessage;
UString tail = name.Mid(pos + 1);
if (name[pos] == kImmediateNameID)
AddCommandLineWildCardToCensr(wildcardCensor, tail, include, recursedType);
else if (name[pos] == kFileListID)
AddToCensorFromListFile(wildcardCensor, tail, include, recursedType);
#ifdef _WIN32
else if (name[pos] == kMapNameID)
ParseMapWithPaths(wildcardCensor, tail, include, recursedType);
#endif
else
throw kUserErrorMessage;
}
}
static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i)
{
switch(i)
{
case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairAction::kIgnore;
case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction::kCopy;
case NUpdateArchive::NPairAction::kCompress: return NUpdateArchive::NPairAction::kCompress;
case NUpdateArchive::NPairAction::kCompressAsAnti: return NUpdateArchive::NPairAction::kCompressAsAnti;
}
throw 98111603;
}
const UString kUpdatePairStateIDSet = L"PQRXYZW";
const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1};
const UString kUpdatePairActionIDSet = L"0123"; //Ignore, Copy, Compress, Create Anti
const wchar_t *kUpdateIgnoreItselfPostStringID = L"-";
const wchar_t kUpdateNewArchivePostCharID = '!';
static bool ParseUpdateCommandString2(const UString &command,
NUpdateArchive::CActionSet &actionSet, UString &postString)
{
for(int i = 0; i < command.Length();)
{
wchar_t c = MyCharUpper(command[i]);
int statePos = kUpdatePairStateIDSet.Find(c);
if (statePos < 0)
{
postString = command.Mid(i);
return true;
}
i++;
if (i >= command.Length())
return false;
int actionPos = kUpdatePairActionIDSet.Find(::MyCharUpper(command[i]));
if (actionPos < 0)
return false;
actionSet.StateActions[statePos] = GetUpdatePairActionType(actionPos);
if (kUpdatePairStateNotSupportedActions[statePos] == actionPos)
return false;
i++;
}
postString.Empty();
return true;
}
static void ParseUpdateCommandString(CUpdateOptions &options,
const UStringVector &updatePostStrings,
const NUpdateArchive::CActionSet &defaultActionSet)
{
for(int i = 0; i < updatePostStrings.Size(); i++)
{
const UString &updateString = updatePostStrings[i];
if(updateString.CompareNoCase(kUpdateIgnoreItselfPostStringID) == 0)
{
if(options.UpdateArchiveItself)
{
options.UpdateArchiveItself = false;
options.Commands.Delete(0);
}
}
else
{
NUpdateArchive::CActionSet actionSet = defaultActionSet;
UString postString;
if (!ParseUpdateCommandString2(updateString, actionSet, postString))
throw kUserErrorMessage;
if(postString.IsEmpty())
{
if(options.UpdateArchiveItself)
options.Commands[0].ActionSet = actionSet;
}
else
{
if(MyCharUpper(postString[0]) != kUpdateNewArchivePostCharID)
throw kUserErrorMessage;
CUpdateArchiveCommand uc;
UString archivePath = postString.Mid(1);
if (archivePath.IsEmpty())
throw kUserErrorMessage;
uc.ArchivePath.BaseExtension = options.ArchivePath.BaseExtension;
uc.ArchivePath.VolExtension = options.ArchivePath.VolExtension;
uc.ArchivePath.ParseFromPath(archivePath);
uc.ActionSet = actionSet;
options.Commands.Add(uc);
}
}
}
}
static const char kByteSymbol = 'B';
static const char kKiloSymbol = 'K';
static const char kMegaSymbol = 'M';
static const char kGigaSymbol = 'G';
static bool ParseComplexSize(const UString &src, UInt64 &result)
{
UString s = src;
s.MakeUpper();
const wchar_t *start = s;
const wchar_t *end;
UInt64 number = ConvertStringToUInt64(start, &end);
int numDigits = end - start;
if (numDigits == 0 || s.Length() > numDigits + 1)
return false;
if (s.Length() == numDigits)
{
result = number;
return true;
}
int numBits;
switch (s[numDigits])
{
case kByteSymbol:
result = number;
return true;
case kKiloSymbol:
numBits = 10;
break;
case kMegaSymbol:
numBits = 20;
break;
case kGigaSymbol:
numBits = 30;
break;
default:
return false;
}
if (number >= ((UInt64)1 << (64 - numBits)))
return false;
result = number << numBits;
return true;
}
static void SetAddCommandOptions(
NCommandType::EEnum commandType,
const CParser &parser,
CUpdateOptions &options)
{
NUpdateArchive::CActionSet defaultActionSet;
switch(commandType)
{
case NCommandType::kAdd:
defaultActionSet = NUpdateArchive::kAddActionSet;
break;
case NCommandType::kDelete:
defaultActionSet = NUpdateArchive::kDeleteActionSet;
break;
default:
defaultActionSet = NUpdateArchive::kUpdateActionSet;
}
options.UpdateArchiveItself = true;
options.Commands.Clear();
CUpdateArchiveCommand updateMainCommand;
updateMainCommand.ActionSet = defaultActionSet;
options.Commands.Add(updateMainCommand);
if(parser[NKey::kUpdate].ThereIs)
ParseUpdateCommandString(options, parser[NKey::kUpdate].PostStrings,
defaultActionSet);
if(parser[NKey::kWorkingDir].ThereIs)
{
const UString &postString = parser[NKey::kWorkingDir].PostStrings[0];
if (postString.IsEmpty())
NDirectory::MyGetTempPath(options.WorkingDir);
else
options.WorkingDir = postString;
}
if(options.SfxMode = parser[NKey::kSfx].ThereIs)
options.SfxModule = parser[NKey::kSfx].PostStrings[0];
if (parser[NKey::kVolume].ThereIs)
{
const UStringVector &sv = parser[NKey::kVolume].PostStrings;
for (int i = 0; i < sv.Size(); i++)
{
const UString &s = sv[i];
UInt64 size;
if (!ParseComplexSize(sv[i], size))
throw "incorrect volume size";
options.VolumesSizes.Add(size);
}
}
}
static void SetMethodOptions(const CParser &parser,
CUpdateOptions &options)
{
if (parser[NKey::kProperty].ThereIs)
{
// options.MethodMode.Properties.Clear();
for(int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++)
{
CProperty property;
const UString &postString = parser[NKey::kProperty].PostStrings[i];
int index = postString.Find(L'=');
if (index < 0)
property.Name = postString;
else
{
property.Name = postString.Left(index);
property.Value = postString.Mid(index + 1);
}
options.MethodMode.Properties.Add(property);
}
}
}
static void SetArchiveType(const UString &archiveType,
#ifndef EXCLUDE_COM
UString &filePath, CLSID &classID,
#else
UString &formatName,
#endif
UString &archiveExtension)
{
CObjectVector<CArchiverInfo> archiverInfoVector;
ReadArchiverInfoList(archiverInfoVector);
if (archiverInfoVector.Size() == 0)
throw "There are no installed archive handlers";
if (archiveType.IsEmpty())
throw "Incorrect archive type was assigned";
for (int i = 0; i < archiverInfoVector.Size(); i++)
{
const CArchiverInfo &archiverInfo = archiverInfoVector[i];
if (archiverInfo.Name.CompareNoCase(archiveType) == 0)
{
#ifndef EXCLUDE_COM
classID = archiverInfo.ClassID;
filePath = archiverInfo.FilePath;
#else
formatName = archiverInfo.Name;
#endif
archiveExtension = archiverInfo.GetMainExtension();
return;
}
}
throw "Incorrect archive type was assigned";
}
CArchiveCommandLineParser::CArchiveCommandLineParser(): parser(kNumSwitches) {}
void CArchiveCommandLineParser::Parse1(UStringVector commandStrings,
CArchiveCommandLineOptions &options)
{
try
{
parser.ParseStrings(kSwitchForms, commandStrings);
}
catch(...)
{
throw kUserErrorMessage;
}
options.IsInTerminal = (isatty(fileno(stdin)) != 0);
options.IsStdOutTerminal = (isatty(fileno(stdout)) != 0);
options.IsStdErrTerminal = (isatty(fileno(stderr)) != 0);
options.StdOutMode = parser[NKey::kStdOut].ThereIs;
options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs;
options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs;
}
void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options)
{
const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
int numNonSwitchStrings = nonSwitchStrings.Size();
if(numNonSwitchStrings < kMinNonSwitchWords)
throw kUserErrorMessage;
if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command))
throw kUserErrorMessage;
NRecursedType::EEnum recursedType;
if (parser[NKey::kRecursed].ThereIs)
recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex);
else
recursedType = NRecursedType::kNonRecursed;
bool thereAreSwitchIncludes = false;
if (parser[NKey::kInclude].ThereIs)
{
thereAreSwitchIncludes = true;
AddSwitchWildCardsToCensor(options.WildcardCensor,
parser[NKey::kInclude].PostStrings, true, recursedType);
}
if (parser[NKey::kExclude].ThereIs)
AddSwitchWildCardsToCensor(options.WildcardCensor,
parser[NKey::kExclude].PostStrings, false, recursedType);
int curCommandIndex = kCommandIndex + 1;
bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs;
if (thereIsArchiveName)
{
if(curCommandIndex >= numNonSwitchStrings)
throw kUserErrorMessage;
options.ArchiveName = nonSwitchStrings[curCommandIndex++];
}
AddToCensorFromNonSwitchesStrings(
curCommandIndex, options.WildcardCensor,
nonSwitchStrings, recursedType, thereAreSwitchIncludes);
options.YesToAll = parser[NKey::kYes].ThereIs;
bool isExtractGroupCommand = options.Command.IsFromExtractGroup();
options.PasswordEnabled = parser[NKey::kPassword].ThereIs;
if(options.PasswordEnabled)
options.Password = parser[NKey::kPassword].PostStrings[0];
options.StdInMode = parser[NKey::kStdIn].ThereIs;
options.ShowDialog = parser[NKey::kShowDialog].ThereIs;
if(isExtractGroupCommand || options.Command.CommandType == NCommandType::kList)
{
if (options.StdInMode)
throw "reading archives from stdin is not implemented";
if (!options.WildcardCensor.AllAreRelative())
throw "cannot use absolute pathnames for this command";
NWildcard::CCensor archiveWildcardCensor;
if (parser[NKey::kArInclude].ThereIs)
{
AddSwitchWildCardsToCensor(archiveWildcardCensor,
parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed);
}
if (parser[NKey::kArExclude].ThereIs)
AddSwitchWildCardsToCensor(archiveWildcardCensor,
parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed);
if (thereIsArchiveName)
AddCommandLineWildCardToCensr(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed);
CObjectVector<CDirItem> dirItems;
EnumerateItems(archiveWildcardCensor, dirItems, NULL);
UStringVector archivePaths;
int i;
for (i = 0; i < dirItems.Size(); i++)
archivePaths.Add(dirItems[i].FullPath);
if (archivePaths.Size() == 0)
throw "there is no such archive";
UStringVector archivePathsFull;
for (i = 0; i < archivePaths.Size(); i++)
{
UString fullPath;
NFile::NDirectory::MyGetFullPathName(archivePaths[i], fullPath);
archivePathsFull.Add(fullPath);
}
CIntVector indices;
SortStringsToIndices(archivePathsFull, indices);
options.ArchivePathsSorted.Reserve(indices.Size());
options.ArchivePathsFullSorted.Reserve(indices.Size());
for (i = 0; i < indices.Size(); i++)
{
options.ArchivePathsSorted.Add(archivePaths[indices[i]]);
options.ArchivePathsFullSorted.Add(archivePathsFull[indices[i]]);
}
if(isExtractGroupCommand)
{
if (options.StdOutMode && options.IsStdOutTerminal)
throw kTerminalOutError;
if(parser[NKey::kOutputDir].ThereIs)
{
options.OutputDir = parser[NKey::kOutputDir].PostStrings[0];
NFile::NName::NormalizeDirPathPrefix(options.OutputDir);
}
options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore;
if(parser[NKey::kOverwrite].ThereIs)
options.OverwriteMode =
k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex];
else if (options.YesToAll)
options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;
}
}
else if(options.Command.IsFromUpdateGroup())
{
CUpdateOptions &updateOptions = options.UpdateOptions;
UString archiveType;
if(parser[NKey::kArchiveType].ThereIs)
archiveType = parser[NKey::kArchiveType].PostStrings[0];
else
archiveType = kDefaultArchiveType;
UString typeExtension;
if (!archiveType.IsEmpty())
{
#ifndef EXCLUDE_COM
SetArchiveType(archiveType, updateOptions.MethodMode.FilePath,
updateOptions.MethodMode.ClassID, typeExtension);
#else
SetArchiveType(archiveType, updateOptions.MethodMode.Name, typeExtension);
#endif
}
UString extension = typeExtension;
if(parser[NKey::kSfx].ThereIs)
extension = kSFXExtension;
updateOptions.ArchivePath.BaseExtension = extension;
updateOptions.ArchivePath.VolExtension = typeExtension;
updateOptions.ArchivePath.ParseFromPath(options.ArchiveName);
SetAddCommandOptions(options.Command.CommandType, parser,
updateOptions);
SetMethodOptions(parser, updateOptions);
options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs;
if (options.EnablePercents)
{
if ((options.StdOutMode && !options.IsStdErrTerminal) ||
(!options.StdOutMode && !options.IsStdOutTerminal))
options.EnablePercents = false;
}
if (updateOptions.EMailMode = parser[NKey::kEmail].ThereIs)
{
updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front();
if (updateOptions.EMailAddress.Length() > 0)
if (updateOptions.EMailAddress[0] == L'.')
{
updateOptions.EMailRemoveAfter = true;
updateOptions.EMailAddress.Delete(0);
}
}
updateOptions.StdOutMode = options.StdOutMode;
updateOptions.StdInMode = options.StdInMode;
if (updateOptions.StdOutMode && updateOptions.EMailMode)
throw "stdout mode and email mode cannot be combined";
if (updateOptions.StdOutMode && options.IsStdOutTerminal)
throw kTerminalOutError;
if(updateOptions.StdInMode)
updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front();
}
else
throw kUserErrorMessage;
}

View File

@@ -0,0 +1,84 @@
// ArchiveCommandLine.h
#ifndef __ARCHIVECOMMANDLINE_H
#define __ARCHIVECOMMANDLINE_H
#include "Common/Wildcard.h"
#include "Common/CommandLineParser.h"
#include "Extract.h"
#include "Update.h"
namespace NCommandType { enum EEnum
{
kAdd = 0,
kUpdate,
kDelete,
kTest,
kExtract,
kFullExtract,
kList
};}
namespace NRecursedType { enum EEnum
{
kRecursed,
kWildCardOnlyRecursed,
kNonRecursed,
};}
struct CArchiveCommand
{
NCommandType::EEnum CommandType;
bool IsFromExtractGroup() const;
bool IsFromUpdateGroup() const;
bool IsTestMode() const { return CommandType == NCommandType::kTest; }
NExtract::NPathMode::EEnum GetPathMode() const;
};
struct CArchiveCommandLineOptions
{
bool HelpMode;
bool IsInTerminal;
bool IsStdOutTerminal;
bool IsStdErrTerminal;
bool StdInMode;
bool StdOutMode;
bool EnableHeaders;
bool YesToAll;
bool ShowDialog;
// NWildcard::CCensor ArchiveWildcardCensor;
NWildcard::CCensor WildcardCensor;
CArchiveCommand Command;
UString ArchiveName;
bool PasswordEnabled;
UString Password;
// Extract
bool AppendName;
UString OutputDir;
NExtract::NOverwriteMode::EEnum OverwriteMode;
UStringVector ArchivePathsSorted;
UStringVector ArchivePathsFullSorted;
CUpdateOptions UpdateOptions;
bool EnablePercents;
CArchiveCommandLineOptions(): StdInMode(false), StdOutMode(false) {};
};
class CArchiveCommandLineParser
{
NCommandLineParser::CParser parser;
public:
CArchiveCommandLineParser();
void Parse1(const UStringVector commandStrings, CArchiveCommandLineOptions &options);
void Parse2(CArchiveCommandLineOptions &options);
};
#endif

View File

@@ -1,4 +1,4 @@
// ExtractCallback.cpp
// ArchiveExtractCallback.cpp
#include "StdAfx.h"
@@ -18,49 +18,47 @@
#include "../../Common/FilePathAutoRename.h"
#include "../Common/ExtractingFilePath.h"
#include "OpenArchive.h"
using namespace NWindows;
static const wchar_t *kCantAutoRename = L"ERROR: Can not create file with auto name";
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,
IFolderArchiveExtractCallback *extractCallback2,
bool stdOutMode,
const UString &directoryPath,
NExtractionMode::NPath::EEnum pathMode,
NExtractionMode::NOverwrite::EEnum overwriteMode,
NExtract::NPathMode::EEnum pathMode,
NExtract::NOverwriteMode::EEnum overwriteMode,
const UStringVector &removePathParts,
const UString &itemDefaultName,
const FILETIME &utcLastWriteTimeDefault,
UINT32 attributesDefault)
// bool passwordIsDefined, const UString &password
// UString srcDirectoryPrefix)
UInt32 attributesDefault)
{
_extractCallback2 = extractCallback2;
// m_PasswordIsDefined = passwordIsDefined;
// m_Password = password;
_stdOutMode = stdOutMode;
_numErrors = 0;
_extractCallback2 = extractCallback2;
_itemDefaultName = itemDefaultName;
_utcLastWriteTimeDefault = utcLastWriteTimeDefault;
_attributesDefault = attributesDefault;
_removePathParts = removePathParts;
_pathMode = pathMode;
_overwriteMode = overwriteMode;
_archiveHandler = archiveHandler;
_directoryPath = directoryPath;
NFile::NName::NormalizeDirPathPrefix(_directoryPath);
// _srcDirectoryPrefix = srcDirectoryPrefix;
}
STDMETHODIMP CArchiveExtractCallback::SetTotal(UINT64 size)
STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 size)
{
return _extractCallback2->SetTotal(size);
}
STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UINT64 *completeValue)
STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 *completeValue)
{
return _extractCallback2->SetCompleted(completeValue);
}
@@ -89,8 +87,8 @@ static UString MakePathNameFromParts(const UStringVector &parts)
}
STDMETHODIMP CArchiveExtractCallback::GetStream(UINT32 index,
ISequentialOutStream **outStream, INT32 askExtractMode)
STDMETHODIMP CArchiveExtractCallback::GetStream(UInt32 index,
ISequentialOutStream **outStream, Int32 askExtractMode)
{
*outStream = 0;
_outFileStream.Release();
@@ -99,9 +97,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UINT32 index,
UString fullPath;
if(propVariant.vt == VT_EMPTY)
{
fullPath = _itemDefaultName;
}
else
{
if(propVariant.vt != VT_BSTR)
@@ -111,9 +107,26 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UINT32 index,
// UString fullPathCorrect = GetCorrectPath(fullPath);
_filePath = fullPath;
_isSplit = false;
RINOK(_archiveHandler->GetProperty(index, kpidPosition, &propVariant));
if (propVariant.vt != VT_EMPTY)
{
if (propVariant.vt != VT_UI8)
return E_FAIL;
_position = propVariant.uhVal.QuadPart;
_isSplit = true;
}
if(askExtractMode == NArchive::NExtract::NAskMode::kExtract)
{
if (_stdOutMode)
{
CMyComPtr<ISequentialOutStream> outStreamLoc = new CStdOutFileStream;
*outStream = outStreamLoc.Detach();
return S_OK;
}
RINOK(_archiveHandler->GetProperty(index, kpidAttributes, &propVariant));
if (propVariant.vt == VT_EMPTY)
{
@@ -128,8 +141,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UINT32 index,
_processedFileInfo.AttributesAreDefined = true;
}
RINOK(_archiveHandler->GetProperty(index, kpidIsFolder, &propVariant));
_processedFileInfo.IsDirectory = VARIANT_BOOLToBool(propVariant.boolVal);
RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.IsDirectory));
RINOK(_archiveHandler->GetProperty(index, kpidLastWriteTime, &propVariant));
switch(propVariant.vt)
@@ -146,9 +158,9 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UINT32 index,
RINOK(_archiveHandler->GetProperty(index, kpidSize, &propVariant));
bool newFileSizeDefined = (propVariant.vt != VT_EMPTY);
UINT64 newFileSize;
UInt64 newFileSize;
if (newFileSizeDefined)
newFileSize = ConvertPropVariantToUINT64(propVariant);
newFileSize = ConvertPropVariantToUInt64(propVariant);
bool isAnti = false;
{
@@ -160,8 +172,6 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UINT32 index,
}
UStringVector pathParts;
// SplitPathToParts(fullPathCorrect, pathParts);
SplitPathToParts(fullPath, pathParts);
if(pathParts.IsEmpty())
@@ -169,14 +179,14 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UINT32 index,
UString processedPath;
switch(_pathMode)
{
case NExtractionMode::NPath::kFullPathnames:
case NExtract::NPathMode::kFullPathnames:
{
// processedPath = fullPathCorrect;
processedPath = GetCorrectPath(fullPath);
processedPath = fullPath;
break;
}
case NExtractionMode::NPath::kCurrentPathnames:
case NExtract::NPathMode::kCurrentPathnames:
{
// for incorrect paths: "/dir1/dir2/file"
int numRemovePathParts = _removePathParts.Size();
if(pathParts.Size() <= numRemovePathParts)
return E_FAIL;
@@ -185,28 +195,25 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UINT32 index,
return E_FAIL;
pathParts.Delete(0, numRemovePathParts);
processedPath = MakePathNameFromParts(pathParts);
processedPath = GetCorrectPath(processedPath);
break;
}
case NExtractionMode::NPath::kNoPathnames:
case NExtract::NPathMode::kNoPathnames:
{
processedPath = pathParts.Back();
pathParts.Delete(0, pathParts.Size() - 1); // Test it!!
break;
}
}
processedPath = GetCorrectPath(processedPath);
if(!_processedFileInfo.IsDirectory)
pathParts.DeleteBack();
for(int i = 0; i < pathParts.Size(); i++)
pathParts[i] = GetCorrectFileName(pathParts[i]);
MakeCorrectPath(pathParts);
if (!isAnti)
if (!pathParts.IsEmpty())
CreateComplexDirectory(pathParts);
const UString fullProcessedPathUnicode = _directoryPath + processedPath;
UString fullProcessedPath = _directoryPath + processedPath;
if(_processedFileInfo.IsDirectory)
@@ -217,18 +224,20 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UINT32 index,
return S_OK;
}
if (!_isSplit)
{
NFile::NFind::CFileInfoW fileInfo;
if(NFile::NFind::FindFile(fullProcessedPath, fileInfo))
{
switch(_overwriteMode)
{
case NExtractionMode::NOverwrite::kSkipExisting:
case NExtract::NOverwriteMode::kSkipExisting:
return S_OK;
case NExtractionMode::NOverwrite::kAskBefore:
case NExtract::NOverwriteMode::kAskBefore:
{
INT32 overwiteResult;
Int32 overwiteResult;
RINOK(_extractCallback2->AskOverwrite(
fullProcessedPathUnicode, &fileInfo.LastWriteTime, &fileInfo.Size,
fullProcessedPath, &fileInfo.LastWriteTime, &fileInfo.Size,
fullPath, &_processedFileInfo.UTCLastWriteTime, newFileSizeDefined?
&newFileSize : NULL, &overwiteResult))
@@ -239,27 +248,43 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UINT32 index,
case NOverwriteAnswer::kNo:
return S_OK;
case NOverwriteAnswer::kNoToAll:
_overwriteMode = NExtractionMode::NOverwrite::kSkipExisting;
_overwriteMode = NExtract::NOverwriteMode::kSkipExisting;
return S_OK;
case NOverwriteAnswer::kYesToAll:
_overwriteMode = NExtractionMode::NOverwrite::kWithoutPrompt;
_overwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;
break;
case NOverwriteAnswer::kYes:
break;
case NOverwriteAnswer::kAutoRename:
_overwriteMode = NExtractionMode::NOverwrite::kAutoRename;
_overwriteMode = NExtract::NOverwriteMode::kAutoRename;
break;
default:
throw 20413;
}
}
}
if (_overwriteMode == NExtractionMode::NOverwrite::kAutoRename)
if (_overwriteMode == NExtract::NOverwriteMode::kAutoRename)
{
if (!AutoRenamePath(fullProcessedPath))
{
UString message = UString(L"can not create name of file ") +
fullProcessedPathUnicode;
UString message = UString(kCantAutoRename) +
fullProcessedPath;
RINOK(_extractCallback2->MessageError(message));
return E_ABORT;
}
}
else if (_overwriteMode == NExtract::NOverwriteMode::kAutoRenameExisting)
{
UString existPath = fullProcessedPath;
if (!AutoRenamePath(existPath))
{
UString message = kCantAutoRename + fullProcessedPath;
RINOK(_extractCallback2->MessageError(message));
return E_ABORT;
}
if(!NFile::NDirectory::MyMoveFile(fullProcessedPath, existPath))
{
UString message = UString(kCantRenameFile) + fullProcessedPath;
RINOK(_extractCallback2->MessageError(message));
return E_ABORT;
}
@@ -267,21 +292,30 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UINT32 index,
else
if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath))
{
UString message = UString(L"can not delete output file ") +
fullProcessedPathUnicode;
UString message = UString(kCantDeleteOutputFile) +
fullProcessedPath;
RINOK(_extractCallback2->MessageError(message));
return E_ABORT;
}
}
}
if (!isAnti)
{
_outFileStreamSpec = new COutFileStream;
CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
if (!_outFileStreamSpec->Open(fullProcessedPath))
if (!_outFileStreamSpec->File.Open(fullProcessedPath,
_isSplit ? OPEN_ALWAYS: CREATE_ALWAYS))
{
UString message = L"can not open output file " + fullProcessedPathUnicode;
RINOK(_extractCallback2->MessageError(message));
return S_OK;
// if (::GetLastError() != ERROR_FILE_EXISTS || !isSplit)
{
UString message = L"can not open output file " + fullProcessedPath;
RINOK(_extractCallback2->MessageError(message));
return S_OK;
}
}
if (_isSplit)
{
RINOK(_outFileStreamSpec->Seek(_position, STREAM_SEEK_SET, NULL));
}
_outFileStream = outStreamLoc;
*outStream = outStreamLoc.Detach();
@@ -295,7 +329,7 @@ STDMETHODIMP CArchiveExtractCallback::GetStream(UINT32 index,
return S_OK;
}
STDMETHODIMP CArchiveExtractCallback::PrepareOperation(INT32 askExtractMode)
STDMETHODIMP CArchiveExtractCallback::PrepareOperation(Int32 askExtractMode)
{
_extractMode = false;
switch (askExtractMode)
@@ -303,7 +337,7 @@ STDMETHODIMP CArchiveExtractCallback::PrepareOperation(INT32 askExtractMode)
case NArchive::NExtract::NAskMode::kExtract:
_extractMode = true;
};
return _extractCallback2->PrepareOperation(_filePath, askExtractMode);
return _extractCallback2->PrepareOperation(_filePath, askExtractMode, _isSplit ? &_position: 0);
}
void CArchiveExtractCallback::AddErrorMessage(LPCTSTR message)
@@ -311,7 +345,7 @@ void CArchiveExtractCallback::AddErrorMessage(LPCTSTR message)
_messages.Add(message);
}
STDMETHODIMP CArchiveExtractCallback::SetOperationResult(INT32 operationResult)
STDMETHODIMP CArchiveExtractCallback::SetOperationResult(Int32 operationResult)
{
switch(operationResult)
{

View File

@@ -1,12 +1,10 @@
// ArchiveExtractCallback.h
#pragma once
#ifndef __ARCHIVEEXTRACTCALLBACK_H
#define __ARCHIVEEXTRACTCALLBACK_H
#include "../../Archive/IArchive.h"
#include "IFolderArchive.h"
#include "IFileExtractCallback.h"
#include "Common/String.h"
#include "Common/MyCom.h"
@@ -14,6 +12,8 @@
#include "../../Common/FileStreams.h"
#include "../../IPassword.h"
#include "ExtractMode.h"
class CArchiveExtractCallback:
public IArchiveExtractCallback,
// public IArchiveVolumeExtractCallback,
@@ -25,14 +25,14 @@ public:
// COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback)
// IProgress
STDMETHOD(SetTotal)(UINT64 aize);
STDMETHOD(SetCompleted)(const UINT64 *completeValue);
STDMETHOD(SetTotal)(UInt64 aize);
STDMETHOD(SetCompleted)(const UInt64 *completeValue);
// IExtractCallBack
STDMETHOD(GetStream)(UINT32 anIndex, ISequentialOutStream **outStream,
INT32 askExtractMode);
STDMETHOD(PrepareOperation)(INT32 askExtractMode);
STDMETHOD(SetOperationResult)(INT32 resultEOperationResult);
STDMETHOD(GetStream)(UInt32 anIndex, ISequentialOutStream **outStream,
Int32 askExtractMode);
STDMETHOD(PrepareOperation)(Int32 askExtractMode);
STDMETHOD(SetOperationResult)(Int32 resultEOperationResult);
// IArchiveVolumeExtractCallback
// STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream);
@@ -45,10 +45,12 @@ private:
CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2;
CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;
UString _directoryPath;
NExtractionMode::NPath::EEnum _pathMode;
NExtractionMode::NOverwrite::EEnum _overwriteMode;
NExtract::NPathMode::EEnum _pathMode;
NExtract::NOverwriteMode::EEnum _overwriteMode;
UString _filePath;
UInt64 _position;
bool _isSplit;
UString _diskFilePath;
@@ -60,48 +62,34 @@ private:
FILETIME UTCLastWriteTime;
bool IsDirectory;
bool AttributesAreDefined;
UINT32 Attributes;
UInt32 Attributes;
} _processedFileInfo;
COutFileStream *_outFileStreamSpec;
CMyComPtr<ISequentialOutStream> _outFileStream;
UStringVector _removePathParts;
UString _itemDefaultName;
FILETIME _utcLastWriteTimeDefault;
UINT32 _attributesDefault;
// bool m_PasswordIsDefined;
// UString m_Password;
// UString _srcDirectoryPrefix;
UInt32 _attributesDefault;
bool _stdOutMode;
void CreateComplexDirectory(const UStringVector &dirPathParts);
/*
void GetPropertyValue(LPITEMIDLIST anItemIDList, PROPID aPropId,
PROPVARIANT *aValue);
bool IsEncrypted(LPITEMIDLIST anItemIDList);
*/
void AddErrorMessage(LPCTSTR message);
public:
// CProgressDialog m_ProcessDialog;
void Init(
IInArchive *archiveHandler,
IFolderArchiveExtractCallback *extractCallback2,
bool stdOutMode,
const UString &directoryPath,
NExtractionMode::NPath::EEnum pathMode,
NExtractionMode::NOverwrite::EEnum overwriteMode,
NExtract::NPathMode::EEnum pathMode,
NExtract::NOverwriteMode::EEnum overwriteMode,
const UStringVector &removePathParts,
const UString &itemDefaultName,
const FILETIME &utcLastWriteTimeDefault,
UINT32 anAttributesDefault
// bool passwordIsDefined, const UString &password
// UString srcDirectoryPrefix
);
UInt32 attributesDefault);
UINT64 _numErrors;
UInt64 _numErrors;
};
#endif

View File

@@ -29,7 +29,7 @@ UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName)
{
NFile::NFind::CFileInfoW fileInfo;
if (!NFile::NFind::FindFile(srcName, fileInfo))
return ::GetLastError();
return resultName;
resultName = fileInfo.Name;
if (!fileInfo.IsDirectory() && !keepName)
{

View File

@@ -1,7 +1,5 @@
// ArchiveName.h
#pragma once
#ifndef __ARCHIVENAME_H
#define __ARCHIVENAME_H
@@ -9,4 +7,4 @@
UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName);
#endif
#endif

View File

@@ -0,0 +1,117 @@
// ArchiveOpenCallback.cpp
#include "StdAfx.h"
#include "ArchiveOpenCallback.h"
#include "Common/StringConvert.h"
#include "Windows/PropVariant.h"
#include "../../Common/FileStreams.h"
using namespace NWindows;
STDMETHODIMP COpenCallbackImp::SetTotal(const UInt64 *files, const UInt64 *bytes)
{
return Callback->SetTotal(files, bytes);
}
STDMETHODIMP COpenCallbackImp::SetCompleted(const UInt64 *files, const UInt64 *bytes)
{
return Callback->SetTotal(files, bytes);
}
STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant propVariant;
if (_subArchiveMode)
{
switch(propID)
{
case kpidName:
propVariant = _subArchiveName;
break;
}
propVariant.Detach(value);
return S_OK;
}
switch(propID)
{
case kpidName:
propVariant = _fileInfo.Name;
break;
case kpidIsFolder:
propVariant = _fileInfo.IsDirectory();
break;
case kpidSize:
propVariant = _fileInfo.Size;
break;
case kpidAttributes:
propVariant = (UInt32)_fileInfo.Attributes;
break;
case kpidLastAccessTime:
propVariant = _fileInfo.LastAccessTime;
break;
case kpidCreationTime:
propVariant = _fileInfo.CreationTime;
break;
case kpidLastWriteTime:
propVariant = _fileInfo.LastWriteTime;
break;
}
propVariant.Detach(value);
return S_OK;
}
int COpenCallbackImp::FindName(const UString &name)
{
for (int i = 0; i < FileNames.Size(); i++)
if (name.CompareNoCase(FileNames[i]) == 0)
return i;
return -1;
}
struct CInFileStreamVol: public CInFileStream
{
UString Name;
COpenCallbackImp *OpenCallbackImp;
CMyComPtr<IArchiveOpenCallback> OpenCallbackRef;
~CInFileStreamVol()
{
int index = OpenCallbackImp->FindName(Name);
if (index >= 0)
OpenCallbackImp->FileNames.Delete(index);
}
};
STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name,
IInStream **inStream)
{
if (_subArchiveMode)
return S_FALSE;
RINOK(Callback->CheckBreak());
*inStream = NULL;
UString fullPath = _folderPrefix + name;
if (!NFile::NFind::FindFile(fullPath, _fileInfo))
return S_FALSE;
if (_fileInfo.IsDirectory())
return S_FALSE;
CInFileStreamVol *inFile = new CInFileStreamVol;
CMyComPtr<IInStream> inStreamTemp = inFile;
if (!inFile->Open(fullPath))
return ::GetLastError();
*inStream = inStreamTemp.Detach();
inFile->Name = name;
inFile->OpenCallbackImp = this;
inFile->OpenCallbackRef = this;
FileNames.Add(name);
return S_OK;
}
#ifndef _NO_CRYPTO
STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password)
{
return Callback->CryptoGetTextPassword(password);
}
#endif

View File

@@ -0,0 +1,87 @@
// ArchiveOpenCallback.h
#ifndef __ARCHIVE_OPEN_CALLBACK_H
#define __ARCHIVE_OPEN_CALLBACK_H
#include "Common/String.h"
#include "Common/MyCom.h"
#include "Windows/FileFind.h"
#ifndef _NO_CRYPTO
#include "../../IPassword.h"
#endif
#include "../../Archive/IArchive.h"
struct IOpenCallbackUI
{
virtual HRESULT CheckBreak() = 0;
virtual HRESULT SetTotal(const UInt64 *files, const UInt64 *bytes) = 0;
virtual HRESULT SetCompleted(const UInt64 *files, const UInt64 *bytes) = 0;
#ifndef _NO_CRYPTO
virtual HRESULT CryptoGetTextPassword(BSTR *password) = 0;
virtual HRESULT GetPasswordIfAny(UString &password) = 0;
#endif
};
class COpenCallbackImp:
public IArchiveOpenCallback,
public IArchiveOpenVolumeCallback,
public IArchiveOpenSetSubArchiveName,
#ifndef _NO_CRYPTO
public ICryptoGetTextPassword,
#endif
public CMyUnknownImp
{
public:
#ifndef _NO_CRYPTO
MY_UNKNOWN_IMP3(
IArchiveOpenVolumeCallback,
ICryptoGetTextPassword,
IArchiveOpenSetSubArchiveName
)
#else
MY_UNKNOWN_IMP2(
IArchiveOpenVolumeCallback,
IArchiveOpenSetSubArchiveName
)
#endif
STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes);
STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes);
// IArchiveOpenVolumeCallback
STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value);
STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream);
#ifndef _NO_CRYPTO
// ICryptoGetTextPassword
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
#endif
STDMETHOD(SetSubArchiveName(const wchar_t *name))
{
_subArchiveMode = true;
_subArchiveName = name;
return S_OK;
}
private:
UString _folderPrefix;
NWindows::NFile::NFind::CFileInfoW _fileInfo;
bool _subArchiveMode;
UString _subArchiveName;
public:
UStringVector FileNames;
IOpenCallbackUI *Callback;
void Init(const UString &folderPrefix, const UString &fileName)
{
_folderPrefix = folderPrefix;
if (!NWindows::NFile::NFind::FindFile(_folderPrefix + fileName, _fileInfo))
throw 1;
FileNames.Clear();
_subArchiveMode = false;
}
int FindName(const UString &name);
};
#endif

View File

@@ -10,7 +10,9 @@
#include "Windows/FileFind.h"
#include "Windows/FileName.h"
#include "Windows/DLL.h"
#ifdef _WIN32
#include "Windows/Registry.h"
#endif
#include "Windows/PropVariant.h"
#include "../../Archive/IArchive.h"
@@ -48,7 +50,7 @@ static void SplitString(const UString &srcString, UStringVector &destStrings)
destStrings.Add(string);
}
typedef UINT32 (WINAPI * GetHandlerPropertyFunc)(
typedef UInt32 (WINAPI * GetHandlerPropertyFunc)(
PROPID propID, PROPVARIANT *value);
/*
@@ -72,7 +74,7 @@ static wchar_t *kFormatFolderName = L"Formats";
static LPCTSTR kRegistryPath = TEXT("Software\\7-zip");
static LPCTSTR kProgramPathValue = TEXT("Path");
UString GetBaseFolderPrefix()
static UString GetBaseFolderPrefixFromRegistry()
{
UString moduleFolderPrefix = GetModuleFolderPrefix();
NFind::CFileInfoW fileInfo;
@@ -80,6 +82,7 @@ UString GetBaseFolderPrefix()
if (fileInfo.IsDirectory())
return moduleFolderPrefix;
CSysString pathSys;
#ifdef _WIN32
{
NRegistry::CKey key;
if(key.Open(HKEY_CURRENT_USER, kRegistryPath, KEY_READ) == ERROR_SUCCESS)
@@ -100,16 +103,25 @@ UString GetBaseFolderPrefix()
return path;
}
}
#endif
return moduleFolderPrefix;
}
typedef UINT32 (WINAPI *CreateObjectPointer)(
typedef UInt32 (WINAPI *CreateObjectPointer)(
const GUID *clsID,
const GUID *interfaceID,
void **outObject);
#endif
#ifndef _SFX
static void SetBuffer(CByteBuffer &bb, const Byte *data, int size)
{
bb.SetCapacity(size);
memmove((Byte *)bb, data, size);
}
#endif
void ReadArchiverInfoList(CObjectVector<CArchiverInfo> &archivers)
{
archivers.Clear();
@@ -123,6 +135,10 @@ void ReadArchiverInfoList(CObjectVector<CArchiverInfo> &archivers)
item.KeepName = false;
item.Name = L"7z";
item.Extensions.Add(CArchiverExtInfo(L"7z"));
#ifndef _SFX
const unsigned char kSig[] = {'7' , 'z', 0xBC, 0xAF, 0x27, 0x1C};
SetBuffer(item.StartSignature, kSig, 6);
#endif
archivers.Add(item);
}
#endif
@@ -135,6 +151,10 @@ void ReadArchiverInfoList(CObjectVector<CArchiverInfo> &archivers)
item.Name = L"BZip2";
item.Extensions.Add(CArchiverExtInfo(L"bz2"));
item.Extensions.Add(CArchiverExtInfo(L"tbz2", L".tar"));
#ifndef _SFX
const unsigned char sig[] = {'B' , 'Z', 'h' };
SetBuffer(item.StartSignature, sig, 3);
#endif
archivers.Add(item);
}
#endif
@@ -147,6 +167,21 @@ void ReadArchiverInfoList(CObjectVector<CArchiverInfo> &archivers)
item.Name = L"GZip";
item.Extensions.Add(CArchiverExtInfo(L"gz"));
item.Extensions.Add(CArchiverExtInfo(L"tgz", L".tar"));
#ifndef _SFX
const unsigned char sig[] = { 0x1F, 0x8B };
SetBuffer(item.StartSignature, sig, 2);
#endif
archivers.Add(item);
}
#endif
#ifdef FORMAT_SPLIT
{
CArchiverInfo item;
item.UpdateEnabled = false;
item.KeepName = true;
item.Name = L"Split";
item.Extensions.Add(CArchiverExtInfo(L"001"));
archivers.Add(item);
}
#endif
@@ -169,6 +204,10 @@ void ReadArchiverInfoList(CObjectVector<CArchiverInfo> &archivers)
item.KeepName = false;
item.Name = L"Zip";
item.Extensions.Add(CArchiverExtInfo(L"zip"));
#ifndef _SFX
const unsigned char sig[] = { 0x50, 0x4B, 0x03, 0x04 };
SetBuffer(item.StartSignature, sig, 4);
#endif
archivers.Add(item);
}
#endif
@@ -199,13 +238,31 @@ void ReadArchiverInfoList(CObjectVector<CArchiverInfo> &archivers)
item.UpdateEnabled = false;
item.Name = L"Arj";
item.Extensions.Add(CArchiverExtInfo(L"arj"));
#ifndef _SFX
const unsigned char sig[] = { 0x60, 0xEA };
SetBuffer(item.StartSignature, sig, 2);
#endif
archivers.Add(item);
}
#endif
#ifdef FORMAT_Z
{
CArchiverInfo item;
item.UpdateEnabled = false;
item.Name = L"Z";
item.Extensions.Add(CArchiverExtInfo(L"Z"));
#ifndef _SFX
const unsigned char sig[] = { 0x1F, 0x9D };
SetBuffer(item.StartSignature, sig, 2);
#endif
archivers.Add(item);
}
#endif
#else
UString folderPath = GetBaseFolderPrefix() +
UString folderPath = GetBaseFolderPrefixFromRegistry() +
kFormatFolderName + L"\\";
NFind::CEnumeratorW enumerator(folderPath + L"*");
NFind::CFileInfoW fileInfo;
@@ -253,6 +310,7 @@ void ReadArchiverInfoList(CObjectVector<CArchiverInfo> &archivers)
UString ext = prop.bstrVal;
// item.Extension = prop.bstrVal;
prop.Clear();
UString addExt;
@@ -282,23 +340,30 @@ void ReadArchiverInfoList(CObjectVector<CArchiverInfo> &archivers)
item.Extensions.Add(extInfo);
}
if (getHandlerProperty(NArchive::kUpdate, &prop) != S_OK)
continue;
if (prop.vt != VT_BOOL)
continue;
item.UpdateEnabled = VARIANT_BOOLToBool(prop.boolVal);
if (getHandlerProperty(NArchive::kUpdate, &prop) == S_OK)
if (prop.vt == VT_BOOL)
item.UpdateEnabled = VARIANT_BOOLToBool(prop.boolVal);
prop.Clear();
if (item.UpdateEnabled)
{
if (getHandlerProperty(NArchive::kKeepName, &prop) != S_OK)
continue;
if (prop.vt != VT_BOOL)
continue;
item.KeepName = VARIANT_BOOLToBool(prop.boolVal);
if (getHandlerProperty(NArchive::kKeepName, &prop) == S_OK)
if (prop.vt == VT_BOOL)
item.KeepName = VARIANT_BOOLToBool(prop.boolVal);
prop.Clear();
}
if (getHandlerProperty(NArchive::kStartSignature, &prop) == S_OK)
{
if (prop.vt == VT_BSTR)
{
UINT len = ::SysStringByteLen(prop.bstrVal);
item.StartSignature.SetCapacity(len);
memmove(item.StartSignature, prop.bstrVal, len);
}
}
prop.Clear();
archivers.Add(item);
}

View File

@@ -1,12 +1,11 @@
// ArchiverInfo.h
#pragma once
#ifndef __ARCHIVERINFO_H
#define __ARCHIVERINFO_H
#include "Common/String.h"
#include "Common/Types.h"
#include "Common/Buffer.h"
struct CArchiverExtInfo
{
@@ -27,6 +26,10 @@ struct CArchiverInfo
#endif
UString Name;
CObjectVector<CArchiverExtInfo> Extensions;
#ifndef _SFX
CByteBuffer StartSignature;
CByteBuffer FinishSignature;
#endif
int FindExtension(const UString &ext) const
{
for (int i = 0; i < Extensions.Size(); i++)

View File

@@ -11,14 +11,18 @@
#include "Windows/Synchronization.h"
#include "Windows/FileMapping.h"
#include "Windows/FileDir.h"
#include "../../FileManager/ProgramLocation.h"
using namespace NWindows;
static LPCWSTR kShowDialogSwitch = L" -ad";
static LPCWSTR kEmailSwitch = L" -seml";
static LPCWSTR kEmailSwitch = L" -seml.";
static LPCWSTR kMapSwitch = L" -i#";
static LPCWSTR kArchiveNoNameSwitch = L" -an";
static LPCWSTR kArchiveMapSwitch = L" -ai#";
static LPCWSTR kStopSwitchParsing = L" --";
static bool IsItWindowsNT()
@@ -31,6 +35,7 @@ static bool IsItWindowsNT()
}
HRESULT MyCreateProcess(const UString &params,
LPCTSTR curDir,
NWindows::NSynchronization::CEvent *event)
{
STARTUPINFO startupInfo;
@@ -45,7 +50,8 @@ HRESULT MyCreateProcess(const UString &params,
PROCESS_INFORMATION processInformation;
BOOL result = ::CreateProcess(NULL, (TCHAR *)(const TCHAR *)
GetSystemString(params),
NULL, NULL, FALSE, 0, NULL, NULL,
NULL, NULL, FALSE, 0, NULL,
curDir,
&startupInfo, &processInformation);
if (result == 0)
return ::GetLastError();
@@ -70,7 +76,7 @@ static UString GetQuotedString(const UString &s)
static UString Get7zGuiPath()
{
UString path = L"\"";
UString path;
UString folder;
if (GetProgramFolderPath(folder))
path += folder;
@@ -78,28 +84,117 @@ static UString Get7zGuiPath()
path += L"7zgn.exe";
else
path += L"7zg.exe";
path += L"\"";
return path;
// path += L"7z.exe";
return GetQuotedString(path);
}
static HRESULT CreateMap(const UStringVector &names,
const UString &id,
CFileMapping &fileMapping, NSynchronization::CEvent &event,
UString &params)
{
UInt32 extraSize = 2;
UInt32 dataSize = 0;
for (int i = 0; i < names.Size(); i++)
dataSize += (names[i].Length() + 1) * sizeof(wchar_t);
UInt32 totalSize = extraSize + dataSize;
UString mappingName;
UString eventName;
CRandom random;
random.Init(GetTickCount());
while(true)
{
int number = random.Generate();
wchar_t temp[32];
ConvertUInt64ToString(UInt32(number), temp);
mappingName = id;
mappingName += L"Mapping";
mappingName += temp;
if (!fileMapping.Create(INVALID_HANDLE_VALUE, NULL,
PAGE_READWRITE, totalSize, GetSystemString(mappingName)))
return E_FAIL;
if (::GetLastError() != ERROR_ALREADY_EXISTS)
break;
fileMapping.Close();
}
while(true)
{
int number = random.Generate();
wchar_t temp[32];
ConvertUInt64ToString(UInt32(number), temp);
eventName = id;
eventName += L"MappingEndEvent";
eventName += temp;
if (!event.Create(true, false, GetSystemString(eventName)))
return E_FAIL;
if (::GetLastError() != ERROR_ALREADY_EXISTS)
break;
event.Close();
}
params += mappingName;
params += L":";
wchar_t string[10];
ConvertUInt64ToString(totalSize, string);
params += string;
params += L":";
params += eventName;
LPVOID data = fileMapping.MapViewOfFile(FILE_MAP_WRITE, 0, totalSize);
if (data == NULL)
return E_FAIL;
try
{
wchar_t *curData = (wchar_t *)data;
*curData = 0;
curData++;
for (int i = 0; i < names.Size(); i++)
{
const UString &s = names[i];
memcpy(curData, (const wchar_t *)s, s.Length() * sizeof(wchar_t));
curData += s.Length();
*curData++ = L'\0';
}
}
catch(...)
{
UnmapViewOfFile(data);
throw;
}
// UnmapViewOfFile(data);
return S_OK;
}
HRESULT CompressFiles(
const UString &curDir,
const UString &archiveName,
const UStringVector &names,
// const UString &outFolder,
bool email,
bool showDialog)
{
/*
UString curDir;
if (names.Size() > 0)
{
NFile::NDirectory::GetOnlyDirPrefix(names[0], curDir);
}
*/
UString params;
params = Get7zGuiPath();
params += L" a";
params += kMapSwitch;
// params += _fileNames[0];
UINT32 extraSize = 2;
UINT32 dataSize = 0;
UInt32 extraSize = 2;
UInt32 dataSize = 0;
for (int i = 0; i < names.Size(); i++)
dataSize += (names[i].Length() + 1) * sizeof(wchar_t);
UINT32 totalSize = extraSize + dataSize;
UInt32 totalSize = extraSize + dataSize;
UString mappingName;
UString eventName;
@@ -111,7 +206,7 @@ HRESULT CompressFiles(
{
int number = random.Generate();
wchar_t temp[32];
ConvertUINT64ToString(UINT32(number), temp);
ConvertUInt64ToString(UInt32(number), temp);
mappingName = L"7zCompressMapping";
mappingName += temp;
if (!fileMapping.Create(INVALID_HANDLE_VALUE, NULL,
@@ -130,7 +225,7 @@ HRESULT CompressFiles(
{
int number = random.Generate();
wchar_t temp[32];
ConvertUINT64ToString(UINT32(number), temp);
ConvertUInt64ToString(UInt32(number), temp);
eventName = L"7zCompressMappingEndEvent";
eventName += temp;
if (!event.Create(true, false, GetSystemString(eventName)))
@@ -146,7 +241,7 @@ HRESULT CompressFiles(
params += mappingName;
params += L":";
wchar_t string[10];
ConvertUINT64ToString(totalSize, string);
ConvertUInt64ToString(totalSize, string);
params += string;
params += L":";
@@ -158,7 +253,9 @@ HRESULT CompressFiles(
if (showDialog)
params += kShowDialogSwitch;
params += kStopSwitchParsing;
params += L" ";
params += GetQuotedString(archiveName);
LPVOID data = fileMapping.MapViewOfFile(FILE_MAP_WRITE, 0, totalSize);
@@ -177,11 +274,14 @@ HRESULT CompressFiles(
const UString &unicodeString = names[i];
memcpy(curData, (const wchar_t *)unicodeString ,
unicodeString .Length() * sizeof(wchar_t));
curData += unicodeString .Length();
curData += unicodeString.Length();
*curData++ = L'\0';
}
// MessageBox(0, params, 0, 0);
RINOK(MyCreateProcess(params, &event));
CSysString sysCurDir = GetSystemString(curDir);
RINOK(MyCreateProcess(params,
(sysCurDir.IsEmpty()? 0: (LPCTSTR)sysCurDir),
&event));
}
catch(...)
{
@@ -190,8 +290,7 @@ HRESULT CompressFiles(
}
UnmapViewOfFile(data);
/*
CThreadCompressMain *compressor = new CThreadCompressMain();;
compressor->FileNames = _fileNames;
@@ -202,13 +301,24 @@ HRESULT CompressFiles(
return S_OK;
}
HRESULT ExtractArchive(const UString &archiveName,
static HRESULT ExtractGroupCommand(const UStringVector &archivePaths,
const UString &params)
{
UString params2 = params;
params2 += kArchiveNoNameSwitch;
params2 += kArchiveMapSwitch;
CFileMapping fileMapping;
NSynchronization::CEvent event;
RINOK(CreateMap(archivePaths, L"7zExtract", fileMapping, event, params2));
return MyCreateProcess(params2, 0, &event);
}
HRESULT ExtractArchives(const UStringVector &archivePaths,
const UString &outFolder, bool showDialog)
{
UString params;
params = Get7zGuiPath();
params += L" x ";
params += GetQuotedString(archiveName);
params += L" x";
if (!outFolder.IsEmpty())
{
params += L" -o";
@@ -216,14 +326,13 @@ HRESULT ExtractArchive(const UString &archiveName,
}
if (showDialog)
params += kShowDialogSwitch;
return MyCreateProcess(params);
return ExtractGroupCommand(archivePaths, params);
}
HRESULT TestArchive(const UString &archiveName)
HRESULT TestArchives(const UStringVector &archivePaths)
{
UString params;
params = Get7zGuiPath();
params += L" t ";
params += GetQuotedString(archiveName);
return MyCreateProcess(params);
params += L" t";
return ExtractGroupCommand(archivePaths, params);
}

View File

@@ -6,17 +6,21 @@
#include "Common/String.h"
#include "Windows/Synchronization.h"
HRESULT MyCreateProcess(const UString &params,
NWindows::NSynchronization::CEvent *event = NULL);
HRESULT CompressFiles(const UString &archiveName,
HRESULT MyCreateProcess(const UString &params,
LPCTSTR lpCurrentDirectory,
NWindows::NSynchronization::CEvent *event = NULL);
HRESULT CompressFiles(
const UString &curDir,
const UString &archiveName,
const UStringVector &names,
// const UString &outFolder,
bool email, bool showDialog);
HRESULT ExtractArchive(const UString &archiveName,
HRESULT ExtractArchives(
const UStringVector &archivePaths,
const UString &outFolder, bool showDialog);
HRESULT TestArchive(const UString &archiveName);
HRESULT TestArchives(const UStringVector &archivePaths);
#endif

View File

@@ -2,32 +2,22 @@
#include "StdAfx.h"
#include "Windows/FileDir.h"
#include "Common/StringConvert.h"
#include "DefaultName.h"
const wchar_t *kEmptyFileAlias = L"[Content]";
static const wchar_t *kEmptyFileAlias = L"[Content]";
using namespace NWindows;
using namespace NFile;
using namespace NDirectory;
UString GetDefaultName(const UString &fullFileName,
UString GetDefaultName2(const UString &fileName,
const UString &extension, const UString &addSubExtension)
{
UString fileName;
if (!GetOnlyName(fullFileName, fileName))
throw 5011749;
int extLength = extension.Length();
int fileNameLength = fileName.Length();
if (fileNameLength <= extLength + 1)
return kEmptyFileAlias;
int dotPos = fileNameLength - (extLength + 1);
if (fileName[dotPos] != '.')
return kEmptyFileAlias;
if (extension.CollateNoCase(fileName.Mid(dotPos + 1)) == 0)
return fileName.Left(dotPos) + addSubExtension;
if (fileNameLength > extLength + 1)
{
int dotPos = fileNameLength - (extLength + 1);
if (fileName[dotPos] == '.')
if (extension.CollateNoCase(fileName.Mid(dotPos + 1)) == 0)
return fileName.Left(dotPos) + addSubExtension;
}
return kEmptyFileAlias;
}

View File

@@ -1,13 +1,11 @@
// DefaultName.h
#pragma once
#ifndef __DEFAULTNAME_H
#define __DEFAULTNAME_H
#include "Common/String.h"
UString GetDefaultName(const UString &fullFileName,
UString GetDefaultName2(const UString &fileName,
const UString &extension, const UString &addSubExtension);
#endif

View File

@@ -1,21 +1,18 @@
// DirItem.h
#pragma once
#ifndef __DIR_ITEM_H
#define __DIR_ITEM_H
// #include "Common/Types.h"
#include "Common/String.h"
// #include "Windows/PropVariant.h"
#include "Common/Types.h"
struct CDirItem
{
UINT32 Attributes;
UInt32 Attributes;
FILETIME CreationTime;
FILETIME LastAccessTime;
FILETIME LastWriteTime;
UINT64 Size;
UInt64 Size;
UString Name;
UString FullPath;
bool IsDirectory() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0 ; }
@@ -28,7 +25,7 @@ struct CArchiveItem
// NWindows::NCOM::CPropVariant LastWriteTime;
FILETIME LastWriteTime;
bool SizeIsDefined;
UINT64 Size;
UInt64 Size;
UString Name;
bool Censored;
int IndexInServer;

View File

@@ -2,8 +2,11 @@
#include "StdAfx.h"
#include "EnumDirItems.h"
#include "Common/StringConvert.h"
#include "Common/Wildcard.h"
#include "Common/MyCom.h"
#include "EnumDirItems.h"
using namespace NWindows;
using namespace NFile;
@@ -28,27 +31,33 @@ void AddDirFileInfo(
dirItems.Add(item);
}
static void EnumerateDirectory(
static HRESULT EnumerateDirectory(
const UString &baseFolderPrefix,
const UString &directory,
const UString &prefix,
CObjectVector<CDirItem> &dirItems)
{
NFind::CEnumeratorW enumerator(baseFolderPrefix + directory + wchar_t(kAnyStringWildcard));
NFind::CFileInfoW fileInfo;
while (enumerator.Next(fileInfo))
while (true)
{
NFind::CFileInfoW fileInfo;
bool found;
if (!enumerator.Next(fileInfo, found))
return ::GetLastError();
if (!found)
break;
AddDirFileInfo(prefix, directory + fileInfo.Name, fileInfo,
dirItems);
if (fileInfo.IsDirectory())
{
EnumerateDirectory(baseFolderPrefix, directory + fileInfo.Name + wchar_t(kDirDelimiter),
prefix + fileInfo.Name + wchar_t(kDirDelimiter), dirItems);
RINOK(EnumerateDirectory(baseFolderPrefix, directory + fileInfo.Name + wchar_t(kDirDelimiter),
prefix + fileInfo.Name + wchar_t(kDirDelimiter), dirItems));
}
}
return S_OK;
}
void EnumerateDirItems(
HRESULT EnumerateDirItems(
const UString &baseFolderPrefix,
const UStringVector &fileNames,
const UString &archiveNamePrefix,
@@ -63,9 +72,88 @@ void EnumerateDirItems(
AddDirFileInfo(archiveNamePrefix, fileName, fileInfo, dirItems);
if (fileInfo.IsDirectory())
{
EnumerateDirectory(baseFolderPrefix, fileName + wchar_t(kDirDelimiter),
RINOK(EnumerateDirectory(baseFolderPrefix, fileName + wchar_t(kDirDelimiter),
archiveNamePrefix + fileInfo.Name + wchar_t(kDirDelimiter),
dirItems);
dirItems));
}
}
return S_OK;
}
static HRESULT EnumerateDirItems(
const NWildcard::CCensorNode &curNode,
const UString &diskPrefix,
const UString &archivePrefix,
const UString &addArchivePrefix,
CObjectVector<CDirItem> &dirItems,
bool enterToSubFolders,
IEnumDirItemCallback *callback)
{
if (!enterToSubFolders)
if (curNode.NeedCheckSubDirs())
enterToSubFolders = true;
if (callback)
RINOK(callback->CheckBreak());
NFind::CEnumeratorW enumerator(diskPrefix + wchar_t(kAnyStringWildcard));
while (true)
{
NFind::CFileInfoW fileInfo;
bool found;
if (!enumerator.Next(fileInfo, found))
return ::GetLastError();
if (!found)
break;
if (callback)
RINOK(callback->CheckBreak());
UString name = fileInfo.Name;
bool enterToSubFolders2 = enterToSubFolders;
if (curNode.CheckPathToRoot(addArchivePrefix + name, !fileInfo.IsDirectory()))
{
AddDirFileInfo(archivePrefix, diskPrefix + fileInfo.Name, fileInfo, dirItems);
if (fileInfo.IsDirectory())
enterToSubFolders2 = true;;
}
if (!fileInfo.IsDirectory())
continue;
const NWildcard::CCensorNode *nextNode = 0;
if (addArchivePrefix.IsEmpty())
{
int index = curNode.FindSubNode(name);
if (index >= 0)
nextNode = &curNode.SubNodes[index];
}
if (!enterToSubFolders2 && nextNode == 0)
continue;
UString archivePrefixNew = archivePrefix;
UString addArchivePrefixNew = addArchivePrefix;
if (nextNode == 0)
{
nextNode = &curNode;
addArchivePrefixNew += name;
addArchivePrefixNew += wchar_t(kDirDelimiter);
}
archivePrefixNew += name;
archivePrefixNew += wchar_t(kDirDelimiter);
RINOK(EnumerateDirItems(*nextNode,
diskPrefix + fileInfo.Name + wchar_t(kDirDelimiter),
archivePrefixNew, addArchivePrefixNew,
dirItems, enterToSubFolders2, callback));
}
return S_OK;
}
HRESULT EnumerateItems(const NWildcard::CCensor &censor,
CObjectVector<CDirItem> &dirItems, IEnumDirItemCallback *callback)
{
for (int i = 0; i < censor.Pairs.Size(); i++)
{
if (callback)
RINOK(callback->CheckBreak());
const NWildcard::CPair &pair = censor.Pairs[i];
RINOK(EnumerateDirItems(pair.Head, pair.Prefix, L"", L"", dirItems, false, callback));
}
return S_OK;
}

View File

@@ -1,14 +1,10 @@
// EnumDirItems.h
#pragma once
#ifndef __ENUM_DIR_ITEMS_H
#define __ENUM_DIR_ITEMS_H
#include "Common/String.h"
#include "Common/Vector.h"
#include "Common/Wildcard.h"
#include "DirItem.h"
// #include "UpdatePairBasic.h"
#include "Windows/FileFind.h"
@@ -18,16 +14,20 @@ void AddDirFileInfo(
NWindows::NFile::NFind::CFileInfoW &fileInfo,
CObjectVector<CDirItem> &dirItems);
void EnumerateDirItems(
HRESULT EnumerateDirItems(
const UString &baseFolderPrefix,
const UStringVector &fileNames,
const UString &archiveNamePrefix,
CObjectVector<CDirItem> &dirItems);
/*
void EnumerateItems(const CSysStringVector &filePaths,
const UString &archiveNamePrefix,
CArchiveStyleDirItemInfoVector &dirFileInfoVector, UINT codePage);
*/
struct IEnumDirItemCallback
{
virtual HRESULT CheckBreak() { return S_OK; }
};
HRESULT EnumerateItems(const NWildcard::CCensor &censor,
CObjectVector<CDirItem> &dirItems, IEnumDirItemCallback *callback);
#endif

27
7zip/UI/Common/ExitCode.h Executable file
View File

@@ -0,0 +1,27 @@
// ExitCode.h
#ifndef __EXIT_CODE_H
#define __EXIT_CODE_H
namespace NExitCode {
enum EEnum {
kSuccess = 0, // Successful operation
kWarning = 1, // Non fatal error(s) occurred
kFatalError = 2, // A fatal error occurred
// kCRCError = 3, // A CRC error occurred when unpacking
// kLockedArchive = 4, // Attempt to modify an archive previously locked
// kWriteError = 5, // Write to disk error
// kOpenError = 6, // Open file error
kUserError = 7, // Command line option error
kMemoryError = 8, // Not enough memory for operation
// kCreateFileError = 9, // Create file error
kUserBreak = 255 // User stopped the process
};
}
#endif

127
7zip/UI/Common/Extract.cpp Executable file
View File

@@ -0,0 +1,127 @@
// Extract.cpp
#include "StdAfx.h"
#include "Extract.h"
#include "Windows/Defs.h"
#include "Windows/PropVariant.h"
#include "Windows/FileDir.h"
#include "OpenArchive.h"
#ifndef EXCLUDE_COM
#include "Windows/DLL.h"
#endif
using namespace NWindows;
HRESULT DecompressArchive(
IInArchive *archive,
const UString &defaultName,
const NWildcard::CCensorNode &wildcardCensor,
const CExtractOptions &options,
IExtractCallbackUI *callback)
{
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)
{
callback->ThereAreNoFiles();
return S_OK;
}
CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);
UStringVector removePathParts;
UString outDir = options.OutputDir;
outDir.Replace(L"*", defaultName);
if(!outDir.IsEmpty())
if(!NFile::NDirectory::CreateComplexDirectory(outDir))
{
throw UString(L"Can not create output directory ") + outDir;
}
extractCallbackSpec->Init(
archive,
callback,
options.StdOutMode,
outDir,
options.PathMode,
options.OverwriteMode,
removePathParts,
options.DefaultItemName,
options.ArchiveFileInfo.LastWriteTime,
options.ArchiveFileInfo.Attributes);
HRESULT result = archive->Extract(&realIndices.Front(),
realIndices.Size(), options.TestMode? 1: 0,
extractCallback);
return callback->ExtractResult(result);
}
HRESULT DecompressArchives(
UStringVector &archivePaths, UStringVector &archivePathsFull,
const NWildcard::CCensorNode &wildcardCensor,
const CExtractOptions &optionsSpec,
IOpenCallbackUI *openCallback,
IExtractCallbackUI *extractCallback)
{
CExtractOptions options = optionsSpec;
for (int i = 0; i < archivePaths.Size(); i++)
{
const UString &archivePath = archivePaths[i];
NFile::NFind::CFileInfoW archiveFileInfo;
if (!NFile::NFind::FindFile(archivePath, archiveFileInfo))
throw "there is no such archive";
if (archiveFileInfo.IsDirectory())
throw "there is no such archive";
options.ArchiveFileInfo = archiveFileInfo;
RINOK(extractCallback->BeforeOpen(archivePath));
CArchiveLink archiveLink;
HRESULT result = MyOpenArchive(archivePath, archiveLink, openCallback);
RINOK(extractCallback->OpenResult(archivePath, result));
if (result != S_OK)
continue;
for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)
{
int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]);
if (index >= 0 && index > i)
{
archivePaths.Delete(index);
archivePathsFull.Delete(index);
}
}
UString password;
RINOK(openCallback->GetPasswordIfAny(password));
if (!password.IsEmpty())
{
RINOK(extractCallback->SetPassword(password));
}
options.DefaultItemName = archiveLink.GetDefaultItemName();
RINOK(DecompressArchive(
archiveLink.GetArchive(), archiveLink.GetDefaultItemName(),
wildcardCensor, options, extractCallback));
}
return S_OK;
}

55
7zip/UI/Common/Extract.h Executable file
View File

@@ -0,0 +1,55 @@
// Extract.h
#ifndef __EXTRACT_H
#define __EXTRACT_H
#include "Common/Wildcard.h"
#include "Windows/FileFind.h"
#include "../../Archive/IArchive.h"
#include "../Common/ZipRegistry.h"
#include "ArchiveExtractCallback.h"
#include "ArchiveOpenCallback.h"
#include "ExtractMode.h"
class CExtractOptions
{
public:
bool StdOutMode;
bool TestMode;
NExtract::NPathMode::EEnum PathMode;
UString OutputDir;
bool YesToAll;
UString DefaultItemName;
NWindows::NFile::NFind::CFileInfoW ArchiveFileInfo;
// bool ShowDialog;
// bool PasswordEnabled;
// UString Password;
NExtract::NOverwriteMode::EEnum OverwriteMode;
CExtractOptions():
StdOutMode(false),
YesToAll(false),
TestMode(false),
PathMode(NExtract::NPathMode::kFullPathnames),
OverwriteMode(NExtract::NOverwriteMode::kAskBefore)
{}
/*
bool FullPathMode() const { return (ExtractMode == NExtractMode::kTest) ||
(ExtractMode == NExtractMode::kFullPath); }
*/
};
HRESULT DecompressArchives(
UStringVector &archivePaths, UStringVector &archivePathsFull,
const NWildcard::CCensorNode &wildcardCensor,
const CExtractOptions &options,
IOpenCallbackUI *openCallback,
IExtractCallbackUI *extractCallback);
#endif

31
7zip/UI/Common/ExtractMode.h Executable file
View File

@@ -0,0 +1,31 @@
// ExtractMode.h
#ifndef __EXTRACT_MODE_H
#define __EXTRACT_MODE_H
namespace NExtract {
namespace NPathMode
{
enum EEnum
{
kFullPathnames,
kCurrentPathnames,
kNoPathnames
};
}
namespace NOverwriteMode
{
enum EEnum
{
kAskBefore,
kWithoutPrompt,
kSkipExisting,
kAutoRename,
kAutoRenameExisting
};
}
}
#endif

View File

@@ -3,20 +3,32 @@
#include "StdAfx.h"
#include "ExtractingFilePath.h"
static void ReplaceDisk(UString &s)
{
int i;
for (i = 0; i < s.Length(); i++)
if (s[i] != ' ')
break;
if (s.Length() > i + 1)
{
if (s[i + 1] == L':')
{
s.Delete(i + 1);
// s.Insert(i + 1, L'_');
}
}
}
UString GetCorrectFileName(const UString &path)
{
UString result = path;
result.Trim();
result.Replace(L"..\\", L"");
result.Replace(L"../", L"");
if (result.Length() > 1)
{
if (result[1] == L':')
{
result.Delete(1);
// result.Insert(first + 1, L'_');
}
UString test = path;
test.Trim();
if (test == L"..")
result.Replace(L"..", L"");
}
ReplaceDisk(result);
return result;
}
@@ -29,7 +41,6 @@ UString GetCorrectPath(const UString &path)
break;
while(result.Length() > first)
{
if (result[first] == L'\\' || result[first] == L'/')
{
result.Delete(first);
@@ -40,15 +51,19 @@ UString GetCorrectPath(const UString &path)
result.Replace(L"..\\", L"");
result.Replace(L"../", L"");
if (result.Length() > 1)
{
if (result[first + 1] == L':')
{
result.Delete(first + 1);
// result.Insert(first + 1, L'_');
}
}
ReplaceDisk(result);
return result;
}
void MakeCorrectPath(UStringVector &pathParts)
{
for (int i = 0; i < pathParts.Size();)
{
UString &s = pathParts[i];
s = GetCorrectFileName(s);
if (s.IsEmpty())
pathParts.Delete(i);
else
i++;
}
}

View File

@@ -1,7 +1,5 @@
// ExtractingFilePath.h
#pragma once
#ifndef __EXTRACTINGFILEPATH_H
#define __EXTRACTINGFILEPATH_H
@@ -9,5 +7,6 @@
UString GetCorrectFileName(const UString &path);
UString GetCorrectPath(const UString &path);
void MakeCorrectPath(UStringVector &pathParts);
#endif

View File

@@ -1,14 +1,12 @@
// HandlerLoader.h
#pragma once
#ifndef __HANDLERLOADER_H
#define __HANDLERLOADER_H
#include "../../ICoder.h"
#include "Windows/DLL.h"
typedef UINT32 (WINAPI * CreateObjectFunc)(
typedef UInt32 (WINAPI * CreateObjectFunc)(
const GUID *clsID,
const GUID *interfaceID,
void **outObject);
@@ -37,6 +35,4 @@ public:
}
};
#endif

View File

@@ -0,0 +1,46 @@
// IFileExtractCallback.h
#ifndef __IFILEEXTRACTCALLBACK_H
#define __IFILEEXTRACTCALLBACK_H
#include "Common/String.h"
namespace NOverwriteAnswer
{
enum EEnum
{
kYes,
kYesToAll,
kNo,
kNoToAll,
kAutoRename,
kCancel,
};
}
// {23170F69-40C1-278A-0000-000100070000}
DEFINE_GUID(IID_IFolderArchiveExtractCallback,
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00);
MIDL_INTERFACE("23170F69-40C1-278A-0000-000100070000")
IFolderArchiveExtractCallback: public IProgress
{
public:
STDMETHOD(AskOverwrite)(
const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,
const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,
Int32 *answer) PURE;
STDMETHOD(PrepareOperation)(const wchar_t *name, Int32 askExtractMode, const UInt64 *position) PURE;
STDMETHOD(MessageError)(const wchar_t *message) PURE;
STDMETHOD(SetOperationResult)(Int32 operationResult) PURE;
};
struct IExtractCallbackUI: IFolderArchiveExtractCallback
{
virtual HRESULT BeforeOpen(const wchar_t *name) = 0;
virtual HRESULT OpenResult(const wchar_t *name, HRESULT result) = 0;
virtual HRESULT ThereAreNoFiles() = 0;
virtual HRESULT ExtractResult(HRESULT result) = 0;
virtual HRESULT SetPassword(const UString &password) = 0;
};
#endif

View File

@@ -4,9 +4,12 @@
#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"
@@ -24,6 +27,10 @@
#include "../../Archive/GZip/GZipHandler.h"
#endif
#ifdef FORMAT_SPLIT
#include "../../Archive/Split/SplitHandler.h"
#endif
#ifdef FORMAT_TAR
#include "../../Archive/Tar/TarHandler.h"
#endif
@@ -32,17 +39,86 @@
#include "../../Archive/Zip/ZipHandler.h"
#endif
#ifdef FORMAT_Z
#include "../../Archive/Z/ZHandler.h"
#endif
#ifndef EXCLUDE_COM
#include "HandlerLoader.h"
#endif
#include "DefaultName.h"
using namespace NWindows;
const UINT64 kMaxCheckStartPosition = 1 << 20;
HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, UString &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
return E_FAIL;
return S_OK;
}
HRESULT ReOpenArchive(IInArchive *archive,
const UString &fileName)
HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result)
{
RINOK(GetArchiveItemPath(archive, index, result));
if (result.IsEmpty())
result = defaultName;
return S_OK;
}
HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index,
const FILETIME &defaultFileTime, FILETIME &fileTime)
{
NCOM::CPropVariant prop;
RINOK(archive->GetProperty(index, kpidLastWriteTime, &prop));
if (prop.vt == VT_FILETIME)
fileTime = prop.filetime;
else if (prop.vt == VT_EMPTY)
fileTime = defaultFileTime;
else
return E_FAIL;
return S_OK;
}
static 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
return E_FAIL;
return S_OK;
}
HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result)
{
return IsArchiveItemProp(archive, index, kpidIsFolder, 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 =
#ifdef _WIN32
1 << 20;
#else
1 << 22;
#endif
HRESULT ReOpenArchive(IInArchive *archive, const UString &fileName)
{
CInFileStream *inStreamSpec = new CInFileStream;
CMyComPtr<IInStream> inStream(inStreamSpec);
@@ -50,49 +126,87 @@ HRESULT ReOpenArchive(IInArchive *archive,
return archive->Open(inStream, &kMaxCheckStartPosition, NULL);
}
HRESULT OpenArchive(const UString &fileName,
#ifndef _SFX
static inline bool TestSignature(const Byte *p1, const Byte *p2, UInt32 size)
{
for (UInt32 i = 0; i < size; i++)
if (p1[i] != p2[i])
return false;
return true;
}
#endif
HRESULT OpenArchive(
IInStream *inStream,
const UString &fileName,
#ifndef EXCLUDE_COM
HMODULE *module,
#endif
IInArchive **archiveResult,
CArchiverInfo &archiverInfoResult,
int &subExtIndex,
UString &defaultItemName,
IArchiveOpenCallback *openArchiveCallback)
{
CInFileStream *inStreamSpec = new CInFileStream;
CMyComPtr<IInStream> inStream(inStreamSpec);
if (!inStreamSpec->Open(fileName))
return GetLastError();
*archiveResult = NULL;
CObjectVector<CArchiverInfo> archiverInfoList;
ReadArchiverInfoList(archiverInfoList);
UString extension;
{
UString name, pureName, dot;
if(!NFile::NDirectory::GetOnlyName(fileName, name))
return E_FAIL;
NFile::NName::SplitNameToPureNameAndExtension(name, pureName, dot, extension);
int dotPos = fileName.ReverseFind(L'.');
if (dotPos >= 0)
extension = fileName.Mid(dotPos + 1);
}
CIntVector orderIndices;
int firstArchiverIndex;
for(firstArchiverIndex = 0;
firstArchiverIndex < archiverInfoList.Size(); firstArchiverIndex++)
int i;
bool finded = false;
for(i = 0; i < archiverInfoList.Size(); i++)
{
int subIndex = archiverInfoList[firstArchiverIndex].FindExtension(extension);
if (subIndex >= 0)
break;
if (archiverInfoList[i].FindExtension(extension) >= 0)
{
orderIndices.Insert(0, i);
finded = true;
}
else
orderIndices.Add(i);
}
if(firstArchiverIndex < archiverInfoList.Size())
orderIndices.Add(firstArchiverIndex);
for(int j = 0; j < archiverInfoList.Size(); j++)
if(j != firstArchiverIndex)
orderIndices.Add(j);
HRESULT badResult = S_OK;
for(int i = 0; i < orderIndices.Size(); i++)
#ifndef _SFX
if (!finded)
{
inStreamSpec->Seek(0, STREAM_SEEK_SET, NULL);
CByteBuffer byteBuffer;
const UInt32 kBufferSize = (200 << 10);
byteBuffer.SetCapacity(kBufferSize);
Byte *buffer = byteBuffer;
RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
UInt32 processedSize;
RINOK(inStream->Read(buffer, kBufferSize, &processedSize));
int numFinded = 0;
for (int pos = (int)processedSize; pos >= 0 ; pos--)
{
for(int i = numFinded; i < orderIndices.Size(); i++)
{
int index = orderIndices[i];
const CArchiverInfo &ai = archiverInfoList[index];
const CByteBuffer &sig = ai.StartSignature;
if (sig.GetCapacity() == 0)
continue;
if (pos + sig.GetCapacity() > processedSize)
continue;
if (TestSignature(buffer + pos, sig, sig.GetCapacity()))
{
orderIndices.Delete(i);
orderIndices.Insert(0, index);
numFinded++;
}
}
}
}
#endif
HRESULT badResult = S_OK;
for(i = 0; i < orderIndices.Size(); i++)
{
inStream->Seek(0, STREAM_SEEK_SET, NULL);
const CArchiverInfo &archiverInfo = archiverInfoList[orderIndices[i]];
#ifndef EXCLUDE_COM
CHandlerLoader loader;
@@ -114,6 +228,11 @@ HRESULT OpenArchive(const UString &fileName,
archive = new NArchive::NGZip::CHandler;
#endif
#ifdef FORMAT_SPLIT
if (archiverInfo.Name.CompareNoCase(L"Split") == 0)
archive = new NArchive::NSplit::CHandler;
#endif
#ifdef FORMAT_TAR
if (archiverInfo.Name.CompareNoCase(L"Tar") == 0)
archive = new NArchive::NTar::CHandler;
@@ -124,6 +243,11 @@ HRESULT OpenArchive(const UString &fileName,
archive = new NArchive::NZip::CHandler;
#endif
#ifdef FORMAT_Z
if (archiverInfo.Name.CompareNoCase(L"Z") == 0)
archive = new NArchive::NZ::CHandler;
#endif
#ifndef EXCLUDE_COM
if (!archive)
@@ -144,28 +268,260 @@ HRESULT OpenArchive(const UString &fileName,
if(result != S_OK)
{
badResult = result;
if(result == E_ABORT)
break;
continue;
// return result;
}
*archiveResult = archive.Detach();
#ifndef EXCLUDE_COM
*module = loader.Detach();
#endif
archiverInfoResult = archiverInfo;
subExtIndex = archiverInfo.FindExtension(extension);
int subExtIndex = archiverInfo.FindExtension(extension);
if (subExtIndex < 0)
subExtIndex = 0;
defaultItemName = GetDefaultName2(fileName,
archiverInfo.Extensions[subExtIndex].Extension,
archiverInfo.Extensions[subExtIndex].AddExtension);
return S_OK;
}
if (badResult != S_OK)
return badResult;
return S_FALSE;
/*
#else
return S_FALSE;
#endif
#endif
*/
}
HRESULT OpenArchive(const UString &filePath,
#ifndef EXCLUDE_COM
HMODULE *module,
#endif
IInArchive **archiveResult,
CArchiverInfo &archiverInfo,
UString &defaultItemName,
IArchiveOpenCallback *openArchiveCallback)
{
CInFileStream *inStreamSpec = new CInFileStream;
CMyComPtr<IInStream> inStream(inStreamSpec);
if (!inStreamSpec->Open(filePath))
return GetLastError();
return OpenArchive(inStream, ExtractFileNameFromPath(filePath),
#ifndef EXCLUDE_COM
module,
#endif
archiveResult, archiverInfo,
defaultItemName, openArchiveCallback);
}
static void MakeDefaultName(UString &name)
{
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);
}
HRESULT OpenArchive(const UString &fileName,
#ifndef EXCLUDE_COM
HMODULE *module0,
HMODULE *module1,
#endif
IInArchive **archive0,
IInArchive **archive1,
CArchiverInfo &archiverInfo0,
CArchiverInfo &archiverInfo1,
UString &defaultItemName0,
UString &defaultItemName1,
IArchiveOpenCallback *openArchiveCallback)
{
HRESULT result = OpenArchive(fileName,
#ifndef EXCLUDE_COM
module0,
#endif
archive0, archiverInfo0, defaultItemName0, openArchiveCallback);
RINOK(result);
CMyComPtr<IInArchiveGetStream> getStream;
result = (*archive0)->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream);
if (result != S_OK || getStream == 0)
return S_OK;
CMyComPtr<ISequentialInStream> subSeqStream;
result = getStream->GetStream(0, &subSeqStream);
if (result != S_OK)
return S_OK;
CMyComPtr<IInStream> subStream;
if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK)
return S_OK;
if (!subStream)
return S_OK;
UInt32 numItems;
RINOK((*archive0)->GetNumberOfItems(&numItems));
if (numItems < 1)
return S_OK;
UString subPath;
RINOK(GetArchiveItemPath(*archive0, 0, subPath))
if (subPath.IsEmpty())
{
MakeDefaultName(defaultItemName0);
subPath = defaultItemName0;
if (archiverInfo0.Name.CompareNoCase(L"7z") == 0)
{
if (subPath.Right(3).CompareNoCase(L".7z") != 0)
subPath += L".7z";
}
}
else
subPath = ExtractFileNameFromPath(subPath);
CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName;
openArchiveCallback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName);
if (setSubArchiveName)
setSubArchiveName->SetSubArchiveName(subPath);
result = OpenArchive(subStream, subPath,
#ifndef EXCLUDE_COM
module1,
#endif
archive1, archiverInfo1, defaultItemName1, openArchiveCallback);
return S_OK;
}
HRESULT MyOpenArchive(const UString &archiveName,
#ifndef EXCLUDE_COM
HMODULE *module,
#endif
IInArchive **archive,
UString &defaultItemName,
IOpenCallbackUI *openCallbackUI)
{
COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;
CMyComPtr<IArchiveOpenCallback> openCallback = openCallbackSpec;
openCallbackSpec->Callback = openCallbackUI;
UString fullName;
int fileNamePartStartIndex;
NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex);
openCallbackSpec->Init(
fullName.Left(fileNamePartStartIndex),
fullName.Mid(fileNamePartStartIndex));
CArchiverInfo archiverInfo;
return OpenArchive(archiveName,
#ifndef EXCLUDE_COM
module,
#endif
archive,
archiverInfo,
defaultItemName,
openCallback);
}
HRESULT MyOpenArchive(const UString &archiveName,
#ifndef EXCLUDE_COM
HMODULE *module0,
HMODULE *module1,
#endif
IInArchive **archive0,
IInArchive **archive1,
UString &defaultItemName0,
UString &defaultItemName1,
UStringVector &volumePaths,
IOpenCallbackUI *openCallbackUI)
{
COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;
CMyComPtr<IArchiveOpenCallback> openCallback = openCallbackSpec;
openCallbackSpec->Callback = openCallbackUI;
UString fullName;
int fileNamePartStartIndex;
NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex);
UString prefix = fullName.Left(fileNamePartStartIndex);
UString name = fullName.Mid(fileNamePartStartIndex);
openCallbackSpec->Init(prefix, name);
CArchiverInfo archiverInfo0, archiverInfo1;
HRESULT result = OpenArchive(archiveName,
#ifndef EXCLUDE_COM
module0,
module1,
#endif
archive0,
archive1,
archiverInfo0,
archiverInfo1,
defaultItemName0,
defaultItemName1,
openCallback);
RINOK(result);
volumePaths.Add(prefix + name);
for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++)
volumePaths.Add(prefix + openCallbackSpec->FileNames[i]);
return S_OK;
}
HRESULT CArchiveLink::Close()
{
if (Archive1 != 0)
RINOK(Archive1->Close());
if (Archive0 != 0)
RINOK(Archive0->Close());
return S_OK;
}
void CArchiveLink::Release()
{
if (Archive1 != 0)
Archive1.Release();
if (Archive0 != 0)
Archive0.Release();
#ifndef EXCLUDE_COM
Library1.Free();
Library0.Free();
#endif
}
HRESULT OpenArchive(const UString &archiveName,
CArchiveLink &archiveLink,
IArchiveOpenCallback *openCallback)
{
return OpenArchive(archiveName,
#ifndef EXCLUDE_COM
&archiveLink.Library0, &archiveLink.Library1,
#endif
&archiveLink.Archive0, &archiveLink.Archive1,
archiveLink.ArchiverInfo0, archiveLink.ArchiverInfo1,
archiveLink.DefaultItemName0, archiveLink.DefaultItemName1,
openCallback);
}
HRESULT MyOpenArchive(const UString &archiveName,
CArchiveLink &archiveLink,
IOpenCallbackUI *openCallbackUI)
{
return MyOpenArchive(archiveName,
#ifndef EXCLUDE_COM
&archiveLink.Library0, &archiveLink.Library1,
#endif
&archiveLink.Archive0, &archiveLink.Archive1,
archiveLink.DefaultItemName0, archiveLink.DefaultItemName1,
archiveLink.VolumePaths,
openCallbackUI);
}
HRESULT ReOpenArchive(CArchiveLink &archiveLink,
const UString &fileName)
{
if (archiveLink.GetNumLevels() > 1)
return E_NOTIMPL;
if (archiveLink.GetNumLevels() == 0)
return MyOpenArchive(fileName, archiveLink, 0);
return ReOpenArchive(archiveLink.GetArchive(), fileName);
}

View File

@@ -4,21 +4,130 @@
#define __OPENARCHIVE_H
#include "Common/String.h"
#include "Windows/FileFind.h"
#include "../../Archive/IArchive.h"
#include "ArchiverInfo.h"
#include "ArchiveOpenCallback.h"
HRESULT OpenArchive(const UString &fileName,
#ifndef EXCLUDE_COM
#include "Windows/DLL.h"
#endif
HRESULT GetArchiveItemPath(IInArchive *archive, UInt32 index, const UString &defaultName, UString &result);
HRESULT GetArchiveItemFileTime(IInArchive *archive, UInt32 index,
const FILETIME &defaultFileTime, FILETIME &fileTime);
HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result);
HRESULT IsArchiveItemAnti(IInArchive *archive, UInt32 index, bool &result);
struct ISetSubArchiveName
{
virtual void SetSubArchiveName(const wchar_t *name) = 0;
};
HRESULT OpenArchive(
IInStream *inStream,
const UString &fileName,
#ifndef EXCLUDE_COM
HMODULE *module,
#endif
IInArchive **archiveResult,
CArchiverInfo &archiverInfoResult,
UString &defaultItemName,
IArchiveOpenCallback *openArchiveCallback);
HRESULT OpenArchive(const UString &filePath,
#ifndef EXCLUDE_COM
HMODULE *module,
#endif
IInArchive **archive,
CArchiverInfo &archiverInfoResult,
int &subExtIndex,
CArchiverInfo &archiverInfo,
UString &defaultItemName,
IArchiveOpenCallback *openArchiveCallback);
HRESULT OpenArchive(const UString &filePath,
#ifndef EXCLUDE_COM
HMODULE *module0,
HMODULE *module1,
#endif
IInArchive **archive0,
IInArchive **archive1,
CArchiverInfo &archiverInfo0,
CArchiverInfo &archiverInfo1,
UString &defaultItemName0,
UString &defaultItemName1,
IArchiveOpenCallback *openArchiveCallback);
HRESULT ReOpenArchive(IInArchive *archive,
const UString &fileName);
HRESULT MyOpenArchive(const UString &archiveName,
#ifndef EXCLUDE_COM
HMODULE *module,
#endif
IInArchive **archive,
UString &defaultItemName,
IOpenCallbackUI *openCallbackUI);
HRESULT MyOpenArchive(const UString &archiveName,
#ifndef EXCLUDE_COM
HMODULE *module0,
HMODULE *module1,
#endif
IInArchive **archive0,
IInArchive **archive1,
UString &defaultItemName0,
UString &defaultItemName1,
UStringVector &volumePaths,
IOpenCallbackUI *openCallbackUI);
struct CArchiveLink
{
#ifndef EXCLUDE_COM
NWindows::NDLL::CLibrary Library0;
NWindows::NDLL::CLibrary Library1;
#endif
CMyComPtr<IInArchive> Archive0;
CMyComPtr<IInArchive> Archive1;
UString DefaultItemName0;
UString DefaultItemName1;
CArchiverInfo ArchiverInfo0;
CArchiverInfo ArchiverInfo1;
UStringVector VolumePaths;
int GetNumLevels() const
{
int result = 0;
if (Archive0)
{
result++;
if (Archive1)
result++;
}
return result;
}
IInArchive *GetArchive() { return Archive1 != 0 ? Archive1: Archive0; }
UString GetDefaultItemName() { return Archive1 != 0 ? DefaultItemName1: DefaultItemName0; }
const CArchiverInfo &GetArchiverInfo() { return Archive1 != 0 ? ArchiverInfo1: ArchiverInfo0; }
HRESULT Close();
void Release();
};
HRESULT OpenArchive(const UString &archiveName,
CArchiveLink &archiveLink,
IArchiveOpenCallback *openCallback);
HRESULT MyOpenArchive(const UString &archiveName,
CArchiveLink &archiveLink,
IOpenCallbackUI *openCallbackUI);
HRESULT ReOpenArchive(CArchiveLink &archiveLink,
const UString &fileName);
#endif

View File

@@ -14,13 +14,24 @@
using namespace NWindows;
static UString ConvertUINT32ToString(UINT32 value)
static UString ConvertUInt32ToString(UInt32 value)
{
wchar_t buffer[32];
ConvertUINT64ToString(value, buffer);
ConvertUInt64ToString(value, buffer);
return buffer;
}
static void ConvertUInt32ToHex(UInt32 value, wchar_t *s)
{
for (int i = 0; i < 8; i++)
{
int t = value & 0xF;
value >>= 4;
s[7 - i] = (wchar_t)((t < 10) ? (L'0' + t) : (L'A' + (t - 10)));
}
s[8] = L'\0';
}
UString ConvertPropertyToString(const PROPVARIANT &propVariant,
PROPID propID, bool full)
{
@@ -38,22 +49,22 @@ UString ConvertPropertyToString(const PROPVARIANT &propVariant,
return UString();
if (!::FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime))
return UString(); // It is error;
return ConvertFileTimeToString2(localFileTime, true, full);
return ConvertFileTimeToString(localFileTime, true, full);
}
case kpidCRC:
{
if(propVariant.vt != VT_UI4)
break;
TCHAR temp[17];
wsprintf(temp, TEXT("%08X"), propVariant.ulVal);
return GetUnicodeString(temp);
wchar_t temp[12];
ConvertUInt32ToHex(propVariant.ulVal, temp);
return temp;
}
case kpidAttributes:
{
if(propVariant.vt != VT_UI4)
break;
UString result;
UINT32 attributes = propVariant.ulVal;
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';
@@ -67,12 +78,12 @@ UString ConvertPropertyToString(const PROPVARIANT &propVariant,
{
if(propVariant.vt != VT_UI4)
break;
UINT32 size = propVariant.ulVal;
UInt32 size = propVariant.ulVal;
if (size % (1 << 20) == 0)
return ConvertUINT32ToString(size >> 20) + L"MB";
return ConvertUInt32ToString(size >> 20) + L"MB";
if (size % (1 << 10) == 0)
return ConvertUINT32ToString(size >> 10) + L"KB";
return ConvertUINT32ToString(size);
return ConvertUInt32ToString(size >> 10) + L"KB";
return ConvertUInt32ToString(size);
}
}
return ConvertPropVariantToString(propVariant);

View File

@@ -1,7 +1,5 @@
// PropIDUtils.h
#pragma once
#ifndef __PROPIDUTILS_H
#define __PROPIDUTILS_H

View File

@@ -11,7 +11,7 @@ static int __cdecl CompareStrings(const void *a1, const void *a2)
return s1.CompareNoCase(s2);
}
void SortStringsToIndices(UStringVector &strings, CIntVector &indices)
void SortStringsToIndices(const UStringVector &strings, CIntVector &indices)
{
indices.Clear();
if (strings.IsEmpty())
@@ -22,9 +22,19 @@ void SortStringsToIndices(UStringVector &strings, CIntVector &indices)
indices.Reserve(numItems);
int i;
for(i = 0; i < numItems; i++)
pointers.Add(&strings.CPointerVector::operator[](i));
pointers.Add((void *)&strings.CPointerVector::operator[](i));
void **stringsBase = (void **)pointers[0];
qsort(&pointers[0], numItems, sizeof(void *), CompareStrings);
for(i = 0; i < numItems; i++)
indices.Add((void **)pointers[i] - stringsBase);
}
void SortStrings(const UStringVector &src, UStringVector &dest)
{
CIntVector indices;
SortStringsToIndices(src, indices);
dest.Clear();
dest.Reserve(indices.Size());
for (int i = 0; i < indices.Size(); i++)
dest.Add(src[indices[i]]);
}

View File

@@ -1,12 +1,11 @@
// SortUtils.h
#pragma once
#ifndef __SORTUTLS_H
#define __SORTUTLS_H
#include "Common/String.h"
void SortStringsToIndices(UStringVector &strings, CIntVector &indices);
void SortStringsToIndices(const UStringVector &strings, CIntVector &indices);
void SortStrings(const UStringVector &src, UStringVector &dest);
#endif

22
7zip/UI/Common/TempFiles.cpp Executable file
View File

@@ -0,0 +1,22 @@
// TempFiles.cpp
#include "StdAfx.h"
#include "TempFiles.h"
#include "Windows/FileDir.h"
#include "Windows/FileIO.h"
using namespace NWindows;
using namespace NFile;
void CTempFiles::Clear()
{
while(!Paths.IsEmpty())
{
NDirectory::DeleteFileAlways(Paths.Back());
Paths.DeleteBack();
}
}

16
7zip/UI/Common/TempFiles.h Executable file
View File

@@ -0,0 +1,16 @@
// TempFiles.h
#ifndef __TEMPFILES_H
#define __TEMPFILES_H
#include "Common/String.h"
class CTempFiles
{
void Clear();
public:
UStringVector Paths;
~CTempFiles() { Clear(); }
};
#endif

850
7zip/UI/Common/Update.cpp Executable file
View File

@@ -0,0 +1,850 @@
// Update.cpp
#include "StdAfx.h"
#ifdef _WIN32
#include <mapi.h>
#endif
#include "Update.h"
#include "Common/IntToString.h"
#include "Common/StringToInt.h"
#include "Common/StringConvert.h"
#include "Common/CommandLineParser.h"
#ifdef _WIN32
#include "Windows/DLL.h"
#endif
#include "Windows/Defs.h"
#include "Windows/FileDir.h"
#include "Windows/FileFind.h"
#include "Windows/FileName.h"
#include "Windows/PropVariant.h"
#include "Windows/PropVariantConversions.h"
// #include "Windows/Synchronization.h"
#include "../../Common/FileStreams.h"
#include "../../Compress/Copy/CopyCoder.h"
#include "../Common/DirItem.h"
#include "../Common/EnumDirItems.h"
#include "../Common/UpdateProduce.h"
#include "../Common/OpenArchive.h"
#include "TempFiles.h"
#include "UpdateCallback.h"
#include "EnumDirItems.h"
#ifdef FORMAT_7Z
#include "../../Archive/7z/7zHandler.h"
#endif
#ifdef FORMAT_BZIP2
#include "../../Archive/BZip2/BZip2Handler.h"
#endif
#ifdef FORMAT_GZIP
#include "../../Archive/GZip/GZipHandler.h"
#endif
#ifdef FORMAT_TAR
#include "../../Archive/Tar/TarHandler.h"
#endif
#ifdef FORMAT_ZIP
#include "../../Archive/Zip/ZipHandler.h"
#endif
#ifndef EXCLUDE_COM
#include "../Common/HandlerLoader.h"
#endif
static const char *kUpdateIsNotSupoorted =
"update operations are not supported for this archive";
using namespace NCommandLineParser;
using namespace NWindows;
using namespace NCOM;
using namespace NFile;
using namespace NName;
static const wchar_t *kTempArchiveFilePrefixString = L"7zi";
static const wchar_t *kTempFolderPrefix = L"7zE";
static const char *kIllegalFileNameMessage = "Illegal file name for temp archive";
using namespace NUpdateArchive;
static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop)
{
const wchar_t *endPtr;
UInt64 result = ConvertStringToUInt64(s, &endPtr);
if (endPtr - (const wchar_t *)s != s.Length())
prop = s;
else if (result <= 0xFFFFFFFF)
prop = (UInt32)result;
else
prop = result;
}
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
{
size_t _streamIndex; // required stream
UInt64 _offsetPos; // offset from start of _streamIndex index
UInt64 _absPos;
UInt64 _length;
struct CSubStreamInfo
{
CMyComPtr<IOutStream> Stream;
UString Name;
UInt64 Pos;
UInt64 RealSize;
};
CObjectVector<CSubStreamInfo> Streams;
public:
// CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
CRecordVector<UInt64> Sizes;
UString Prefix;
CTempFiles *TempFiles;
void Init()
{
_streamIndex = 0;
_offsetPos = 0;
_absPos = 0;
_length = 0;
}
MY_UNKNOWN_IMP1(IOutStream)
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
STDMETHOD(SetSize)(Int64 newSize);
};
// static NSynchronization::CCriticalSection g_TempPathsCS;
STDMETHODIMP COutMultiVolStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
if(processedSize != NULL)
*processedSize = 0;
while(size > 0)
{
if (_streamIndex >= (size_t)Streams.Size())
{
CSubStreamInfo subStream;
wchar_t temp[32];
ConvertUInt64ToString(_streamIndex + 1, temp);
UString res = temp;
while (res.Length() < 3)
res = UString(L'0') + res;
UString name = Prefix + res;
COutFileStream *streamSpec = new COutFileStream;
subStream.Stream = streamSpec;
if(!streamSpec->Create(name, false))
return ::GetLastError();
{
// NSynchronization::CCriticalSectionLock lock(g_TempPathsCS);
TempFiles->Paths.Add(name);
}
subStream.Pos = 0;
subStream.RealSize = 0;
subStream.Name = name;
Streams.Add(subStream);
continue;
}
CSubStreamInfo &subStream = Streams[_streamIndex];
int index = _streamIndex;
if (index >= Sizes.Size())
index = Sizes.Size() - 1;
UInt64 volSize = Sizes[index];
if (_offsetPos >= volSize)
{
_offsetPos -= volSize;
_streamIndex++;
continue;
}
if (_offsetPos != subStream.Pos)
{
// CMyComPtr<IOutStream> outStream;
// RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));
RINOK(subStream.Stream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));
subStream.Pos = _offsetPos;
}
UInt32 curSize = (UInt32)MyMin((UInt64)size, volSize - subStream.Pos);
UInt32 realProcessed;
RINOK(subStream.Stream->Write(data, curSize, &realProcessed));
data = (void *)((Byte *)data + realProcessed);
size -= realProcessed;
subStream.Pos += realProcessed;
_offsetPos += realProcessed;
_absPos += realProcessed;
if (_absPos > _length)
_length = _absPos;
if (_offsetPos > subStream.RealSize)
subStream.RealSize = _offsetPos;
if(processedSize != NULL)
*processedSize += realProcessed;
if (subStream.Pos == volSize)
{
_streamIndex++;
_offsetPos = 0;
}
if (realProcessed != curSize)
return E_FAIL;
}
return S_OK;
}
STDMETHODIMP COutMultiVolStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize)
{
return Write(data, size, processedSize);
}
STDMETHODIMP COutMultiVolStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
{
if(seekOrigin >= 3)
return STG_E_INVALIDFUNCTION;
switch(seekOrigin)
{
case STREAM_SEEK_SET:
_absPos = offset;
break;
case STREAM_SEEK_CUR:
_absPos += offset;
break;
case STREAM_SEEK_END:
_absPos = _length + offset;
break;
}
_offsetPos = _absPos;
if (newPosition != NULL)
*newPosition = _absPos;
_streamIndex = 0;
return S_OK;
}
STDMETHODIMP COutMultiVolStream::SetSize(Int64 newSize)
{
if (newSize < 0)
return E_INVALIDARG;
int i = 0;
while (i < Streams.Size())
{
CSubStreamInfo &subStream = Streams[i++];
if ((UInt64)newSize < subStream.RealSize)
{
RINOK(subStream.Stream->SetSize(newSize));
subStream.RealSize = newSize;
break;
}
newSize -= subStream.RealSize;
}
while (i < Streams.Size())
{
{
CSubStreamInfo &subStream = Streams.Back();
subStream.Stream.Release();
NDirectory::DeleteFileAlways(subStream.Name);
}
Streams.DeleteBack();
}
_offsetPos = _absPos;
_streamIndex = 0;
_length = newSize;
return S_OK;
}
static HRESULT Compress(
const CActionSet &actionSet,
IInArchive *archive,
const CCompressionMethodMode &compressionMethod,
CArchivePath &archivePath,
const CObjectVector<CArchiveItem> &archiveItems,
bool stdInMode,
const UString &stdInFileName,
bool stdOutMode,
const CObjectVector<CDirItem> &dirItems,
bool sfxMode,
const UString &sfxModule,
const CRecordVector<UInt64> &volumesSizes,
CTempFiles &tempFiles,
CUpdateErrorInfo &errorInfo,
IUpdateCallbackUI *callback)
{
#ifndef EXCLUDE_COM
CHandlerLoader loader;
#endif
CMyComPtr<IOutArchive> outArchive;
if(archive != NULL)
{
CMyComPtr<IInArchive> archive2 = archive;
HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive);
if(result != S_OK)
throw kUpdateIsNotSupoorted;
}
else
{
#ifndef EXCLUDE_COM
if (loader.CreateHandler(compressionMethod.FilePath,
compressionMethod.ClassID, (void **)&outArchive, true) != S_OK)
throw kUpdateIsNotSupoorted;
#endif
#ifdef FORMAT_7Z
if (compressionMethod.Name.CompareNoCase(L"7z") == 0)
outArchive = new NArchive::N7z::CHandler;
#endif
#ifdef FORMAT_BZIP2
if (compressionMethod.Name.CompareNoCase(L"BZip2") == 0)
outArchive = new NArchive::NBZip2::CHandler;
#endif
#ifdef FORMAT_GZIP
if (compressionMethod.Name.CompareNoCase(L"GZip") == 0)
outArchive = new NArchive::NGZip::CHandler;
#endif
#ifdef FORMAT_TAR
if (compressionMethod.Name.CompareNoCase(L"Tar") == 0)
outArchive = new NArchive::NTar::CHandler;
#endif
#ifdef FORMAT_ZIP
if (compressionMethod.Name.CompareNoCase(L"Zip") == 0)
outArchive = new NArchive::NZip::CHandler;
#endif
}
if (outArchive == 0)
throw kUpdateIsNotSupoorted;
NFileTimeType::EEnum fileTimeType;
UInt32 value;
RINOK(outArchive->GetFileTimeType(&value));
switch(value)
{
case NFileTimeType::kWindows:
case NFileTimeType::kDOS:
case NFileTimeType::kUnix:
fileTimeType = NFileTimeType::EEnum(value);
break;
default:
return E_FAIL;
}
CObjectVector<CUpdatePair> updatePairs;
GetUpdatePairInfoList(dirItems, archiveItems, fileTimeType, updatePairs); // must be done only once!!!
CObjectVector<CUpdatePair2> updatePairs2;
UpdateProduce(dirItems, archiveItems, updatePairs, actionSet, updatePairs2);
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec );
updateCallbackSpec->StdInMode = stdInMode;
updateCallbackSpec->Callback = callback;
updateCallbackSpec->DirItems = &dirItems;
updateCallbackSpec->ArchiveItems = &archiveItems;
updateCallbackSpec->UpdatePairs = &updatePairs2;
CMyComPtr<ISequentialOutStream> outStream;
const UString &archiveName = archivePath.GetFinalPath();
if (!stdOutMode)
{
UString resultPath;
int pos;
if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos))
throw 1417161;
NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));
}
if (volumesSizes.Size() == 0)
{
if (stdOutMode)
outStream = new CStdOutFileStream;
else
{
COutFileStream *outStreamSpec = new COutFileStream;
outStream = outStreamSpec;
bool isOK = false;
UString realPath;
for (int i = 0; i < (1 << 16); i++)
{
if (archivePath.Temp)
{
if (i > 0)
{
wchar_t s[32];
ConvertUInt64ToString(i, s);
archivePath.TempPostfix = s;
}
realPath = archivePath.GetTempPath();
}
else
realPath = archivePath.GetFinalPath();
if (outStreamSpec->Create(realPath, false))
{
tempFiles.Paths.Add(realPath);
isOK = true;
break;
}
if (::GetLastError() != ERROR_FILE_EXISTS)
break;
if (!archivePath.Temp)
break;
}
if (!isOK)
{
errorInfo.SystemError = ::GetLastError();
errorInfo.FileName = realPath;
errorInfo.Message = L"Can not open file";
return E_FAIL;
}
}
}
else
{
if (stdOutMode)
return E_FAIL;
COutMultiVolStream *volStreamSpec = new COutMultiVolStream;
outStream = volStreamSpec;
volStreamSpec->Sizes = volumesSizes;
volStreamSpec->Prefix = archivePath.GetFinalPath() + UString(L".");
volStreamSpec->TempFiles = &tempFiles;
volStreamSpec->Init();
/*
updateCallbackSpec->VolumesSizes = volumesSizes;
updateCallbackSpec->VolName = archivePath.Prefix + archivePath.Name;
if (!archivePath.VolExtension.IsEmpty())
updateCallbackSpec->VolExt = UString(L'.') + archivePath.VolExtension;
*/
}
CMyComPtr<ISetProperties> setProperties;
if (outArchive.QueryInterface(IID_ISetProperties, &setProperties) == S_OK)
{
UStringVector realNames;
CPropVariant *values = new CPropVariant[compressionMethod.Properties.Size()];
try
{
int i;
for(i = 0; i < compressionMethod.Properties.Size(); i++)
{
const CProperty &property = compressionMethod.Properties[i];
NCOM::CPropVariant propVariant;
if (!property.Value.IsEmpty())
ParseNumberString(property.Value, propVariant);
realNames.Add(property.Name);
values[i] = propVariant;
}
CRecordVector<const wchar_t *> names;
for(i = 0; i < realNames.Size(); i++)
names.Add((const wchar_t *)realNames[i]);
RINOK(setProperties->SetProperties(&names.Front(), values, names.Size()));
}
catch(...)
{
delete []values;
throw;
}
delete []values;
}
if (sfxMode)
{
CInFileStream *sfxStreamSpec = new CInFileStream;
CMyComPtr<IInStream> sfxStream(sfxStreamSpec);
if (!sfxStreamSpec->Open(sfxModule))
{
errorInfo.SystemError = ::GetLastError();
errorInfo.Message = L"Can't open sfx module";
errorInfo.FileName = sfxModule;
return E_FAIL;
}
CMyComPtr<ISequentialOutStream> sfxOutStream;
if (volumesSizes.Size() == 0)
sfxOutStream = outStream;
else
{
COutFileStream *outStreamSpec = new COutFileStream;
sfxOutStream = outStreamSpec;
UString realPath = archivePath.GetFinalPath();
if (!outStreamSpec->Create(realPath, false))
{
errorInfo.SystemError = ::GetLastError();
errorInfo.FileName = realPath;
errorInfo.Message = L"Can not open file";
return E_FAIL;
}
}
RINOK(CopyBlock(sfxStream, sfxOutStream));
}
HRESULT result = outArchive->UpdateItems(outStream, updatePairs2.Size(),
updateCallback);
callback->Finilize();
return result;
}
HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor,
IInArchive *archive,
const UString &defaultItemName,
const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo,
CObjectVector<CArchiveItem> &archiveItems)
{
archiveItems.Clear();
UInt32 numItems;
RINOK(archive->GetNumberOfItems(&numItems));
archiveItems.Reserve(numItems);
for(UInt32 i = 0; i < numItems; i++)
{
CArchiveItem ai;
RINOK(GetArchiveItemPath(archive, i, defaultItemName, ai.Name));
RINOK(IsArchiveItemFolder(archive, i, ai.IsDirectory));
ai.Censored = censor.CheckPath(ai.Name, !ai.IsDirectory);
RINOK(GetArchiveItemFileTime(archive, i,
archiveFileInfo.LastWriteTime, ai.LastWriteTime));
CPropVariant propertySize;
RINOK(archive->GetProperty(i, kpidSize, &propertySize));
if (ai.SizeIsDefined = (propertySize.vt != VT_EMPTY))
ai.Size = ConvertPropVariantToUInt64(propertySize);
ai.IndexInServer = i;
archiveItems.Add(ai);
}
return S_OK;
}
static HRESULT UpdateWithItemLists(
CUpdateOptions &options,
IInArchive *archive,
const CObjectVector<CArchiveItem> &archiveItems,
const CObjectVector<CDirItem> &dirItems,
CTempFiles &tempFiles,
CUpdateErrorInfo &errorInfo,
IUpdateCallbackUI2 *callback)
{
for(int i = 0; i < options.Commands.Size(); i++)
{
CUpdateArchiveCommand &command = options.Commands[i];
if (options.StdOutMode)
{
RINOK(callback->StartArchive(0, archive != 0));
}
else
{
RINOK(callback->StartArchive(command.ArchivePath.GetFinalPath(),
i == 0 && options.UpdateArchiveItself && archive != 0));
}
RINOK(Compress(command.ActionSet, archive,
options.MethodMode,
command.ArchivePath,
archiveItems,
options.StdInMode, options.StdInFileName,
options.StdOutMode,
dirItems,
options.SfxMode, options.SfxModule,
options.VolumesSizes,
tempFiles,
errorInfo, callback));
RINOK(callback->FinishArchive());
}
return S_OK;
}
#ifdef _WIN32
class CCurrentDirRestorer
{
CSysString m_CurrentDirectory;
public:
CCurrentDirRestorer()
{ NFile::NDirectory::MyGetCurrentDirectory(m_CurrentDirectory); }
~CCurrentDirRestorer()
{ RestoreDirectory();}
bool RestoreDirectory()
{ return BOOLToBool(::SetCurrentDirectory(m_CurrentDirectory)); }
};
#endif
struct CEnumDirItemUpdateCallback: public IEnumDirItemCallback
{
IUpdateCallbackUI2 *Callback;
HRESULT CheckBreak() { return Callback->CheckBreak(); }
};
HRESULT UpdateArchive(const NWildcard::CCensor &censor,
CUpdateOptions &options,
CUpdateErrorInfo &errorInfo,
IOpenCallbackUI *openCallback,
IUpdateCallbackUI2 *callback)
{
if (options.StdOutMode && options.EMailMode)
return E_FAIL;
if (options.VolumesSizes.Size() > 0 && (options.EMailMode || options.SfxMode))
return E_NOTIMPL;
if (options.SfxMode)
{
CProperty property;
property.Name = L"rsfx";
property.Value = L"on";
options.MethodMode.Properties.Add(property);
if (options.SfxModule.IsEmpty())
{
errorInfo.Message = L"sfx file is not specified";
return E_FAIL;
}
UString name = options.SfxModule;
if (!NDirectory::MySearchPath(NULL, name, NULL, options.SfxModule))
{
errorInfo.Message = L"can't find specified sfx module";
return E_FAIL;
}
}
const UString archiveName = options.ArchivePath.GetFinalPath();
UString defaultItemName;
NFind::CFileInfoW archiveFileInfo;
CArchiveLink archiveLink;
IInArchive *archive = 0;
if (NFind::FindFile(archiveName, archiveFileInfo))
{
if (archiveFileInfo.IsDirectory())
throw "there is no such archive";
if (options.VolumesSizes.Size() > 0)
return E_NOTIMPL;
HRESULT result = MyOpenArchive(archiveName, archiveLink, openCallback);
RINOK(callback->OpenResult(archiveName, result));
RINOK(result);
if (archiveLink.VolumePaths.Size() > 1)
{
errorInfo.SystemError = E_NOTIMPL;
errorInfo.Message = L"Updating for multivolume archives is not implemented";
return E_NOTIMPL;
}
archive = archiveLink.GetArchive();
defaultItemName = archiveLink.GetDefaultItemName();
}
else
{
/*
if (archiveType.IsEmpty())
throw "type of archive is not specified";
*/
}
CObjectVector<CDirItem> dirItems;
if (options.StdInMode)
{
CDirItem item;
item.FullPath = item.Name = options.StdInFileName;
item.Size = (UInt64)(Int64)-1;
item.Attributes = 0;
SYSTEMTIME st;
FILETIME ft;
GetSystemTime(&st);
SystemTimeToFileTime(&st, &ft);
item.CreationTime = item.LastAccessTime = item.LastWriteTime = ft;
dirItems.Add(item);
}
else
{
bool needScanning = false;
for(int i = 0; i < options.Commands.Size(); i++)
if (options.Commands[i].ActionSet.NeedScanning())
needScanning = true;
if (needScanning)
{
CEnumDirItemUpdateCallback enumCallback;
enumCallback.Callback = callback;
RINOK(callback->StartScanning());
RINOK(EnumerateItems(censor, dirItems, &enumCallback));
RINOK(callback->FinishScanning());
}
}
UString tempDirPrefix;
bool usesTempDir = false;
#ifdef _WIN32
NDirectory::CTempDirectoryW tempDirectory;
if (options.EMailMode && options.EMailRemoveAfter)
{
tempDirectory.Create(kTempFolderPrefix);
tempDirPrefix = tempDirectory.GetPath();
NormalizeDirPathPrefix(tempDirPrefix);
usesTempDir = true;
}
#endif
CTempFiles tempFiles;
bool createTempFile = false;
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)
{
createTempFile = true;
ap.Temp = true;
if (!options.WorkingDir.IsEmpty())
{
ap.TempPrefix = options.WorkingDir;
NormalizeDirPathPrefix(ap.TempPrefix);
}
}
}
for(int i = 0; i < options.Commands.Size(); i++)
{
CArchivePath &ap = options.Commands[i].ArchivePath;
if (usesTempDir)
{
// Check it
ap.Prefix = tempDirPrefix;
// ap.Temp = true;
// ap.TempPrefix = tempDirPrefix;
}
if (i > 0 || !createTempFile)
{
const UString &path = ap.GetFinalPath();
if (NFind::DoesFileExist(path))
{
errorInfo.SystemError = 0;
errorInfo.Message = L"File already exists";
errorInfo.FileName = path;
return E_FAIL;
}
}
}
CObjectVector<CArchiveItem> archiveItems;
if (archive != NULL)
{
RINOK(EnumerateInArchiveItems(censor,
archive, defaultItemName, archiveFileInfo, archiveItems));
}
RINOK(UpdateWithItemLists(options, archive, archiveItems, dirItems,
tempFiles, errorInfo, callback));
if (archive != NULL)
{
RINOK(archiveLink.Close());
archiveLink.Release();
}
tempFiles.Paths.Clear();
if(createTempFile)
{
try
{
CArchivePath &ap = options.Commands[0].ArchivePath;
const UString &tempPath = ap.GetTempPath();
if (archive != NULL)
if (!NDirectory::DeleteFileAlways(archiveName))
{
errorInfo.SystemError = ::GetLastError();
errorInfo.Message = L"delete file error";
errorInfo.FileName = archiveName;
return E_FAIL;
}
if (!NDirectory::MyMoveFile(tempPath, archiveName))
{
errorInfo.SystemError = ::GetLastError();
errorInfo.Message = L"move file error";
errorInfo.FileName = tempPath;
errorInfo.FileName2 = archiveName;
return E_FAIL;
}
}
catch(...)
{
throw;
}
}
#ifdef _WIN32
if (options.EMailMode)
{
NDLL::CLibrary mapiLib;
if (!mapiLib.Load(TEXT("Mapi32.dll")))
{
errorInfo.SystemError = ::GetLastError();
errorInfo.Message = L"can not load Mapi32.dll";
return E_FAIL;
}
LPMAPISENDDOCUMENTS fnSend = (LPMAPISENDDOCUMENTS)
mapiLib.GetProcAddress("MAPISendDocuments");
if (fnSend == 0)
{
errorInfo.SystemError = ::GetLastError();
errorInfo.Message = L"can not find MAPISendDocuments function";
return E_FAIL;
}
UStringVector fullPaths;
int i;
for(i = 0; i < options.Commands.Size(); i++)
{
CArchivePath &ap = options.Commands[i].ArchivePath;
UString arcPath;
if(!NFile::NDirectory::MyGetFullPathName(ap.GetFinalPath(), arcPath))
{
errorInfo.SystemError = ::GetLastError();
return E_FAIL;
}
fullPaths.Add(arcPath);
}
CCurrentDirRestorer curDirRestorer;
for(i = 0; i < fullPaths.Size(); i++)
{
UString arcPath = fullPaths[i];
UString fileName = ExtractFileNameFromPath(arcPath);
AString path = GetAnsiString(arcPath);
AString name = GetAnsiString(fileName);
// Warning!!! MAPISendDocuments function changes Current directory
fnSend(0, ";", (LPSTR)(LPCSTR)path, (LPSTR)(LPCSTR)name, 0);
}
}
#endif
return S_OK;
}

157
7zip/UI/Common/Update.h Executable file
View File

@@ -0,0 +1,157 @@
// Update.h
#ifndef __UPDATE_H
#define __UPDATE_H
#include "Common/Wildcard.h"
#include "Windows/FileFind.h"
#include "../../Archive/IArchive.h"
#include "UpdateAction.h"
#include "ArchiveOpenCallback.h"
#include "UpdateCallback.h"
struct CArchivePath
{
UString Prefix; // path(folder) prefix including slash
UString Name; // base name
UString BaseExtension; // archive type extension or "exe" extension
UString VolExtension; // archive type extension for volumes
bool Temp;
UString TempPrefix; // path(folder) for temp location
UString TempPostfix;
CArchivePath(): Temp(false) {};
void ParseFromPath(const UString &path)
{
SplitPathToParts(path, Prefix, Name);
if (Name.IsEmpty())
return;
int dotPos = Name.ReverseFind(L'.');
if (dotPos < 0)
return;
if (dotPos == Name.Length() - 1)
{
Name = Name.Left(dotPos);
BaseExtension.Empty();
return;
}
if (BaseExtension.CompareNoCase(Name.Mid(dotPos + 1)) == 0)
Name = Name.Left(dotPos);
else
BaseExtension.Empty();
}
UString GetPathWithoutExt() const
{
return Prefix + Name;
}
UString GetFinalPath() const
{
UString path = GetPathWithoutExt();
if (!BaseExtension.IsEmpty())
path += UString(L'.') + BaseExtension;
return path;
}
UString GetTempPath() const
{
UString path = TempPrefix + Name;
if (!BaseExtension.IsEmpty())
path += UString(L'.') + BaseExtension;
path += L".tmp";
path += TempPostfix;
return path;
}
};
struct CUpdateArchiveCommand
{
CArchivePath ArchivePath;
NUpdateArchive::CActionSet ActionSet;
};
struct CProperty
{
UString Name;
UString Value;
};
struct CCompressionMethodMode
{
#ifndef EXCLUDE_COM
UString FilePath;
CLSID ClassID;
#else
UString Name;
#endif
CObjectVector<CProperty> Properties;
};
struct CUpdateOptions
{
CCompressionMethodMode MethodMode;
CObjectVector<CUpdateArchiveCommand> Commands;
bool UpdateArchiveItself;
CArchivePath ArchivePath;
bool SfxMode;
UString SfxModule;
bool StdInMode;
UString StdInFileName;
bool StdOutMode;
bool EMailMode;
bool EMailRemoveAfter;
UString EMailAddress;
UString WorkingDir;
CUpdateOptions():
UpdateArchiveItself(true),
SfxMode(false),
StdInMode(false),
StdOutMode(false),
EMailMode(false),
EMailRemoveAfter(false)
{};
CRecordVector<UInt64> VolumesSizes;
};
struct CErrorInfo
{
DWORD SystemError;
UString FileName;
UString FileName2;
UString Message;
CErrorInfo(): SystemError(0) {};
};
struct CUpdateErrorInfo: public CErrorInfo
{
};
struct IUpdateCallbackUI2: public IUpdateCallbackUI
{
virtual HRESULT OpenResult(const wchar_t *name, HRESULT result) = 0;
virtual HRESULT StartScanning() = 0;
virtual HRESULT FinishScanning() = 0;
virtual HRESULT StartArchive(const wchar_t *name, bool updating) = 0;
virtual HRESULT FinishArchive() = 0;
};
HRESULT UpdateArchive(const NWildcard::CCensor &censor,
CUpdateOptions &options,
CUpdateErrorInfo &errorInfo,
IOpenCallbackUI *openCallback,
IUpdateCallbackUI2 *callback);
#endif

View File

@@ -1,7 +1,5 @@
// UpdateAction.h
#pragma once
#ifndef __UPDATE_ACTION_H
#define __UPDATE_ACTION_H
@@ -34,6 +32,17 @@ namespace NUpdateArchive {
struct CActionSet
{
NPairAction::EEnum StateActions[NPairState::kNumValues];
bool NeedScanning() const
{
int i;
for (i = 0; i < NPairState::kNumValues; i++)
if (StateActions[i] == NPairAction::kCompress)
return true;
for (i = 1; i < NPairState::kNumValues; i++)
if (StateActions[i] != NPairAction::kIgnore)
return true;
return false;
}
};
extern const CActionSet kAddActionSet;
extern const CActionSet kUpdateActionSet;

242
7zip/UI/Common/UpdateCallback.cpp Executable file
View File

@@ -0,0 +1,242 @@
// UpdateCallback.cpp
#include "StdAfx.h"
#include "UpdateCallback.h"
#include "Common/StringConvert.h"
#include "Common/IntToString.h"
#include "Common/Defs.h"
#include "Windows/PropVariant.h"
#include "../../Common/FileStreams.h"
using namespace NWindows;
CArchiveUpdateCallback::CArchiveUpdateCallback():
Callback(0),
StdInMode(false),
DirItems(0),
ArchiveItems(0),
UpdatePairs(0)
{}
STDMETHODIMP CArchiveUpdateCallback::SetTotal(UInt64 size)
{
return Callback->SetTotal(size);
}
STDMETHODIMP CArchiveUpdateCallback::SetCompleted(const UInt64 *completeValue)
{
return Callback->SetCompleted(completeValue);
}
/*
STATPROPSTG kProperties[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsFolder, VT_BOOL},
{ NULL, kpidSize, VT_UI8},
{ NULL, kpidLastAccessTime, VT_FILETIME},
{ NULL, kpidCreationTime, VT_FILETIME},
{ NULL, kpidLastWriteTime, VT_FILETIME},
{ NULL, kpidAttributes, VT_UI4},
{ NULL, kpidIsAnti, VT_BOOL}
};
*/
STDMETHODIMP CArchiveUpdateCallback::EnumProperties(IEnumSTATPROPSTG **enumerator)
{
return E_NOTIMPL;
/*
return CStatPropEnumerator::CreateEnumerator(kProperties,
sizeof(kProperties) / sizeof(kProperties[0]), enumerator);
*/
}
STDMETHODIMP CArchiveUpdateCallback::GetUpdateItemInfo(UInt32 index,
Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive)
{
RINOK(Callback->CheckBreak());
const CUpdatePair2 &updatePair = (*UpdatePairs)[index];
if(newData != NULL)
*newData = BoolToInt(updatePair.NewData);
if(newProperties != NULL)
*newProperties = BoolToInt(updatePair.NewProperties);
if(indexInArchive != NULL)
{
if (updatePair.ExistInArchive)
{
if (ArchiveItems == 0)
*indexInArchive = updatePair.ArchiveItemIndex;
else
*indexInArchive = (*ArchiveItems)[updatePair.ArchiveItemIndex].IndexInServer;
}
else
*indexInArchive = UInt32(-1);
}
return S_OK;
}
STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
const CUpdatePair2 &updatePair = (*UpdatePairs)[index];
NWindows::NCOM::CPropVariant propVariant;
if (propID == kpidIsAnti)
{
propVariant = updatePair.IsAnti;
propVariant.Detach(value);
return S_OK;
}
if (updatePair.IsAnti)
{
switch(propID)
{
case kpidIsFolder:
case kpidPath:
break;
case kpidSize:
propVariant = (UInt64)0;
propVariant.Detach(value);
return S_OK;
default:
propVariant.Detach(value);
return S_OK;
}
}
if(updatePair.ExistOnDisk)
{
const CDirItem &dirItem = (*DirItems)[updatePair.DirItemIndex];
switch(propID)
{
case kpidPath:
propVariant = dirItem.Name;
break;
case kpidIsFolder:
propVariant = dirItem.IsDirectory();
break;
case kpidSize:
propVariant = dirItem.Size;
break;
case kpidAttributes:
propVariant = dirItem.Attributes;
break;
case kpidLastAccessTime:
propVariant = dirItem.LastAccessTime;
break;
case kpidCreationTime:
propVariant = dirItem.CreationTime;
break;
case kpidLastWriteTime:
propVariant = dirItem.LastWriteTime;
break;
}
}
else
{
if (propID == kpidPath)
{
if (updatePair.NewNameIsDefined)
{
propVariant = updatePair.NewName;
propVariant.Detach(value);
return S_OK;
}
}
if (updatePair.ExistInArchive && Archive)
{
UInt32 indexInArchive;
if (ArchiveItems == 0)
indexInArchive = updatePair.ArchiveItemIndex;
else
indexInArchive = (*ArchiveItems)[updatePair.ArchiveItemIndex].IndexInServer;
return Archive->GetProperty(indexInArchive, propID, value);
}
}
propVariant.Detach(value);
return S_OK;
}
STDMETHODIMP CArchiveUpdateCallback::GetStream(UInt32 index,
ISequentialInStream **inStream)
{
const CUpdatePair2 &updatePair = (*UpdatePairs)[index];
if(!updatePair.NewData)
return E_FAIL;
RINOK(Callback->CheckBreak());
RINOK(Callback->Finilize());
if(updatePair.IsAnti)
{
return Callback->GetStream((*ArchiveItems)[updatePair.ArchiveItemIndex].Name, true);
}
const CDirItem &dirItem = (*DirItems)[updatePair.DirItemIndex];
RINOK(Callback->GetStream(dirItem.Name, false));
if(dirItem.IsDirectory())
return S_OK;
if (StdInMode)
{
CStdInFileStream *inStreamSpec = new CStdInFileStream;
CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
*inStream = inStreamLoc.Detach();
}
else
{
CInFileStream *inStreamSpec = new CInFileStream;
CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
UString path = DirPrefix + dirItem.FullPath;
if(!inStreamSpec->Open(path))
{
return Callback->OpenFileError(path, ::GetLastError());
}
*inStream = inStreamLoc.Detach();
}
return S_OK;
}
STDMETHODIMP CArchiveUpdateCallback::SetOperationResult(Int32 operationResult)
{
return Callback->SetOperationResult(operationResult);
}
STDMETHODIMP CArchiveUpdateCallback::GetVolumeSize(UInt32 index, UInt64 *size)
{
if (VolumesSizes.Size() == 0)
return S_FALSE;
if (index >= (UInt32)VolumesSizes.Size())
index = VolumesSizes.Size() - 1;
*size = VolumesSizes[index];
return S_OK;
}
STDMETHODIMP CArchiveUpdateCallback::GetVolumeStream(UInt32 index, ISequentialOutStream **volumeStream)
{
wchar_t temp[32];
ConvertUInt64ToString(index + 1, temp);
UString res = temp;
while (res.Length() < 2)
res = UString(L'0') + res;
UString fileName = VolName;
fileName += L'.';
fileName += res;
fileName += VolExt;
COutFileStream *streamSpec = new COutFileStream;
CMyComPtr<ISequentialOutStream> streamLoc(streamSpec);
if(!streamSpec->Create(fileName, false))
return ::GetLastError();
*volumeStream = streamLoc.Detach();
return S_OK;
}
STDMETHODIMP CArchiveUpdateCallback::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
{
return Callback->CryptoGetTextPassword2(passwordIsDefined, password);
}

70
7zip/UI/Common/UpdateCallback.h Executable file
View File

@@ -0,0 +1,70 @@
// UpdateCallback.h
#ifndef __UPDATECALLBACK_H
#define __UPDATECALLBACK_H
#include "Common/MyCom.h"
#include "Common/String.h"
#include "../../IPassword.h"
#include "../Common/UpdatePair.h"
#include "../Common/UpdateProduce.h"
struct IUpdateCallbackUI
{
virtual HRESULT SetTotal(UInt64 size) = 0;
virtual HRESULT SetCompleted(const UInt64 *completeValue) = 0;
virtual HRESULT CheckBreak() = 0;
virtual HRESULT Finilize() = 0;
virtual HRESULT GetStream(const wchar_t *name, bool isAnti) = 0;
virtual HRESULT OpenFileError(const wchar_t *name, DWORD systemError) = 0;
virtual HRESULT SetOperationResult(Int32 operationResult) = 0;
virtual HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) = 0;
virtual HRESULT CloseProgress() { return S_OK; };
};
class CArchiveUpdateCallback:
public IArchiveUpdateCallback2,
public ICryptoGetTextPassword2,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP2(IArchiveUpdateCallback2,
ICryptoGetTextPassword2)
// IProgress
STDMETHOD(SetTotal)(UInt64 size);
STDMETHOD(SetCompleted)(const UInt64 *completeValue);
// IUpdateCallback
STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator);
STDMETHOD(GetUpdateItemInfo)(UInt32 index,
Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive);
STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream);
STDMETHOD(SetOperationResult)(Int32 operationResult);
STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size);
STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream);
STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password);
public:
CRecordVector<UInt64> VolumesSizes;
UString VolName;
UString VolExt;
IUpdateCallbackUI *Callback;
UString DirPrefix;
bool StdInMode;
const CObjectVector<CDirItem> *DirItems;
const CObjectVector<CArchiveItem> *ArchiveItems;
const CObjectVector<CUpdatePair2> *UpdatePairs;
CMyComPtr<IInArchive> Archive;
CArchiveUpdateCallback();
};
#endif

View File

@@ -11,7 +11,6 @@
#include "SortUtils.h"
using namespace NWindows;
// using namespace NCOM;
using namespace NTime;
static int MyCompareTime(NFileTimeType::EEnum fileTimeType,
@@ -23,7 +22,7 @@ static int MyCompareTime(NFileTimeType::EEnum fileTimeType,
return ::CompareFileTime(&time1, &time2);
case NFileTimeType::kUnix:
{
time_t unixTime1, unixTime2;
UInt32 unixTime1, unixTime2;
if (!FileTimeToUnixTime(time1, unixTime1))
throw 4191614;
if (!FileTimeToUnixTime(time2, unixTime2))
@@ -32,7 +31,7 @@ static int MyCompareTime(NFileTimeType::EEnum fileTimeType,
}
case NFileTimeType::kDOS:
{
UINT32 dosTime1, dosTime2;
UInt32 dosTime1, dosTime2;
if (!FileTimeToDosTime(time1, dosTime1))
throw 4191616;
if (!FileTimeToDosTime(time2, dosTime2))
@@ -51,23 +50,32 @@ static const char *kSameTimeChangedSizeCollisionMessaged =
"Collision between files with same date/time and different sizes:\n";
*/
static void TestDuplicateString(const UStringVector &strings,
const CIntVector &indices)
static inline int MyFileNameCompare(const UString &s1, const UString &s2)
{
return
#ifdef _WIN32
s1.CollateNoCase(s2);
#else
s1.Compare(s2);
#endif
}
static void TestDuplicateString(const UStringVector &strings, const CIntVector &indices)
{
for(int i = 0; i + 1 < indices.Size(); i++)
if (strings[indices[i]].CollateNoCase(strings[indices[i + 1]]) == 0)
if (MyFileNameCompare(strings[indices[i]], strings[indices[i + 1]]) == 0)
{
UString message = kDuplicateFileNameMessage;
message += L"\n";
message += strings[indices[i]];
message += L"\n";
message += strings[indices[i+1]];
message += strings[indices[i + 1]];
throw message;
}
}
void GetUpdatePairInfoList(
const CObjectVector<CDirItem> &dirItems,
const CObjectVector<CDirItem> &dirItems,
const CObjectVector<CArchiveItem> &archiveItems,
NFileTimeType::EEnum fileTimeType,
CObjectVector<CUpdatePair> &updatePairs)
@@ -96,7 +104,7 @@ void GetUpdatePairInfoList(
archiveItemIndex2 = archiveIndices[archiveItemIndex];
const CDirItem &dirItem = dirItems[dirItemIndex2];
const CArchiveItem &archiveItem = archiveItems[archiveItemIndex2];
int compareResult = dirItem.Name.CollateNoCase(archiveItem.Name);
int compareResult = MyFileNameCompare(dirItem.Name, archiveItem.Name);
if (compareResult < 0)
{
pair.State = NUpdateArchive::NPairState::kOnlyOnDisk;

View File

@@ -1,9 +1,7 @@
// UpdatePair.h
#pragma once
#ifndef __UPDATEPAIR_H
#define __UPDATEPAIR_H
#ifndef __UPDATE_PAIR_H
#define __UPDATE_PAIR_H
#include "DirItem.h"
#include "UpdateAction.h"

View File

@@ -1,9 +1,7 @@
// UpdateProduce.h
#pragma once
#ifndef __UPDATEPRODUCE_H
#define __UPDATEPRODUCE_H
#ifndef __UPDATE_PRODUCE_H
#define __UPDATE_PRODUCE_H
#include "UpdatePair.h"

View File

@@ -5,6 +5,7 @@
#include "WorkDir.h"
#include "Common/StringConvert.h"
#include "Common/Wildcard.h"
#include "Windows/FileName.h"
#include "Windows/FileDir.h"
@@ -16,23 +17,13 @@ using namespace NWindows;
using namespace NFile;
using namespace NName;
static UString GetContainingDir(const UString &path)
{
UString resultPath;
int pos;
if(!NFile::NDirectory::MyGetFullPathName(path, resultPath, pos))
throw 141716;
return resultPath.Left(pos);
}
UString GetWorkDir(const NWorkDir::CInfo &workDirInfo,
const UString &archiveName)
UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path)
{
NWorkDir::NMode::EEnum mode = workDirInfo.Mode;
if (workDirInfo.ForRemovableOnly)
{
mode = NWorkDir::NMode::kCurrent;
UString prefix = archiveName.Left(3);
UString prefix = path.Left(3);
if (prefix[1] == L':' && prefix[2] == L'\\')
{
UINT driveType = GetDriveType(GetSystemString(prefix, GetCurrentCodePage()));
@@ -51,7 +42,7 @@ UString GetWorkDir(const NWorkDir::CInfo &workDirInfo,
{
case NWorkDir::NMode::kCurrent:
{
return GetContainingDir(archiveName);
return ExtractDirPrefixFromPath(path);
}
case NWorkDir::NMode::kSpecified:
{
@@ -59,7 +50,7 @@ UString GetWorkDir(const NWorkDir::CInfo &workDirInfo,
NormalizeDirPathPrefix(tempDir);
return tempDir;
}
default: // NZipSettings::NWorkDir::NMode::kSystem:
default:
{
UString tempDir;
if(!NFile::NDirectory::MyGetTempPath(tempDir))

View File

@@ -1,14 +1,10 @@
// WorkDir.h
#pragma once
#ifndef __WORKDIR_H
#define __WORKDIR_H
#include "../Common/ZipRegistry.h"
#include "ZipRegistry.h"
UString GetWorkDir(const NWorkDir::CInfo &workDirInfo,
const UString &archiveName);
UString GetWorkDir(const NWorkDir::CInfo &workDirInfo, const UString &path);
#endif

View File

@@ -36,7 +36,7 @@ static CSysString GetKeyPath(const CSysString &path)
return CSysString(kCUBasePath) + CSysString('\\') + CSysString(path);
}
void SaveExtractionInfo(const NExtraction::CInfo &info)
void SaveExtractionInfo(const NExtract::CInfo &info)
{
NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
CKey extractionKey;
@@ -48,20 +48,20 @@ void SaveExtractionInfo(const NExtraction::CInfo &info)
for(int i = 0; i < info.Paths.Size(); i++)
{
TCHAR numberString[16];
ConvertUINT64ToString(i, numberString);
ConvertUInt64ToString(i, numberString);
pathHistoryKey.SetValue(numberString, info.Paths[i]);
}
}
extractionKey.SetValue(kExtractionExtractModeValueName, UINT32(info.PathMode));
extractionKey.SetValue(kExtractionOverwriteModeValueName, UINT32(info.OverwriteMode));
extractionKey.SetValue(kExtractionExtractModeValueName, UInt32(info.PathMode));
extractionKey.SetValue(kExtractionOverwriteModeValueName, UInt32(info.OverwriteMode));
extractionKey.SetValue(kExtractionShowPasswordValueName, info.ShowPassword);
}
void ReadExtractionInfo(NExtraction::CInfo &info)
void ReadExtractionInfo(NExtract::CInfo &info)
{
info.Paths.Clear();
info.PathMode = NExtraction::NPathMode::kFullPathnames;
info.OverwriteMode = NExtraction::NOverwriteMode::kAskBefore;
info.PathMode = NExtract::NPathMode::kCurrentPathnames;
info.OverwriteMode = NExtract::NOverwriteMode::kAskBefore;
info.ShowPassword = false;
NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
@@ -77,7 +77,7 @@ void ReadExtractionInfo(NExtraction::CInfo &info)
while(true)
{
TCHAR numberString[16];
ConvertUINT64ToString(info.Paths.Size(), numberString);
ConvertUInt64ToString(info.Paths.Size(), numberString);
CSysString path;
if (pathHistoryKey.QueryValue(numberString, path) != ERROR_SUCCESS)
break;
@@ -85,29 +85,29 @@ void ReadExtractionInfo(NExtraction::CInfo &info)
}
}
}
UINT32 extractModeIndex;
UInt32 extractModeIndex;
if (extractionKey.QueryValue(kExtractionExtractModeValueName, extractModeIndex) == ERROR_SUCCESS)
{
switch (extractModeIndex)
{
case NExtraction::NPathMode::kFullPathnames:
case NExtraction::NPathMode::kCurrentPathnames:
case NExtraction::NPathMode::kNoPathnames:
info.PathMode = NExtraction::NPathMode::EEnum(extractModeIndex);
case NExtract::NPathMode::kFullPathnames:
case NExtract::NPathMode::kCurrentPathnames:
case NExtract::NPathMode::kNoPathnames:
info.PathMode = NExtract::NPathMode::EEnum(extractModeIndex);
break;
}
}
UINT32 overwriteModeIndex;
UInt32 overwriteModeIndex;
if (extractionKey.QueryValue(kExtractionOverwriteModeValueName, overwriteModeIndex) == ERROR_SUCCESS)
{
switch (overwriteModeIndex)
{
case NExtraction::NOverwriteMode::kAskBefore:
case NExtraction::NOverwriteMode::kWithoutPrompt:
case NExtraction::NOverwriteMode::kSkipExisting:
case NExtraction::NOverwriteMode::kAutoRename:
case NExtraction::NOverwriteMode::kAutoRenameExisting:
info.OverwriteMode = NExtraction::NOverwriteMode::EEnum(overwriteModeIndex);
case NExtract::NOverwriteMode::kAskBefore:
case NExtract::NOverwriteMode::kWithoutPrompt:
case NExtract::NOverwriteMode::kSkipExisting:
case NExtract::NOverwriteMode::kAutoRename:
case NExtract::NOverwriteMode::kAutoRenameExisting:
info.OverwriteMode = NExtract::NOverwriteMode::EEnum(overwriteModeIndex);
break;
}
}
@@ -151,7 +151,7 @@ void SaveCompressionInfo(const NCompression::CInfo &info)
for(int i = 0; i < info.HistoryArchives.Size(); i++)
{
TCHAR numberString[16];
ConvertUINT64ToString(i, numberString);
ConvertUInt64ToString(i, numberString);
historyArchivesKey.SetValue(numberString, info.HistoryArchives[i]);
}
}
@@ -171,7 +171,7 @@ void SaveCompressionInfo(const NCompression::CInfo &info)
formatKey.DeleteValue(kCompressionOptions);
else
formatKey.SetValue(kCompressionOptions, fo.Options);
if (fo.Level == UINT32(-1))
if (fo.Level == UInt32(-1))
formatKey.DeleteValue(kCompressionLevel);
else
formatKey.SetValue(kCompressionLevel, fo.Level);
@@ -179,18 +179,18 @@ void SaveCompressionInfo(const NCompression::CInfo &info)
formatKey.DeleteValue(kCompressionMethod);
else
formatKey.SetValue(kCompressionMethod, fo.Method);
if (fo.Dictionary == UINT32(-1))
if (fo.Dictionary == UInt32(-1))
formatKey.DeleteValue(kCompressionDictionary);
else
formatKey.SetValue(kCompressionDictionary, fo.Dictionary);
if (fo.Order == UINT32(-1))
if (fo.Order == UInt32(-1))
formatKey.DeleteValue(kCompressionOrder);
else
formatKey.SetValue(kCompressionOrder, fo.Order);
}
}
compressionKey.SetValue(kCompressionLevelValueName, UINT32(info.Level));
compressionKey.SetValue(kCompressionLevelValueName, UInt32(info.Level));
compressionKey.SetValue(kCompressionLastFormatValueName,
GetSystemString(info.ArchiveType));
@@ -235,7 +235,7 @@ void ReadCompressionInfo(NCompression::CInfo &info)
while(true)
{
TCHAR numberString[16];
ConvertUINT64ToString(info.HistoryArchives.Size(), numberString);
ConvertUInt64ToString(info.HistoryArchives.Size(), numberString);
CSysString path;
if (historyArchivesKey.QueryValue(numberString, path) != ERROR_SUCCESS)
break;
@@ -269,13 +269,13 @@ void ReadCompressionInfo(NCompression::CInfo &info)
if (formatKey.QueryValue(kCompressionOptions, fo.Options) != ERROR_SUCCESS)
fo.Options.Empty();
if (formatKey.QueryValue(kCompressionLevel, fo.Level) != ERROR_SUCCESS)
fo.Level = UINT32(-1);
fo.Level = UInt32(-1);
if (formatKey.QueryValue(kCompressionMethod, fo.Method) != ERROR_SUCCESS)
fo.Method.Empty();;
if (formatKey.QueryValue(kCompressionDictionary, fo.Dictionary) != ERROR_SUCCESS)
fo.Dictionary = UINT32(-1);
fo.Dictionary = UInt32(-1);
if (formatKey.QueryValue(kCompressionOrder, fo.Order) != ERROR_SUCCESS)
fo.Order = UINT32(-1);
fo.Order = UInt32(-1);
info.FormatOptionsVector.Add(fo);
}
@@ -283,7 +283,7 @@ void ReadCompressionInfo(NCompression::CInfo &info)
}
}
UINT32 level;
UInt32 level;
if (compressionKey.QueryValue(kCompressionLevelValueName, level) == ERROR_SUCCESS)
info.Level = level;
CSysString archiveType;
@@ -318,7 +318,7 @@ void SaveWorkDirInfo(const NWorkDir::CInfo &info)
NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
CKey optionsKey;
optionsKey.Create(HKEY_CURRENT_USER, GetKeyPath(kOptionsInfoKeyName));
optionsKey.SetValue(kWorkDirTypeValueName, UINT32(info.Mode));
optionsKey.SetValue(kWorkDirTypeValueName, UInt32(info.Mode));
optionsKey.SetValue(kWorkDirPathValueName, GetSystemString(info.Path));
optionsKey.SetValue(kTempRemovableOnlyValueName, info.ForRemovableOnly);
}
@@ -332,7 +332,7 @@ void ReadWorkDirInfo(NWorkDir::CInfo &info)
if(optionsKey.Open(HKEY_CURRENT_USER, GetKeyPath(kOptionsInfoKeyName), KEY_READ) != ERROR_SUCCESS)
return;
UINT32 dirType;
UInt32 dirType;
if (optionsKey.QueryValue(kWorkDirTypeValueName, dirType) != ERROR_SUCCESS)
return;
switch (dirType)
@@ -380,7 +380,7 @@ bool ReadCascadedMenu()
{ return ReadOption(kCascadedMenuValueName, false); }
static void SaveValue(const TCHAR *value, UINT32 valueToWrite)
static void SaveValue(const TCHAR *value, UInt32 valueToWrite)
{
NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
CKey optionsKey;
@@ -388,7 +388,7 @@ static void SaveValue(const TCHAR *value, UINT32 valueToWrite)
optionsKey.SetValue(value, valueToWrite);
}
static bool ReadValue(const TCHAR *value, UINT32 &result)
static bool ReadValue(const TCHAR *value, UInt32 &result)
{
NSynchronization::CCriticalSectionLock lock(g_RegistryOperationsCriticalSection);
CKey optionsKey;
@@ -397,8 +397,8 @@ static bool ReadValue(const TCHAR *value, UINT32 &result)
return (optionsKey.QueryValue(value, result) == ERROR_SUCCESS);
}
void SaveContextMenuStatus(UINT32 value)
void SaveContextMenuStatus(UInt32 value)
{ SaveValue(kContextMenuValueName, value); }
bool ReadContextMenuStatus(UINT32 &value)
bool ReadContextMenuStatus(UInt32 &value)
{ return ReadValue(kContextMenuValueName, value); }

View File

@@ -1,36 +1,14 @@
// ZipRegistry.h
#pragma once
#ifndef __ZIPREGISTRY_H
#define __ZIPREGISTRY_H
#include "Common/String.h"
#include "Common/Types.h"
#include "ExtractMode.h"
namespace NExtraction {
namespace NPathMode
{
enum EEnum
{
kFullPathnames,
kCurrentPathnames,
kNoPathnames
};
}
namespace NOverwriteMode
{
enum EEnum
{
kAskBefore,
kWithoutPrompt,
kSkipExisting,
kAutoRename,
kAutoRenameExisting
};
}
namespace NExtract
{
struct CInfo
{
NPathMode::EEnum PathMode;
@@ -46,13 +24,13 @@ namespace NCompression {
{
CSysString FormatID;
CSysString Options;
UINT32 Level;
UInt32 Level;
CSysString Method;
UINT32 Dictionary;
UINT32 Order;
UInt32 Dictionary;
UInt32 Order;
void Init()
{
Level = Dictionary = Order = UINT32(-1);
Level = Dictionary = Order = UInt32(-1);
Method.Empty();
// Options.Empty();
}
@@ -63,7 +41,7 @@ namespace NCompression {
{
CSysStringVector HistoryArchives;
// bool LevelIsDefined;
UINT32 Level;
UInt32 Level;
UString ArchiveType;
bool Solid;
@@ -101,8 +79,8 @@ namespace NWorkDir{
};
}
void SaveExtractionInfo(const NExtraction::CInfo &info);
void ReadExtractionInfo(NExtraction::CInfo &info);
void SaveExtractionInfo(const NExtract::CInfo &info);
void ReadExtractionInfo(NExtract::CInfo &info);
void SaveCompressionInfo(const NCompression::CInfo &info);
void ReadCompressionInfo(NCompression::CInfo &info);
@@ -113,7 +91,7 @@ void ReadWorkDirInfo(NWorkDir::CInfo &info);
void SaveCascadedMenu(bool enabled);
bool ReadCascadedMenu();
void SaveContextMenuStatus(UINT32 value);
bool ReadContextMenuStatus(UINT32 &value);
void SaveContextMenuStatus(UInt32 value);
bool ReadContextMenuStatus(UInt32 &value);
#endif

View File

@@ -1,64 +0,0 @@
// ArError.h
#pragma once
#ifndef __ARERROR_H
#define __ARERROR_H
namespace NExitCode {
struct CSystemError
{
UINT32 ErrorValue;
CSystemError(UINT32 anErrorValue): ErrorValue(anErrorValue) {}
};
struct CMultipleErrors
{
UINT64 NumErrors;
CMultipleErrors(UINT64 aNumErrors): NumErrors(aNumErrors) {}
};
enum EEnum {
kSuccess = 0, // Successful operation (User exit)
kWarning = 1, // Non fatal error(s) occurred
kFatalError = 2, // A fatal error occurred
kCRCError = 3, // A CRC error occurred when unpacking
kLockedArchive = 4, // Attempt to modify an archive previously locked
kWriteError = 5, // Write to disk error
kOpenError = 6, // Open file error
kUserError = 7, // Command line option error
kMemoryError = 8, // Not enough memory for operation
kNotSupported = 102, // format of file doesn't supported
kFileError = 103, //
kVerError = 110, // Version doesn't supported
kMethodError = 111, // Unsupported method
kUserQuit = 120, // Unsupported method
kFileIsNotArchive = 130, // File Is Not Archive
kCommonError = 150,
kInputArchiveException = 160, // archive file does not exist
kErrorsDuringDecompression = 170, // Errors during decompression
kDirFileWith64BitSize = 171,
kFileTimeWinToDosConvertError = 172,
kFileChangedDuringOperation = 180,
kUserBreak = 255 // User stopped the process
};
}
#endif

View File

@@ -1,28 +0,0 @@
// CompressionMethodUtils.h
#pragma once
#ifndef __COMPRESSIONMETHODUTILS_H
#define __COMPRESSIONMETHODUTILS_H
struct CProperty
{
UString Name;
UString Value;
};
struct CCompressionMethodMode
{
#ifndef EXCLUDE_COM
UString FilePath;
CLSID ClassID1;
#else
UString Name;
#endif
CObjectVector<CProperty> Properties;
bool PasswordIsDefined;
bool AskPassword;
UString Password;
};
#endif

View File

@@ -158,14 +158,6 @@ SOURCE=.\StdAfx.h
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\ArError.h
# End Source File
# Begin Source File
SOURCE=.\CompressionMode.h
# End Source File
# Begin Source File
SOURCE=.\ConsoleClose.cpp
# End Source File
# Begin Source File
@@ -174,19 +166,11 @@ SOURCE=.\ConsoleClose.h
# End Source File
# Begin Source File
SOURCE=.\Extract.cpp
SOURCE=.\ExtractCallbackConsole.cpp
# End Source File
# Begin Source File
SOURCE=.\Extract.h
# End Source File
# Begin Source File
SOURCE=.\ExtractCallback.cpp
# End Source File
# Begin Source File
SOURCE=.\ExtractCallback.h
SOURCE=.\ExtractCallbackConsole.h
# End Source File
# Begin Source File
@@ -206,11 +190,11 @@ SOURCE=.\MainAr.cpp
# End Source File
# Begin Source File
SOURCE=.\OpenCallback.cpp
SOURCE=.\OpenCallbackConsole.cpp
# End Source File
# Begin Source File
SOURCE=.\OpenCallback.h
SOURCE=.\OpenCallbackConsole.h
# End Source File
# Begin Source File
@@ -222,27 +206,11 @@ SOURCE=.\PercentPrinter.h
# End Source File
# Begin Source File
SOURCE=.\TempFiles.cpp
SOURCE=.\UpdateCallbackConsole.cpp
# End Source File
# Begin Source File
SOURCE=.\TempFiles.h
# End Source File
# Begin Source File
SOURCE=.\Update.cpp
# End Source File
# Begin Source File
SOURCE=.\Update.h
# End Source File
# Begin Source File
SOURCE=.\UpdateCallback.cpp
# End Source File
# Begin Source File
SOURCE=.\UpdateCallback.h
SOURCE=.\UpdateCallbackConsole.h
# End Source File
# Begin Source File
@@ -328,20 +296,24 @@ SOURCE=..\..\..\Windows\Registry.cpp
SOURCE=..\..\..\Windows\Registry.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\System.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\System.h
# End Source File
# End Group
# Begin Group "Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\Common\Alloc.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Alloc.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Buffer.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\CommandLineParser.cpp
# End Source File
# Begin Source File
@@ -422,6 +394,14 @@ SOURCE=..\..\..\Common\StringConvert.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\StringToInt.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\StringToInt.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\UTFConvert.cpp
# End Source File
# Begin Source File
@@ -450,6 +430,30 @@ SOURCE=..\..\..\Common\Wildcard.h
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\Common\ArchiveCommandLine.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\ArchiveCommandLine.h
# End Source File
# Begin Source File
SOURCE=..\Common\ArchiveExtractCallback.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\ArchiveExtractCallback.h
# End Source File
# Begin Source File
SOURCE=..\Common\ArchiveOpenCallback.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\ArchiveOpenCallback.h
# End Source File
# Begin Source File
SOURCE=..\Common\ArchiverInfo.cpp
# End Source File
# Begin Source File
@@ -458,6 +462,10 @@ SOURCE=..\Common\ArchiverInfo.h
# End Source File
# Begin Source File
SOURCE=..\Common\CompressionMode.h
# End Source File
# Begin Source File
SOURCE=..\Common\DefaultName.cpp
# End Source File
# Begin Source File
@@ -478,6 +486,18 @@ SOURCE=..\Common\EnumDirItems.h
# End Source File
# Begin Source File
SOURCE=..\Common\ExitCode.h
# End Source File
# Begin Source File
SOURCE=..\Common\Extract.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\Extract.h
# End Source File
# Begin Source File
SOURCE=..\Common\ExtractingFilePath.cpp
# End Source File
# Begin Source File
@@ -490,6 +510,10 @@ SOURCE=..\Common\HandlerLoader.h
# End Source File
# Begin Source File
SOURCE=..\Common\IFileExtractCallback.h
# End Source File
# Begin Source File
SOURCE=..\Common\OpenArchive.cpp
# End Source File
# Begin Source File
@@ -514,6 +538,22 @@ SOURCE=..\Common\SortUtils.h
# End Source File
# Begin Source File
SOURCE=..\Common\TempFiles.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\TempFiles.h
# End Source File
# Begin Source File
SOURCE=..\Common\Update.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\Update.h
# End Source File
# Begin Source File
SOURCE=..\Common\UpdateAction.cpp
# End Source File
# Begin Source File
@@ -522,6 +562,14 @@ SOURCE=..\Common\UpdateAction.h
# End Source File
# Begin Source File
SOURCE=..\Common\UpdateCallback.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\UpdateCallback.h
# End Source File
# Begin Source File
SOURCE=..\Common\UpdatePair.cpp
# End Source File
# Begin Source File
@@ -544,6 +592,10 @@ SOURCE=..\Common\WorkDir.cpp
SOURCE=..\Common\WorkDir.h
# End Source File
# Begin Source File
SOURCE=..\Common\ZipRegistry.h
# End Source File
# End Group
# Begin Group "7-zip Common"

View File

@@ -1,7 +1,5 @@
// ConsoleCloseUtils.h
#pragma once
#ifndef __CONSOLECLOSEUTILS_H
#define __CONSOLECLOSEUTILS_H
@@ -24,4 +22,3 @@ void CheckCtrlBreak();
}
#endif

View File

@@ -1,94 +0,0 @@
// Extract.cpp
#include "StdAfx.h"
#include "Extract.h"
#include "ExtractCallback.h"
#include "ArError.h"
#include "Common/StdOutStream.h"
#include "Windows/Defs.h"
#include "Windows/PropVariant.h"
#include "Windows/FileDir.h"
using namespace NWindows;
static const char *kEverythingIsOk = "Everything is Ok";
HRESULT DeCompressArchiveSTD(
IInArchive *archive,
const NWildcard::CCensor &wildcardCensor,
const CExtractOptions &options)
{
CRecordVector<UINT32> realIndices;
UINT32 numItems;
RINOK(archive->GetNumberOfItems(&numItems));
for(UINT32 i = 0; i < numItems; i++)
{
NCOM::CPropVariant propVariant;
RINOK(archive->GetProperty(i, kpidPath, &propVariant));
UString filePath;
if(propVariant.vt == VT_EMPTY)
filePath = options.DefaultItemName;
else
{
if(propVariant.vt != VT_BSTR)
return E_FAIL;
filePath = propVariant.bstrVal;
}
if (!wildcardCensor.CheckName(filePath))
continue;
realIndices.Add(i);
}
if (realIndices.Size() == 0)
{
g_StdOut << endl << "No files to process" << endl;
return S_OK;
}
CExtractCallbackImp *extractCallbackSpec = new CExtractCallbackImp;
CMyComPtr<IArchiveExtractCallback> extractCallback(extractCallbackSpec);
UStringVector removePathParts;
NExtraction::CInfo extractionInfo;
extractionInfo.PathMode = options.FullPathMode() ? NExtraction::NPathMode::kFullPathnames:
NExtraction::NPathMode::kNoPathnames;
if (options.YesToAll)
extractionInfo.OverwriteMode = NExtraction::NOverwriteMode::kWithoutPrompt;
else
{
extractionInfo.OverwriteMode = options.OverwriteMode;
}
if(!options.OutputBaseDir.IsEmpty())
if(!NFile::NDirectory::CreateComplexDirectory(options.OutputBaseDir))
{
throw "Can not create output directory";
}
extractCallbackSpec->Init(archive,
options.OutputBaseDir,
extractionInfo, removePathParts,
options.DefaultItemName,
options.ArchiveFileInfo.LastWriteTime,
options.ArchiveFileInfo.Attributes,
options.PasswordEnabled,
options.Password);
HRESULT result = archive->Extract(&realIndices.Front(),
realIndices.Size(), options.ExtractMode == NExtractMode::kTest,
extractCallback);
if (extractCallbackSpec->m_NumErrors != 0)
throw NExitCode::CMultipleErrors(extractCallbackSpec->m_NumErrors);
if (result != S_OK)
throw NExitCode::CSystemError(result);
g_StdOut << endl << kEverythingIsOk << endl;
return S_OK;
}

View File

@@ -1,65 +0,0 @@
// Extract.h
#pragma once
#ifndef __EXTRACT_H
#define __EXTRACT_H
#include "Common/Wildcard.h"
#include "Windows/FileFind.h"
#include "../../Archive/IArchive.h"
#include "../Common/ZipRegistry.h"
namespace NExtractMode {
enum EEnum
{
kTest,
kFullPath,
kExtractToOne
};
}
class CExtractOptions
{
public:
NExtractMode::EEnum ExtractMode;
UString OutputBaseDir;
bool YesToAll;
UString DefaultItemName;
NWindows::NFile::NFind::CFileInfoW ArchiveFileInfo;
bool PasswordEnabled;
UString Password;
NExtraction::NOverwriteMode::EEnum OverwriteMode;
CExtractOptions(NExtractMode::EEnum extractMode, const UString &outputBaseDir,
bool yesToAll, bool passwordEnabled, const UString &password,
NExtraction::NOverwriteMode::EEnum overwriteMode):
ExtractMode(extractMode),
OutputBaseDir(outputBaseDir),
YesToAll(yesToAll),
PasswordEnabled(passwordEnabled),
Password(password),
OverwriteMode(overwriteMode)
{}
bool TestMode() const { return (ExtractMode == NExtractMode::kTest); }
bool FullPathMode() const { return (ExtractMode == NExtractMode::kTest) ||
(ExtractMode == NExtractMode::kFullPath); }
};
HRESULT DeCompressArchiveSTD(IInArchive *archive,
const NWildcard::CCensor &wildcardCensor,
const CExtractOptions &options);
/*
bool DeCompressArchiveSTD(TTWildCardInputArchive &anArchive,
const TTExtractOptions &anOptions);
*/
#endif

View File

@@ -1,405 +0,0 @@
// ExtractCallback.h
#include "StdAfx.h"
#include "ExtractCallback.h"
#include "UserInputUtils.h"
#include "ConsoleClose.h"
#include "Common/StdOutStream.h"
#include "Common/StdInStream.h"
#include "Common/Wildcard.h"
#include "Common/StringConvert.h"
#include "Windows/COM.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"
using namespace NWindows;
using namespace NFile;
using namespace NDirectory;
static const char *kTestingString = "Testing ";
static const char *kExtractingString = "Extracting ";
static const char *kSkippingString = "Skipping ";
static const char *kCantAutoRename = "can not create file with auto name\n";
static const char *kCantRenameFile = "can not rename existing file\n";
static const char *kCantDeleteOutputFile = "can not delete output file ";
void CExtractCallbackImp::Init(IInArchive *archive,
const UString &directoryPath,
const NExtraction::CInfo &extractModeInfo,
const UStringVector &removePathParts,
const UString &itemDefaultName,
const FILETIME &utcLastWriteTimeDefault,
UINT32 attributesDefault,
bool passwordIsDefined,
const UString &password)
{
m_PasswordIsDefined = passwordIsDefined;
m_Password = password;
m_NumErrors = 0;
m_ItemDefaultName = itemDefaultName;
m_UTCLastWriteTimeDefault = utcLastWriteTimeDefault;
m_AttributesDefault = attributesDefault;
m_RemovePathParts = removePathParts;
m_ExtractModeInfo = extractModeInfo;
m_ArchiveHandler = archive;
m_DirectoryPath = directoryPath;
NFile::NName::NormalizeDirPathPrefix(m_DirectoryPath);
}
bool CExtractCallbackImp::IsEncrypted(UINT32 index)
{
NCOM::CPropVariant propVariant;
if(m_ArchiveHandler->GetProperty(index, kpidEncrypted, &propVariant) != S_OK)
return false;
if (propVariant.vt != VT_BOOL)
return false;
return VARIANT_BOOLToBool(propVariant.boolVal);
}
STDMETHODIMP CExtractCallbackImp::SetTotal(UINT64 size)
{
return S_OK;
}
STDMETHODIMP CExtractCallbackImp::SetCompleted(const UINT64 *completeValue)
{
if (NConsoleClose::TestBreakSignal())
return E_ABORT;
return S_OK;
}
void CExtractCallbackImp::CreateComplexDirectory(const UStringVector &dirPathParts)
{
UString fullPath = m_DirectoryPath;
for(int i = 0; i < dirPathParts.Size(); i++)
{
fullPath += dirPathParts[i];
MyCreateDirectory(fullPath);
fullPath += (wchar_t)NFile::NName::kDirDelimiter;
}
}
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;
}
STDMETHODIMP CExtractCallbackImp::GetStream(UINT32 index,
ISequentialOutStream **outStream, INT32 askExtractMode)
{
*outStream = NULL;
if (NConsoleClose::TestBreakSignal())
return E_ABORT;
m_OutFileStream.Release();
NCOM::CPropVariant propVariantName;
RINOK(m_ArchiveHandler->GetProperty(index, kpidPath, &propVariantName));
UString fullPath;
if(propVariantName.vt == VT_EMPTY)
fullPath = m_ItemDefaultName;
else
{
if(propVariantName.vt != VT_BSTR)
return E_FAIL;
fullPath = propVariantName.bstrVal;
}
m_FilePath = fullPath;
UString fullPathCorrect = GetCorrectPath(fullPath);
if(askExtractMode == NArchive::NExtract::NAskMode::kExtract)
{
NCOM::CPropVariant propVariant;
RINOK(m_ArchiveHandler->GetProperty(index, kpidAttributes, &propVariant));
if (propVariant.vt == VT_EMPTY)
{
m_ProcessedFileInfo.Attributes = m_AttributesDefault;
m_ProcessedFileInfo.AttributesAreDefined = false;
}
else
{
if (propVariant.vt != VT_UI4)
throw "incorrect item";
m_ProcessedFileInfo.Attributes = propVariant.ulVal;
m_ProcessedFileInfo.AttributesAreDefined = true;
}
RINOK(m_ArchiveHandler->GetProperty(index, kpidIsFolder, &propVariant));
m_ProcessedFileInfo.IsDirectory = VARIANT_BOOLToBool(propVariant.boolVal);
bool isAnti = false;
{
NCOM::CPropVariant propVariantTemp;
RINOK(m_ArchiveHandler->GetProperty(index, kpidIsAnti,
&propVariantTemp));
if (propVariantTemp.vt == VT_BOOL)
isAnti = VARIANT_BOOLToBool(propVariantTemp.boolVal);
}
RINOK(m_ArchiveHandler->GetProperty(index, kpidLastWriteTime, &propVariant));
switch(propVariant.vt)
{
case VT_EMPTY:
m_ProcessedFileInfo.UTCLastWriteTime = m_UTCLastWriteTimeDefault;
break;
case VT_FILETIME:
m_ProcessedFileInfo.UTCLastWriteTime = propVariant.filetime;
break;
default:
return E_FAIL;
}
// GetPropertyValue(anItemIDList, kpidSize, &propVariant);
// UINT64 newFileSize = ConvertPropVariantToUINT64(propVariant);
UStringVector pathParts;
SplitPathToParts(fullPathCorrect, pathParts);
if(pathParts.IsEmpty())
return E_FAIL;
UString processedPath;
switch(m_ExtractModeInfo.PathMode)
{
case NExtraction::NPathMode::kFullPathnames:
{
processedPath = fullPathCorrect;
break;
}
case NExtraction::NPathMode::kCurrentPathnames:
{
int numRemovePathParts = m_RemovePathParts.Size();
if(pathParts.Size() <= numRemovePathParts)
return E_FAIL;
for(int i = 0; i < numRemovePathParts; i++)
if(m_RemovePathParts[i].CollateNoCase(pathParts[i]) != 0)
return E_FAIL;
pathParts.Delete(0, numRemovePathParts);
processedPath = MakePathNameFromParts(pathParts);
break;
}
case NExtraction::NPathMode::kNoPathnames:
{
processedPath = pathParts.Back();
pathParts.Delete(0, pathParts.Size() - 1); // Test it!!
break;
}
}
if(!m_ProcessedFileInfo.IsDirectory)
pathParts.DeleteBack();
if (!pathParts.IsEmpty())
{
if (!isAnti)
CreateComplexDirectory(pathParts);
}
UString fullProcessedPath = m_DirectoryPath + GetCorrectPath(processedPath);
if(m_ProcessedFileInfo.IsDirectory)
{
m_DiskFilePath = fullProcessedPath;
if (isAnti)
MyRemoveDirectory(m_DiskFilePath);
return S_OK;
}
NFile::NFind::CFileInfoW fileInfo;
if(NFile::NFind::FindFile(fullProcessedPath, fileInfo))
{
switch(m_ExtractModeInfo.OverwriteMode)
{
case NExtraction::NOverwriteMode::kSkipExisting:
return S_OK;
case NExtraction::NOverwriteMode::kAskBefore:
{
/*
NOverwriteDialog::CFileInfo oldFileInfo, newFileInfo;
oldFileInfo.Time = fileInfo.LastWriteTime;
oldFileInfo.Size = fileInfo.Size;
oldFileInfo.Name = fullProcessedPath;
newFileInfo.Time = m_ProcessedFileInfo.UTCLastWriteTime;
newFileInfo.Size = newFileSize;
newFileInfo.Name = fullPath;
NOverwriteDialog::NResult::EEnum result =
NOverwriteDialog::Execute(oldFileInfo, newFileInfo);
*/
g_StdOut << "file " << fullProcessedPath <<
"\nalready exists. Overwrite with " << endl;
g_StdOut << fullPathCorrect;
NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit();
switch(overwriteAnswer)
{
case NUserAnswerMode::kQuit:
return E_ABORT;
case NUserAnswerMode::kNo:
return S_OK;
case NUserAnswerMode::kNoAll:
m_ExtractModeInfo.OverwriteMode = NExtraction::NOverwriteMode::kSkipExisting;
return S_OK;
case NUserAnswerMode::kYesAll:
m_ExtractModeInfo.OverwriteMode = NExtraction::NOverwriteMode::kWithoutPrompt;
break;
case NUserAnswerMode::kYes:
break;
case NUserAnswerMode::kAutoRename:
m_ExtractModeInfo.OverwriteMode = NExtraction::NOverwriteMode::kAutoRename;
break;
default:
throw 20413;
}
break;
}
}
if (m_ExtractModeInfo.OverwriteMode == NExtraction::NOverwriteMode::kAutoRename)
{
if (!AutoRenamePath(fullProcessedPath))
{
g_StdOut << kCantAutoRename;
g_StdOut << fullProcessedPath;
return E_ABORT;
}
}
else if (m_ExtractModeInfo.OverwriteMode == NExtraction::NOverwriteMode::kAutoRenameExisting)
{
UString existPath = fullProcessedPath;
if (!AutoRenamePath(existPath))
{
g_StdOut << kCantAutoRename;
g_StdOut << fullProcessedPath;
return E_ABORT;
}
if(!MyMoveFile(fullProcessedPath, existPath))
{
g_StdOut << kCantRenameFile;
return E_ABORT;
}
}
else
if (!DeleteFileAlways(fullProcessedPath))
{
g_StdOut << kCantDeleteOutputFile << endl;
g_StdOut << fullProcessedPath;
return E_ABORT;
}
}
if (!isAnti)
{
m_OutFileStreamSpec = new COutFileStream;
CMyComPtr<ISequentialOutStream> outStreamLoc(m_OutFileStreamSpec);
if (!m_OutFileStreamSpec->Open(fullProcessedPath))
{
m_NumErrors++;
g_StdOut << "Can not open output file " << endl;
g_StdOut << fullProcessedPath << endl;
return S_OK;
}
m_OutFileStream = outStreamLoc;
*outStream = outStreamLoc.Detach();
}
m_DiskFilePath = fullProcessedPath;
}
else
{
*outStream = NULL;
}
return S_OK;
}
STDMETHODIMP CExtractCallbackImp::PrepareOperation(INT32 askExtractMode)
{
m_ExtractMode = false;
switch (askExtractMode)
{
case NArchive::NExtract::NAskMode::kExtract:
m_ExtractMode = true;
g_StdOut << kExtractingString;
break;
case NArchive::NExtract::NAskMode::kTest:
g_StdOut << kTestingString;
break;
case NArchive::NExtract::NAskMode::kSkip:
g_StdOut << kSkippingString;
break;
};
g_StdOut << m_FilePath;
return S_OK;
}
STDMETHODIMP CExtractCallbackImp::SetOperationResult(INT32 resultEOperationResult)
{
switch(resultEOperationResult)
{
case NArchive::NExtract::NOperationResult::kOK:
{
break;
}
default:
{
m_NumErrors++;
switch(resultEOperationResult)
{
case NArchive::NExtract::NOperationResult::kUnSupportedMethod:
g_StdOut << " Unsupported Method";
break;
case NArchive::NExtract::NOperationResult::kCRCError:
g_StdOut << " CRC Failed";
break;
case NArchive::NExtract::NOperationResult::kDataError:
g_StdOut << " Data Error";
break;
default:
g_StdOut << " Unknown Error";
// m_OutFileStream.Release();
// return E_FAIL;
}
}
}
if(m_OutFileStream != NULL)
m_OutFileStreamSpec->File.SetLastWriteTime(&m_ProcessedFileInfo.UTCLastWriteTime);
m_OutFileStream.Release();
if (m_ExtractMode && m_ProcessedFileInfo.AttributesAreDefined)
MySetFileAttributes(m_DiskFilePath, m_ProcessedFileInfo.Attributes);
g_StdOut << endl;
return S_OK;
}
STDMETHODIMP CExtractCallbackImp::CryptoGetTextPassword(BSTR *password)
{
if (!m_PasswordIsDefined)
{
g_StdOut << "\nEnter password:";
AString oemPassword = g_StdIn.ScanStringUntilNewLine();
m_Password = MultiByteToUnicodeString(oemPassword, CP_OEMCP);
m_PasswordIsDefined = true;
}
CMyComBSTR tempName(m_Password);
*password = tempName.Detach();
return S_OK;
}

View File

@@ -1,77 +0,0 @@
// ExtractCallback.h
#pragma once
#ifndef __EXTRACTCALLBACK_H
#define __EXTRACTCALLBACK_H
#include "Common/String.h"
#include "../../Common/FileStreams.h"
#include "../../IPassword.h"
#include "../../Archive/IArchive.h"
#include "../Common/ZipRegistry.h"
class CExtractCallbackImp:
public IArchiveExtractCallback,
public ICryptoGetTextPassword,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP1(ICryptoGetTextPassword)
// IProgress
STDMETHOD(SetTotal)(UINT64 size);
STDMETHOD(SetCompleted)(const UINT64 *completeValue);
// IExtractCallback200
STDMETHOD(GetStream)(UINT32 index, ISequentialOutStream **outStream,
INT32 askExtractMode);
STDMETHOD(PrepareOperation)(INT32 askExtractMode);
STDMETHOD(SetOperationResult)(INT32 resultEOperationResult);
// ICryptoGetTextPassword
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
private:
CMyComPtr<IInArchive> m_ArchiveHandler;
UString m_DirectoryPath;
NExtraction::CInfo m_ExtractModeInfo;
UString m_FilePath;
UString m_DiskFilePath;
bool m_ExtractMode;
struct CProcessedFileInfo
{
FILETIME UTCLastWriteTime;
bool IsDirectory;
bool AttributesAreDefined;
UINT32 Attributes;
} m_ProcessedFileInfo;
COutFileStream *m_OutFileStreamSpec;
CMyComPtr<ISequentialOutStream> m_OutFileStream;
UStringVector m_RemovePathParts;
UString m_ItemDefaultName;
FILETIME m_UTCLastWriteTimeDefault;
UINT32 m_AttributesDefault;
bool m_PasswordIsDefined;
UString m_Password;
void CreateComplexDirectory(const UStringVector &dirPathParts);
bool IsEncrypted(UINT32 index);
public:
void Init(IInArchive *archive, const UString &directoryPath,
const NExtraction::CInfo &anExtractModeInfo,
const UStringVector &removePathParts,
const UString &itemDefaultName,
const FILETIME &utcLastWriteTimeDefault, UINT32 attributesDefault,
bool passwordIsDefined, const UString &password);
UINT64 m_NumErrors;
};
#endif

View File

@@ -0,0 +1,227 @@
// ExtractCallbackConsole.h
#include "StdAfx.h"
#include "ExtractCallbackConsole.h"
#include "UserInputUtils.h"
#include "ConsoleClose.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/Error.h"
#include "Windows/PropVariantConversions.h"
#include "../../Common/FilePathAutoRename.h"
#include "../Common/ExtractingFilePath.h"
using namespace NWindows;
using namespace NFile;
using namespace NDirectory;
static const char *kTestingString = "Testing ";
static const char *kExtractingString = "Extracting ";
static const char *kSkippingString = "Skipping ";
static const char *kCantAutoRename = "can not create file with auto name\n";
static const char *kCantRenameFile = "can not rename existing file\n";
static const char *kCantDeleteOutputFile = "can not delete output file ";
static const char *kError = "ERROR: ";
static const char *kMemoryExceptionMessage = "Can't allocate required memory!";
static const char *kProcessing = "Processing archive: ";
static const char *kEverythingIsOk = "Everything is Ok";
static const char *kNoFiles = "No files to process";
static const char *kUnsupportedMethod = "Unsupported Method";
static const char *kCRCFailed = "CRC Failed";
static const char *kDataError = "Data Error";
static const char *kUnknownError = "Unknown Error";
STDMETHODIMP CExtractCallbackConsole::SetTotal(UInt64 size)
{
if (NConsoleClose::TestBreakSignal())
return E_ABORT;
return S_OK;
}
STDMETHODIMP CExtractCallbackConsole::SetCompleted(const UInt64 *completeValue)
{
if (NConsoleClose::TestBreakSignal())
return E_ABORT;
return S_OK;
}
STDMETHODIMP CExtractCallbackConsole::AskOverwrite(
const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,
const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,
Int32 *answer)
{
(*OutStream) << "file " << existName <<
"\nalready exists. Overwrite with " << endl;
(*OutStream) << newName;
NUserAnswerMode::EEnum overwriteAnswer = ScanUserYesNoAllQuit(OutStream);
switch(overwriteAnswer)
{
case NUserAnswerMode::kQuit:
return E_ABORT;
case NUserAnswerMode::kNo:
*answer = NOverwriteAnswer::kNo;
break;
case NUserAnswerMode::kNoAll:
*answer = NOverwriteAnswer::kNoToAll;
break;
case NUserAnswerMode::kYesAll:
*answer = NOverwriteAnswer::kYesToAll;
break;
case NUserAnswerMode::kYes:
*answer = NOverwriteAnswer::kYes;
break;
case NUserAnswerMode::kAutoRename:
*answer = NOverwriteAnswer::kAutoRename;
break;
default:
return E_FAIL;
}
return S_OK;
}
STDMETHODIMP CExtractCallbackConsole::PrepareOperation(const wchar_t *name, Int32 askExtractMode, const UInt64 *position)
{
switch (askExtractMode)
{
case NArchive::NExtract::NAskMode::kExtract:
(*OutStream) << kExtractingString;
break;
case NArchive::NExtract::NAskMode::kTest:
(*OutStream) << kTestingString;
break;
case NArchive::NExtract::NAskMode::kSkip:
(*OutStream) << kSkippingString;
break;
};
(*OutStream) << name;
if (position != 0)
(*OutStream) << " <" << *position << ">";
return S_OK;
}
STDMETHODIMP CExtractCallbackConsole::MessageError(const wchar_t *message)
{
(*OutStream) << message << endl;
return S_OK;
}
STDMETHODIMP CExtractCallbackConsole::SetOperationResult(Int32 operationResult)
{
switch(operationResult)
{
case NArchive::NExtract::NOperationResult::kOK:
break;
default:
{
NumFileErrorsInCurrentArchive++;
NumFileErrors++;
(*OutStream) << " ";
switch(operationResult)
{
case NArchive::NExtract::NOperationResult::kUnSupportedMethod:
(*OutStream) << kUnsupportedMethod;
break;
case NArchive::NExtract::NOperationResult::kCRCError:
(*OutStream) << kCRCFailed;
break;
case NArchive::NExtract::NOperationResult::kDataError:
(*OutStream) << kDataError;
break;
default:
(*OutStream) << kUnknownError;
}
}
}
(*OutStream) << endl;
return S_OK;
}
STDMETHODIMP CExtractCallbackConsole::CryptoGetTextPassword(BSTR *password)
{
if (!PasswordIsDefined)
{
Password = GetPassword(OutStream);
PasswordIsDefined = true;
}
CMyComBSTR tempName(Password);
*password = tempName.Detach();
return S_OK;
}
HRESULT CExtractCallbackConsole::BeforeOpen(const wchar_t *name)
{
NumArchives++;
NumFileErrorsInCurrentArchive = 0;
(*OutStream) << endl << kProcessing << name << endl;
return S_OK;
}
HRESULT CExtractCallbackConsole::OpenResult(const wchar_t *name, HRESULT result)
{
(*OutStream) << endl;
if (result != S_OK)
{
(*OutStream) << "Error: " << name << " is not supported archive" << endl;
NumArchiveErrors++;
}
return S_OK;
}
HRESULT CExtractCallbackConsole::ThereAreNoFiles()
{
(*OutStream) << endl << kNoFiles << endl;
return S_OK;
}
HRESULT CExtractCallbackConsole::ExtractResult(HRESULT result)
{
if (result == S_OK)
{
(*OutStream) << endl;
if (NumFileErrorsInCurrentArchive == 0)
(*OutStream) << kEverythingIsOk << endl;
else
{
NumArchiveErrors++;
(*OutStream) << "Sub items Errors: " << NumFileErrorsInCurrentArchive << endl;
}
}
if (result == S_OK)
return result;
if (result == E_ABORT)
return result;
(*OutStream) << endl << kError;
if (result == E_OUTOFMEMORY)
(*OutStream) << kMemoryExceptionMessage;
else
{
UString message;
NError::MyFormatMessage(result, message);
(*OutStream) << message;
}
(*OutStream) << endl;
NumArchiveErrors++;
return S_OK;
}
HRESULT CExtractCallbackConsole::SetPassword(const UString &password)
{
PasswordIsDefined = true;
Password = password;
return S_OK;
}

View File

@@ -0,0 +1,65 @@
// ExtractCallbackConsole.h
#ifndef __EXTRACTCALLBACKCONSOLE_H
#define __EXTRACTCALLBACKCONSOLE_H
#include "Common/String.h"
#include "Common/StdOutStream.h"
#include "../../Common/FileStreams.h"
#include "../../IPassword.h"
#include "../../Archive/IArchive.h"
#include "../Common/ArchiveExtractCallback.h"
class CExtractCallbackConsole:
public IExtractCallbackUI,
public ICryptoGetTextPassword,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP2(IFolderArchiveExtractCallback, ICryptoGetTextPassword)
STDMETHOD(SetTotal)(UInt64 total);
STDMETHOD(SetCompleted)(const UInt64 *completeValue);
// IFolderArchiveExtractCallback
STDMETHOD(AskOverwrite)(
const wchar_t *existName, const FILETIME *existTime, const UInt64 *existSize,
const wchar_t *newName, const FILETIME *newTime, const UInt64 *newSize,
Int32 *answer);
STDMETHOD (PrepareOperation)(const wchar_t *name, Int32 askExtractMode, const UInt64 *position);
STDMETHOD(MessageError)(const wchar_t *message);
STDMETHOD(SetOperationResult)(Int32 operationResult);
// ICryptoGetTextPassword
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
HRESULT BeforeOpen(const wchar_t *name);
HRESULT OpenResult(const wchar_t *name, HRESULT result);
HRESULT ThereAreNoFiles();
HRESULT ExtractResult(HRESULT result);
HRESULT SetPassword(const UString &password);
public:
bool PasswordIsDefined;
UString Password;
UInt64 NumArchives;
UInt64 NumArchiveErrors;
UInt64 NumFileErrors;
UInt64 NumFileErrorsInCurrentArchive;
CStdOutStream *OutStream;
void CExtractCallbackConsole::Init()
{
NumArchives = 0;
NumArchiveErrors = 0;
NumFileErrors = 0;
NumFileErrorsInCurrentArchive = 0;
}
};
#endif

View File

@@ -13,45 +13,40 @@
#include "Windows/PropVariant.h"
#include "Windows/Defs.h"
#include "Windows/PropVariantConversions.h"
#include "Windows/FileDir.h"
#include "../../Archive/IArchive.h"
#include "../Common/PropIDUtils.h"
#include "../Common/OpenArchive.h"
#include "OpenCallbackConsole.h"
using namespace NWindows;
/*
static const char kEmptyFlag = '.';
static const char kPasswordFlag = '*';
static const char kSolidFlag = 'S';
static const char kSplitBeforeFlag = 'B';
static const char kSplitAfterFlag = 'A';
static const char kCommentedFlag = 'C';
*/
static const char kEmptyAttributeChar = '.';
//static const char kVolumeAttributeChar = 'V';
static const char kDirectoryAttributeChar = 'D';
static const char kReadonlyAttributeChar = 'R';
static const char kHiddenAttributeChar = 'H';
static const char kSystemAttributeChar = 'S';
static const char kArchiveAttributeChar = 'A';
static AString GetAttributesString(DWORD winAttributes, bool directory)
static const char *kListing = "Listing archive: ";
static const wchar_t *kFilesMessage = L"files";
static void GetAttributesString(DWORD wa, bool directory, char *s)
{
AString s;
// s = ((winAttributes & kLabelFileAttribute) != 0) ?
// kVolumeAttributeChar: kEmptyAttributeChar;
s += ((winAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 || directory) ?
kDirectoryAttributeChar: kEmptyAttributeChar;
s += ((winAttributes & FILE_ATTRIBUTE_READONLY) != 0)?
kReadonlyAttributeChar: kEmptyAttributeChar;
s += ((winAttributes & FILE_ATTRIBUTE_HIDDEN) != 0) ?
kHiddenAttributeChar: kEmptyAttributeChar;
s += ((winAttributes & FILE_ATTRIBUTE_SYSTEM) != 0) ?
kSystemAttributeChar: kEmptyAttributeChar;
s += ((winAttributes & FILE_ATTRIBUTE_ARCHIVE) != 0) ?
kArchiveAttributeChar: kEmptyAttributeChar;
return s;
s[0] = ((wa & FILE_ATTRIBUTE_DIRECTORY) != 0 || directory) ?
kDirectoryAttributeChar: kEmptyAttributeChar;
s[1] = ((wa & FILE_ATTRIBUTE_READONLY) != 0)?
kReadonlyAttributeChar: kEmptyAttributeChar;
s[2] = ((wa & FILE_ATTRIBUTE_HIDDEN) != 0) ?
kHiddenAttributeChar: kEmptyAttributeChar;
s[3] = ((wa & FILE_ATTRIBUTE_SYSTEM) != 0) ?
kSystemAttributeChar: kEmptyAttributeChar;
s[4] = ((wa & FILE_ATTRIBUTE_ARCHIVE) != 0) ?
kArchiveAttributeChar: kEmptyAttributeChar;
s[5] = '\0';
}
enum EAdjustment
@@ -127,9 +122,9 @@ public:
HRESULT PrintItemInfo(IInArchive *archive,
const UString &defaultItemName,
const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo,
UINT32 index);
HRESULT PrintSummaryInfo(UINT64 numFiles, const UINT64 *size,
const UINT64 *compressedSize);
UInt32 index);
HRESULT PrintSummaryInfo(UInt64 numFiles, const UInt64 *size,
const UInt64 *compressedSize);
};
void CFieldPrinter::Init(const CFieldInfoInit *standardFieldTable, int numItems)
@@ -155,7 +150,8 @@ void CFieldPrinter::PrintTitle()
{
const CFieldInfo &fieldInfo = _fields[i];
PrintSpaces(fieldInfo.PrefixSpacesWidth);
PrintString(fieldInfo.TitleAdjustment, fieldInfo.Width, fieldInfo.Name);
PrintString(fieldInfo.TitleAdjustment,
((fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width), fieldInfo.Name);
}
}
@@ -176,8 +172,7 @@ BOOL IsFileTimeZero(CONST FILETIME *lpFileTime)
return (lpFileTime->dwLowDateTime == 0) && (lpFileTime->dwHighDateTime == 0);
}
const char *kEmptyTimeString = " ";
static const char *kEmptyTimeString = " ";
void PrintTime(const NCOM::CPropVariant &propVariant)
{
if (propVariant.vt != VT_FILETIME)
@@ -189,14 +184,9 @@ void PrintTime(const NCOM::CPropVariant &propVariant)
FILETIME localFileTime;
if (!FileTimeToLocalFileTime(&propVariant.filetime, &localFileTime))
throw "FileTimeToLocalFileTime error";
SYSTEMTIME st;
if (FileTimeToSystemTime(&localFileTime, &st))
{
char s[32];
wsprintfA(s, "%04u-%02u-%02u %02u:%02u:%02u",
st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
char s[32];
if (ConvertFileTimeToString(localFileTime, s, true, true))
g_StdOut << s;
}
else
g_StdOut << kEmptyTimeString;
}
@@ -205,7 +195,7 @@ void PrintTime(const NCOM::CPropVariant &propVariant)
HRESULT CFieldPrinter::PrintItemInfo(IInArchive *archive,
const UString &defaultItemName,
const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo,
UINT32 index)
UInt32 index)
{
for (int i = 0; i < _fields.Size(); i++)
{
@@ -213,8 +203,8 @@ HRESULT CFieldPrinter::PrintItemInfo(IInArchive *archive,
PrintSpaces(fieldInfo.PrefixSpacesWidth);
NCOM::CPropVariant propVariant;
RINOK(archive->GetProperty(index,
fieldInfo.PropID, &propVariant));
RINOK(archive->GetProperty(index, fieldInfo.PropID, &propVariant));
int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width;
if (propVariant.vt == VT_EMPTY)
{
switch(fieldInfo.PropID)
@@ -226,7 +216,7 @@ HRESULT CFieldPrinter::PrintItemInfo(IInArchive *archive,
propVariant = archiveFileInfo.LastWriteTime;
break;
default:
PrintSpaces(fieldInfo.Width);
PrintSpaces(width);
continue;
}
}
@@ -240,39 +230,37 @@ HRESULT CFieldPrinter::PrintItemInfo(IInArchive *archive,
{
if (propVariant.vt != VT_UI4)
throw "incorrect item";
UINT32 attributes = propVariant.ulVal;
NCOM::CPropVariant propVariantIsFolder;
RINOK(archive->GetProperty(index,
kpidIsFolder, &propVariantIsFolder));
if(propVariantIsFolder.vt != VT_BOOL)
return E_FAIL;
g_StdOut << GetAttributesString(attributes, VARIANT_BOOLToBool(propVariantIsFolder.boolVal));
UInt32 attributes = propVariant.ulVal;
bool isFolder;
RINOK(IsArchiveItemFolder(archive, index, isFolder));
char s[8];
GetAttributesString(attributes, isFolder, s);
g_StdOut << s;
continue;
}
if (propVariant.vt == VT_BSTR)
{
PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, propVariant.bstrVal);
PrintString(fieldInfo.TextAdjustment, width, propVariant.bstrVal);
continue;
}
PrintString(fieldInfo.TextAdjustment, fieldInfo.Width,
PrintString(fieldInfo.TextAdjustment, width,
ConvertPropertyToString(propVariant, fieldInfo.PropID));
}
return S_OK;
}
void PrintNumberString(EAdjustment adjustment, int width, const UINT64 *value)
void PrintNumberString(EAdjustment adjustment, int width, const UInt64 *value)
{
wchar_t textString[32] = { 0 };
if (value != NULL)
ConvertUINT64ToString(*value, textString);
ConvertUInt64ToString(*value, textString);
PrintString(adjustment, width, textString);
}
static const wchar_t *kFilesMessage = L"files";
HRESULT CFieldPrinter::PrintSummaryInfo(UINT64 numFiles,
const UINT64 *size, const UINT64 *compressedSize)
HRESULT CFieldPrinter::PrintSummaryInfo(UInt64 numFiles,
const UInt64 *size, const UInt64 *compressedSize)
{
for (int i = 0; i < _fields.Size(); i++)
{
@@ -286,11 +274,11 @@ HRESULT CFieldPrinter::PrintSummaryInfo(UINT64 numFiles,
else if (fieldInfo.PropID == kpidPath)
{
wchar_t textString[32];
ConvertUINT64ToString(numFiles, textString);
ConvertUInt64ToString(numFiles, textString);
UString temp = textString;
temp += L" ";
temp += kFilesMessage;
PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, temp);
PrintString(fieldInfo.TextAdjustment, 0, temp);
}
else
PrintString(fieldInfo.TextAdjustment, fieldInfo.Width, L"");
@@ -298,84 +286,147 @@ HRESULT CFieldPrinter::PrintSummaryInfo(UINT64 numFiles,
return S_OK;
}
bool GetUINT64Value(IInArchive *archive, UINT32 index,
PROPID propID, UINT64 &value)
bool GetUInt64Value(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &value)
{
NCOM::CPropVariant propVariant;
if (archive->GetProperty(index, propID, &propVariant) != S_OK)
throw "GetPropertyValue error";
if (propVariant.vt == VT_EMPTY)
return false;
value = ConvertPropVariantToUINT64(propVariant);
value = ConvertPropVariantToUInt64(propVariant);
return true;
}
HRESULT ListArchive(IInArchive *archive,
const UString &defaultItemName,
const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo,
const NWildcard::CCensor &wildcardCensor/*, bool fullPathMode,
NListMode::EEnum mode*/)
HRESULT ListArchives(UStringVector &archivePaths, UStringVector &archivePathsFull,
const NWildcard::CCensorNode &wildcardCensor,
bool enableHeaders, bool &passwordEnabled, UString &password)
{
CFieldPrinter fieldPrinter;
fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0]));
fieldPrinter.PrintTitle();
g_StdOut << endl;
fieldPrinter.PrintTitleLines();
g_StdOut << endl;
// bool nameFirst = (fullPathMode && (mode != NListMode::kDefault)) || (mode == NListMode::kAll);
UINT64 numFiles = 0, totalPackSize = 0, totalUnPackSize = 0;
UINT64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0;
UINT32 numItems;
RINOK(archive->GetNumberOfItems(&numItems));
for(UINT32 i = 0; i < numItems; i++)
UInt64 numFiles2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0;
UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0;
int numErrors = 0;
for (int i = 0; i < archivePaths.Size(); i++)
{
if (NConsoleClose::TestBreakSignal())
return E_ABORT;
NCOM::CPropVariant propVariant;
RINOK(archive->GetProperty(i, kpidPath, &propVariant));
UString filePath;
if(propVariant.vt == VT_EMPTY)
filePath = defaultItemName;
else
const UString &archiveName = archivePaths[i];
NFile::NFind::CFileInfoW archiveFileInfo;
if (!NFile::NFind::FindFile(archiveName, archiveFileInfo) || archiveFileInfo.IsDirectory())
{
if(propVariant.vt != VT_BSTR)
return E_FAIL;
filePath = propVariant.bstrVal;
}
if (!wildcardCensor.CheckName(filePath))
g_StdOut << endl << "Error: " << archiveName << " is not archive" << endl;
numErrors++;
continue;
}
if (archiveFileInfo.IsDirectory())
{
g_StdOut << endl << "Error: " << archiveName << " is not file" << endl;
numErrors++;
continue;
}
fieldPrinter.PrintItemInfo(archive, defaultItemName, archiveFileInfo, i);
CArchiveLink archiveLink;
UINT64 packSize, unpackSize;
if (!GetUINT64Value(archive, i, kpidSize, unpackSize))
unpackSize = 0;
else
totalUnPackSizePointer = &totalUnPackSize;
if (!GetUINT64Value(archive, i, kpidPackedSize, packSize))
packSize = 0;
else
totalPackSizePointer = &totalPackSize;
COpenCallbackConsole openCallback;
openCallback.OutStream = &g_StdOut;
openCallback.PasswordIsDefined = passwordEnabled;
openCallback.Password = password;
g_StdOut << endl;
HRESULT result = MyOpenArchive(archiveName, archiveLink, &openCallback);
if (result != S_OK)
{
g_StdOut << endl << "Error: " << archiveName << " is not supported archive" << endl;
numErrors++;
continue;
}
numFiles++;
totalPackSize += packSize;
totalUnPackSize += unpackSize;
for (int v = 0; v < archiveLink.VolumePaths.Size(); v++)
{
int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]);
if (index >= 0 && index > i)
{
archivePaths.Delete(index);
archivePathsFull.Delete(index);
}
}
IInArchive *archive = archiveLink.GetArchive();
const UString defaultItemName = archiveLink.GetDefaultItemName();
if (enableHeaders)
g_StdOut << endl << kListing << archiveName << endl << endl;
if (enableHeaders)
{
fieldPrinter.PrintTitle();
g_StdOut << endl;
fieldPrinter.PrintTitleLines();
g_StdOut << endl;
}
UInt64 numFiles = 0, totalPackSize = 0, totalUnPackSize = 0;
UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0;
UInt32 numItems;
RINOK(archive->GetNumberOfItems(&numItems));
for(UInt32 i = 0; i < numItems; i++)
{
if (NConsoleClose::TestBreakSignal())
return E_ABORT;
UString filePath;
RINOK(GetArchiveItemPath(archive, i, defaultItemName, filePath));
bool isFolder;
RINOK(IsArchiveItemFolder(archive, i, isFolder));
if (!wildcardCensor.CheckPath(filePath, !isFolder))
continue;
fieldPrinter.PrintItemInfo(archive, defaultItemName, archiveFileInfo, i);
UInt64 packSize, unpackSize;
if (!GetUInt64Value(archive, i, kpidSize, unpackSize))
unpackSize = 0;
else
totalUnPackSizePointer = &totalUnPackSize;
if (!GetUInt64Value(archive, i, kpidPackedSize, packSize))
packSize = 0;
else
totalPackSizePointer = &totalPackSize;
g_StdOut << endl;
numFiles++;
totalPackSize += packSize;
totalUnPackSize += unpackSize;
}
if (enableHeaders)
{
fieldPrinter.PrintTitleLines();
g_StdOut << endl;
fieldPrinter.PrintSummaryInfo(numFiles, totalUnPackSizePointer, totalPackSizePointer);
g_StdOut << endl;
}
if (totalPackSizePointer != 0)
{
totalPackSizePointer2 = &totalPackSize2;
totalPackSize2 += totalPackSize;
}
if (totalUnPackSizePointer != 0)
{
totalUnPackSizePointer2 = &totalUnPackSize2;
totalUnPackSize2 += totalUnPackSize;
}
numFiles2 += numFiles;
}
fieldPrinter.PrintTitleLines();
g_StdOut << endl;
/*
if(numFiles == 0)
g_StdOut << kNoFilesMessage);
else
*/
fieldPrinter.PrintSummaryInfo(numFiles, totalUnPackSizePointer, totalPackSizePointer);
g_StdOut << endl;
if (enableHeaders && archivePaths.Size() > 1)
{
g_StdOut << endl;
fieldPrinter.PrintTitleLines();
g_StdOut << endl;
fieldPrinter.PrintSummaryInfo(numFiles2, totalUnPackSizePointer2, totalPackSizePointer2);
g_StdOut << endl;
g_StdOut << "Archives: " << archivePaths.Size() << endl;
}
if (numErrors > 0)
g_StdOut << endl << "Errors: " << numErrors;
return S_OK;
}

View File

@@ -1,31 +1,13 @@
// List.h
#pragma once
#ifndef __LIST_H
#define __LIST_H
#include "../../Archive/IArchive.h"
#include "Common/Wildcard.h"
#include "Windows/FileFind.h"
/*
namespace NListMode
{
enum EEnum
{
kDefault,
kAdd,
kAll
};
}
*/
HRESULT ListArchive(IInArchive *archive,
const UString &defaultItemName,
const NWindows::NFile::NFind::CFileInfoW &srchiveFileInfo,
const NWildcard::CCensor &wildcardCensor/*, bool fullPathMode,
NListMode::EEnum mode*/);
HRESULT ListArchives(UStringVector &archivePaths, UStringVector &archivePathsFull,
const NWildcard::CCensorNode &wildcardCensor,
bool enableHeaders, bool &passwordEnabled, UString &password);
#endif

View File

File diff suppressed because it is too large Load Diff

View File

@@ -4,28 +4,34 @@
// #include <locale.h>
#include "Windows/COM.h"
#include "Windows/Error.h"
#include "Common/StdOutStream.h"
#include "Common/NewHandler.h"
#include "Common/Exception.h"
#include "Common/StringConvert.h"
#include "../Common/ExitCode.h"
#include "ConsoleClose.h"
#include "ArError.h"
using namespace NWindows;
// extern int Main2(int numArguments, const char *arguments[]);
extern int Main2();
CStdOutStream *g_StdStream = 0;
extern int Main2(
#ifndef _WIN32
int numArguments, const char *arguments[]
#endif
);
static const char *kExceptionErrorMessage = "\n\nError:\n";
static const char *kUserBreak = "\nBreak signaled\n";
static const char *kMemoryExceptionMessage = "\n\nMemory Error! Can't allocate!\n";
static const char *kMemoryExceptionMessage = "\n\nERROR: Can't allocate required memory!\n";
static const char *kUnknownExceptionMessage = "\n\nUnknown Error\n";
static const char *kInternalExceptionMessage = "\n\nInternal Error #";
#ifdef UNICODE
static inline bool IsItWindowsNT()
{
OSVERSIONINFO versionInfo;
@@ -34,81 +40,100 @@ static inline bool IsItWindowsNT()
return false;
return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
}
#endif
int __cdecl main()
// int __cdecl main(int numArguments, const char *arguments[])
int
#ifdef _MSC_VER
__cdecl
#endif
main
(
#ifndef _WIN32
int numArguments, const char *arguments[]
#endif
)
{
g_StdStream = &g_StdOut;
#ifdef UNICODE
if (!IsItWindowsNT())
{
g_StdOut << "This program requires Windows NT/2000/XP";
(*g_StdStream) << "This program requires Windows NT/2000/XP/2003";
return NExitCode::kFatalError;
}
#endif
// setlocale(LC_COLLATE, ".OCP");
int result=1;
NCOM::CComInitializer comInitializer;
NConsoleClose::CCtrlHandlerSetter ctrlHandlerSetter;
try
{
NConsoleClose::CCtrlHandlerSetter aCtrlHandlerSetter;
try
{
// result = Main2(numArguments, arguments);
result = Main2();
}
catch(const NConsoleClose::CCtrlBreakException &)
{
g_StdOut << endl << kUserBreak;
return (NExitCode::kUserBreak);
}
return Main2(
#ifndef _WIN32
numArguments, arguments
#endif
);
}
catch(const CNewException)
catch(const CNewException &)
{
g_StdOut << kMemoryExceptionMessage;
(*g_StdStream) << kMemoryExceptionMessage;
return (NExitCode::kMemoryError);
}
catch(const CSystemException &e)
catch(const NConsoleClose::CCtrlBreakException &)
{
g_StdOut << "System Error: " << (UINT64)(e.ErrorCode);
return (NExitCode::kFatalError);
(*g_StdStream) << endl << kUserBreak;
return (NExitCode::kUserBreak);
}
catch(NExitCode::EEnum &aExitCode)
{
g_StdOut << kInternalExceptionMessage << aExitCode << endl;
return (aExitCode);
}
catch(const NExitCode::CSystemError &systemError)
catch(const CSystemException &systemError)
{
if (systemError.ErrorCode == E_OUTOFMEMORY)
{
(*g_StdStream) << kMemoryExceptionMessage;
return (NExitCode::kMemoryError);
}
if (systemError.ErrorCode == E_ABORT)
{
(*g_StdStream) << endl << kUserBreak;
return (NExitCode::kUserBreak);
}
UString message;
NError::MyFormatMessage(systemError.ErrorValue, message);
g_StdOut << endl << endl << "System error:" << endl <<
NError::MyFormatMessage(systemError.ErrorCode, message);
(*g_StdStream) << endl << endl << "System error:" << endl <<
message << endl;
return (NExitCode::kFatalError);
}
catch(NExitCode::EEnum &exitCode)
{
(*g_StdStream) << kInternalExceptionMessage << exitCode << endl;
return (exitCode);
}
/*
catch(const NExitCode::CMultipleErrors &multipleErrors)
{
g_StdOut << endl << multipleErrors.NumErrors << " errors" << endl;
(*g_StdStream) << endl << multipleErrors.NumErrors << " errors" << endl;
return (NExitCode::kFatalError);
}
*/
catch(const UString &s)
{
g_StdOut << kExceptionErrorMessage << s << endl;
(*g_StdStream) << kExceptionErrorMessage << s << endl;
return (NExitCode::kFatalError);
}
catch(const AString &s)
{
(*g_StdStream) << kExceptionErrorMessage << s << endl;
return (NExitCode::kFatalError);
}
catch(const char *s)
{
g_StdOut << kExceptionErrorMessage << s << endl;
(*g_StdStream) << kExceptionErrorMessage << s << endl;
return (NExitCode::kFatalError);
}
catch(int t)
{
g_StdOut << kInternalExceptionMessage << t << endl;
(*g_StdStream) << kInternalExceptionMessage << t << endl;
return (NExitCode::kFatalError);
}
catch(...)
{
g_StdOut << kUnknownExceptionMessage;
(*g_StdStream) << kUnknownExceptionMessage;
return (NExitCode::kFatalError);
}
return result;
}

View File

@@ -1,92 +0,0 @@
// OpenCallback.cpp
#include "StdAfx.h"
#include "OpenCallback.h"
#include "Common/StdOutStream.h"
#include "Common/StdInStream.h"
#include "Common/StringConvert.h"
#include "../../Common/FileStreams.h"
#include "Windows/PropVariant.h"
#include "ConsoleClose.h"
STDMETHODIMP COpenCallbackImp::SetTotal(const UINT64 *files, const UINT64 *bytes)
{
if (NConsoleClose::TestBreakSignal())
return E_ABORT;
return S_OK;
}
STDMETHODIMP COpenCallbackImp::SetCompleted(const UINT64 *files, const UINT64 *bytes)
{
if (NConsoleClose::TestBreakSignal())
return E_ABORT;
return S_OK;
}
STDMETHODIMP COpenCallbackImp::GetProperty(PROPID propID, PROPVARIANT *value)
{
NWindows::NCOM::CPropVariant propVariant;
switch(propID)
{
case kpidName:
propVariant = _fileInfo.Name;
break;
case kpidIsFolder:
propVariant = _fileInfo.IsDirectory();
break;
case kpidSize:
propVariant = _fileInfo.Size;
break;
case kpidAttributes:
propVariant = (UINT32)_fileInfo.Attributes;
break;
case kpidLastAccessTime:
propVariant = _fileInfo.LastAccessTime;
break;
case kpidCreationTime:
propVariant = _fileInfo.CreationTime;
break;
case kpidLastWriteTime:
propVariant = _fileInfo.LastWriteTime;
break;
}
propVariant.Detach(value);
return S_OK;
}
STDMETHODIMP COpenCallbackImp::GetStream(const wchar_t *name,
IInStream **inStream)
{
*inStream = NULL;
UString fullPath = _folderPrefix + name;
if (!NWindows::NFile::NFind::FindFile(fullPath, _fileInfo))
return S_FALSE;
if (_fileInfo.IsDirectory())
return S_FALSE;
CInFileStream *inFile = new CInFileStream;
CMyComPtr<IInStream> inStreamTemp = inFile;
if (!inFile->Open(fullPath))
return ::GetLastError();
*inStream = inStreamTemp.Detach();
return S_OK;
}
STDMETHODIMP COpenCallbackImp::CryptoGetTextPassword(BSTR *password)
{
if (!PasswordIsDefined)
{
g_StdOut << "\nEnter password:";
AString oemPassword = g_StdIn.ScanStringUntilNewLine();
Password = MultiByteToUnicodeString(oemPassword, CP_OEMCP);
PasswordIsDefined = true;
}
CMyComBSTR temp(Password);
*password = temp.Detach();
return S_OK;
}

View File

@@ -1,52 +0,0 @@
// OpenCallback.h
#pragma once
#ifndef __OPENCALLBACK_H
#define __OPENCALLBACK_H
#include "Common/String.h"
#include "Common/MyCom.h"
#include "Windows/FileFind.h"
#include "../../Archive/IArchive.h"
#include "../../IPassword.h"
class COpenCallbackImp:
public IArchiveOpenCallback,
public IArchiveOpenVolumeCallback,
public ICryptoGetTextPassword,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP2(
IArchiveOpenVolumeCallback,
ICryptoGetTextPassword
)
STDMETHOD(SetTotal)(const UINT64 *files, const UINT64 *bytes);
STDMETHOD(SetCompleted)(const UINT64 *files, const UINT64 *bytes);
// IArchiveOpenVolumeCallback
STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value);
STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream);
// ICryptoGetTextPassword
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
private:
UString _folderPrefix;
NWindows::NFile::NFind::CFileInfoW _fileInfo;
public:
bool PasswordIsDefined;
UString Password;
COpenCallbackImp(): PasswordIsDefined(false) {}
void LoadFileInfo(const UString &folderPrefix, const UString &fileName)
{
_folderPrefix = folderPrefix;
if (!NWindows::NFile::NFind::FindFile(_folderPrefix + fileName, _fileInfo))
throw 1;
}
};
#endif

View File

@@ -0,0 +1,47 @@
// OpenCallbackConsole.cpp
#include "StdAfx.h"
#include "OpenCallbackConsole.h"
#include "ConsoleClose.h"
#include "UserInputUtils.h"
HRESULT COpenCallbackConsole::CheckBreak()
{
if (NConsoleClose::TestBreakSignal())
return E_ABORT;
return S_OK;
}
HRESULT COpenCallbackConsole::SetTotal(const UInt64 *files, const UInt64 *bytes)
{
return CheckBreak();
}
HRESULT COpenCallbackConsole::SetCompleted(const UInt64 *files, const UInt64 *bytes)
{
return CheckBreak();
}
HRESULT COpenCallbackConsole::CryptoGetTextPassword(BSTR *password)
{
RINOK(CheckBreak());
if (!PasswordIsDefined)
{
Password = GetPassword(OutStream);
PasswordIsDefined = true;
}
CMyComBSTR temp(Password);
*password = temp.Detach();
return S_OK;
}
HRESULT COpenCallbackConsole::GetPasswordIfAny(UString &password)
{
if (PasswordIsDefined)
password = Password;
return S_OK;
}

View File

@@ -0,0 +1,24 @@
// OpenCallbackConsole.h
#ifndef __OPENCALLBACKCONSOLE_H
#define __OPENCALLBACKCONSOLE_H
#include "Common/StdOutStream.h"
#include "../Common/ArchiveOpenCallback.h"
class COpenCallbackConsole: public IOpenCallbackUI
{
public:
HRESULT CheckBreak();
HRESULT SetTotal(const UInt64 *files, const UInt64 *bytes);
HRESULT SetCompleted(const UInt64 *files, const UInt64 *bytes);
HRESULT CryptoGetTextPassword(BSTR *password);
HRESULT GetPasswordIfAny(UString &password);
CStdOutStream *OutStream;
bool PasswordIsDefined;
UString Password;
COpenCallbackConsole(): PasswordIsDefined(false) {}
};
#endif

View File

@@ -2,7 +2,6 @@
#include "StdAfx.h"
#include "Common/StdOutStream.h"
#include "Common/IntToString.h"
#include "Common/String.h"
@@ -14,7 +13,7 @@ static const char *kCloseString = "\b\b\b\b \b\b\b\b";
static const char *kPercentFormatString1 = "\b\b\b\b";
static const int kNumDigits = 3;
CPercentPrinter::CPercentPrinter(UINT64 minStepSize):
CPercentPrinter::CPercentPrinter(UInt64 minStepSize):
m_MinStepSize(minStepSize),
m_ScreenPos(0),
m_StringIsPrinted(false)
@@ -27,53 +26,51 @@ CPercentPrinter::CPercentPrinter(UINT64 minStepSize):
void CPercentPrinter::PreparePrint()
{
if (m_ScreenPos < kNumPercentSpaces)
g_StdOut << (m_Spaces + m_ScreenPos);
(*OutStream) << (m_Spaces + m_ScreenPos);
m_ScreenPos = kNumPercentSpaces;
g_StdOut << kPrepareString;
(*OutStream) << kPrepareString;
}
void CPercentPrinter::ClosePrint()
{
g_StdOut << kCloseString;
(*OutStream) << kCloseString;
m_StringIsPrinted = false;
}
void CPercentPrinter::PrintString(const char *s)
{
m_ScreenPos += MyStringLen(s);
g_StdOut << s;
(*OutStream) << s;
}
void CPercentPrinter::PrintString(const wchar_t *s)
{
m_ScreenPos += MyStringLen(s);
g_StdOut << s;
(*OutStream) << s;
}
void CPercentPrinter::PrintNewLine()
{
m_ScreenPos = 0;
g_StdOut << "\n";
(*OutStream) << "\n";
m_StringIsPrinted = false;
}
void CPercentPrinter::SetRatio(UINT64 doneValue)
void CPercentPrinter::SetRatio(UInt64 doneValue)
{ m_CurValue = doneValue; }
void CPercentPrinter::RePrintRatio()
{
if (m_Total == 0)
return;
UINT64 ratio = m_CurValue * 100 / m_Total;
// char temp[32];
// sprintf(temp, kPercentFormatString, ratio);
UInt64 ratio = m_CurValue * 100 / m_Total;
char temp[32 + kNumDigits] = " "; // for 4 digits;
ConvertUINT64ToString(ratio, temp + kNumDigits);
int len = lstrlenA(temp + kNumDigits);
lstrcatA(temp, "%");
ConvertUInt64ToString(ratio, temp + kNumDigits);
int len = strlen(temp + kNumDigits);
strcat(temp, "%");
int pos = (len > kNumDigits)? kNumDigits : len;
g_StdOut << kPercentFormatString1;
g_StdOut << (temp + pos);
(*OutStream) << kPercentFormatString1;
(*OutStream) << (temp + pos);
m_PrevValue = m_CurValue;
m_StringIsPrinted = true;
}

View File

@@ -1,25 +1,27 @@
// PercentPrinter.h
#pragma once
#ifndef __PERCENTPRINTER_H
#define __PERCENTPRINTER_H
#include "Common/Defs.h"
#include "Common/Types.h"
#include "Common/StdOutStream.h"
const int kNumPercentSpaces = 70;
class CPercentPrinter
{
UINT64 m_MinStepSize;
UINT64 m_PrevValue;
UINT64 m_CurValue;
UINT64 m_Total;
UINT32 m_ScreenPos;
UInt64 m_MinStepSize;
UInt64 m_PrevValue;
UInt64 m_CurValue;
UInt64 m_Total;
UInt32 m_ScreenPos;
char m_Spaces[kNumPercentSpaces + 1];
bool m_StringIsPrinted;
public:
CPercentPrinter(UINT64 minStepSize = 1);
void SetTotal(UINT64 total)
CStdOutStream *OutStream;
CPercentPrinter(UInt64 minStepSize = 1);
void SetTotal(UInt64 total)
{
m_Total = total;
m_PrevValue = 0;
@@ -30,7 +32,7 @@ public:
void PrintNewLine();
void PreparePrint();
void ClosePrint();
void SetRatio(UINT64 doneValue);
void SetRatio(UInt64 doneValue);
void RePrintRatio();
void PrintRatio();
};

View File

@@ -1,3 +1,3 @@
// StdAfx.cpp
#include "stdafx.h"
#include "StdAfx.h"

View File

@@ -1,16 +1,8 @@
// stdafx.h
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#ifdef WIN32
#include <windows.h>
#include <tchar.h>
#endif
#include <stdio.h>
#include <time.h>
#include <vector>
#include "../../../Common/MyWindows.h"
#endif

View File

@@ -1,39 +0,0 @@
// TempFiles.cpp
#include "StdAfx.h"
#include "TempFiles.h"
#include "Windows/FileDir.h"
#include "Windows/FileIO.h"
using namespace NWindows;
using namespace NFile;
void CFileVectorBundle::DisableDeleting(int index)
{
m_FileNames.Delete(index);
}
bool CFileVectorBundle::Add(const UString &filePath, bool tryToOpen)
{
if (tryToOpen)
{
NIO::COutFile file;
if (!file.Open(filePath))
return false;
}
m_FileNames.Add(filePath);
return true;
}
void CFileVectorBundle::Clear()
{
while(!m_FileNames.IsEmpty())
{
NDirectory::DeleteFileAlways(m_FileNames.Back());
m_FileNames.DeleteBack();
}
}

View File

@@ -1,20 +0,0 @@
// FileCreationUtils.h
#pragma once
#ifndef __FILECREATIONUTILS_H
#define __FILECREATIONUTILS_H
#include "Common/String.h"
class CFileVectorBundle
{
UStringVector m_FileNames;
public:
~CFileVectorBundle() { Clear(); }
bool Add(const UString &filePath, bool tryToOpen = true);
void DisableDeleting(int index);
void Clear();
};
#endif

View File

@@ -1,503 +0,0 @@
// Update.cpp
#include "StdAfx.h"
#include "Update.h"
#include "Common/StdOutStream.h"
#include "Common/StringConvert.h"
#include "Common/MyCom.h"
#include "Windows/Defs.h"
#include "Windows/Error.h"
#include "Windows/FileDir.h"
#include "Windows/FileFind.h"
#include "Windows/FileName.h"
#include "Windows/PropVariant.h"
#include "Windows/PropVariantConversions.h"
#include "Windows/Error.h"
#include "../../Common/FileStreams.h"
#include "../../Compress/Copy/CopyCoder.h"
#include "../Common/DirItem.h"
#include "../Common/EnumDirItems.h"
#include "../Common/UpdateProduce.h"
#include "TempFiles.h"
#include "ConsoleClose.h"
#include "UpdateCallback.h"
#ifdef FORMAT_7Z
#include "../../Archive/7z/7zHandler.h"
#endif
#ifdef FORMAT_BZIP2
#include "../../Archive/BZip2/BZip2Handler.h"
#endif
#ifdef FORMAT_GZIP
#include "../../Archive/GZip/GZipHandler.h"
#endif
#ifdef FORMAT_TAR
#include "../../Archive/Tar/TarHandler.h"
#endif
#ifdef FORMAT_ZIP
#include "../../Archive/Zip/ZipHandler.h"
#endif
#ifndef EXCLUDE_COM
#include "../Common/HandlerLoader.h"
#endif
static const char *kCreatingArchiveMessage = "Creating archive ";
static const char *kUpdatingArchiveMessage = "Updating archive ";
static const char *kScanningMessage = "Scanning";
static const char *kNoFilesScannedMessage = "No files scanned";
static const char *kTotalFilesAddedMessage = "Total files added to archive: ";
using namespace NWindows;
using namespace NCOM;
using namespace NFile;
using namespace NName;
static wchar_t *kTempArchiveFilePrefixString = L"7zi";
static const char *kEverythingIsOk = "Everything is Ok";
static const char *kIllegalFileNameMessage = "Illegal file name for temp archive";
using namespace NUpdateArchive;
static bool ParseNumberString(const UString &srcString, UINT32 &number)
{
wchar_t *anEndPtr;
number = wcstoul(srcString, &anEndPtr, 10);
return (anEndPtr - srcString == srcString.Length());
}
static HRESULT CopyBlock(ISequentialInStream *inStream, ISequentialOutStream *outStream)
{
CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
return copyCoder->Code(inStream, outStream, NULL, NULL, NULL);
}
HRESULT Compress(
const CActionSet &actionSet,
IInArchive *archive,
const CCompressionMethodMode &compressionMethod,
const UString &archiveName,
const CObjectVector<CArchiveItem> &archiveItems,
const CObjectVector<CDirItem> &dirItems,
bool enablePercents,
bool sfxMode,
const UString &sfxModule)
{
#ifndef EXCLUDE_COM
CHandlerLoader loader;
#endif
CMyComPtr<IOutArchive> outArchive;
if(archive != NULL)
{
CMyComPtr<IInArchive> archive2 = archive;
HRESULT result = archive2.QueryInterface(IID_IOutArchive, &outArchive);
if(result != S_OK)
{
throw "update operations are not supported for this archive";
}
}
else
{
#ifndef EXCLUDE_COM
HRESULT result = loader.CreateHandler(compressionMethod.FilePath,
compressionMethod.ClassID1, (void **)&outArchive, true);
if (result != S_OK)
{
throw "update operations are not supported for this archive";
return E_FAIL;
}
#endif
#ifdef FORMAT_7Z
if (compressionMethod.Name.CompareNoCase(L"7z") == 0)
outArchive = new NArchive::N7z::CHandler;
#endif
#ifdef FORMAT_BZIP2
if (compressionMethod.Name.CompareNoCase(L"BZip2") == 0)
outArchive = new NArchive::NBZip2::CHandler;
#endif
#ifdef FORMAT_GZIP
if (compressionMethod.Name.CompareNoCase(L"GZip") == 0)
outArchive = new NArchive::NGZip::CHandler;
#endif
#ifdef FORMAT_TAR
if (compressionMethod.Name.CompareNoCase(L"Tar") == 0)
outArchive = new NArchive::NTar::CHandler;
#endif
#ifdef FORMAT_ZIP
if (compressionMethod.Name.CompareNoCase(L"Zip") == 0)
outArchive = new NArchive::NZip::CHandler;
#endif
if (outArchive == 0)
{
throw "update operations are not supported for this archive";
return E_FAIL;
}
}
NFileTimeType::EEnum fileTimeType;
UINT32 value;
RINOK(outArchive->GetFileTimeType(&value));
switch(value)
{
case NFileTimeType::kWindows:
case NFileTimeType::kDOS:
case NFileTimeType::kUnix:
fileTimeType = NFileTimeType::EEnum(value);
break;
default:
return E_FAIL;
}
CObjectVector<CUpdatePair> updatePairs;
GetUpdatePairInfoList(dirItems, archiveItems, fileTimeType, updatePairs); // must be done only once!!!
CObjectVector<CUpdatePair2> operationChain;
UpdateProduce(dirItems, archiveItems, updatePairs, actionSet,
operationChain);
CUpdateCallbackImp *updateCallbackSpec = new CUpdateCallbackImp;
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec );
updateCallbackSpec->Init(&dirItems, &archiveItems, &operationChain, enablePercents,
compressionMethod.PasswordIsDefined, compressionMethod.Password,
compressionMethod.AskPassword);
COutFileStream *outStreamSpec = new COutFileStream;
CMyComPtr<IOutStream> outStream(outStreamSpec);
{
UString resultPath;
int pos;
if(! NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos))
throw 141716;
NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));
}
if (!outStreamSpec->Open(archiveName))
{
UString message;
NError::MyFormatMessage(::GetLastError(), message);
g_StdOut << message << endl;
return E_FAIL;
}
CMyComPtr<ISetProperties> setProperties;
if (outArchive.QueryInterface(IID_ISetProperties, &setProperties) == S_OK)
{
CObjectVector<CMyComBSTR> realNames;
std::vector<CPropVariant> values;
int i;
for(i = 0; i < compressionMethod.Properties.Size(); i++)
{
const CProperty &property = compressionMethod.Properties[i];
NCOM::CPropVariant propVariant;
UINT32 number;
if (!property.Value.IsEmpty())
{
if (ParseNumberString(property.Value, number))
propVariant = number;
else
propVariant = property.Value;
}
CMyComBSTR comBSTR(property.Name);
realNames.Add(comBSTR);
values.push_back(propVariant);
}
std::vector<BSTR> names;
for(i = 0; i < realNames.Size(); i++)
names.push_back(realNames[i]);
RINOK(setProperties->SetProperties(&names.front(),
&values.front(), names.size()));
}
if (sfxMode)
{
CInFileStream *sfxStreamSpec = new CInFileStream;
CMyComPtr<IInStream> sfxStream(sfxStreamSpec);
if (!sfxStreamSpec->Open(sfxModule))
throw "Can't open sfx module";
RINOK(CopyBlock(sfxStream, outStream));
}
return outArchive->UpdateItems(outStream, operationChain.Size(),
updateCallback);
}
static void EnumerateDirItems(const NWildcard::CCensorNode &curNode,
const UString &directory,
const UString &prefix,
bool checkNameFull,
CObjectVector<CDirItem> &dirItems,
bool enterToSubFolders)
{
NConsoleClose::CheckCtrlBreak();
NFind::CEnumeratorW enumerator(directory + wchar_t(kAnyStringWildcard));
NFind::CFileInfoW fileInfo;
while (enumerator.Next(fileInfo))
{
NConsoleClose::CheckCtrlBreak();
UString unicodeName = fileInfo.Name;
if (checkNameFull)
{
if (curNode.CheckNameFull(unicodeName))
AddDirFileInfo(prefix, directory + fileInfo.Name, fileInfo,
dirItems);
}
else
{
if (curNode.CheckNameRecursive(unicodeName))
AddDirFileInfo(prefix, directory + fileInfo.Name, fileInfo,
dirItems);
}
if (enterToSubFolders && fileInfo.IsDirectory())
{
const NWildcard::CCensorNode *nextNode = &curNode;
if (checkNameFull)
{
nextNode = ((NWildcard::CCensorNode *)&curNode)->FindSubNode(unicodeName);
if (nextNode == NULL)
nextNode = &curNode;
}
EnumerateDirItems(*nextNode,
directory + fileInfo.Name + wchar_t(kDirDelimiter),
prefix + unicodeName + wchar_t(kDirDelimiter),
nextNode != (&curNode), dirItems, true);
}
}
}
static void EnumerateItems(const NWildcard::CCensorNode &curNode,
const UString &directory,
const UString &prefix,
CObjectVector<CDirItem> &dirItems)
{
NConsoleClose::CheckCtrlBreak();
if (!curNode.GetAllowedRecursedNamesVector(false).IsEmpty() ||
!curNode.GetAllowedRecursedNamesVector(true).IsEmpty())
{
EnumerateDirItems(curNode, directory, prefix, true, dirItems,
true);
return;
}
if (!curNode.GetAllowedNamesVector(false, true).IsEmpty())
{
EnumerateDirItems(curNode, directory, prefix, true, dirItems,
false);
}
else
{
const UStringVector &directNames = curNode.GetAllowedNamesVector(false, false);
for (int i = 0; i < directNames.Size(); i++)
{
const UString &nameSpec = directNames[i];
if (curNode.CheckName(nameSpec, false, false))
continue;
NFind::CFileInfoW fileInfo;
if (!NFind::FindFile(directory + nameSpec, fileInfo))
continue;
AddDirFileInfo(prefix, directory + fileInfo.Name, fileInfo, dirItems);
}
}
for (int i = 0; i < curNode.SubNodes.Size(); i++)
{
const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i];
EnumerateItems(nextNode,
directory + nextNode.Name + wchar_t(kDirDelimiter),
prefix + nextNode.Name + wchar_t(kDirDelimiter),
dirItems);
}
}
HRESULT GetFileTime(IInArchive *archive, UINT32 index,
FILETIME &fileTime, const FILETIME &defaultFileTime)
{
CPropVariant property;
RINOK(archive->GetProperty(index, kpidLastWriteTime, &property));
if (property.vt == VT_FILETIME)
fileTime = property.filetime;
else if (property.vt == VT_EMPTY)
fileTime = defaultFileTime;
else
throw 4190407;
return S_OK;
}
HRESULT EnumerateInArchiveItems(const NWildcard::CCensor &censor,
IInArchive *archive,
const UString &defaultItemName,
const NWindows::NFile::NFind::CFileInfoW &archiveFileInfo,
CObjectVector<CArchiveItem> &archiveItems)
{
archiveItems.Clear();
UINT32 numItems;
RINOK(archive->GetNumberOfItems(&numItems));
archiveItems.Reserve(numItems);
for(UINT32 i = 0; i < numItems; i++)
{
CArchiveItem archiveItem;
NCOM::CPropVariant propVariantPath;
RINOK(archive->GetProperty(i, kpidPath, &propVariantPath));
UString filePath;
if(propVariantPath.vt == VT_EMPTY)
archiveItem.Name = defaultItemName;
else
{
if(propVariantPath.vt != VT_BSTR)
return E_FAIL;
archiveItem.Name = propVariantPath.bstrVal;
}
archiveItem.Censored = censor.CheckName(archiveItem.Name);
RINOK(GetFileTime(archive, i, archiveItem.LastWriteTime,
archiveFileInfo.LastWriteTime));
CPropVariant propertySize;
RINOK(archive->GetProperty(i, kpidSize, &propertySize));
if (archiveItem.SizeIsDefined = (propertySize.vt != VT_EMPTY))
archiveItem.Size = ConvertPropVariantToUINT64(propertySize);
CPropVariant propertyIsFolder;
RINOK(archive->GetProperty(i, kpidIsFolder, &propertyIsFolder));
if(propertyIsFolder.vt != VT_BOOL)
return E_FAIL;
archiveItem.IsDirectory = VARIANT_BOOLToBool(propertyIsFolder.boolVal);
archiveItem.IndexInServer = i;
archiveItems.Add(archiveItem);
}
return S_OK;
}
static HRESULT UpdateWithItemLists(
const CUpdateArchiveOptions &options,
IInArchive *archive,
const CObjectVector<CArchiveItem> &archiveItems,
const CObjectVector<CDirItem> &dirItems,
bool enablePercents)
{
for(int i = 0; i < options.Commands.Size(); i++)
{
const CUpdateArchiveCommand &command = options.Commands[i];
const UString &realArchivePath = command.ArchivePath;
if (i == 0 && options.UpdateArchiveItself)
{
if(archive != 0)
g_StdOut << kUpdatingArchiveMessage;
else
g_StdOut << kCreatingArchiveMessage;
g_StdOut << options.ArchivePath;
}
else
g_StdOut << kCreatingArchiveMessage << realArchivePath;
g_StdOut << endl << endl;
RINOK(Compress(command.ActionSet, archive,
options.MethodMode, realArchivePath,
archiveItems, dirItems, enablePercents,
options.SfxMode, options.SfxModule));
g_StdOut << endl;
}
return S_OK;
}
HRESULT UpdateArchiveStdMain(const NWildcard::CCensor &censor,
CUpdateArchiveOptions &options, const UString &workingDir,
IInArchive *archive,
const UString *defaultItemName,
const NWindows::NFile::NFind::CFileInfoW *archiveFileInfo,
bool enablePercents)
{
CObjectVector<CDirItem> dirItems;
g_StdOut << kScanningMessage;
EnumerateItems(censor._head, L"", L"", dirItems);
g_StdOut << endl;
CFileVectorBundle fileVectorBundle;
if(options.UpdateArchiveItself)
{
if (!NDirectory::MyGetTempFileName(workingDir, kTempArchiveFilePrefixString,
options.Commands[0].ArchivePath))
throw "create temp file error";
}
int i;
for(i = 0; i < options.Commands.Size(); i++)
{
fileVectorBundle.Add(options.Commands[i].ArchivePath,
i > 0 || !options.UpdateArchiveItself);
// SetBanOnFile(censor,currentDir, options.Commands[i].ArchivePath);
}
g_StdOut << endl;
CObjectVector<CArchiveItem> archiveItems;
if (archive != NULL)
{
RINOK(EnumerateInArchiveItems(censor,
archive, *defaultItemName, *archiveFileInfo, archiveItems));
}
RINOK(UpdateWithItemLists(options, archive, archiveItems, dirItems, enablePercents));
if (archive != NULL)
{
RINOK(archive->Close());
}
int firstNotTempArchiveIndex = options.UpdateArchiveItself ? 1 : 0;
for(i = options.Commands.Size() - 1; i >= firstNotTempArchiveIndex; i--)
fileVectorBundle.DisableDeleting(i);
if(options.UpdateArchiveItself)
{
try
{
if (archive != NULL)
if (!NDirectory::DeleteFileAlways(options.ArchivePath))
throw "delete file error";
if (!NDirectory::MyMoveFile(options.Commands[0].ArchivePath, options.ArchivePath))
{
g_StdOut << endl << "Error: ";
g_StdOut << NError::MyFormatMessage(::GetLastError()) << endl;
g_StdOut << options.Commands[0].ArchivePath << endl;
g_StdOut << options.ArchivePath << endl;
throw "move file error";
}
}
catch(...)
{
fileVectorBundle.DisableDeleting(0);
throw;
}
}
g_StdOut << kEverythingIsOk << endl;
return S_OK;
}

View File

@@ -1,41 +0,0 @@
// Update.h
#pragma once
#ifndef __UPDATE_H
#define __UPDATE_H
#include "Common/Wildcard.h"
#include "../Common/UpdateAction.h"
// #include "ProxyHandler.h"
#include "Windows/FileFind.h"
#include "../../Archive/IArchive.h"
#include "CompressionMode.h"
struct CUpdateArchiveCommand
{
UString ArchivePath;
NUpdateArchive::CActionSet ActionSet;
};
struct CUpdateArchiveOptions
{
CObjectVector<CUpdateArchiveCommand> Commands;
bool UpdateArchiveItself;
bool SfxMode;
UString SfxModule;
UString ArchivePath;
CCompressionMethodMode MethodMode;
};
HRESULT UpdateArchiveStdMain(const NWildcard::CCensor &censor,
CUpdateArchiveOptions &options, const UString &workingDir,
IInArchive *archive,
const UString *defaultItemName,
const NWindows::NFile::NFind::CFileInfoW *archiveFileInfo,
bool enablePercents);
#endif

View File

@@ -1,259 +0,0 @@
// UpdateCallback.cpp
#include "StdAfx.h"
#include "UpdateCallback.h"
#include "Common/StdInStream.h"
#include "Common/StdOutStream.h"
#include "Common/StringConvert.h"
#include "Common/Defs.h"
#include "Windows/PropVariant.h"
#include "../../Common/FileStreams.h"
// #include "Interface/EnumStatProp.h"
#include "ConsoleClose.h"
CUpdateCallbackImp::CUpdateCallbackImp():
m_PercentPrinter(1 << 16) {}
void CUpdateCallbackImp::Init(
const CObjectVector<CDirItem> *dirItems,
const CObjectVector<CArchiveItem> *archiveItems, // test CItemInfoExList
CObjectVector<CUpdatePair2> *updatePairs,
bool enablePercents,
bool passwordIsDefined,
const UString &password,
bool askPassword)
{
_passwordIsDefined = passwordIsDefined;
_password = password;
_askPassword = askPassword;
m_EnablePercents = enablePercents;
m_DirItems = dirItems;
m_ArchiveItems = archiveItems;
m_UpdatePairs = updatePairs;
m_PercentCanBePrint = false;
m_NeedBeClosed = false;
}
void CUpdateCallbackImp::Finilize()
{
if (m_NeedBeClosed)
{
if (m_EnablePercents)
{
m_PercentPrinter.ClosePrint();
m_PercentCanBePrint = false;
m_NeedBeClosed = false;
}
m_PercentPrinter.PrintNewLine();
}
}
STDMETHODIMP CUpdateCallbackImp::SetTotal(UINT64 size)
{
if (m_EnablePercents)
m_PercentPrinter.SetTotal(size);
return S_OK;
}
STDMETHODIMP CUpdateCallbackImp::SetCompleted(const UINT64 *completeValue)
{
if (completeValue != NULL)
{
if (m_EnablePercents)
{
m_PercentPrinter.SetRatio(*completeValue);
if (m_PercentCanBePrint)
m_PercentPrinter.PrintRatio();
}
}
if (NConsoleClose::TestBreakSignal())
return E_ABORT;
return S_OK;
}
/*
STATPROPSTG kProperties[] =
{
{ NULL, kpidPath, VT_BSTR},
{ NULL, kpidIsFolder, VT_BOOL},
{ NULL, kpidSize, VT_UI8},
{ NULL, kpidLastAccessTime, VT_FILETIME},
{ NULL, kpidCreationTime, VT_FILETIME},
{ NULL, kpidLastWriteTime, VT_FILETIME},
{ NULL, kpidAttributes, VT_UI4},
{ NULL, kpidIsAnti, VT_BOOL}
};
*/
STDMETHODIMP CUpdateCallbackImp::EnumProperties(IEnumSTATPROPSTG **enumerator)
{
return E_NOTIMPL;
/*
return CStatPropEnumerator::CreateEnumerator(kProperties,
sizeof(kProperties) / sizeof(kProperties[0]), enumerator);
*/
}
STDMETHODIMP CUpdateCallbackImp::GetUpdateItemInfo(UINT32 index,
INT32 *newData, INT32 *newProperties, UINT32 *indexInArchive)
{
if (NConsoleClose::TestBreakSignal())
return E_ABORT;
const CUpdatePair2 &updatePair = (*m_UpdatePairs)[index];
if(newData != NULL)
*newData = BoolToInt(updatePair.NewData);
if(newProperties != NULL)
*newProperties = BoolToInt(updatePair.NewProperties);
if(indexInArchive != NULL)
{
if (updatePair.ExistInArchive)
*indexInArchive = (*m_ArchiveItems)[updatePair.ArchiveItemIndex].IndexInServer;
else
*indexInArchive = UINT32(-1);
}
return S_OK;
}
STDMETHODIMP CUpdateCallbackImp::GetProperty(UINT32 index, PROPID propID, PROPVARIANT *value)
{
const CUpdatePair2 &updatePair = (*m_UpdatePairs)[index];
NWindows::NCOM::CPropVariant propVariant;
if (propID == kpidIsAnti)
{
propVariant = updatePair.IsAnti;
propVariant.Detach(value);
return S_OK;
}
if (updatePair.IsAnti)
{
switch(propID)
{
case kpidIsFolder:
case kpidPath:
break;
case kpidSize:
propVariant = (UINT64)0;
propVariant.Detach(value);
return S_OK;
default:
propVariant.Detach(value);
return S_OK;
}
}
if(updatePair.ExistOnDisk)
{
const CDirItem &dirItem =
(*m_DirItems)[updatePair.DirItemIndex];
switch(propID)
{
case kpidPath:
propVariant = dirItem.Name;
break;
case kpidIsFolder:
propVariant = dirItem.IsDirectory();
break;
case kpidSize:
propVariant = dirItem.Size;
break;
case kpidAttributes:
propVariant = dirItem.Attributes;
break;
case kpidLastAccessTime:
propVariant = dirItem.LastAccessTime;
break;
case kpidCreationTime:
propVariant = dirItem.CreationTime;
break;
case kpidLastWriteTime:
propVariant = dirItem.LastWriteTime;
break;
}
}
propVariant.Detach(value);
return S_OK;
}
STDMETHODIMP CUpdateCallbackImp::GetStream(UINT32 index,
IInStream **inStream)
{
const CUpdatePair2 &updatePair = (*m_UpdatePairs)[index];
if(!updatePair.NewData)
return E_FAIL;
if (NConsoleClose::TestBreakSignal())
return E_ABORT;
Finilize();
if(updatePair.IsAnti)
{
m_PercentPrinter.PrintString("Anti item ");
m_PercentPrinter.PrintString(
(*m_ArchiveItems)[updatePair.ArchiveItemIndex].Name);
}
else
{
const CDirItem &dirItem =
(*m_DirItems)[updatePair.DirItemIndex];
m_PercentPrinter.PrintString("Compressing ");
m_PercentPrinter.PrintString(dirItem.Name);
}
if (m_EnablePercents)
{
m_PercentCanBePrint = true;
m_PercentPrinter.PreparePrint();
m_PercentPrinter.RePrintRatio();
}
if(updatePair.IsAnti)
return S_OK;
const CDirItem &dirItem =
(*m_DirItems)[updatePair.DirItemIndex];
if(dirItem.IsDirectory())
return S_OK;
CInFileStream *inStreamSpec = new CInFileStream;
CMyComPtr<IInStream> inStreamLoc(inStreamSpec);
if(!inStreamSpec->Open(dirItem.FullPath))
return ::GetLastError();
*inStream = inStreamLoc.Detach();
return S_OK;
}
STDMETHODIMP CUpdateCallbackImp::SetOperationResult(INT32 operationResult)
{
m_NeedBeClosed = true;
return S_OK;
}
STDMETHODIMP CUpdateCallbackImp::CryptoGetTextPassword2(INT32 *passwordIsDefined, BSTR *password)
{
if (!_passwordIsDefined)
{
if (_askPassword)
{
g_StdOut << "\nEnter password:";
AString oemPassword = g_StdIn.ScanStringUntilNewLine();
_password = MultiByteToUnicodeString(oemPassword, CP_OEMCP);
_passwordIsDefined = true;
}
}
*passwordIsDefined = BoolToInt(_passwordIsDefined);
CMyComBSTR tempName(_password);
*password = tempName.Detach();
return S_OK;
}

View File

@@ -1,78 +0,0 @@
// UpdateCallback.h
#pragma once
#ifndef __UPDATECALLBACK_H
#define __UPDATECALLBACK_H
// #include "../Format/Common/ArchiveInterface.h"
#include "Common/MyCom.h"
#include "Common/String.h"
#include "../../IPassword.h"
#include "../Common/UpdatePair.h"
#include "../Common/UpdateProduce.h"
#include "PercentPrinter.h"
class CUpdateCallbackImp:
public IArchiveUpdateCallback,
public ICryptoGetTextPassword2,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP1(ICryptoGetTextPassword2)
// IProfress
STDMETHOD(SetTotal)(UINT64 size);
STDMETHOD(SetCompleted)(const UINT64 *completeValue);
// IUpdateCallback
STDMETHOD(EnumProperties)(IEnumSTATPROPSTG **enumerator);
STDMETHOD(GetUpdateItemInfo)(UINT32 index,
INT32 *newData, INT32 *newProperties, UINT32 *indexInArchive);
STDMETHOD(GetProperty)(UINT32 index, PROPID propID, PROPVARIANT *value);
STDMETHOD(GetStream)(UINT32 index, IInStream **inStream);
STDMETHOD(SetOperationResult)(INT32 operationResult);
STDMETHOD(CryptoGetTextPassword2)(INT32 *passwordIsDefined, BSTR *password);
private:
const CObjectVector<CDirItem> *m_DirItems;
const CObjectVector<CArchiveItem> *m_ArchiveItems;
const CObjectVector<CUpdatePair2> *m_UpdatePairs;
CPercentPrinter m_PercentPrinter;
bool m_EnablePercents;
bool m_PercentCanBePrint;
bool m_NeedBeClosed;
bool _passwordIsDefined;
UString _password;
bool _askPassword;
public:
CUpdateCallbackImp();
~CUpdateCallbackImp()
{ Finilize(); }
void Init(
const CObjectVector<CDirItem> *dirItems,
const CObjectVector<CArchiveItem> *archiveItems, // test CItemInfoExList
CObjectVector<CUpdatePair2> *updatePairs,
bool enablePercents,
bool passwordIsDefined,
const UString &password,
bool askPassword);
void Finilize();
};
#endif

View File

@@ -0,0 +1,159 @@
// UpdateCallbackConsole.cpp
#include "StdAfx.h"
#include "UpdateCallbackConsole.h"
#include "Windows/Error.h"
#include "ConsoleClose.h"
#include "UserInputUtils.h"
using namespace NWindows;
static const char *kCreatingArchiveMessage = "Creating archive ";
static const char *kUpdatingArchiveMessage = "Updating archive ";
static const char *kScanningMessage = "Scanning";
static const char *kNoFilesScannedMessage = "No files scanned";
static const char *kTotalFilesAddedMessage = "Total files added to archive: ";
HRESULT CUpdateCallbackConsole::OpenResult(const wchar_t *name, HRESULT result)
{
(*OutStream) << endl;
if (result != S_OK)
(*OutStream) << "Error: " << name << " is not supported archive" << endl;
return S_OK;
}
HRESULT CUpdateCallbackConsole::StartScanning()
{
(*OutStream) << kScanningMessage;
return S_OK;
}
HRESULT CUpdateCallbackConsole::FinishScanning()
{
(*OutStream) << endl << endl;
return S_OK;
}
HRESULT CUpdateCallbackConsole::StartArchive(const wchar_t *name, bool updating)
{
if(updating)
(*OutStream) << kUpdatingArchiveMessage;
else
(*OutStream) << kCreatingArchiveMessage;
if (name != 0)
(*OutStream) << name;
else
(*OutStream) << "StdOut";
(*OutStream) << endl << endl;
return S_OK;
}
HRESULT CUpdateCallbackConsole::FinishArchive()
{
(*OutStream) << endl;
return S_OK;
}
HRESULT CUpdateCallbackConsole::CheckBreak()
{
if (NConsoleClose::TestBreakSignal())
return E_ABORT;
return S_OK;
}
HRESULT CUpdateCallbackConsole::Finilize()
{
if (m_NeedBeClosed)
{
if (EnablePercents)
{
m_PercentPrinter.ClosePrint();
m_PercentCanBePrint = false;
}
if (!StdOutMode)
m_PercentPrinter.PrintNewLine();
m_NeedBeClosed = false;
}
return S_OK;
}
HRESULT CUpdateCallbackConsole::SetTotal(UInt64 size)
{
if (EnablePercents)
m_PercentPrinter.SetTotal(size);
return S_OK;
}
HRESULT CUpdateCallbackConsole::SetCompleted(const UInt64 *completeValue)
{
if (completeValue != NULL)
{
if (EnablePercents)
{
m_PercentPrinter.SetRatio(*completeValue);
if (m_PercentCanBePrint)
m_PercentPrinter.PrintRatio();
}
}
if (NConsoleClose::TestBreakSignal())
return E_ABORT;
return S_OK;
}
HRESULT CUpdateCallbackConsole::GetStream(const wchar_t *name, bool isAnti)
{
if (StdOutMode)
return S_OK;
if(isAnti)
m_PercentPrinter.PrintString("Anti item ");
else
m_PercentPrinter.PrintString("Compressing ");
m_PercentPrinter.PrintString(name);
if (EnablePercents)
{
m_PercentCanBePrint = true;
m_PercentPrinter.PreparePrint();
m_PercentPrinter.RePrintRatio();
}
return S_OK;
}
HRESULT CUpdateCallbackConsole::OpenFileError(const wchar_t *name, DWORD systemError)
{
FailedCodes.Add(systemError);
FailedFiles.Add(name);
// if (systemError == ERROR_SHARING_VIOLATION)
{
m_PercentPrinter.ClosePrint();
m_PercentPrinter.PrintNewLine();
m_PercentPrinter.PrintString("WARNING: ");
m_PercentPrinter.PrintString(NError::MyFormatMessageW(systemError));
return S_FALSE;
}
return systemError;
}
HRESULT CUpdateCallbackConsole::SetOperationResult(Int32 operationResult)
{
m_NeedBeClosed = true;
return S_OK;
}
HRESULT CUpdateCallbackConsole::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
{
if (!PasswordIsDefined)
{
if (AskPassword)
{
Password = GetPassword(OutStream);
PasswordIsDefined = true;
}
}
*passwordIsDefined = BoolToInt(PasswordIsDefined);
CMyComBSTR tempName(Password);
*password = tempName.Detach();
return S_OK;
}

View File

@@ -0,0 +1,68 @@
// UpdateCallbackConsole.h
#ifndef __UPDATECALLBACKCONSOLE_H
#define __UPDATECALLBACKCONSOLE_H
#include "Common/String.h"
#include "Common/StdOutStream.h"
#include "PercentPrinter.h"
#include "../Common/Update.h"
class CUpdateCallbackConsole: public IUpdateCallbackUI2
{
CPercentPrinter m_PercentPrinter;
bool m_PercentCanBePrint;
bool m_NeedBeClosed;
CStdOutStream *OutStream;
public:
bool EnablePercents;
bool StdOutMode;
bool PasswordIsDefined;
UString Password;
bool AskPassword;
CUpdateCallbackConsole():
m_PercentPrinter(1 << 16),
PasswordIsDefined(false),
AskPassword(false),
StdOutMode(false),
EnablePercents(true)
{}
~CUpdateCallbackConsole() { Finilize(); }
void Init(CStdOutStream *outStream)
{
m_PercentCanBePrint = false;
m_NeedBeClosed = false;
FailedFiles.Clear();
FailedCodes.Clear();
OutStream = outStream;
m_PercentPrinter.OutStream = outStream;
}
HRESULT OpenResult(const wchar_t *name, HRESULT result);
HRESULT StartScanning();
HRESULT FinishScanning();
HRESULT StartArchive(const wchar_t *name, bool updating);
HRESULT FinishArchive();
HRESULT CheckBreak();
HRESULT Finilize();
HRESULT SetTotal(UInt64 size);
HRESULT SetCompleted(const UInt64 *completeValue);
HRESULT GetStream(const wchar_t *name, bool isAnti);
HRESULT OpenFileError(const wchar_t *name, DWORD systemError);
HRESULT SetOperationResult(Int32 operationResult);
HRESULT CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password);
UStringVector FailedFiles;
CRecordVector<HRESULT> FailedCodes;
};
#endif

View File

@@ -3,16 +3,16 @@
#include "StdAfx.h"
#include "Common/StdInStream.h"
#include "Common/StdOutStream.h"
#include "Common/StringConvert.h"
#include "UserInputUtils.h"
static const char kYes = 'Y';
static const char kNo = 'N';
static const char kYesAll = 'A';
static const char kNoAll = 'S';
static const char kAutoRename = 'U';
static const char kQuit = 'Q';
static const char kYes = 'Y';
static const char kNo = 'N';
static const char kYesAll = 'A';
static const char kNoAll = 'S';
static const char kAutoRename = 'U';
static const char kQuit = 'Q';
static const char *kFirstQuestionMessage = "?\n";
static const char *kHelpQuestionMessage =
@@ -22,12 +22,12 @@ static const char *kHelpQuestionMessage =
// in: anAll
// out: anAll, anYes;
NUserAnswerMode::EEnum ScanUserYesNoAllQuit()
NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream)
{
g_StdOut << kFirstQuestionMessage;
(*outStream) << kFirstQuestionMessage;
do
{
g_StdOut << kHelpQuestionMessage;
(*outStream) << kHelpQuestionMessage;
AString scannedString = g_StdIn.ScanStringUntilNewLine();
scannedString.Trim();
if(!scannedString.IsEmpty())
@@ -49,3 +49,10 @@ NUserAnswerMode::EEnum ScanUserYesNoAllQuit()
}
while(true);
}
UString GetPassword(CStdOutStream *outStream)
{
(*outStream) << "\nEnter password:";
AString oemPassword = g_StdIn.ScanStringUntilNewLine();
return MultiByteToUnicodeString(oemPassword, CP_OEMCP);
}

View File

@@ -1,10 +1,10 @@
// UserInputUtils.h
#pragma once
#ifndef __USERINPUTUTILS_H
#define __USERINPUTUTILS_H
#include "Common/StdOutStream.h"
namespace NUserAnswerMode {
enum EEnum
@@ -18,6 +18,7 @@ enum EEnum
};
}
NUserAnswerMode::EEnum ScanUserYesNoAllQuit();
NUserAnswerMode::EEnum ScanUserYesNoAllQuit(CStdOutStream *outStream);
UString GetPassword(CStdOutStream *outStream);
#endif

View File

@@ -66,8 +66,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,12,0,0
PRODUCTVERSION 3,12,0,0
FILEVERSION 4,20,0,0
PRODUCTVERSION 4,20,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -85,14 +85,14 @@ BEGIN
VALUE "Comments", "\0"
VALUE "CompanyName", "Igor Pavlov\0"
VALUE "FileDescription", "7-Zip Console version\0"
VALUE "FileVersion", "3, 12, 0, 0\0"
VALUE "FileVersion", "4, 20, 0, 0\0"
VALUE "InternalName", "7z\0"
VALUE "LegalCopyright", "Copyright (C) 1999-2003 Igor Pavlov\0"
VALUE "LegalCopyright", "Copyright (C) 1999-2005 Igor Pavlov\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "7z.exe\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "7-Zip\0"
VALUE "ProductVersion", "3, 12, 0, 0\0"
VALUE "ProductVersion", "4, 20, 0, 0\0"
VALUE "SpecialBuild", "\0"
END
END

View File

@@ -13,7 +13,6 @@
#include "Windows/FileFind.h"
#include "Windows/FileDir.h"
#include "Windows/FileName.h"
#include "Windows/System.h"
#include "Windows/Thread.h"
#include "Windows/Window.h"
@@ -260,13 +259,18 @@ static UString GetSubFolderNameForExtract(const UString &archiveName)
{
int dotPos = archiveName.ReverseFind('.');
if (dotPos >= 0)
return archiveName.Left(dotPos);
{
UString res = archiveName.Left(dotPos);
res.TrimRight();
return res;
}
return archiveName + UString(L"~");
}
STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
UINT commandIDFirst, UINT commandIDLast, UINT flags)
{
LoadLangOneTime();
if(_fileNames.Size() == 0)
return E_FAIL;
UINT currentCommandID = commandIDFirst;
@@ -311,7 +315,6 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
if(_fileNames.Size() == 1 && currentCommandID + 6 <= commandIDLast)
{
const UString &fileName = _fileNames.Front();
UString folderPrefix;
NFile::NDirectory::GetOnlyDirPrefix(fileName, folderPrefix);
@@ -328,7 +331,28 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, GetSystemString(mainString));
_commandMap.push_back(commandMapItem);
}
}
}
if(_fileNames.Size() > 0 && currentCommandID + 10 <= commandIDLast)
{
bool thereAreFolders = false;
for(int i = 0; i < _fileNames.Size(); i++)
{
NFile::NFind::CFileInfoW fileInfo;
if (!NFile::NFind::FindFile(_fileNames[i], fileInfo))
return E_FAIL;
if (fileInfo.IsDirectory())
thereAreFolders = true;
}
const UString &fileName = _fileNames.Front();
if (!thereAreFolders)
{
UString folderPrefix;
NFile::NDirectory::GetOnlyDirPrefix(fileName, folderPrefix);
NFile::NFind::CFileInfoW fileInfo;
if (!NFile::NFind::FindFile(fileName, fileInfo))
return E_FAIL;
// Extract
if ((contextMenuFlags & NContextMenuFlags::kExtract) != 0)
{
@@ -357,14 +381,17 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
CCommandMapItem commandMapItem;
UString s;
FillCommand2(kExtractTo, s, commandMapItem);
UString folder = GetSubFolderNameForExtract(fileInfo.Name) +
UString(L'\\');
UString folder;
if (_fileNames.Size() == 1)
folder = GetSubFolderNameForExtract(fileInfo.Name);
else
folder = L'*';
folder += L'\\';
commandMapItem.Folder = folderPrefix + folder;
s = MyFormatNew(s, folder);
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, GetSystemString(s));
_commandMap.push_back(commandMapItem);
}
// Test
if ((contextMenuFlags & NContextMenuFlags::kTest) != 0)
{
@@ -374,11 +401,6 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
_commandMap.push_back(commandMapItem);
}
}
}
if(_fileNames.Size() > 0 && currentCommandID + 6 <= commandIDLast)
{
const UString &fileName = _fileNames.Front();
UString archiveName = CreateArchiveName(fileName, _fileNames.Size() > 1, false);
UString archiveName7z = archiveName + L".7z";
UString archivePathPrefix;
@@ -388,7 +410,8 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
if ((contextMenuFlags & NContextMenuFlags::kCompress) != 0)
{
CCommandMapItem commandMapItem;
commandMapItem.Archive = archivePathPrefix + archiveName;
commandMapItem.Folder = archivePathPrefix;
commandMapItem.Archive = archiveName;
FillCommand(kCompress, mainString, commandMapItem);
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, GetSystemString(mainString));
_commandMap.push_back(commandMapItem);
@@ -401,7 +424,8 @@ STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
CCommandMapItem commandMapItem;
UString s;
FillCommand2(kCompressTo, s, commandMapItem);
commandMapItem.Archive = archivePathPrefix + archiveName7z;
commandMapItem.Folder = archivePathPrefix;
commandMapItem.Archive = archiveName7z;
UString t = UString(L"\"") + archiveName7z + UString(L"\"");
s = MyFormatNew(s, t);
MyInsertMenu(popupMenu, subIndex++, currentCommandID++, GetSystemString(s));
@@ -609,20 +633,20 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo)
params += L" \"";
params += _fileNames[0];
params += L"\"";
MyCreateProcess(params);
MyCreateProcess(params, 0);
break;
}
case kExtract:
case kExtractHere:
case kExtractTo:
{
ExtractArchive(_fileNames[0], commandMapItem.Folder,
ExtractArchives(_fileNames, commandMapItem.Folder,
(commandInternalID == kExtract));
break;
}
case kTest:
{
TestArchive(_fileNames[0]);
TestArchives(_fileNames);
break;
}
case kCompress:
@@ -634,7 +658,8 @@ STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo)
(commandInternalID == kCompressToEmail);
bool showDialog = (commandInternalID == kCompress) ||
(commandInternalID == kCompressEmail);
CompressFiles(commandMapItem.Archive, _fileNames, email, showDialog);
CompressFiles(commandMapItem.Folder, commandMapItem.Archive,
_fileNames, email, showDialog);
break;
}
}

View File

@@ -1,7 +1,5 @@
// ContextMenu.h
#pragma once
#ifndef __CONTEXTMENU_H
#define __CONTEXTMENU_H
@@ -9,10 +7,14 @@
DEFINE_GUID(CLSID_CZipContextMenu,
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00);
#include <vector>
#include "Common/String.h"
#include "../../FileManager/PluginInterface.h"
class CZipContextMenu:
public IContextMenu,
public IShellExtInit,
@@ -89,4 +91,4 @@ private:
CCommandMapItem &commandMapItem);
};
#endif
#endif

View File

@@ -1,7 +1,5 @@
// ContextMenuFlags.h
#pragma once
#ifndef __SEVENZIP_CONTEXTMENUFLAGS_H
#define __SEVENZIP_CONTEXTMENUFLAGS_H

View File

@@ -1,4 +1,4 @@
// DLLExports.cpp : Implementation of DLL Exports.
// DLLExports.cpp
#include "StdAfx.h"
@@ -8,9 +8,9 @@
#include <ShlGuid.h>
#include <windows.h>
// #include "../../Compress/Interface/CompressInterface.h"
#include "../../IPassword.h"
#include "../Agent/Agent.h"
#include "../../FileManager/LangUtils.h"
#include "Common/ComTry.h"
#include "ContextMenu.h"
@@ -44,9 +44,9 @@ extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID)
{
// setlocale(LC_COLLATE, ".ACP");
g_hInstance = hInstance;
if (dwReason == DLL_PROCESS_ATTACH)
{
g_hInstance = hInstance;
#ifdef UNICODE
if (!IsItWindowsNT())
return FALSE;
@@ -56,7 +56,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID)
}
else if (dwReason == DLL_PROCESS_DETACH)
_Module.Term();
return TRUE; // ok
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
@@ -93,6 +93,7 @@ STDAPI CreateObject(
const GUID *interfaceID,
void **outObject)
{
LoadLangOneTime();
COM_TRY_BEGIN
*outObject = 0;
if (*classID == CLSID_CAgentArchiveHandler)

View File

@@ -182,6 +182,14 @@ SOURCE=.\StdAfx.h
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\Common\ArchiveExtractCallback.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\ArchiveExtractCallback.h
# End Source File
# Begin Source File
SOURCE=..\Common\ArchiveName.cpp
# End Source File
# Begin Source File
@@ -190,6 +198,14 @@ SOURCE=..\Common\ArchiveName.h
# End Source File
# Begin Source File
SOURCE=..\Common\ArchiveOpenCallback.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\ArchiveOpenCallback.h
# End Source File
# Begin Source File
SOURCE=..\Common\ArchiverInfo.cpp
# End Source File
# Begin Source File
@@ -266,6 +282,14 @@ SOURCE=..\Common\UpdateAction.h
# End Source File
# Begin Source File
SOURCE=..\Common\UpdateCallback.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\UpdateCallback.h
# End Source File
# Begin Source File
SOURCE=..\Common\UpdatePair.cpp
# End Source File
# Begin Source File
@@ -396,14 +420,6 @@ SOURCE=..\Agent\AgentProxy.h
# End Source File
# Begin Source File
SOURCE=..\Agent\ArchiveExtractCallback.cpp
# End Source File
# Begin Source File
SOURCE=..\Agent\ArchiveExtractCallback.h
# End Source File
# Begin Source File
SOURCE=..\Agent\ArchiveFolder.cpp
# End Source File
# Begin Source File
@@ -416,39 +432,19 @@ SOURCE=..\Agent\ArchiveFolderOut.cpp
# End Source File
# Begin Source File
SOURCE=..\Agent\ArchiveUpdateCallback.cpp
# End Source File
# Begin Source File
SOURCE=..\Agent\ArchiveUpdateCallback.h
SOURCE=..\Agent\IFileExtractCallback.h
# End Source File
# Begin Source File
SOURCE=..\Agent\IFolderArchive.h
# End Source File
# End Group
# Begin Group "Spec Interfaces"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\Format\Common\ArchiveInterface.h
SOURCE=..\Agent\UpdateCallbackAgent.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\ArchiveStyleDirItemInfo.h
# End Source File
# Begin Source File
SOURCE=..\..\Compress\Interface\CompressInterface.h
# End Source File
# Begin Source File
SOURCE=..\Common\FolderArchiveInterface.h
# End Source File
# Begin Source File
SOURCE=..\Format\Common\FormatCryptoInterface.h
SOURCE=..\Agent\UpdateCallbackAgent.h
# End Source File
# End Group
# Begin Group "FileManager"
@@ -507,6 +503,14 @@ SOURCE=..\..\FileManager\RegistryUtils.h
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\..\Common\Alloc.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\Alloc.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Common\IntToString.cpp
# End Source File
# Begin Source File
@@ -731,14 +735,6 @@ SOURCE=..\..\..\Windows\Synchronization.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\System.cpp
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\System.h
# End Source File
# Begin Source File
SOURCE=..\..\..\Windows\Window.cpp
# End Source File
# Begin Source File
@@ -797,7 +793,7 @@ SOURCE=.\OptionsDialog.h
# End Source File
# Begin Source File
SOURCE=.\RegistryContextMenu..cpp
SOURCE=.\RegistryContextMenu.cpp
# End Source File
# Begin Source File

Some files were not shown because too many files have changed in this diff Show More