Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/UI/Agent/Agent.cpp')
-rwxr-xr-xCPP/7zip/UI/Agent/Agent.cpp578
1 files changed, 578 insertions, 0 deletions
diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp
new file mode 100755
index 00000000..f983e2f9
--- /dev/null
+++ b/CPP/7zip/UI/Agent/Agent.cpp
@@ -0,0 +1,578 @@
+// 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/DefaultName.h"
+#include "../Common/ArchiveExtractCallback.h"
+
+#include "Agent.h"
+
+#ifdef FORMAT_7Z
+#include "../../Archive/7z/7zHandler.h"
+#endif
+
+extern "C"
+{
+ #include "../../../../C/Sort.h"
+}
+
+
+using namespace NWindows;
+
+STDMETHODIMP CAgentFolder::GetAgentFolder(CAgentFolder **agentFolder)
+{
+ *agentFolder = this;
+ return S_OK;
+}
+
+void CAgentFolder::LoadFolder(CProxyFolder *folder)
+{
+ int i;
+ CProxyItem item;
+ item.Folder = folder;
+ for (i = 0; i < folder->Folders.Size(); i++)
+ {
+ item.Index = i;
+ _items.Add(item);
+ LoadFolder(&folder->Folders[i]);
+ }
+ int start = folder->Folders.Size();
+ for (i = 0; i < folder->Files.Size(); i++)
+ {
+ item.Index = start + i;
+ _items.Add(item);
+ }
+}
+
+
+STDMETHODIMP CAgentFolder::LoadItems()
+{
+ _items.Clear();
+ if (_flatMode)
+ LoadFolder(_proxyFolderItem);
+ return S_OK;
+}
+
+STDMETHODIMP CAgentFolder::GetNumberOfItems(UINT32 *numItems)
+{
+ if (_flatMode)
+ *numItems = _items.Size();
+ else
+ *numItems = _proxyFolderItem->Folders.Size() +_proxyFolderItem->Files.Size();
+ return S_OK;
+}
+
+/*
+STDMETHODIMP CAgentFolder::GetNumberOfSubFolders(UINT32 *aNumSubFolders)
+{
+ *aNumSubFolders = _proxyFolderItem->Folders.Size();
+ return S_OK;
+}
+*/
+
+UString CAgentFolder::GetName(UInt32 index) const
+{
+ UInt32 realIndex;
+ const CProxyFolder *folder;
+ if (_flatMode)
+ {
+ const CProxyItem &item = _items[index];
+ folder = item.Folder;
+ realIndex = item.Index;
+ }
+ else
+ {
+ folder = _proxyFolderItem;
+ realIndex = index;
+ }
+
+ if (realIndex < (UINT32)folder->Folders.Size())
+ return folder->Folders[realIndex].Name;
+ return folder->Files[realIndex - folder->Folders.Size()].Name;
+}
+
+UString CAgentFolder::GetPrefix(UInt32 index) const
+{
+ if (!_flatMode)
+ return UString();
+ const CProxyItem &item = _items[index];
+ const CProxyFolder *folder = item.Folder;
+ UString path;
+ while(folder != _proxyFolderItem)
+ {
+ path = folder->Name + UString(L"\\") + path;
+ folder = folder->Parent;
+ }
+ return path;
+}
+
+UString CAgentFolder::GetFullPathPrefixPlusPrefix(UInt32 index) const
+{
+ return _proxyFolderItem->GetFullPathPrefix() + GetPrefix(index);
+}
+
+void CAgentFolder::GetPrefixIfAny(UInt32 index, NCOM::CPropVariant &propVariant) const
+{
+ if (!_flatMode)
+ return;
+ propVariant = GetPrefix(index);
+}
+
+
+STDMETHODIMP CAgentFolder::GetProperty(UINT32 itemIndex, PROPID propID, PROPVARIANT *value)
+{
+ NCOM::CPropVariant propVariant;
+ const CProxyFolder *folder;
+ UInt32 realIndex;
+ if (_flatMode)
+ {
+ const CProxyItem &item = _items[itemIndex];
+ folder = item.Folder;
+ realIndex = item.Index;
+ }
+ else
+ {
+ folder = _proxyFolderItem;
+ realIndex = itemIndex;
+ }
+
+ if (realIndex < (UINT32)folder->Folders.Size())
+ {
+ const CProxyFolder &item = folder->Folders[realIndex];
+ switch(propID)
+ {
+ case kpidIsFolder:
+ propVariant = true;
+ break;
+ case kpidName:
+ propVariant = item.Name;
+ break;
+ case kpidPrefix:
+ GetPrefixIfAny(itemIndex, propVariant);
+ break;
+ default:
+ if (item.IsLeaf)
+ return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value);
+ }
+ }
+ else
+ {
+ realIndex -= folder->Folders.Size();
+ const CProxyFile &item = folder->Files[realIndex];
+ switch(propID)
+ {
+ case kpidIsFolder:
+ propVariant = false;
+ break;
+ case kpidName:
+ propVariant = item.Name;
+ break;
+ case kpidPrefix:
+ GetPrefixIfAny(itemIndex, propVariant);
+ break;
+ default:
+ return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value);
+ }
+ }
+ propVariant.Detach(value);
+ return S_OK;
+}
+
+HRESULT CAgentFolder::BindToFolder(CProxyFolder *folder, IFolderFolder **resultFolder)
+{
+ CMyComPtr<IFolderFolder> parentFolder;
+ if (folder->Parent != _proxyFolderItem)
+ {
+ RINOK(BindToFolder(folder->Parent, &parentFolder));
+ }
+ else
+ parentFolder = this;
+ CAgentFolder *folderSpec = new CAgentFolder;
+ CMyComPtr<IFolderFolder> agentFolder = folderSpec;
+ folderSpec->Init(_proxyArchive, folder, parentFolder, _agentSpec);
+ *resultFolder = agentFolder.Detach();
+ return S_OK;
+}
+
+STDMETHODIMP CAgentFolder::BindToFolder(UINT32 index, IFolderFolder **resultFolder)
+{
+ COM_TRY_BEGIN
+
+ CProxyFolder *folder;
+ UInt32 realIndex;
+ if (_flatMode)
+ {
+ const CProxyItem &item = _items[index];
+ folder = item.Folder;
+ realIndex = item.Index;
+ }
+ else
+ {
+ folder = _proxyFolderItem;
+ realIndex = index;
+ }
+ if (realIndex >= (UINT32)folder->Folders.Size())
+ return E_INVALIDARG;
+ return BindToFolder(&folder->Folders[realIndex], resultFolder);
+ 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
+ RINOK(_agentSpec->GetArchive()->GetNumberOfProperties(numProperties));
+ if (_flatMode)
+ (*numProperties)++;
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgentFolder::GetPropertyInfo(UINT32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType)
+{
+ COM_TRY_BEGIN
+ UINT32 numProperties;
+ _agentSpec->GetArchive()->GetNumberOfProperties(&numProperties);
+ if (index < numProperties)
+ {
+ RINOK(_agentSpec->GetArchive()->GetPropertyInfo(index, name, propID, varType));
+ if (*propID == kpidPath)
+ *propID = kpidName;
+ }
+ else
+ {
+ *name = NULL;
+ *propID = kpidPrefix;
+ *varType = VT_BSTR;
+ }
+ 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;
+ for (;;)
+ {
+ 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
+}
+
+STDMETHODIMP CAgentFolder::SetFlatMode(Int32 flatMode)
+{
+ _flatMode = IntToBool(flatMode);
+ return S_OK;
+}
+
+#endif
+
+void CAgentFolder::GetRealIndices(const UINT32 *indices, UINT32 numItems, CUIntVector &realIndices) const
+{
+ if (!_flatMode)
+ {
+ _proxyFolderItem->GetRealIndices(indices, numItems, realIndices);
+ return;
+ }
+ realIndices.Clear();
+ for(UINT32 i = 0; i < numItems; i++)
+ {
+ const CProxyItem &item = _items[indices[i]];
+ const CProxyFolder *folder = item.Folder;
+ UInt32 realIndex = item.Index;
+ if (realIndex < (UINT32)folder->Folders.Size())
+ continue;
+ realIndices.Add(folder->Files[realIndex - folder->Folders.Size()].Index);
+ }
+ HeapSort(&realIndices.Front(), realIndices.Size());
+}
+
+STDMETHODIMP CAgentFolder::Extract(const UINT32 *indices,
+ UINT32 numItems,
+ NExtract::NPathMode::EEnum pathMode,
+ NExtract::NOverwriteMode::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;
+ }
+
+ /*
+ if (_flatMode)
+ pathMode = NExtract::NPathMode::kNoPathnames;
+ */
+
+ extractCallbackSpec->Init(_agentSpec->GetArchive(),
+ extractCallback2,
+ false,
+ path,
+ pathMode,
+ overwriteMode,
+ pathParts,
+ _agentSpec->DefaultName,
+ _agentSpec->DefaultTime,
+ _agentSpec->DefaultAttributes
+ // ,_agentSpec->_srcDirectoryPrefix
+ );
+ CUIntVector realIndices;
+ GetRealIndices(indices, numItems, realIndices);
+ return _agentSpec->GetArchive()->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 archiverInfo0, archiverInfo1;
+ HRESULT res = OpenArchive(_archiveFilePath, _archiveLink, openArchiveCallback);
+ // _archive = _archiveLink.GetArchive();
+ DefaultName = _archiveLink.GetDefaultItemName();
+ const CArchiverInfo &ai = _archiveLink.GetArchiverInfo();
+
+ RINOK(res);
+ DefaultTime = fileInfo.LastWriteTime;
+ DefaultAttributes = fileInfo.Attributes;
+ ArchiveType = ai.Name;
+ if (archiveType != 0)
+ {
+ CMyComBSTR name = ArchiveType;
+ *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(_archiveLink, _archiveFilePath));
+ return ReadItems();
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgent::Close()
+{
+ COM_TRY_BEGIN
+ RINOK(_archiveLink.Close());
+ if (_archiveLink.GetNumLevels() > 1)
+ {
+ // return S_OK;
+ }
+ // _archive->Close();
+ return S_OK;
+ 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(GetArchive(),
+ 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(
+ NExtract::NPathMode::EEnum pathMode,
+ NExtract::NOverwriteMode::EEnum overwriteMode,
+ const wchar_t *path,
+ INT32 testMode,
+ IFolderArchiveExtractCallback *extractCallback2)
+{
+ COM_TRY_BEGIN
+ CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
+ CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
+ extractCallbackSpec->Init(GetArchive(),
+ extractCallback2,
+ false,
+ path,
+ pathMode,
+ overwriteMode,
+ UStringVector(),
+ DefaultName,
+ DefaultTime,
+ DefaultAttributes
+ // ,_srcDirectoryPrefix
+ );
+ return GetArchive()->Extract(0, (UInt32)(Int32)-1, testMode, extractCallback);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgent::GetNumberOfProperties(UINT32 *numProperties)
+{
+ COM_TRY_BEGIN
+ return GetArchive()->GetNumberOfProperties(numProperties);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgent::GetPropertyInfo(UINT32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType)
+{
+ COM_TRY_BEGIN
+ RINOK(GetArchive()->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 GetArchive()->GetArchiveProperty(propID, value);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgent::GetNumberOfArchiveProperties(UINT32 *numProperties)
+{
+ COM_TRY_BEGIN
+ return GetArchive()->GetNumberOfArchiveProperties(numProperties);
+ COM_TRY_END
+}
+
+STDMETHODIMP CAgent::GetArchivePropertyInfo(UINT32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType)
+{
+ COM_TRY_BEGIN
+ return GetArchive()->GetArchivePropertyInfo(index,
+ name, propID, varType);
+ COM_TRY_END
+}
+