This commit is contained in:
Igor Pavlov
2003-12-11 00:00:00 +00:00
committed by Kornel Lesiński
commit 8c1b5c7b7e
982 changed files with 118799 additions and 0 deletions

407
7zip/UI/Agent/Agent.cpp Executable file
View File

@@ -0,0 +1,407 @@
// Agent.cpp
#include "StdAfx.h"
#include "Common/StringConvert.h"
#include "Common/ComTry.h"
#include "Windows/Defs.h"
#include "Windows/PropVariant.h"
#include "Windows/FileFind.h"
#include "../Common/OpenArchive.h"
#include "../Common/DefaultName.h"
#include "Agent.h"
#include "ArchiveExtractCallback.h"
#ifdef FORMAT_7Z
#include "../../Archive/7z/7zHandler.h"
#endif
using namespace NWindows;
STDMETHODIMP CAgentFolder::GetAgentFolder(CAgentFolder **agentFolder)
{
*agentFolder = this;
return S_OK;
}
STDMETHODIMP CAgentFolder::LoadItems()
{
return S_OK;
}
STDMETHODIMP CAgentFolder::GetNumberOfItems(UINT32 *numItems)
{
*numItems = _proxyFolderItem->Folders.Size() +
_proxyFolderItem->Files.Size();
return S_OK;
}
/*
STDMETHODIMP CAgentFolder::GetNumberOfSubFolders(UINT32 *aNumSubFolders)
{
*aNumSubFolders = _proxyFolderItem->Folders.Size();
return S_OK;
}
*/
STDMETHODIMP CAgentFolder::GetProperty(UINT32 itemIndex, PROPID propID, PROPVARIANT *value)
{
NCOM::CPropVariant propVariant;
if (itemIndex < (UINT32)_proxyFolderItem->Folders.Size())
{
const CProxyFolder &item = _proxyFolderItem->Folders[itemIndex];
switch(propID)
{
case kpidIsFolder:
propVariant = true;
break;
case kpidName:
propVariant = item.Name;
break;
default:
if (item.IsLeaf)
return _agentSpec->_archive->GetProperty(item.Index,
propID, value);
}
}
else
{
itemIndex -= _proxyFolderItem->Folders.Size();
const CProxyFile &item = _proxyFolderItem->Files[itemIndex];
switch(propID)
{
case kpidIsFolder:
propVariant = false;
break;
case kpidName:
propVariant = item.Name;
break;
default:
return _agentSpec->_archive->GetProperty(item.Index,
propID, value);
}
}
propVariant.Detach(value);
return S_OK;
}
STDMETHODIMP CAgentFolder::BindToFolder(UINT32 index, IFolderFolder **resultFolder)
{
COM_TRY_BEGIN
if (index >= (UINT32)_proxyFolderItem->Folders.Size())
return E_INVALIDARG;
CAgentFolder *folderSpec = new CAgentFolder;
CMyComPtr<IFolderFolder> agentFolder = folderSpec;
folderSpec->Init(_proxyArchive, &_proxyFolderItem->Folders[index],
this, _agentSpec);
*resultFolder = agentFolder.Detach();
return S_OK;
COM_TRY_END
}
STDMETHODIMP CAgentFolder::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder)
{
COM_TRY_BEGIN
int index = _proxyFolderItem->FindDirSubItemIndex(name);
if (index < 0)
return E_INVALIDARG;
return BindToFolder(index, resultFolder);
COM_TRY_END
}
STDMETHODIMP CAgentFolder::BindToParentFolder(IFolderFolder **resultFolder)
{
COM_TRY_BEGIN
CMyComPtr<IFolderFolder> parentFolder = _parentFolder;
*resultFolder = parentFolder.Detach();
return S_OK;
COM_TRY_END
}
STDMETHODIMP CAgentFolder::GetName(BSTR *name)
{
CMyComBSTR temp = _proxyFolderItem->Name;
*name = temp.Detach();
return S_OK;
}
#ifdef NEW_FOLDER_INTERFACE
struct CArchiveItemPropertyTemp
{
UString Name;
PROPID ID;
VARTYPE Type;
};
STDMETHODIMP CAgentFolder::GetNumberOfProperties(UINT32 *numProperties)
{
COM_TRY_BEGIN
return _agentSpec->_archive->GetNumberOfProperties(numProperties);
COM_TRY_END
}
STDMETHODIMP CAgentFolder::GetPropertyInfo(UINT32 index,
BSTR *name, PROPID *propID, VARTYPE *varType)
{
COM_TRY_BEGIN
RINOK(_agentSpec->_archive->GetPropertyInfo(index, name, propID, varType));
if (*propID == kpidPath)
*propID = kpidName;
return S_OK;
COM_TRY_END
}
STDMETHODIMP CAgentFolder::GetTypeID(BSTR *name)
{
COM_TRY_BEGIN
UString temp = UString(L"7-Zip.") + _agentSpec->ArchiveType;
CMyComBSTR bstrTemp = temp;
*name = bstrTemp.Detach();
return S_OK;
COM_TRY_END
}
STDMETHODIMP CAgentFolder::GetPath(BSTR *path)
{
COM_TRY_BEGIN
UStringVector pathParts;
pathParts.Clear();
CMyComPtr<IFolderFolder> currentFolder = this;
while (true)
{
CMyComPtr<IFolderFolder> newFolder;
currentFolder->BindToParentFolder(&newFolder);
if (newFolder == NULL)
break;
CMyComBSTR aName;
currentFolder->GetName(&aName);
pathParts.Insert(0, (const wchar_t *)aName);
currentFolder = newFolder;
}
UString prefix;
for(int i = 0; i < pathParts.Size(); i++)
{
prefix += pathParts[i];
prefix += L'\\';
}
CMyComBSTR tempPath = prefix;
*path = tempPath.Detach();
return S_OK;
COM_TRY_END
}
#endif
STDMETHODIMP CAgentFolder::Extract(const UINT32 *indices,
UINT32 numItems,
NExtractionMode::NPath::EEnum pathMode,
NExtractionMode::NOverwrite::EEnum overwriteMode,
const wchar_t *path,
INT32 testMode,
IFolderArchiveExtractCallback *extractCallback2)
{
COM_TRY_BEGIN
CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
UStringVector pathParts;
CProxyFolder *currentProxyFolder = _proxyFolderItem;
while (currentProxyFolder->Parent)
{
pathParts.Insert(0, currentProxyFolder->Name);
currentProxyFolder = currentProxyFolder->Parent;
}
extractCallbackSpec->Init(_agentSpec->_archive,
extractCallback2,
path,
pathMode,
overwriteMode,
pathParts,
_agentSpec->DefaultName,
_agentSpec->DefaultTime,
_agentSpec->DefaultAttributes
// ,_agentSpec->_srcDirectoryPrefix
);
CUIntVector realIndices;
_proxyFolderItem->GetRealIndices(indices, numItems, realIndices);
return _agentSpec->_archive->Extract(&realIndices.Front(),
realIndices.Size(), testMode, extractCallback);
COM_TRY_END
}
/////////////////////////////////////////
// CAgent
CAgent::CAgent():
_proxyArchive(NULL)
{
}
CAgent::~CAgent()
{
if (_proxyArchive != NULL)
delete _proxyArchive;
}
STDMETHODIMP CAgent::Open(
const wchar_t *filePath,
BSTR *archiveType,
// CLSID *clsIDResult,
IArchiveOpenCallback *openArchiveCallback)
{
COM_TRY_BEGIN
_archiveFilePath = filePath;
NFile::NFind::CFileInfoW fileInfo;
if (!NFile::NFind::FindFile(_archiveFilePath, fileInfo))
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);
RINOK(res);
DefaultName = GetDefaultName(_archiveFilePath,
archiverInfo.Extensions[subExtIndex].Extension,
archiverInfo.Extensions[subExtIndex].AddExtension);
DefaultTime = fileInfo.LastWriteTime;
DefaultAttributes = fileInfo.Attributes;
ArchiveType = archiverInfo.Name;
if (archiveType != 0)
{
CMyComBSTR name = archiverInfo.Name;
*archiveType = name.Detach();
}
return S_OK;
COM_TRY_END
}
STDMETHODIMP CAgent::ReOpen(
// const wchar_t *filePath,
IArchiveOpenCallback *openArchiveCallback)
{
COM_TRY_BEGIN
if (_proxyArchive != NULL)
{
delete _proxyArchive;
_proxyArchive = NULL;
}
RINOK(ReOpenArchive(_archive, _archiveFilePath));
return ReadItems();
COM_TRY_END
}
STDMETHODIMP CAgent::Close()
{
COM_TRY_BEGIN
return _archive->Close();
COM_TRY_END
}
/*
STDMETHODIMP CAgent::EnumProperties(IEnumSTATPROPSTG **EnumProperties)
{
return _archive->EnumProperties(EnumProperties);
}
*/
HRESULT CAgent::ReadItems()
{
if (_proxyArchive != NULL)
return S_OK;
_proxyArchive = new CProxyArchive();
return _proxyArchive->Load(_archive,
DefaultName,
// _defaultTime,
// _defaultAttributes,
NULL);
}
STDMETHODIMP CAgent::BindToRootFolder(IFolderFolder **resultFolder)
{
COM_TRY_BEGIN
RINOK(ReadItems());
CAgentFolder *folderSpec = new CAgentFolder;
CMyComPtr<IFolderFolder> rootFolder = folderSpec;
folderSpec->Init(_proxyArchive, &_proxyArchive->RootFolder, NULL, this);
*resultFolder = rootFolder.Detach();
return S_OK;
COM_TRY_END
}
STDMETHODIMP CAgent::Extract(
NExtractionMode::NPath::EEnum pathMode,
NExtractionMode::NOverwrite::EEnum overwriteMode,
const wchar_t *path,
INT32 testMode,
IFolderArchiveExtractCallback *extractCallback2)
{
COM_TRY_BEGIN
CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
extractCallbackSpec->Init(_archive,
extractCallback2,
path,
pathMode,
overwriteMode,
UStringVector(),
DefaultName,
DefaultTime,
DefaultAttributes
// ,_srcDirectoryPrefix
);
return _archive->Extract(0, -1, testMode, extractCallback);
COM_TRY_END
}
STDMETHODIMP CAgent::GetNumberOfProperties(UINT32 *numProperties)
{
COM_TRY_BEGIN
return _archive->GetNumberOfProperties(numProperties);
COM_TRY_END
}
STDMETHODIMP CAgent::GetPropertyInfo(UINT32 index,
BSTR *name, PROPID *propID, VARTYPE *varType)
{
COM_TRY_BEGIN
RINOK(_archive->GetPropertyInfo(index, name, propID, varType));
if (*propID == kpidPath)
*propID = kpidName;
return S_OK;
COM_TRY_END
}
STDMETHODIMP CAgent::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
return _archive->GetArchiveProperty(propID, value);
COM_TRY_END
}
STDMETHODIMP CAgent::GetNumberOfArchiveProperties(UINT32 *numProperties)
{
COM_TRY_BEGIN
return _archive->GetNumberOfArchiveProperties(numProperties);
COM_TRY_END
}
STDMETHODIMP CAgent::GetArchivePropertyInfo(UINT32 index,
BSTR *name, PROPID *propID, VARTYPE *varType)
{
COM_TRY_BEGIN
return _archive->GetArchivePropertyInfo(index,
name, propID, varType);
COM_TRY_END
}

292
7zip/UI/Agent/Agent.h Executable file
View File

@@ -0,0 +1,292 @@
// Agent/Agent.h
#pragma once
#ifndef __AGENT_AGENT_H
#define __AGENT_AGENT_H
#include "Windows/PropVariant.h"
#include "Common/MyCom.h"
#include "../Common/UpdateAction.h"
#include "../Common/ArchiverInfo.h"
#include "IFolderArchive.h"
#include "AgentProxy.h"
#ifndef EXCLUDE_COM
#include "Windows/DLL.h"
#endif
#ifdef NEW_FOLDER_INTERFACE
#include "../../FileManager/IFolder.h"
#endif
class CAgentFolder;
// {23170F69-40C1-278A-0000-000100050001}
DEFINE_GUID(IID_IArchiveFolderInternal,
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x01);
MIDL_INTERFACE("23170F69-40C1-278A-0000-000100050001")
IArchiveFolderInternal: public IUnknown
{
public:
STDMETHOD(GetAgentFolder)(CAgentFolder **agentFolder) PURE;
};
class CAgent;
class CAgentFolder:
public IFolderFolder,
public IArchiveFolder,
public IArchiveFolderInternal,
#ifdef NEW_FOLDER_INTERFACE
public IEnumProperties,
public IFolderGetTypeID,
public IFolderGetPath,
public IFolderOperations,
#endif
public CMyUnknownImp
{
public:
MY_QUERYINTERFACE_BEGIN
MY_QUERYINTERFACE_ENTRY(IFolderFolder)
MY_QUERYINTERFACE_ENTRY(IArchiveFolder)
MY_QUERYINTERFACE_ENTRY(IArchiveFolderInternal)
#ifdef NEW_FOLDER_INTERFACE
MY_QUERYINTERFACE_ENTRY(IEnumProperties)
MY_QUERYINTERFACE_ENTRY(IFolderGetTypeID)
MY_QUERYINTERFACE_ENTRY(IFolderGetPath)
MY_QUERYINTERFACE_ENTRY(IFolderOperations)
#endif
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
// IFolderFolder
STDMETHOD(LoadItems)();
STDMETHOD(GetNumberOfItems)(UINT32 *numItems);
STDMETHOD(GetProperty)(UINT32 itemIndex, PROPID propID, PROPVARIANT *value);
STDMETHOD(BindToFolder)(UINT32 index, IFolderFolder **resultFolder);
STDMETHOD(BindToFolder)(const wchar_t *name, IFolderFolder **resultFolder);
STDMETHOD(BindToParentFolder)(IFolderFolder **resultFolder);
STDMETHOD(GetName)(BSTR *name);
// IArchiveFolder
STDMETHOD(Extract)(const UINT32 *indices, UINT32 numItems,
NExtractionMode::NPath::EEnum pathMode,
NExtractionMode::NOverwrite::EEnum overwriteMode,
const wchar_t *path,
INT32 testMode,
IFolderArchiveExtractCallback *extractCallback);
STDMETHOD(GetAgentFolder)(CAgentFolder **agentFolder);
#ifdef NEW_FOLDER_INTERFACE
STDMETHOD(GetNumberOfProperties)(UINT32 *numProperties);
STDMETHOD(GetPropertyInfo)(UINT32 index,
BSTR *name, PROPID *propID, VARTYPE *varType);
STDMETHOD(GetTypeID)(BSTR *name);
STDMETHOD(GetPath)(BSTR *path);
// IFolderOperations
STDMETHOD(CreateFolder)(const wchar_t *name, IProgress *progress);
STDMETHOD(CreateFile)(const wchar_t *name, IProgress *progress);
STDMETHOD(Rename)(UINT32 index, const wchar_t *newName, IProgress *progress);
STDMETHOD(Delete)(const UINT32 *indices, UINT32 numItems, IProgress *progress);
STDMETHOD(CopyTo)(const UINT32 *indices, UINT32 numItems,
const wchar_t *path, IFolderOperationsExtractCallback *callback);
STDMETHOD(MoveTo)(const UINT32 *indices, UINT32 numItems,
const wchar_t *path, IFolderOperationsExtractCallback *callback);
STDMETHOD(CopyFrom)(const wchar_t *fromFolderPath,
const wchar_t **itemsPaths, UINT32 numItems, IProgress *progress);
STDMETHOD(SetProperty)(UINT32 index, PROPID propID, const PROPVARIANT *value, IProgress *progress);
#endif
CAgentFolder(): _proxyFolderItem(NULL) {}
void Init(CProxyArchive *proxyHandler,
CProxyFolder *proxyFolderItem,
IFolderFolder *parentFolder,
CAgent *agent)
{
_proxyArchive = proxyHandler;
_proxyFolderItem = proxyFolderItem;
_parentFolder = parentFolder;
_agent = (IInFolderArchive *)agent;
_agentSpec = agent;
}
void GetPathParts(UStringVector &pathParts);
HRESULT CommonUpdateOperation(
bool deleteOperation,
bool createFolderOperation,
bool renameOperation,
const wchar_t *newItemName,
const NUpdateArchive::CActionSet *actionSet,
const UINT32 *indices, UINT32 numItems,
IFolderArchiveUpdateCallback *updateCallback100);
public:
CProxyArchive *_proxyArchive;
CProxyFolder *_proxyFolderItem;
CMyComPtr<IFolderFolder> _parentFolder;
CMyComPtr<IInFolderArchive> _agent;
CAgent *_agentSpec;
};
// {23170F69-40C1-278A-1000-000100030000}
DEFINE_GUID(CLSID_CAgentArchiveHandler,
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00);
class CAgent:
public IInFolderArchive,
#ifndef EXTRACT_ONLY
public IOutFolderArchive,
public ISetProperties,
#endif
public CMyUnknownImp
{
public:
MY_QUERYINTERFACE_BEGIN
MY_QUERYINTERFACE_ENTRY(IInFolderArchive)
#ifndef EXTRACT_ONLY
MY_QUERYINTERFACE_ENTRY(IOutFolderArchive)
MY_QUERYINTERFACE_ENTRY(ISetProperties)
#endif
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
STDMETHOD(Open)(
const wchar_t *filePath,
// CLSID *clsIDResult,
BSTR *archiveType,
IArchiveOpenCallback *openArchiveCallback);
STDMETHOD(ReOpen)(
// const wchar_t *filePath,
IArchiveOpenCallback *openArchiveCallback);
/*
STDMETHOD(ReOpen)(IInStream *stream,
const wchar_t *defaultName,
const FILETIME *defaultTime,
UINT32 defaultAttributes,
const UINT64 *maxCheckStartPosition,
IArchiveOpenCallback *openArchiveCallback);
*/
STDMETHOD(Close)();
STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value);
STDMETHOD(GetNumberOfProperties)(UINT32 *numProperties);
STDMETHOD(GetPropertyInfo)(UINT32 index,
BSTR *name, PROPID *propID, VARTYPE *varType);
STDMETHOD(GetNumberOfArchiveProperties)(UINT32 *numProperties);
STDMETHOD(GetArchivePropertyInfo)(UINT32 index,
BSTR *name, PROPID *propID, VARTYPE *varType);
STDMETHOD(BindToRootFolder)(IFolderFolder **resultFolder);
STDMETHOD(Extract)(
NExtractionMode::NPath::EEnum pathMode,
NExtractionMode::NOverwrite::EEnum overwriteMode,
const wchar_t *path,
INT32 testMode,
IFolderArchiveExtractCallback *extractCallback2);
#ifndef EXTRACT_ONLY
STDMETHOD(SetFolder)(IFolderFolder *folder);
STDMETHOD(SetFiles)(const wchar_t *folderPrefix, const wchar_t **names, UINT32 numNames);
STDMETHOD(DeleteItems)(const wchar_t *newArchiveName, const UINT32 *indices,
UINT32 numItems, IFolderArchiveUpdateCallback *updateCallback);
STDMETHOD(DoOperation)(
const wchar_t *filePath,
const CLSID *clsID,
const wchar_t *newArchiveName,
const BYTE *stateActions,
const wchar_t *sfxModule,
IFolderArchiveUpdateCallback *updateCallback);
HRESULT CommonUpdate(const wchar_t *newArchiveName,
int numUpdateItems,
IArchiveUpdateCallback *updateCallback);
HRESULT CreateFolder(
const wchar_t *newArchiveName,
const wchar_t *folderName,
IFolderArchiveUpdateCallback *updateCallback100);
HRESULT RenameItem(
const wchar_t *newArchiveName,
const UINT32 *indices, UINT32 numItems,
const wchar_t *newItemName,
IFolderArchiveUpdateCallback *updateCallback100);
// ISetProperties
STDMETHOD(SetProperties)(const BSTR *names, const PROPVARIANT *values, INT32 numProperties);
#endif
CAgent();
~CAgent();
private:
HRESULT ReadItems();
public:
CProxyArchive *_proxyArchive;
#ifndef EXCLUDE_COM
NWindows::NDLL::CLibrary _library;
#endif
CMyComPtr<IInArchive> _archive;
// CLSID _CLSID;
// CMyComPtr<IArchiveFolder> m_RootFolder;
UString DefaultName;
FILETIME DefaultTime;
UINT32 DefaultAttributes;
UString ArchiveType;
UStringVector _names;
UString _folderPrefix;
UString _archiveNamePrefix;
CProxyFolder *_archiveFolderItem;
UString _archiveFilePath;
#ifndef EXTRACT_ONLY
CObjectVector<CMyComBSTR> m_PropNames;
std::vector<NWindows::NCOM::CPropVariant> m_PropValues;
#endif
};
#ifdef NEW_FOLDER_INTERFACE
class CArchiveFolderManager:
public IFolderManager,
public IFolderManagerGetIconPath,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP2(
IFolderManager,
IFolderManagerGetIconPath
)
// IFolderManager
STDMETHOD(OpenFolderFile)(const wchar_t *filePath, IFolderFolder **resultFolder, IProgress *progress);
STDMETHOD(GetTypes)(BSTR *types);
STDMETHOD(GetExtension)(const wchar_t *type, BSTR *extension);
STDMETHOD(CreateFolderFile)(const wchar_t *type, const wchar_t *filePath, IProgress *progress);
STDMETHOD(GetIconPath)(const wchar_t *type, BSTR *iconPath);
CArchiveFolderManager(): _formatsLoaded(false) {}
private:
void LoadFormats();
int FindFormat(const UString &type);
bool _formatsLoaded;
CObjectVector<CArchiverInfo> _formats;
};
#endif
#endif

469
7zip/UI/Agent/AgentOut.cpp Executable file
View File

@@ -0,0 +1,469 @@
// Zip/Handler.cpp
#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 "Windows/Defs.h"
#include "Windows/PropVariant.h"
#include "Windows/PropVariantConversions.h"
#include "Windows/FileDir.h"
#include "../../Common/FileStreams.h"
#include "Agent.h"
#include "ArchiveUpdateCallback.h"
using namespace NWindows;
using namespace NCOM;
static HRESULT CopyBlock(ISequentialInStream *inStream, ISequentialOutStream *outStream)
{
CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
return copyCoder->Code(inStream, outStream, NULL, NULL, NULL);
}
STDMETHODIMP CAgent::SetFolder(IFolderFolder *folder)
{
_archiveNamePrefix.Empty();
if (folder == NULL)
{
_archiveFolderItem = NULL;
return S_OK;
// folder = m_RootFolder;
}
else
{
CMyComPtr<IFolderFolder> archiveFolder = folder;
CMyComPtr<IArchiveFolderInternal> archiveFolderInternal;
RINOK(archiveFolder.QueryInterface(
IID_IArchiveFolderInternal, &archiveFolderInternal));
CAgentFolder *agentFolder;
RINOK(archiveFolderInternal->GetAgentFolder(&agentFolder));
_archiveFolderItem = agentFolder->_proxyFolderItem;
}
UStringVector pathParts;
pathParts.Clear();
CMyComPtr<IFolderFolder> folderItem = folder;
if (_archiveFolderItem != NULL)
while (true)
{
CMyComPtr<IFolderFolder> newFolder;
folderItem->BindToParentFolder(&newFolder);
if (newFolder == NULL)
break;
CMyComBSTR name;
folderItem->GetName(&name);
pathParts.Insert(0, (const wchar_t *)name);
folderItem = newFolder;
}
for(int i = 0; i < pathParts.Size(); i++)
{
_archiveNamePrefix += pathParts[i];
_archiveNamePrefix += L'\\';
}
return S_OK;
}
STDMETHODIMP CAgent::SetFiles(const wchar_t *folderPrefix,
const wchar_t **names, UINT32 numNames)
{
_folderPrefix = folderPrefix;
_names.Clear();
_names.Reserve(numNames);
for (int i = 0; i < numNames; i++)
_names.Add(names[i]);
return S_OK;
}
static HRESULT GetFileTime(CAgent *agent, UINT32 itemIndex, FILETIME &fileTime)
{
CPropVariant property;
RINOK(agent->_archive->GetProperty(itemIndex, kpidLastWriteTime, &property));
if (property.vt == VT_FILETIME)
fileTime = property.filetime;
else if (property.vt == VT_EMPTY)
fileTime = agent->DefaultTime;
else
throw 4190407;
return S_OK;
}
static HRESULT EnumerateArchiveItems(CAgent *agent,
const CProxyFolder &item,
const UString &prefix,
CObjectVector<CArchiveItem> &archiveItems)
{
int i;
for(i = 0; i < item.Files.Size(); i++)
{
const CProxyFile &fileItem = item.Files[i];
CArchiveItem archiveItem;
RINOK(::GetFileTime(agent, fileItem.Index, archiveItem.LastWriteTime));
CPropVariant property;
agent->_archive->GetProperty(fileItem.Index, kpidSize, &property);
if (archiveItem.SizeIsDefined = (property.vt != VT_EMPTY))
archiveItem.Size = ConvertPropVariantToUINT64(property);
archiveItem.IsDirectory = false;
archiveItem.Name = prefix + fileItem.Name;
archiveItem.Censored = true; // test it
archiveItem.IndexInServer = fileItem.Index;
archiveItems.Add(archiveItem);
}
for(i = 0; i < item.Folders.Size(); i++)
{
const CProxyFolder &dirItem = item.Folders[i];
UString fullName = prefix + dirItem.Name;
if(dirItem.IsLeaf)
{
CArchiveItem archiveItem;
RINOK(::GetFileTime(agent, dirItem.Index, archiveItem.LastWriteTime));
archiveItem.IsDirectory = true;
archiveItem.SizeIsDefined = false;
archiveItem.Name = fullName;
archiveItem.Censored = true; // test it
archiveItem.IndexInServer = dirItem.Index;
archiveItems.Add(archiveItem);
}
RINOK(EnumerateArchiveItems(agent, dirItem, fullName + UString(L'\\'), archiveItems));
}
return S_OK;
}
STDMETHODIMP CAgent::DoOperation(
const wchar_t *filePath,
const CLSID *clsID,
const wchar_t *newArchiveName,
const BYTE *stateActions,
const wchar_t *sfxModule,
IFolderArchiveUpdateCallback *updateCallback100)
{
NUpdateArchive::CActionSet actionSet;
for (int i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
actionSet.StateActions[i] = (NUpdateArchive::NPairAction::EEnum)stateActions[i];
CObjectVector<CDirItem> dirItems;
UString folderPrefix = _folderPrefix;
NFile::NName::NormalizeDirPathPrefix(folderPrefix);
::EnumerateDirItems(folderPrefix, _names, _archiveNamePrefix, dirItems);
CMyComPtr<IOutArchive> outArchive;
if (_archive)
{
RINOK(_archive.QueryInterface(IID_IOutArchive, &outArchive));
}
else
{
CHandlerLoader loader;
RINOK(loader.CreateHandler(filePath, *clsID, (void **)&outArchive, true));
_library.Attach(loader.Detach());
}
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;
CObjectVector<CArchiveItem> archiveItems;
if (_archive)
{
RINOK(ReadItems());
EnumerateArchiveItems(this, _proxyArchive->RootFolder, L"", archiveItems);
}
GetUpdatePairInfoList(dirItems, archiveItems, fileTimeType, updatePairs);
CObjectVector<CUpdatePair2> operationChain;
UpdateProduce(dirItems, archiveItems, updatePairs, actionSet,
operationChain);
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec );
updateCallbackSpec->Init(folderPrefix,&dirItems, &archiveItems,
&operationChain, NULL, updateCallback100);
COutFileStream *outStreamSpec = new COutFileStream;
CMyComPtr<IOutStream> outStream(outStreamSpec);
UString archiveName = newArchiveName;
{
UString resultPath;
int pos;
if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos))
throw 141716;
NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));
}
if (!outStreamSpec->Open(archiveName))
{
// ShowLastErrorMessage();
return E_FAIL;
}
CMyComPtr<ISetProperties> setProperties;
if (outArchive->QueryInterface(&setProperties) == S_OK)
{
if (m_PropNames.Size() == 0)
{
RINOK(setProperties->SetProperties(0, 0, 0));
}
else
{
std::vector<BSTR> 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()));
}
}
m_PropNames.Clear();
m_PropValues.clear();
if (sfxModule != NULL)
{
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);
}
HRESULT CAgent::CommonUpdate(const wchar_t *newArchiveName,
int numUpdateItems,
IArchiveUpdateCallback *updateCallback)
{
CMyComPtr<IOutArchive> outArchive;
RINOK(_archive.QueryInterface(IID_IOutArchive, &outArchive));
COutFileStream *outStreamSpec = new COutFileStream;
CMyComPtr<IOutStream> outStream(outStreamSpec);
UString archiveName = newArchiveName;
{
UString resultPath;
int pos;
if(!NFile::NDirectory::MyGetFullPathName(archiveName, resultPath, pos))
throw 141716;
NFile::NDirectory::CreateComplexDirectory(resultPath.Left(pos));
}
if (!outStreamSpec->Open(archiveName))
{
// ShowLastErrorMessage();
return E_FAIL;
}
return outArchive->UpdateItems(outStream, numUpdateItems, updateCallback);
}
STDMETHODIMP CAgent::DeleteItems(
const wchar_t *newArchiveName,
const UINT32 *indices, UINT32 numItems,
IFolderArchiveUpdateCallback *updateCallback100)
{
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
CUIntVector realIndices;
_archiveFolderItem->GetRealIndices(indices, numItems, realIndices);
CObjectVector<CUpdatePair2> updatePairs;
int curIndex = 0;
UINT32 numItemsInArchive;
RINOK(_archive->GetNumberOfItems(&numItemsInArchive));
for (int i = 0; i < numItemsInArchive; i++)
{
if (curIndex < realIndices.Size())
if (realIndices[curIndex] == i)
{
curIndex++;
continue;
}
CUpdatePair2 updatePair;
updatePair.NewData = updatePair.NewProperties = false;
updatePair.ExistInArchive = true;
updatePair.ExistOnDisk = false;
updatePair.IsAnti = false;
updatePair.ArchiveItemIndex = i;
updatePairs.Add(updatePair);
}
updateCallbackSpec->Init(L"", NULL, NULL, &updatePairs, NULL, updateCallback100);
return CommonUpdate(newArchiveName, updatePairs.Size(), updateCallback);
}
HRESULT CAgent::CreateFolder(
const wchar_t *newArchiveName,
const wchar_t *folderName,
IFolderArchiveUpdateCallback *updateCallback100)
{
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
CObjectVector<CUpdatePair2> updatePairs;
UINT32 numItemsInArchive;
RINOK(_archive->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.ArchiveItemIndex = i;
updatePairs.Add(updatePair);
}
CUpdatePair2 updatePair;
updatePair.NewData = updatePair.NewProperties = true;
updatePair.ExistInArchive = false;
updatePair.ExistOnDisk = true;
updatePair.IsAnti = false;
updatePair.ArchiveItemIndex = -1;
updatePair.DirItemIndex = 0;
updatePairs.Add(updatePair);
CObjectVector<CDirItem> dirItems;
CDirItem dirItem;
dirItem.Attributes = FILE_ATTRIBUTE_DIRECTORY;
dirItem.Size = 0;
dirItem.Name = _archiveFolderItem->GetFullPathPrefix() + folderName;
SYSTEMTIME systemTime;
FILETIME fileTime;
::GetSystemTime(&systemTime);
::SystemTimeToFileTime(&systemTime, &fileTime);
dirItem.LastAccessTime = dirItem.LastWriteTime =
dirItem.CreationTime = fileTime;
dirItems.Add(dirItem);
updateCallbackSpec->Init(L"", &dirItems, NULL, &updatePairs, NULL, updateCallback100);
return CommonUpdate(newArchiveName, updatePairs.Size(), updateCallback);
}
HRESULT CAgent::RenameItem(
const wchar_t *newArchiveName,
const UINT32 *indices, UINT32 numItems,
const wchar_t *newItemName,
IFolderArchiveUpdateCallback *updateCallback100)
{
if (numItems != 1)
return E_INVALIDARG;
CArchiveUpdateCallback *updateCallbackSpec = new CArchiveUpdateCallback;
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
CUIntVector realIndices;
_archiveFolderItem->GetRealIndices(indices, numItems, realIndices);
UString fullPrefix = _archiveFolderItem->GetFullPathPrefix();
UString oldItemPath = fullPrefix +
_archiveFolderItem->GetItemName(indices[0]);
UString newItemPath = fullPrefix + newItemName;
CObjectVector<CUpdatePair2> updatePairs;
int curIndex = 0;
UINT32 numItemsInArchive;
RINOK(_archive->GetNumberOfItems(&numItemsInArchive));
for (int i = 0; i < numItemsInArchive; i++)
{
if (curIndex < realIndices.Size())
if (realIndices[curIndex] == i)
{
CUpdatePair2 updatePair;
updatePair.NewData = false;
updatePair.NewProperties = true;
updatePair.ExistInArchive = true;
updatePair.ExistOnDisk = false;
updatePair.IsAnti = false; // ?
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;
}
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;
}
CUpdatePair2 updatePair;
updatePair.NewData = updatePair.NewProperties = false;
updatePair.ExistInArchive = true;
updatePair.ExistOnDisk = false;
updatePair.IsAnti = false;
updatePair.ArchiveItemIndex = i;
updatePairs.Add(updatePair);
}
updateCallbackSpec->Init(L"", NULL, NULL, &updatePairs, _archive, updateCallback100);
return CommonUpdate(newArchiveName, updatePairs.Size(), updateCallback);
}
STDMETHODIMP CAgent::SetProperties(const BSTR *names,
const PROPVARIANT *values, INT32 numProperties)
{
m_PropNames.Clear();
m_PropValues.clear();
for (int i = 0; i < numProperties; i++)
{
m_PropNames.Add(names[i]);
m_PropValues.push_back(values[i]);
}
return S_OK;
}

198
7zip/UI/Agent/AgentProxy.cpp Executable file
View File

@@ -0,0 +1,198 @@
// AgentProxy.cpp
#include "StdAfx.h"
#include "AgentProxy.h"
#include "Common/MyCom.h"
#include "Windows/PropVariant.h"
#include "Windows/Defs.h"
using namespace NWindows;
int CProxyFolder::FindDirSubItemIndex(const UString &name, int &insertPos) const
{
int left = 0, right = Folders.Size();
while(true)
{
if (left == right)
{
insertPos = left;
return -1;
}
int mid = (left + right) / 2;
int compare = name.CollateNoCase(Folders[mid].Name);
if (compare == 0)
return mid;
if (compare < 0)
right = mid;
else
left = mid + 1;
}
}
int CProxyFolder::FindDirSubItemIndex(const UString &name) const
{
int insertPos;
return FindDirSubItemIndex(name, insertPos);
}
void CProxyFolder::AddFileSubItem(UINT32 index, const UString &name)
{
Files.Add(CProxyFile());
Files.Back().Name = name;
Files.Back().Index = index;
}
CProxyFolder* CProxyFolder::AddDirSubItem(UINT32 index, bool leaf,
const UString &name)
{
int insertPos;
int folderIndex = FindDirSubItemIndex(name, insertPos);
if (folderIndex >= 0)
{
CProxyFolder *item = &Folders[folderIndex];
if(leaf)
{
item->Index = index;
item->IsLeaf = true;
}
return item;
}
Folders.Insert(insertPos, CProxyFolder());
CProxyFolder *item = &Folders[insertPos];
item->Name = name;
item->Index = index;
item->Parent = this;
item->IsLeaf = leaf;
return item;
}
void CProxyFolder::Clear()
{
Folders.Clear();
Files.Clear();
}
UString CProxyFolder::GetFullPathPrefix() const
{
UString result;
const CProxyFolder *current = this;
while (current->Parent != NULL)
{
result = current->Name + UString(L'\\') + result;
current = current->Parent;
}
return result;
}
UString CProxyFolder::GetItemName(UINT32 index) const
{
if (index < (UINT32)Folders.Size())
return Folders[index].Name;
return Files[index - Folders.Size()].Name;
}
void CProxyFolder::AddRealIndices(CUIntVector &realIndices) const
{
if (IsLeaf)
realIndices.Add(Index);
for(int i = 0; i < Folders.Size(); i++)
Folders[i].AddRealIndices(realIndices);
for(i = 0; i < Files.Size(); i++)
realIndices.Add(Files[i].Index);
}
void CProxyFolder::GetRealIndices(const UINT32 *indices,
UINT32 numItems, CUIntVector &realIndices) const
{
realIndices.Clear();
for(UINT32 i = 0; i < numItems; i++)
{
int index = indices[i];
int numDirItems = Folders.Size();
if (index < numDirItems)
Folders[index].AddRealIndices(realIndices);
else
realIndices.Add(Files[index - numDirItems].Index);
}
realIndices.Sort();
}
///////////////////////////////////////////////
// CProxyArchive
HRESULT CProxyArchive::Reload(IInArchive *archive, IProgress *progress)
{
RootFolder.Clear();
return ReadObjects(archive, progress);
}
HRESULT CProxyArchive::Load(IInArchive *archive,
const UString &defaultName,
// const FILETIME &defaultTime,
// UINT32 defaultAttributes,
IProgress *progress)
{
DefaultName = defaultName;
// DefaultTime = defaultTime;
// DefaultAttributes = defaultAttributes;
return Reload(archive, progress);
}
HRESULT CProxyArchive::ReadObjects(IInArchive *archiveHandler, IProgress *progress)
{
UINT32 numItems;
RINOK(archiveHandler->GetNumberOfItems(&numItems));
if (progress != NULL)
{
UINT64 totalItems = numItems;
RINOK(progress->SetTotal(totalItems));
}
for(UINT32 i = 0; i < numItems; i++)
{
if (progress != NULL)
{
UINT64 currentItemIndex = i;
RINOK(progress->SetCompleted(&currentItemIndex));
}
NCOM::CPropVariant propVariantPath;
RINOK(archiveHandler->GetProperty(i, kpidPath, &propVariantPath));
CProxyFolder *currentItem = &RootFolder;
UString fileName;
if(propVariantPath.vt == VT_EMPTY)
fileName = DefaultName;
else
{
if(propVariantPath.vt != VT_BSTR)
return E_FAIL;
UString filePath = propVariantPath.bstrVal;
int len = filePath.Length();
for (int i = 0; i < len; i++)
{
wchar_t c = filePath[i];
if (c == '\\' || c == '/')
{
currentItem = currentItem->AddDirSubItem(-1, false, fileName);
fileName.Empty();
}
else
fileName += c;
}
}
NCOM::CPropVariant propVariantIsFolder;
RINOK(archiveHandler->GetProperty(i,
kpidIsFolder, &propVariantIsFolder));
if(propVariantIsFolder.vt != VT_BOOL)
return E_FAIL;
if(VARIANT_BOOLToBool(propVariantIsFolder.boolVal))
currentItem->AddDirSubItem(i, true, fileName);
else
currentItem->AddFileSubItem(i, fileName);
}
return S_OK;
}

58
7zip/UI/Agent/AgentProxy.h Executable file
View File

@@ -0,0 +1,58 @@
// AgentProxy.h
#pragma once
#ifndef __AGENT_PROXY_H
#define __AGENT_PROXY_H
#include "Common/String.h"
#include "../../Archive/IArchive.h"
class CProxyFile
{
public:
UINT32 Index;
UString Name;
};
class CProxyFolder: public CProxyFile
{
public:
CProxyFolder *Parent;
CObjectVector<CProxyFolder> Folders;
CObjectVector<CProxyFile> Files;
bool IsLeaf;
CProxyFolder(): Parent(NULL) {};
int FindDirSubItemIndex(const UString &name, int &insertPos) const;
int FindDirSubItemIndex(const UString &name) const;
CProxyFolder* AddDirSubItem(UINT32 index,
bool leaf, const UString &name);
void AddFileSubItem(UINT32 index, const UString &name);
void Clear();
UString GetFullPathPrefix() const;
UString GetItemName(UINT32 index) const;
void AddRealIndices(CUIntVector &realIndices) const;
void GetRealIndices(const UINT32 *indices, UINT32 numItems,
CUIntVector &realIndices) const;
};
class CProxyArchive
{
HRESULT ReadObjects(IInArchive *inArchive, IProgress *progress);
public:
UString DefaultName;
// FILETIME DefaultTime;
// UINT32 DefaultAttributes;
CProxyFolder RootFolder;
HRESULT Reload(IInArchive *archive, IProgress *progress);
HRESULT Load(IInArchive *archive,
const UString &defaultName,
// const FILETIME &defaultTime,
// UINT32 defaultAttributes,
IProgress *progress);
};
#endif

View File

@@ -0,0 +1,358 @@
// ExtractCallback.cpp
#include "StdAfx.h"
#include "ArchiveExtractCallback.h"
#include "Common/Wildcard.h"
#include "Common/StringConvert.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;
void CArchiveExtractCallback::Init(
IInArchive *archiveHandler,
IFolderArchiveExtractCallback *extractCallback2,
const UString &directoryPath,
NExtractionMode::NPath::EEnum pathMode,
NExtractionMode::NOverwrite::EEnum overwriteMode,
const UStringVector &removePathParts,
const UString &itemDefaultName,
const FILETIME &utcLastWriteTimeDefault,
UINT32 attributesDefault)
// bool passwordIsDefined, const UString &password
// UString srcDirectoryPrefix)
{
_extractCallback2 = extractCallback2;
// m_PasswordIsDefined = passwordIsDefined;
// m_Password = password;
_numErrors = 0;
_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)
{
return _extractCallback2->SetTotal(size);
}
STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UINT64 *completeValue)
{
return _extractCallback2->SetCompleted(completeValue);
}
void CArchiveExtractCallback::CreateComplexDirectory(const UStringVector &dirPathParts)
{
UString fullPath = _directoryPath;
for(int i = 0; i < dirPathParts.Size(); i++)
{
fullPath += dirPathParts[i];
NFile::NDirectory::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 CArchiveExtractCallback::GetStream(UINT32 index,
ISequentialOutStream **outStream, INT32 askExtractMode)
{
*outStream = 0;
_outFileStream.Release();
NCOM::CPropVariant propVariant;
RINOK(_archiveHandler->GetProperty(index, kpidPath, &propVariant));
UString fullPath;
if(propVariant.vt == VT_EMPTY)
{
fullPath = _itemDefaultName;
}
else
{
if(propVariant.vt != VT_BSTR)
return E_FAIL;
fullPath = propVariant.bstrVal;
}
// UString fullPathCorrect = GetCorrectPath(fullPath);
_filePath = fullPath;
if(askExtractMode == NArchive::NExtract::NAskMode::kExtract)
{
RINOK(_archiveHandler->GetProperty(index, kpidAttributes, &propVariant));
if (propVariant.vt == VT_EMPTY)
{
_processedFileInfo.Attributes = _attributesDefault;
_processedFileInfo.AttributesAreDefined = false;
}
else
{
if (propVariant.vt != VT_UI4)
throw "incorrect item";
_processedFileInfo.Attributes = propVariant.ulVal;
_processedFileInfo.AttributesAreDefined = true;
}
RINOK(_archiveHandler->GetProperty(index, kpidIsFolder, &propVariant));
_processedFileInfo.IsDirectory = VARIANT_BOOLToBool(propVariant.boolVal);
RINOK(_archiveHandler->GetProperty(index, kpidLastWriteTime, &propVariant));
switch(propVariant.vt)
{
case VT_EMPTY:
_processedFileInfo.UTCLastWriteTime = _utcLastWriteTimeDefault;
break;
case VT_FILETIME:
_processedFileInfo.UTCLastWriteTime = propVariant.filetime;
break;
default:
return E_FAIL;
}
RINOK(_archiveHandler->GetProperty(index, kpidSize, &propVariant));
bool newFileSizeDefined = (propVariant.vt != VT_EMPTY);
UINT64 newFileSize;
if (newFileSizeDefined)
newFileSize = ConvertPropVariantToUINT64(propVariant);
bool isAnti = false;
{
NCOM::CPropVariant propVariantTemp;
RINOK(_archiveHandler->GetProperty(index, kpidIsAnti,
&propVariantTemp));
if (propVariantTemp.vt == VT_BOOL)
isAnti = VARIANT_BOOLToBool(propVariantTemp.boolVal);
}
UStringVector pathParts;
// SplitPathToParts(fullPathCorrect, pathParts);
SplitPathToParts(fullPath, pathParts);
if(pathParts.IsEmpty())
return E_FAIL;
UString processedPath;
switch(_pathMode)
{
case NExtractionMode::NPath::kFullPathnames:
{
// processedPath = fullPathCorrect;
processedPath = GetCorrectPath(fullPath);
break;
}
case NExtractionMode::NPath::kCurrentPathnames:
{
int numRemovePathParts = _removePathParts.Size();
if(pathParts.Size() <= numRemovePathParts)
return E_FAIL;
for(int i = 0; i < numRemovePathParts; i++)
if(_removePathParts[i].CollateNoCase(pathParts[i]) != 0)
return E_FAIL;
pathParts.Delete(0, numRemovePathParts);
processedPath = MakePathNameFromParts(pathParts);
processedPath = GetCorrectPath(processedPath);
break;
}
case NExtractionMode::NPath::kNoPathnames:
{
processedPath = pathParts.Back();
pathParts.Delete(0, pathParts.Size() - 1); // Test it!!
break;
}
}
if(!_processedFileInfo.IsDirectory)
pathParts.DeleteBack();
for(int i = 0; i < pathParts.Size(); i++)
pathParts[i] = GetCorrectFileName(pathParts[i]);
if (!isAnti)
if (!pathParts.IsEmpty())
CreateComplexDirectory(pathParts);
const UString fullProcessedPathUnicode = _directoryPath + processedPath;
UString fullProcessedPath = _directoryPath + processedPath;
if(_processedFileInfo.IsDirectory)
{
_diskFilePath = fullProcessedPath;
if (isAnti)
NFile::NDirectory::MyRemoveDirectory(_diskFilePath);
return S_OK;
}
NFile::NFind::CFileInfoW fileInfo;
if(NFile::NFind::FindFile(fullProcessedPath, fileInfo))
{
switch(_overwriteMode)
{
case NExtractionMode::NOverwrite::kSkipExisting:
return S_OK;
case NExtractionMode::NOverwrite::kAskBefore:
{
INT32 overwiteResult;
RINOK(_extractCallback2->AskOverwrite(
fullProcessedPathUnicode, &fileInfo.LastWriteTime, &fileInfo.Size,
fullPath, &_processedFileInfo.UTCLastWriteTime, newFileSizeDefined?
&newFileSize : NULL, &overwiteResult))
switch(overwiteResult)
{
case NOverwriteAnswer::kCancel:
return E_ABORT;
case NOverwriteAnswer::kNo:
return S_OK;
case NOverwriteAnswer::kNoToAll:
_overwriteMode = NExtractionMode::NOverwrite::kSkipExisting;
return S_OK;
case NOverwriteAnswer::kYesToAll:
_overwriteMode = NExtractionMode::NOverwrite::kWithoutPrompt;
break;
case NOverwriteAnswer::kYes:
break;
case NOverwriteAnswer::kAutoRename:
_overwriteMode = NExtractionMode::NOverwrite::kAutoRename;
break;
default:
throw 20413;
}
}
}
if (_overwriteMode == NExtractionMode::NOverwrite::kAutoRename)
{
if (!AutoRenamePath(fullProcessedPath))
{
UString message = UString(L"can not create name of file ") +
fullProcessedPathUnicode;
RINOK(_extractCallback2->MessageError(message));
return E_ABORT;
}
}
else
if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath))
{
UString message = UString(L"can not delete output file ") +
fullProcessedPathUnicode;
RINOK(_extractCallback2->MessageError(message));
return E_ABORT;
}
}
if (!isAnti)
{
_outFileStreamSpec = new COutFileStream;
CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec);
if (!_outFileStreamSpec->Open(fullProcessedPath))
{
UString message = L"can not open output file " + fullProcessedPathUnicode;
RINOK(_extractCallback2->MessageError(message));
return S_OK;
}
_outFileStream = outStreamLoc;
*outStream = outStreamLoc.Detach();
}
_diskFilePath = fullProcessedPath;
}
else
{
*outStream = NULL;
}
return S_OK;
}
STDMETHODIMP CArchiveExtractCallback::PrepareOperation(INT32 askExtractMode)
{
_extractMode = false;
switch (askExtractMode)
{
case NArchive::NExtract::NAskMode::kExtract:
_extractMode = true;
};
return _extractCallback2->PrepareOperation(_filePath, askExtractMode);
}
void CArchiveExtractCallback::AddErrorMessage(LPCTSTR message)
{
_messages.Add(message);
}
STDMETHODIMP CArchiveExtractCallback::SetOperationResult(INT32 operationResult)
{
switch(operationResult)
{
case NArchive::NExtract::NOperationResult::kOK:
case NArchive::NExtract::NOperationResult::kUnSupportedMethod:
case NArchive::NExtract::NOperationResult::kCRCError:
case NArchive::NExtract::NOperationResult::kDataError:
break;
default:
_outFileStream.Release();
return E_FAIL;
}
if(_outFileStream != NULL)
_outFileStreamSpec->File.SetLastWriteTime(&_processedFileInfo.UTCLastWriteTime);
_outFileStream.Release();
if (_extractMode && _processedFileInfo.AttributesAreDefined)
NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attributes);
RINOK(_extractCallback2->SetOperationResult(operationResult));
return S_OK;
}
/*
STDMETHODIMP CArchiveExtractCallback::GetInStream(
const wchar_t *name, ISequentialInStream **inStream)
{
CInFileStream *inFile = new CInFileStream;
CMyComPtr<ISequentialInStream> inStreamTemp = inFile;
if (!inFile->Open(_srcDirectoryPrefix + name))
return ::GetLastError();
*inStream = inStreamTemp.Detach();
return S_OK;
}
*/
STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)
{
if (!_cryptoGetTextPassword)
{
RINOK(_extractCallback2.QueryInterface(IID_ICryptoGetTextPassword,
&_cryptoGetTextPassword));
}
return _cryptoGetTextPassword->CryptoGetTextPassword(password);
}

View File

@@ -0,0 +1,107 @@
// ArchiveExtractCallback.h
#pragma once
#ifndef __ARCHIVEEXTRACTCALLBACK_H
#define __ARCHIVEEXTRACTCALLBACK_H
#include "../../Archive/IArchive.h"
#include "IFolderArchive.h"
#include "Common/String.h"
#include "Common/MyCom.h"
#include "../../Common/FileStreams.h"
#include "../../IPassword.h"
class CArchiveExtractCallback:
public IArchiveExtractCallback,
// public IArchiveVolumeExtractCallback,
public ICryptoGetTextPassword,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP1(ICryptoGetTextPassword)
// COM_INTERFACE_ENTRY(IArchiveVolumeExtractCallback)
// IProgress
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);
// IArchiveVolumeExtractCallback
// STDMETHOD(GetInStream)(const wchar_t *name, ISequentialInStream **inStream);
// ICryptoGetTextPassword
STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword);
private:
CMyComPtr<IInArchive> _archiveHandler;
CMyComPtr<IFolderArchiveExtractCallback> _extractCallback2;
CMyComPtr<ICryptoGetTextPassword> _cryptoGetTextPassword;
UString _directoryPath;
NExtractionMode::NPath::EEnum _pathMode;
NExtractionMode::NOverwrite::EEnum _overwriteMode;
UString _filePath;
UString _diskFilePath;
CSysStringVector _messages;
bool _extractMode;
struct CProcessedFileInfo
{
FILETIME UTCLastWriteTime;
bool IsDirectory;
bool AttributesAreDefined;
UINT32 Attributes;
} _processedFileInfo;
COutFileStream *_outFileStreamSpec;
CMyComPtr<ISequentialOutStream> _outFileStream;
UStringVector _removePathParts;
UString _itemDefaultName;
FILETIME _utcLastWriteTimeDefault;
UINT32 _attributesDefault;
// bool m_PasswordIsDefined;
// UString m_Password;
// UString _srcDirectoryPrefix;
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,
const UString &directoryPath,
NExtractionMode::NPath::EEnum pathMode,
NExtractionMode::NOverwrite::EEnum overwriteMode,
const UStringVector &removePathParts,
const UString &itemDefaultName,
const FILETIME &utcLastWriteTimeDefault,
UINT32 anAttributesDefault
// bool passwordIsDefined, const UString &password
// UString srcDirectoryPrefix
);
UINT64 _numErrors;
};
#endif

67
7zip/UI/Agent/ArchiveFolder.cpp Executable file
View File

@@ -0,0 +1,67 @@
// Zip/ArchiveFolder.cpp
#include "StdAfx.h"
#include "Common/ComTry.h"
#include "Common/StringConvert.h"
#include "Windows/Defs.h"
#include "Windows/PropVariant.h"
#include "Windows/PropVariantConversions.h"
#include "Windows/FileDir.h"
#include "../../Common/FileStreams.h"
#include "../Common/UpdatePair.h"
#include "Agent.h"
#include "ArchiveExtractCallback.h"
using namespace NWindows;
using namespace NCOM;
STDMETHODIMP CAgentFolder::CopyTo(const UINT32 *indices, UINT32 numItems,
const wchar_t *path, IFolderOperationsExtractCallback *callback)
{
COM_TRY_BEGIN
CArchiveExtractCallback *extractCallbackSpec = new
CArchiveExtractCallback;
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
UStringVector pathParts;
CProxyFolder *currentProxyFolder = _proxyFolderItem;
while (currentProxyFolder->Parent)
{
pathParts.Insert(0, currentProxyFolder->Name);
currentProxyFolder = currentProxyFolder->Parent;
}
CMyComPtr<IFolderArchiveExtractCallback> extractCallback2;
{
CMyComPtr<IFolderOperationsExtractCallback> callbackWrap = callback;
RINOK(callbackWrap.QueryInterface(
IID_IFolderArchiveExtractCallback, &extractCallback2));
}
extractCallbackSpec->Init(_agentSpec->_archive,
extractCallback2,
path,
NExtractionMode::NPath::kCurrentPathnames,
NExtractionMode::NOverwrite::kAskBefore,
pathParts,
_agentSpec->DefaultName,
_agentSpec->DefaultTime,
_agentSpec->DefaultAttributes
// ,_agentSpec->_srcDirectoryPrefix
);
CUIntVector realIndices;
_proxyFolderItem->GetRealIndices(indices, numItems, realIndices);
return _agentSpec->_archive->Extract(&realIndices.Front(),
realIndices.Size(), BoolToInt(false), extractCallback);
COM_TRY_END
}
STDMETHODIMP CAgentFolder::MoveTo(const UINT32 *indices, UINT32 numItems,
const wchar_t *path, IFolderOperationsExtractCallback *callback)
{
return E_NOTIMPL;
}

View File

@@ -0,0 +1,98 @@
// Zip/ArchiveFolder.cpp
#include "StdAfx.h"
#include "Agent.h"
#include "Common/StringConvert.h"
#include "../Common/OpenArchive.h"
static const UINT64 kMaxCheckStartPosition = 1 << 20;
static inline UINT GetCurrentFileCodePage()
{ return AreFileApisANSI() ? CP_ACP : CP_OEMCP; }
void CArchiveFolderManager::LoadFormats()
{
if (!_formatsLoaded)
ReadArchiverInfoList(_formats);
}
int CArchiveFolderManager::FindFormat(const UString &type)
{
// LoadFormats();
for (int i = 0; i < _formats.Size(); i++)
if (type.CompareNoCase(_formats[i].Name) == 0)
return i;
return -1;
}
STDMETHODIMP CArchiveFolderManager::OpenFolderFile(const wchar_t *filePath,
IFolderFolder **resultFolder, IProgress *progress)
{
CMyComPtr<IArchiveOpenCallback> openArchiveCallback;
if (progress != 0)
{
CMyComPtr<IProgress> progressWrapper = progress;
progressWrapper.QueryInterface(IID_IArchiveOpenCallback, &openArchiveCallback);
}
CAgent *agent = new CAgent();
CComPtr<IInFolderArchive> archive = agent;
RINOK(agent->Open(filePath, NULL, openArchiveCallback));
return agent->BindToRootFolder(resultFolder);
}
/*
HRESULT CAgent::FolderReOpen(
IArchiveOpenCallback *openArchiveCallback)
{
return ReOpenArchive(_archive, _archiveFilePath);
}
*/
STDMETHODIMP CArchiveFolderManager::GetTypes(BSTR *types)
{
LoadFormats();
UString typesStrings;
for(int i = 0; i < _formats.Size(); i++)
{
if (i != 0)
typesStrings += L' ';
typesStrings += _formats[i].Name;
}
CMyComBSTR valueTemp = typesStrings;
*types = valueTemp.Detach();
return S_OK;
}
STDMETHODIMP CArchiveFolderManager::GetExtension(const wchar_t *type, BSTR *extension)
{
*extension = 0;
int formatIndex = FindFormat(type);
if (formatIndex < 0)
return E_INVALIDARG;
// CMyComBSTR valueTemp = _formats[formatIndex].GetAllExtensions();
CMyComBSTR valueTemp = _formats[formatIndex].Extensions[0].Extension;
*extension = valueTemp.Detach();
return S_OK;
}
STDMETHODIMP CArchiveFolderManager::GetIconPath(const wchar_t *type, BSTR *iconPath)
{
*iconPath = 0;
int formatIndex = FindFormat(type);
if (formatIndex < 0)
return E_INVALIDARG;
CMyComBSTR iconPathTemp = _formats[formatIndex].FilePath;
*iconPath = iconPathTemp.Detach();
return S_OK;
}
STDMETHODIMP CArchiveFolderManager::CreateFolderFile(const wchar_t *type, const wchar_t *filePath, IProgress *progress)
{
return E_NOTIMPL;
}

View File

@@ -0,0 +1,219 @@
// FolderOut.cpp
#include "StdAfx.h"
#include "Agent.h"
#include "Common/StringConvert.h"
#include "Common/ComTry.h"
#include "Windows/FileDir.h"
// #include "../Common/CompressEngineCommon.h"
#include "../Common/ZipRegistry.h"
#include "../Common/UpdateAction.h"
#include "../Common/WorkDir.h"
using namespace NWindows;
using namespace NFile;
using namespace NDirectory;
static LPCWSTR kTempArcivePrefix = L"7zA";
void CAgentFolder::GetPathParts(UStringVector &pathParts)
{
pathParts.Clear();
CMyComPtr<IFolderFolder> folder = this;
while (true)
{
CMyComPtr<IFolderFolder> newFolder;
folder->BindToParentFolder(&newFolder);
if (newFolder == NULL)
break;
CMyComBSTR name;
folder->GetName(&name);
pathParts.Insert(0, (const wchar_t *)name);
folder = newFolder;
}
}
HRESULT CAgentFolder::CommonUpdateOperation(
bool deleteOperation,
bool createFolderOperation,
bool renameOperation,
const wchar_t *newItemName,
const NUpdateArchive::CActionSet *actionSet,
const UINT32 *indices, UINT32 numItems,
IFolderArchiveUpdateCallback *updateCallback100)
{
NWorkDir::CInfo workDirInfo;
ReadWorkDirInfo(workDirInfo);
UString archiveFilePath = _agentSpec->_archiveFilePath;
UString workDir = GetWorkDir(workDirInfo, archiveFilePath );
CreateComplexDirectory(workDir);
CTempFileW tempFile;
UString tempFileName;
if (tempFile.Create(workDir, kTempArcivePrefix, tempFileName) == 0)
return E_FAIL;
/*
if (SetOutProperties(anOutArchive, aCompressionInfo.Method) != S_OK)
return NFileOperationReturnCode::kError;
*/
////////////////////////////
// Save FolderItem;
UStringVector pathParts;
GetPathParts(pathParts);
HRESULT result;
if (deleteOperation)
result = _agentSpec->DeleteItems(tempFileName,
indices, numItems, updateCallback100);
else if (createFolderOperation)
{
result = _agentSpec->CreateFolder(tempFileName,
newItemName, updateCallback100);
}
else if (renameOperation)
{
result = _agentSpec->RenameItem(
tempFileName,
indices, numItems,
newItemName,
updateCallback100);
}
else
{
BYTE actionSetByte[NUpdateArchive::NPairState::kNumValues];
for (int i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
actionSetByte[i] = actionSet->StateActions[i];
result = _agentSpec->DoOperation(NULL, NULL,
tempFileName, actionSetByte, NULL, updateCallback100);
}
if (result != S_OK)
return result;
_agentSpec->Close();
// m_FolderItem = NULL;
if (!DeleteFileAlways(archiveFilePath ))
return GetLastError();
tempFile.DisableDeleting();
if (!MyMoveFile(tempFileName, archiveFilePath ))
return GetLastError();
RINOK(_agentSpec->ReOpen(NULL));
////////////////////////////
// Restore FolderItem;
CMyComPtr<IFolderFolder> archiveFolder;
RINOK(_agentSpec->BindToRootFolder(&archiveFolder));
for (int i = 0; i < pathParts.Size(); i++)
{
CMyComPtr<IFolderFolder> newFolder;
archiveFolder->BindToFolder(pathParts[i], &newFolder);
if(!newFolder)
break;
archiveFolder = newFolder;
}
CMyComPtr<IArchiveFolderInternal> archiveFolderInternal;
RINOK(archiveFolder.QueryInterface(IID_IArchiveFolderInternal, &archiveFolderInternal));
CAgentFolder *agentFolder;
RINOK(archiveFolderInternal->GetAgentFolder(&agentFolder));
_proxyFolderItem = agentFolder->_proxyFolderItem;
_proxyArchive = agentFolder->_proxyArchive;
_parentFolder = agentFolder->_parentFolder;
return S_OK;
}
STDMETHODIMP CAgentFolder::CopyFrom(
const wchar_t *fromFolderPath, // test it
const wchar_t **itemsPaths,
UINT32 numItems,
IProgress *progress)
{
COM_TRY_BEGIN
RINOK(_agentSpec->SetFiles(fromFolderPath, itemsPaths, numItems));
RINOK(_agentSpec->SetFolder(this));
CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
if (progress != 0)
{
CMyComPtr<IProgress> progressWrapper = progress;
RINOK(progressWrapper.QueryInterface(
IID_IFolderArchiveUpdateCallback, &updateCallback100));
}
return CommonUpdateOperation(false, false, false, NULL,
&NUpdateArchive::kAddActionSet, 0, 0, updateCallback100);
COM_TRY_END
}
STDMETHODIMP CAgentFolder::Delete(const UINT32 *indices, UINT32 numItems, IProgress *progress)
{
COM_TRY_BEGIN
RINOK(_agentSpec->SetFolder(this));
CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
if (progress != 0)
{
CMyComPtr<IProgress> progressWrapper = progress;
RINOK(progressWrapper.QueryInterface(
IID_IFolderArchiveUpdateCallback, &updateCallback100));
}
return CommonUpdateOperation(true, false, false, NULL,
&NUpdateArchive::kDeleteActionSet, indices, numItems, updateCallback100);
COM_TRY_END
}
STDMETHODIMP CAgentFolder::CreateFolder(const wchar_t *name, IProgress *progress)
{
COM_TRY_BEGIN
if (_proxyFolderItem->FindDirSubItemIndex(name) >= 0)
return ERROR_ALREADY_EXISTS;
RINOK(_agentSpec->SetFolder(this));
CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
if (progress != 0)
{
CMyComPtr<IProgress> progressWrapper = progress;
RINOK(progressWrapper.QueryInterface(
IID_IFolderArchiveUpdateCallback, &updateCallback100));
}
return CommonUpdateOperation(false, true, false, name, NULL, NULL,
0, updateCallback100);
COM_TRY_END
}
STDMETHODIMP CAgentFolder::Rename(UINT32 index, const wchar_t *newName, IProgress *progress)
{
COM_TRY_BEGIN
CUIntVector realIndices;
CUIntVector indices;
indices.Add(index);
RINOK(_agentSpec->SetFolder(this));
CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
if (progress != 0)
{
CMyComPtr<IProgress> progressWrapper = progress;
RINOK(progressWrapper.QueryInterface(
IID_IFolderArchiveUpdateCallback, &updateCallback100));
}
return CommonUpdateOperation(false, false, true, newName, NULL, &indices.Front(),
indices.Size(), updateCallback100);
COM_TRY_END
}
STDMETHODIMP CAgentFolder::CreateFile(const wchar_t *name, IProgress *progress)
{
return E_NOTIMPL;
}
STDMETHODIMP CAgentFolder::SetProperty(UINT32 index, PROPID propID,
const PROPVARIANT *value, IProgress *progress)
{
return E_NOTIMPL;
}

View File

@@ -0,0 +1,229 @@
// 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

@@ -0,0 +1,71 @@
// 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

141
7zip/UI/Agent/IFolderArchive.h Executable file
View File

@@ -0,0 +1,141 @@
// IFolderArchive.h
#pragma once
#ifndef __IFOLDERARCHIVE_H
#define __IFOLDERARCHIVE_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;
};
// {23170F69-40C1-278A-0000-000100050000}
DEFINE_GUID(IID_IArchiveFolder,
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00);
MIDL_INTERFACE("23170F69-40C1-278A-0000-000100050000")
IArchiveFolder: public IUnknown
{
public:
STDMETHOD(Extract)(const UINT32 *indices, UINT32 numItems,
NExtractionMode::NPath::EEnum pathMode,
NExtractionMode::NOverwrite::EEnum overwriteMode,
const wchar_t *path,
INT32 testMode,
IFolderArchiveExtractCallback *extractCallback2) PURE;
};
// {23170F69-40C1-278A-0000-000100060000}
DEFINE_GUID(IID_IInFolderArchive,
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00);
MIDL_INTERFACE("23170F69-40C1-278A-0000-000100060000")
IInFolderArchive: public IUnknown
{
public:
STDMETHOD(Open)(const wchar_t *filePath,
// CLSID *clsIDResult,
BSTR *archiveType,
IArchiveOpenCallback *openArchiveCallback) PURE;
STDMETHOD(ReOpen)(
// const wchar_t *filePath,
IArchiveOpenCallback *openArchiveCallback) PURE;
STDMETHOD(Close)() PURE;
STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) PURE;
STDMETHOD(GetNumberOfProperties)(UINT32 *numProperties) PURE;
STDMETHOD(GetPropertyInfo)(UINT32 index,
BSTR *name, PROPID *propID, VARTYPE *varType) PURE;
STDMETHOD(GetNumberOfArchiveProperties)(UINT32 *numProperties) PURE;
STDMETHOD(GetArchivePropertyInfo)(UINT32 index,
BSTR *name, PROPID *propID, VARTYPE *varType) PURE;
STDMETHOD(BindToRootFolder)(IFolderFolder **resultFolder) PURE;
STDMETHOD(Extract)(
NExtractionMode::NPath::EEnum pathMode,
NExtractionMode::NOverwrite::EEnum overwriteMode,
const wchar_t *path,
INT32 testMode,
IFolderArchiveExtractCallback *extractCallback2) PURE;
};
// {23170F69-40C1-278A-0000-0001000B0000}
DEFINE_GUID(IID_IFolderArchiveUpdateCallback,
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0B, 0x00, 0x00);
MIDL_INTERFACE("23170F69-40C1-278A-0000-0001000B0000")
IFolderArchiveUpdateCallback: public IProgress
{
public:
STDMETHOD(CompressOperation)(const wchar_t *name) PURE;
STDMETHOD(DeleteOperation)(const wchar_t *name) PURE;
STDMETHOD(OperationResult)(INT32 operationResult) PURE;
};
// {23170F69-40C1-278A-0000-0001000A0000}
DEFINE_GUID(IID_IOutFolderArchive,
0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x00, 0x00);
MIDL_INTERFACE("23170F69-40C1-278A-0000-0001000A0000")
IOutFolderArchive: public IUnknown
{
STDMETHOD(SetFolder)(IFolderFolder *folder) PURE;
STDMETHOD(SetFiles)(const wchar_t *folderPrefix, const wchar_t **names, UINT32 numNames) PURE;
STDMETHOD(DeleteItems)(const wchar_t *newArchiveName,
const UINT32 *indices, UINT32 numItems, IFolderArchiveUpdateCallback *updateCallback) PURE;
STDMETHOD(DoOperation)(
const wchar_t *filePath,
const CLSID *clsID,
const wchar_t *newArchiveName,
const BYTE *stateActions,
const wchar_t *sfxModule,
IFolderArchiveUpdateCallback *updateCallback) PURE;
};
#endif