chore: initial commit (extracted from Launchers monorepo)
Plugin: ns7zip v2.0.0 Architectures: x86-ansi, x86-unicode, amd64-unicode License: LGPL-2.1-or-later
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,358 @@
|
||||
// Agent/Agent.h
|
||||
|
||||
#ifndef ZIP7_INC_AGENT_AGENT_H
|
||||
#define ZIP7_INC_AGENT_AGENT_H
|
||||
|
||||
#include "../../../Common/MyCom.h"
|
||||
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
|
||||
#include "../Common/LoadCodecs.h"
|
||||
#include "../Common/OpenArchive.h"
|
||||
#include "../Common/UpdateAction.h"
|
||||
|
||||
#include "../FileManager/IFolder.h"
|
||||
|
||||
#include "AgentProxy.h"
|
||||
#include "IFolderArchive.h"
|
||||
|
||||
extern CCodecs *g_CodecsObj;
|
||||
HRESULT LoadGlobalCodecs();
|
||||
void FreeGlobalCodecs();
|
||||
|
||||
class CAgentFolder;
|
||||
|
||||
Z7_PURE_INTERFACES_BEGIN
|
||||
|
||||
#define Z7_IFACEM_IArchiveFolderInternal(x) \
|
||||
x(GetAgentFolder(CAgentFolder **agentFolder))
|
||||
Z7_IFACE_CONSTR_FOLDERARC(IArchiveFolderInternal, 0xC)
|
||||
|
||||
Z7_PURE_INTERFACES_END
|
||||
|
||||
struct CProxyItem
|
||||
{
|
||||
unsigned DirIndex;
|
||||
unsigned Index;
|
||||
};
|
||||
|
||||
class CAgent;
|
||||
|
||||
enum AGENT_OP
|
||||
{
|
||||
AGENT_OP_Uni,
|
||||
AGENT_OP_Delete,
|
||||
AGENT_OP_CreateFolder,
|
||||
AGENT_OP_Rename,
|
||||
AGENT_OP_CopyFromFile,
|
||||
AGENT_OP_Comment
|
||||
};
|
||||
|
||||
class CAgentFolder Z7_final:
|
||||
public IFolderFolder,
|
||||
public IFolderAltStreams,
|
||||
public IFolderProperties,
|
||||
public IArchiveGetRawProps,
|
||||
public IGetFolderArcProps,
|
||||
public IFolderCompare,
|
||||
public IFolderGetItemName,
|
||||
public IArchiveFolder,
|
||||
public IArchiveFolderInternal,
|
||||
public IInArchiveGetStream,
|
||||
public IFolderSetZoneIdMode,
|
||||
public IFolderSetZoneIdFile,
|
||||
public IFolderOperations,
|
||||
public IFolderSetFlatMode,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_COM_QI_BEGIN2(IFolderFolder)
|
||||
Z7_COM_QI_ENTRY(IFolderAltStreams)
|
||||
Z7_COM_QI_ENTRY(IFolderProperties)
|
||||
Z7_COM_QI_ENTRY(IArchiveGetRawProps)
|
||||
Z7_COM_QI_ENTRY(IGetFolderArcProps)
|
||||
Z7_COM_QI_ENTRY(IFolderCompare)
|
||||
Z7_COM_QI_ENTRY(IFolderGetItemName)
|
||||
Z7_COM_QI_ENTRY(IArchiveFolder)
|
||||
Z7_COM_QI_ENTRY(IArchiveFolderInternal)
|
||||
Z7_COM_QI_ENTRY(IInArchiveGetStream)
|
||||
Z7_COM_QI_ENTRY(IFolderSetZoneIdMode)
|
||||
Z7_COM_QI_ENTRY(IFolderSetZoneIdFile)
|
||||
Z7_COM_QI_ENTRY(IFolderOperations)
|
||||
Z7_COM_QI_ENTRY(IFolderSetFlatMode)
|
||||
Z7_COM_QI_END
|
||||
Z7_COM_ADDREF_RELEASE
|
||||
|
||||
Z7_IFACE_COM7_IMP(IFolderFolder)
|
||||
Z7_IFACE_COM7_IMP(IFolderAltStreams)
|
||||
Z7_IFACE_COM7_IMP(IFolderProperties)
|
||||
Z7_IFACE_COM7_IMP(IArchiveGetRawProps)
|
||||
Z7_IFACE_COM7_IMP(IGetFolderArcProps)
|
||||
Z7_IFACE_COM7_IMP(IFolderCompare)
|
||||
Z7_IFACE_COM7_IMP(IFolderGetItemName)
|
||||
Z7_IFACE_COM7_IMP(IArchiveFolder)
|
||||
Z7_IFACE_COM7_IMP(IArchiveFolderInternal)
|
||||
Z7_IFACE_COM7_IMP(IInArchiveGetStream)
|
||||
Z7_IFACE_COM7_IMP(IFolderSetZoneIdMode)
|
||||
Z7_IFACE_COM7_IMP(IFolderSetZoneIdFile)
|
||||
Z7_IFACE_COM7_IMP(IFolderOperations)
|
||||
Z7_IFACE_COM7_IMP(IFolderSetFlatMode)
|
||||
|
||||
void LoadFolder(unsigned proxyDirIndex);
|
||||
public:
|
||||
HRESULT BindToFolder_Internal(unsigned proxyDirIndex, IFolderFolder **resultFolder);
|
||||
HRESULT BindToAltStreams_Internal(unsigned proxyDirIndex, IFolderFolder **resultFolder);
|
||||
int GetRealIndex(unsigned index) const;
|
||||
void GetRealIndices(const UInt32 *indices, UInt32 numItems,
|
||||
bool includeAltStreams, bool includeFolderSubItemsInFlatMode, CUIntVector &realIndices) const;
|
||||
|
||||
int CompareItems3(UInt32 index1, UInt32 index2, PROPID propID);
|
||||
int CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw);
|
||||
|
||||
CAgentFolder():
|
||||
_isAltStreamFolder(false),
|
||||
_flatMode(false),
|
||||
_loadAltStreams(false), // _loadAltStreams alt streams works in flat mode, but we don't use it now
|
||||
_proxyDirIndex(0),
|
||||
_zoneMode(NExtract::NZoneIdMode::kNone)
|
||||
/* , _replaceAltStreamCharsMode(0) */
|
||||
{}
|
||||
|
||||
void Init(const CProxyArc *proxy, const CProxyArc2 *proxy2,
|
||||
unsigned proxyDirIndex,
|
||||
/* IFolderFolder *parentFolder, */
|
||||
CAgent *agent)
|
||||
{
|
||||
_proxy = proxy;
|
||||
_proxy2 = proxy2;
|
||||
_proxyDirIndex = proxyDirIndex;
|
||||
_isAltStreamFolder = false;
|
||||
if (_proxy2)
|
||||
_isAltStreamFolder = _proxy2->IsAltDir(proxyDirIndex);
|
||||
// _parentFolder = parentFolder;
|
||||
_agent = (IInFolderArchive *)agent;
|
||||
_agentSpec = agent;
|
||||
}
|
||||
|
||||
void GetPathParts(UStringVector &pathParts, bool &isAltStreamFolder);
|
||||
HRESULT CommonUpdateOperation(
|
||||
AGENT_OP operation,
|
||||
bool moveMode,
|
||||
const wchar_t *newItemName,
|
||||
const NUpdateArchive::CActionSet *actionSet,
|
||||
const UInt32 *indices, UInt32 numItems,
|
||||
IProgress *progress);
|
||||
|
||||
|
||||
void GetPrefix(UInt32 index, UString &prefix) const;
|
||||
UString GetName(UInt32 index) const;
|
||||
UString GetFullPrefix(UInt32 index) const; // relative too root folder of archive
|
||||
|
||||
public:
|
||||
bool _isAltStreamFolder;
|
||||
bool _flatMode;
|
||||
bool _loadAltStreams; // in Flat mode
|
||||
const CProxyArc *_proxy;
|
||||
const CProxyArc2 *_proxy2;
|
||||
unsigned _proxyDirIndex;
|
||||
NExtract::NZoneIdMode::EEnum _zoneMode;
|
||||
CByteBuffer _zoneBuf;
|
||||
// Int32 _replaceAltStreamCharsMode;
|
||||
// CMyComPtr<IFolderFolder> _parentFolder;
|
||||
CMyComPtr<IInFolderArchive> _agent;
|
||||
CAgent *_agentSpec;
|
||||
CRecordVector<CProxyItem> _items;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class CAgent Z7_final:
|
||||
public IInFolderArchive,
|
||||
public IFolderArcProps,
|
||||
#ifndef Z7_EXTRACT_ONLY
|
||||
public IOutFolderArchive,
|
||||
public ISetProperties,
|
||||
#endif
|
||||
public CMyUnknownImp
|
||||
{
|
||||
Z7_COM_QI_BEGIN2(IInFolderArchive)
|
||||
Z7_COM_QI_ENTRY(IFolderArcProps)
|
||||
#ifndef Z7_EXTRACT_ONLY
|
||||
Z7_COM_QI_ENTRY(IOutFolderArchive)
|
||||
Z7_COM_QI_ENTRY(ISetProperties)
|
||||
#endif
|
||||
Z7_COM_QI_END
|
||||
Z7_COM_ADDREF_RELEASE
|
||||
|
||||
Z7_IFACE_COM7_IMP(IInFolderArchive)
|
||||
Z7_IFACE_COM7_IMP(IFolderArcProps)
|
||||
|
||||
#ifndef Z7_EXTRACT_ONLY
|
||||
Z7_IFACE_COM7_IMP(ISetProperties)
|
||||
|
||||
public:
|
||||
Z7_IFACE_COM7_IMP(IOutFolderArchive)
|
||||
HRESULT CommonUpdate(ISequentialOutStream *outArchiveStream,
|
||||
unsigned numUpdateItems, IArchiveUpdateCallback *updateCallback);
|
||||
|
||||
HRESULT CreateFolder(ISequentialOutStream *outArchiveStream,
|
||||
const wchar_t *folderName, IFolderArchiveUpdateCallback *updateCallback100);
|
||||
|
||||
HRESULT RenameItem(ISequentialOutStream *outArchiveStream,
|
||||
const UInt32 *indices, UInt32 numItems, const wchar_t *newItemName,
|
||||
IFolderArchiveUpdateCallback *updateCallback100);
|
||||
|
||||
HRESULT CommentItem(ISequentialOutStream *outArchiveStream,
|
||||
const UInt32 *indices, UInt32 numItems, const wchar_t *newItemName,
|
||||
IFolderArchiveUpdateCallback *updateCallback100);
|
||||
|
||||
HRESULT UpdateOneFile(ISequentialOutStream *outArchiveStream,
|
||||
const UInt32 *indices, UInt32 numItems, const wchar_t *diskFilePath,
|
||||
IFolderArchiveUpdateCallback *updateCallback100);
|
||||
#endif
|
||||
|
||||
private:
|
||||
HRESULT ReadItems();
|
||||
|
||||
public:
|
||||
CProxyArc *_proxy;
|
||||
CProxyArc2 *_proxy2;
|
||||
CArchiveLink _archiveLink;
|
||||
|
||||
UString ArchiveType;
|
||||
|
||||
FStringVector _names;
|
||||
FString _folderPrefix; // for new files from disk
|
||||
|
||||
UString _updatePathPrefix;
|
||||
CAgentFolder *_agentFolder;
|
||||
|
||||
UString _archiveFilePath; // it can be path of non-existing file if file is virtual
|
||||
|
||||
DWORD _attrib;
|
||||
bool _updatePathPrefix_is_AltFolder;
|
||||
bool ThereIsPathProp;
|
||||
bool _isDeviceFile;
|
||||
bool _isHashHandler;
|
||||
|
||||
FString _hashBaseFolderPrefix;
|
||||
|
||||
#ifndef Z7_EXTRACT_ONLY
|
||||
CObjectVector<UString> m_PropNames;
|
||||
CObjectVector<NWindows::NCOM::CPropVariant> m_PropValues;
|
||||
#endif
|
||||
|
||||
CAgent();
|
||||
~CAgent();
|
||||
|
||||
const CArc &GetArc() const { return _archiveLink.Arcs.Back(); }
|
||||
IInArchive *GetArchive() const { if ( _archiveLink.Arcs.IsEmpty()) return NULL; return GetArc().Archive; }
|
||||
bool CanUpdate() const;
|
||||
|
||||
bool Is_Attrib_ReadOnly() const
|
||||
{
|
||||
return _attrib != INVALID_FILE_ATTRIBUTES && (_attrib & FILE_ATTRIBUTE_READONLY);
|
||||
}
|
||||
|
||||
bool IsThere_ReadOnlyArc() const
|
||||
{
|
||||
FOR_VECTOR (i, _archiveLink.Arcs)
|
||||
{
|
||||
const CArc &arc = _archiveLink.Arcs[i];
|
||||
if (arc.FormatIndex < 0
|
||||
|| arc.IsReadOnly
|
||||
|| !g_CodecsObj->Formats[arc.FormatIndex].UpdateEnabled)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
UString GetTypeOfArc(const CArc &arc) const
|
||||
{
|
||||
if (arc.FormatIndex < 0)
|
||||
return UString("Parser");
|
||||
return g_CodecsObj->GetFormatNamePtr(arc.FormatIndex);
|
||||
}
|
||||
|
||||
UString GetErrorMessage() const
|
||||
{
|
||||
UString s;
|
||||
for (int i = (int)_archiveLink.Arcs.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
const CArc &arc = _archiveLink.Arcs[i];
|
||||
|
||||
UString s2;
|
||||
if (arc.ErrorInfo.ErrorFormatIndex >= 0)
|
||||
{
|
||||
if (arc.ErrorInfo.ErrorFormatIndex == arc.FormatIndex)
|
||||
s2 += "Warning: The archive is open with offset";
|
||||
else
|
||||
{
|
||||
s2 += "Cannot open the file as [";
|
||||
s2 += g_CodecsObj->GetFormatNamePtr(arc.ErrorInfo.ErrorFormatIndex);
|
||||
s2 += "] archive";
|
||||
}
|
||||
}
|
||||
|
||||
if (!arc.ErrorInfo.ErrorMessage.IsEmpty())
|
||||
{
|
||||
if (!s2.IsEmpty())
|
||||
s2.Add_LF();
|
||||
s2 += "\n[";
|
||||
s2 += GetTypeOfArc(arc);
|
||||
s2 += "]: ";
|
||||
s2 += arc.ErrorInfo.ErrorMessage;
|
||||
}
|
||||
|
||||
if (!s2.IsEmpty())
|
||||
{
|
||||
if (!s.IsEmpty())
|
||||
s += "--------------------\n";
|
||||
s += arc.Path;
|
||||
s.Add_LF();
|
||||
s += s2;
|
||||
s.Add_LF();
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void KeepModeForNextOpen() { _archiveLink.KeepModeForNextOpen(); }
|
||||
};
|
||||
|
||||
|
||||
// #ifdef NEW_FOLDER_INTERFACE
|
||||
|
||||
struct CCodecIcons
|
||||
{
|
||||
struct CIconPair
|
||||
{
|
||||
UString Ext;
|
||||
int IconIndex;
|
||||
};
|
||||
CObjectVector<CIconPair> IconPairs;
|
||||
|
||||
// void Clear() { IconPairs.Clear(); }
|
||||
void LoadIcons(HMODULE m);
|
||||
bool FindIconIndex(const UString &ext, int &iconIndex) const;
|
||||
};
|
||||
|
||||
|
||||
Z7_CLASS_IMP_COM_1(
|
||||
CArchiveFolderManager
|
||||
, IFolderManager
|
||||
)
|
||||
CObjectVector<CCodecIcons> CodecIconsVector;
|
||||
CCodecIcons InternalIcons;
|
||||
bool WasLoaded;
|
||||
|
||||
void LoadFormats();
|
||||
// int FindFormat(const UString &type);
|
||||
public:
|
||||
CArchiveFolderManager():
|
||||
WasLoaded(false)
|
||||
{}
|
||||
};
|
||||
|
||||
// #endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,718 @@
|
||||
// AgentOut.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/Wildcard.h"
|
||||
|
||||
#include "../../../Windows/FileDir.h"
|
||||
#include "../../../Windows/FileName.h"
|
||||
#include "../../../Windows/TimeUtils.h"
|
||||
|
||||
#include "../../Compress/CopyCoder.h"
|
||||
|
||||
#include "../../Common/FileStreams.h"
|
||||
|
||||
#include "../../Archive/Common/ItemNameUtils.h"
|
||||
|
||||
#include "Agent.h"
|
||||
#include "UpdateCallbackAgent.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NCOM;
|
||||
|
||||
Z7_COM7F_IMF(CAgent::SetFolder(IFolderFolder *folder))
|
||||
{
|
||||
_updatePathPrefix.Empty();
|
||||
_updatePathPrefix_is_AltFolder = false;
|
||||
_agentFolder = NULL;
|
||||
|
||||
if (!folder)
|
||||
return S_OK;
|
||||
|
||||
{
|
||||
Z7_DECL_CMyComPtr_QI_FROM(
|
||||
IArchiveFolderInternal,
|
||||
afi, folder)
|
||||
if (afi)
|
||||
{
|
||||
RINOK(afi->GetAgentFolder(&_agentFolder))
|
||||
}
|
||||
if (!_agentFolder)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (_proxy2)
|
||||
_updatePathPrefix = _proxy2->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex, _updatePathPrefix_is_AltFolder);
|
||||
else
|
||||
_updatePathPrefix = _proxy->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CAgent::SetFiles(const wchar_t *folderPrefix,
|
||||
const wchar_t * const *names, UInt32 numNames))
|
||||
{
|
||||
_folderPrefix = us2fs(folderPrefix);
|
||||
_names.ClearAndReserve(numNames);
|
||||
for (UInt32 i = 0; i < numNames; i++)
|
||||
_names.AddInReserved(us2fs(names[i]));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT EnumerateArchiveItems(CAgent *agent,
|
||||
const CProxyDir &item,
|
||||
const UString &prefix,
|
||||
CObjectVector<CArcItem> &arcItems)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < item.SubFiles.Size(); i++)
|
||||
{
|
||||
unsigned arcIndex = item.SubFiles[i];
|
||||
const CProxyFile &fileItem = agent->_proxy->Files[arcIndex];
|
||||
CArcItem ai;
|
||||
RINOK(agent->GetArc().GetItem_MTime(arcIndex, ai.MTime))
|
||||
RINOK(agent->GetArc().GetItem_Size(arcIndex, ai.Size, ai.Size_Defined))
|
||||
ai.IsDir = false;
|
||||
ai.Name = prefix + fileItem.Name;
|
||||
ai.Censored = true; // test it
|
||||
ai.IndexInServer = arcIndex;
|
||||
arcItems.Add(ai);
|
||||
}
|
||||
|
||||
for (i = 0; i < item.SubDirs.Size(); i++)
|
||||
{
|
||||
const CProxyDir &dirItem = agent->_proxy->Dirs[item.SubDirs[i]];
|
||||
UString fullName = prefix + dirItem.Name;
|
||||
if (dirItem.IsLeaf())
|
||||
{
|
||||
CArcItem ai;
|
||||
RINOK(agent->GetArc().GetItem_MTime((unsigned)dirItem.ArcIndex, ai.MTime))
|
||||
ai.IsDir = true;
|
||||
ai.Size_Defined = false;
|
||||
ai.Name = fullName;
|
||||
ai.Censored = true; // test it
|
||||
ai.IndexInServer = (unsigned)dirItem.ArcIndex;
|
||||
arcItems.Add(ai);
|
||||
}
|
||||
RINOK(EnumerateArchiveItems(agent, dirItem, fullName + WCHAR_PATH_SEPARATOR, arcItems))
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT EnumerateArchiveItems2(const CAgent *agent,
|
||||
unsigned dirIndex,
|
||||
const UString &prefix,
|
||||
CObjectVector<CArcItem> &arcItems)
|
||||
{
|
||||
const CProxyDir2 &dir = agent->_proxy2->Dirs[dirIndex];
|
||||
FOR_VECTOR (i, dir.Items)
|
||||
{
|
||||
unsigned arcIndex = dir.Items[i];
|
||||
const CProxyFile2 &file = agent->_proxy2->Files[arcIndex];
|
||||
CArcItem ai;
|
||||
ai.IndexInServer = arcIndex;
|
||||
ai.Name = prefix + file.Name;
|
||||
ai.Censored = true; // test it
|
||||
RINOK(agent->GetArc().GetItem_MTime(arcIndex, ai.MTime))
|
||||
ai.IsDir = file.IsDir();
|
||||
ai.Size_Defined = false;
|
||||
ai.IsAltStream = file.IsAltStream;
|
||||
if (!ai.IsDir)
|
||||
{
|
||||
RINOK(agent->GetArc().GetItem_Size(arcIndex, ai.Size, ai.Size_Defined))
|
||||
ai.IsDir = false;
|
||||
}
|
||||
arcItems.Add(ai);
|
||||
|
||||
if (file.AltDirIndex != -1)
|
||||
{
|
||||
RINOK(EnumerateArchiveItems2(agent, (unsigned)file.AltDirIndex, ai.Name + L':', arcItems))
|
||||
}
|
||||
|
||||
if (ai.IsDir)
|
||||
{
|
||||
RINOK(EnumerateArchiveItems2(agent, (unsigned)file.DirIndex, ai.Name + WCHAR_PATH_SEPARATOR, arcItems))
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
struct CAgUpCallbackImp Z7_final: public IUpdateProduceCallback
|
||||
{
|
||||
const CObjectVector<CArcItem> *_arcItems;
|
||||
IFolderArchiveUpdateCallback *_callback;
|
||||
|
||||
CAgUpCallbackImp(const CObjectVector<CArcItem> *a,
|
||||
IFolderArchiveUpdateCallback *callback): _arcItems(a), _callback(callback) {}
|
||||
HRESULT ShowDeleteFile(unsigned arcIndex) Z7_override;
|
||||
};
|
||||
|
||||
HRESULT CAgUpCallbackImp::ShowDeleteFile(unsigned arcIndex)
|
||||
{
|
||||
return _callback->DeleteOperation((*_arcItems)[arcIndex].Name);
|
||||
}
|
||||
|
||||
|
||||
static void SetInArchiveInterfaces(CAgent *agent, CArchiveUpdateCallback *upd)
|
||||
{
|
||||
if (agent->_archiveLink.Arcs.IsEmpty())
|
||||
return;
|
||||
const CArc &arc = agent->GetArc();
|
||||
upd->Arc = &arc;
|
||||
upd->Archive = arc.Archive;
|
||||
|
||||
upd->ArcFileName = ExtractFileNameFromPath(arc.Path);
|
||||
}
|
||||
|
||||
struct CDirItemsCallback_AgentOut Z7_final: public IDirItemsCallback
|
||||
{
|
||||
CMyComPtr<IFolderScanProgress> FolderScanProgress;
|
||||
IFolderArchiveUpdateCallback *FolderArchiveUpdateCallback;
|
||||
HRESULT ErrorCode;
|
||||
|
||||
CDirItemsCallback_AgentOut(): FolderArchiveUpdateCallback(NULL), ErrorCode(S_OK) {}
|
||||
|
||||
HRESULT ScanError(const FString &name, DWORD systemError) Z7_override
|
||||
{
|
||||
const HRESULT hres = HRESULT_FROM_WIN32(systemError);
|
||||
if (FolderArchiveUpdateCallback)
|
||||
return FolderScanProgress->ScanError(fs2us(name), hres);
|
||||
ErrorCode = hres;
|
||||
return ErrorCode;
|
||||
}
|
||||
|
||||
HRESULT ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir) Z7_override
|
||||
{
|
||||
if (FolderScanProgress)
|
||||
return FolderScanProgress->ScanProgress(st.NumDirs, st.NumFiles + st.NumAltStreams,
|
||||
st.GetTotalBytes(), fs2us(path), BoolToInt(isDir));
|
||||
if (FolderArchiveUpdateCallback)
|
||||
return FolderArchiveUpdateCallback->SetNumFiles(st.NumFiles);
|
||||
return S_OK;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CAgent::DoOperation(
|
||||
FStringVector *requestedPaths,
|
||||
FStringVector *processedPaths,
|
||||
CCodecs *codecs,
|
||||
int formatIndex,
|
||||
ISequentialOutStream *outArchiveStream,
|
||||
const Byte *stateActions,
|
||||
const wchar_t *sfxModule,
|
||||
IFolderArchiveUpdateCallback *updateCallback100))
|
||||
{
|
||||
if (!CanUpdate())
|
||||
return E_NOTIMPL;
|
||||
|
||||
NUpdateArchive::CActionSet actionSet;
|
||||
{
|
||||
for (unsigned i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
|
||||
actionSet.StateActions[i] = (NUpdateArchive::NPairAction::EEnum)stateActions[i];
|
||||
}
|
||||
|
||||
CDirItemsCallback_AgentOut enumCallback;
|
||||
if (updateCallback100)
|
||||
{
|
||||
enumCallback.FolderArchiveUpdateCallback = updateCallback100;
|
||||
updateCallback100->QueryInterface(IID_IFolderScanProgress, (void **)&enumCallback.FolderScanProgress);
|
||||
}
|
||||
|
||||
CDirItems dirItems;
|
||||
dirItems.Callback = &enumCallback;
|
||||
|
||||
{
|
||||
FString folderPrefix = _folderPrefix;
|
||||
if (!NFile::NName::IsAltStreamPrefixWithColon(fs2us(folderPrefix)))
|
||||
NFile::NName::NormalizeDirPathPrefix(folderPrefix);
|
||||
|
||||
RINOK(dirItems.EnumerateItems2(folderPrefix, _updatePathPrefix, _names, requestedPaths))
|
||||
|
||||
if (_updatePathPrefix_is_AltFolder)
|
||||
{
|
||||
FOR_VECTOR(i, dirItems.Items)
|
||||
{
|
||||
CDirItem &item = dirItems.Items[i];
|
||||
if (item.IsDir())
|
||||
return E_NOTIMPL;
|
||||
item.IsAltStream = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CMyComPtr<IOutArchive> outArchive;
|
||||
|
||||
if (GetArchive())
|
||||
{
|
||||
RINOK(GetArchive()->QueryInterface(IID_IOutArchive, (void **)&outArchive))
|
||||
}
|
||||
else
|
||||
{
|
||||
if (formatIndex < 0)
|
||||
return E_FAIL;
|
||||
RINOK(codecs->CreateOutArchive((unsigned)formatIndex, outArchive))
|
||||
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
{
|
||||
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
|
||||
outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
|
||||
if (setCompressCodecsInfo)
|
||||
{
|
||||
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs))
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NFileTimeType::EEnum fileTimeType = NFileTimeType::kNotDefined;
|
||||
UInt32 value;
|
||||
RINOK(outArchive->GetFileTimeType(&value))
|
||||
// we support any future fileType here.
|
||||
// 22.00:
|
||||
fileTimeType = (NFileTimeType::EEnum)value;
|
||||
/*
|
||||
switch (value)
|
||||
{
|
||||
case NFileTimeType::kWindows:
|
||||
case NFileTimeType::kDOS:
|
||||
case NFileTimeType::kUnix:
|
||||
fileTimeType = NFileTimeType::EEnum(value);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
CObjectVector<CArcItem> arcItems;
|
||||
if (GetArchive())
|
||||
{
|
||||
RINOK(ReadItems())
|
||||
if (_proxy2)
|
||||
{
|
||||
RINOK(EnumerateArchiveItems2(this, k_Proxy2_RootDirIndex, L"", arcItems))
|
||||
RINOK(EnumerateArchiveItems2(this, k_Proxy2_AltRootDirIndex, L":", arcItems))
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(EnumerateArchiveItems(this, _proxy->Dirs[0], L"", arcItems))
|
||||
}
|
||||
}
|
||||
|
||||
CRecordVector<CUpdatePair2> updatePairs2;
|
||||
|
||||
{
|
||||
CRecordVector<CUpdatePair> updatePairs;
|
||||
GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs);
|
||||
CAgUpCallbackImp upCallback(&arcItems, updateCallback100);
|
||||
UpdateProduce(updatePairs, actionSet, updatePairs2, &upCallback);
|
||||
}
|
||||
|
||||
UInt32 numFiles = 0;
|
||||
{
|
||||
FOR_VECTOR (i, updatePairs2)
|
||||
if (updatePairs2[i].NewData)
|
||||
numFiles++;
|
||||
}
|
||||
|
||||
if (updateCallback100)
|
||||
{
|
||||
RINOK(updateCallback100->SetNumFiles(numFiles))
|
||||
}
|
||||
|
||||
CUpdateCallbackAgent updateCallbackAgent;
|
||||
updateCallbackAgent.SetCallback(updateCallback100);
|
||||
CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
|
||||
|
||||
updateCallback->DirItems = &dirItems;
|
||||
updateCallback->ArcItems = &arcItems;
|
||||
updateCallback->UpdatePairs = &updatePairs2;
|
||||
|
||||
SetInArchiveInterfaces(this, updateCallback.ClsPtr());
|
||||
|
||||
updateCallback->Callback = &updateCallbackAgent;
|
||||
|
||||
CByteBuffer processedItems;
|
||||
if (processedPaths)
|
||||
{
|
||||
unsigned num = dirItems.Items.Size();
|
||||
processedItems.Alloc(num);
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
processedItems[i] = 0;
|
||||
updateCallback->ProcessedItemsStatuses = processedItems;
|
||||
}
|
||||
|
||||
Z7_DECL_CMyComPtr_QI_FROM(
|
||||
ISetProperties,
|
||||
setProperties, outArchive)
|
||||
if (setProperties)
|
||||
{
|
||||
if (m_PropNames.Size() == 0)
|
||||
{
|
||||
RINOK(setProperties->SetProperties(NULL, NULL, 0))
|
||||
}
|
||||
else
|
||||
{
|
||||
CRecordVector<const wchar_t *> names;
|
||||
FOR_VECTOR (i, m_PropNames)
|
||||
names.Add((const wchar_t *)m_PropNames[i]);
|
||||
|
||||
CPropVariant *propValues = new CPropVariant[m_PropValues.Size()];
|
||||
try
|
||||
{
|
||||
FOR_VECTOR (i, m_PropValues)
|
||||
propValues[i] = m_PropValues[i];
|
||||
RINOK(setProperties->SetProperties(names.ConstData(), propValues, names.Size()))
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
delete []propValues;
|
||||
return E_FAIL;
|
||||
}
|
||||
delete []propValues;
|
||||
}
|
||||
}
|
||||
m_PropNames.Clear();
|
||||
m_PropValues.Clear();
|
||||
|
||||
if (sfxModule != NULL)
|
||||
{
|
||||
CMyComPtr2_Create<IInStream, CInFileStream> sfxStream;
|
||||
if (!sfxStream->Open(us2fs(sfxModule)))
|
||||
return E_FAIL;
|
||||
// throw "Can't open sfx module";
|
||||
RINOK(NCompress::CopyStream(sfxStream, outArchiveStream, NULL))
|
||||
}
|
||||
|
||||
const HRESULT res = outArchive->UpdateItems(outArchiveStream, updatePairs2.Size(), updateCallback);
|
||||
if (res == S_OK && processedPaths)
|
||||
{
|
||||
{
|
||||
/* OutHandler for 7z archives doesn't report compression operation for empty files.
|
||||
So we must include these files manually */
|
||||
FOR_VECTOR(i, updatePairs2)
|
||||
{
|
||||
const CUpdatePair2 &up = updatePairs2[i];
|
||||
if (up.DirIndex != -1 && up.NewData)
|
||||
{
|
||||
const CDirItem &di = dirItems.Items[(unsigned)up.DirIndex];
|
||||
if (!di.IsDir() && di.Size == 0)
|
||||
processedItems[(unsigned)up.DirIndex] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FOR_VECTOR (i, dirItems.Items)
|
||||
if (processedItems[i] != 0)
|
||||
processedPaths->Add(dirItems.GetPhyPath(i));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CAgent::DoOperation2(
|
||||
FStringVector *requestedPaths,
|
||||
FStringVector *processedPaths,
|
||||
ISequentialOutStream *outArchiveStream,
|
||||
const Byte *stateActions, const wchar_t *sfxModule, IFolderArchiveUpdateCallback *updateCallback100))
|
||||
{
|
||||
return DoOperation(requestedPaths, processedPaths, g_CodecsObj, -1, outArchiveStream, stateActions, sfxModule, updateCallback100);
|
||||
}
|
||||
|
||||
HRESULT CAgent::CommonUpdate(ISequentialOutStream *outArchiveStream,
|
||||
unsigned numUpdateItems, IArchiveUpdateCallback *updateCallback)
|
||||
{
|
||||
if (!CanUpdate())
|
||||
return E_NOTIMPL;
|
||||
CMyComPtr<IOutArchive> outArchive;
|
||||
RINOK(GetArchive()->QueryInterface(IID_IOutArchive, (void **)&outArchive))
|
||||
return outArchive->UpdateItems(outArchiveStream, numUpdateItems, updateCallback);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CAgent::DeleteItems(ISequentialOutStream *outArchiveStream,
|
||||
const UInt32 *indices, UInt32 numItems,
|
||||
IFolderArchiveUpdateCallback *updateCallback100))
|
||||
{
|
||||
if (!CanUpdate())
|
||||
return E_NOTIMPL;
|
||||
CRecordVector<CUpdatePair2> updatePairs;
|
||||
CUpdateCallbackAgent updateCallbackAgent;
|
||||
updateCallbackAgent.SetCallback(updateCallback100);
|
||||
CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
|
||||
|
||||
CUIntVector realIndices;
|
||||
_agentFolder->GetRealIndices(indices, numItems,
|
||||
true, // includeAltStreams
|
||||
false, // includeFolderSubItemsInFlatMode, we don't want to delete subItems in Flat Mode
|
||||
realIndices);
|
||||
unsigned curIndex = 0;
|
||||
UInt32 numItemsInArchive;
|
||||
RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive))
|
||||
|
||||
UString deletePath;
|
||||
|
||||
for (UInt32 i = 0; i < numItemsInArchive; i++)
|
||||
{
|
||||
if (curIndex < realIndices.Size())
|
||||
if (realIndices[curIndex] == i)
|
||||
{
|
||||
RINOK(GetArc().GetItem_Path2(i, deletePath))
|
||||
RINOK(updateCallback100->DeleteOperation(deletePath))
|
||||
|
||||
curIndex++;
|
||||
continue;
|
||||
}
|
||||
CUpdatePair2 up2;
|
||||
up2.SetAs_NoChangeArcItem(i);
|
||||
updatePairs.Add(up2);
|
||||
}
|
||||
updateCallback->UpdatePairs = &updatePairs;
|
||||
|
||||
SetInArchiveInterfaces(this, updateCallback.ClsPtr());
|
||||
|
||||
updateCallback->Callback = &updateCallbackAgent;
|
||||
return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
|
||||
}
|
||||
|
||||
HRESULT CAgent::CreateFolder(ISequentialOutStream *outArchiveStream,
|
||||
const wchar_t *folderName, IFolderArchiveUpdateCallback *updateCallback100)
|
||||
{
|
||||
if (!CanUpdate())
|
||||
return E_NOTIMPL;
|
||||
CRecordVector<CUpdatePair2> updatePairs;
|
||||
CDirItems dirItems;
|
||||
CUpdateCallbackAgent updateCallbackAgent;
|
||||
updateCallbackAgent.SetCallback(updateCallback100);
|
||||
CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
|
||||
|
||||
UInt32 numItemsInArchive;
|
||||
RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive))
|
||||
for (UInt32 i = 0; i < numItemsInArchive; i++)
|
||||
{
|
||||
CUpdatePair2 up2;
|
||||
up2.SetAs_NoChangeArcItem(i);
|
||||
updatePairs.Add(up2);
|
||||
}
|
||||
CUpdatePair2 up2;
|
||||
up2.NewData = up2.NewProps = true;
|
||||
up2.UseArcProps = false;
|
||||
up2.DirIndex = 0;
|
||||
|
||||
updatePairs.Add(up2);
|
||||
|
||||
updatePairs.ReserveDown();
|
||||
|
||||
CDirItem di;
|
||||
|
||||
di.Attrib = FILE_ATTRIBUTE_DIRECTORY;
|
||||
di.Size = 0;
|
||||
bool isAltStreamFolder = false;
|
||||
if (_proxy2)
|
||||
di.Name = _proxy2->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex, isAltStreamFolder);
|
||||
else
|
||||
di.Name = _proxy->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex);
|
||||
di.Name += folderName;
|
||||
|
||||
FILETIME ft;
|
||||
NTime::GetCurUtcFileTime(ft);
|
||||
di.CTime = di.ATime = di.MTime = ft;
|
||||
|
||||
dirItems.Items.Add(di);
|
||||
|
||||
updateCallback->Callback = &updateCallbackAgent;
|
||||
updateCallback->DirItems = &dirItems;
|
||||
updateCallback->UpdatePairs = &updatePairs;
|
||||
|
||||
SetInArchiveInterfaces(this, updateCallback.ClsPtr());
|
||||
|
||||
return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
|
||||
}
|
||||
|
||||
|
||||
HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream,
|
||||
const UInt32 *indices, UInt32 numItems, const wchar_t *newItemName,
|
||||
IFolderArchiveUpdateCallback *updateCallback100)
|
||||
{
|
||||
if (!CanUpdate())
|
||||
return E_NOTIMPL;
|
||||
if (numItems != 1)
|
||||
return E_INVALIDARG;
|
||||
if (!_archiveLink.IsOpen)
|
||||
return E_FAIL;
|
||||
CRecordVector<CUpdatePair2> updatePairs;
|
||||
CUpdateCallbackAgent updateCallbackAgent;
|
||||
updateCallbackAgent.SetCallback(updateCallback100);
|
||||
CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
|
||||
|
||||
CUIntVector realIndices;
|
||||
_agentFolder->GetRealIndices(indices, numItems,
|
||||
true, // includeAltStreams
|
||||
true, // includeFolderSubItemsInFlatMode
|
||||
realIndices);
|
||||
|
||||
const UInt32 ind0 = indices[0];
|
||||
const int mainRealIndex = _agentFolder->GetRealIndex(ind0);
|
||||
const UString fullPrefix = _agentFolder->GetFullPrefix(ind0);
|
||||
UString name = _agentFolder->GetName(ind0);
|
||||
// 22.00 : we normalize name
|
||||
NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(name);
|
||||
const UString oldItemPath = fullPrefix + name;
|
||||
const UString newItemPath = fullPrefix + newItemName;
|
||||
|
||||
UStringVector newNames;
|
||||
|
||||
unsigned curIndex = 0;
|
||||
UInt32 numItemsInArchive;
|
||||
RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive))
|
||||
|
||||
for (UInt32 i = 0; i < numItemsInArchive; i++)
|
||||
{
|
||||
CUpdatePair2 up2;
|
||||
up2.SetAs_NoChangeArcItem(i);
|
||||
if (curIndex < realIndices.Size())
|
||||
if (realIndices[curIndex] == i)
|
||||
{
|
||||
up2.NewProps = true;
|
||||
RINOK(GetArc().IsItem_Anti(i, up2.IsAnti)) // it must work without that line too.
|
||||
|
||||
UString oldFullPath;
|
||||
RINOK(GetArc().GetItem_Path2(i, oldFullPath))
|
||||
|
||||
if (!IsPath1PrefixedByPath2(oldFullPath, oldItemPath))
|
||||
return E_INVALIDARG;
|
||||
|
||||
up2.NewNameIndex = (int)newNames.Add(newItemPath + oldFullPath.Ptr(oldItemPath.Len()));
|
||||
up2.IsMainRenameItem = (mainRealIndex == (int)i);
|
||||
curIndex++;
|
||||
}
|
||||
updatePairs.Add(up2);
|
||||
}
|
||||
|
||||
updateCallback->Callback = &updateCallbackAgent;
|
||||
updateCallback->UpdatePairs = &updatePairs;
|
||||
updateCallback->NewNames = &newNames;
|
||||
|
||||
SetInArchiveInterfaces(this, updateCallback.ClsPtr());
|
||||
|
||||
return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
|
||||
}
|
||||
|
||||
|
||||
HRESULT CAgent::CommentItem(ISequentialOutStream *outArchiveStream,
|
||||
const UInt32 *indices, UInt32 numItems, const wchar_t *newItemName,
|
||||
IFolderArchiveUpdateCallback *updateCallback100)
|
||||
{
|
||||
if (!CanUpdate())
|
||||
return E_NOTIMPL;
|
||||
if (numItems != 1)
|
||||
return E_INVALIDARG;
|
||||
if (!_archiveLink.IsOpen)
|
||||
return E_FAIL;
|
||||
|
||||
CRecordVector<CUpdatePair2> updatePairs;
|
||||
CUpdateCallbackAgent updateCallbackAgent;
|
||||
updateCallbackAgent.SetCallback(updateCallback100);
|
||||
CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
|
||||
|
||||
const int mainRealIndex = _agentFolder->GetRealIndex(indices[0]);
|
||||
|
||||
if (mainRealIndex < 0)
|
||||
return E_NOTIMPL;
|
||||
|
||||
UInt32 numItemsInArchive;
|
||||
RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive))
|
||||
|
||||
UString newName = newItemName;
|
||||
|
||||
for (UInt32 i = 0; i < numItemsInArchive; i++)
|
||||
{
|
||||
CUpdatePair2 up2;
|
||||
up2.SetAs_NoChangeArcItem(i);
|
||||
if ((int)i == mainRealIndex)
|
||||
up2.NewProps = true;
|
||||
updatePairs.Add(up2);
|
||||
}
|
||||
|
||||
updateCallback->Callback = &updateCallbackAgent;
|
||||
updateCallback->UpdatePairs = &updatePairs;
|
||||
updateCallback->CommentIndex = mainRealIndex;
|
||||
updateCallback->Comment = &newName;
|
||||
|
||||
SetInArchiveInterfaces(this, updateCallback.ClsPtr());
|
||||
|
||||
return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
HRESULT CAgent::UpdateOneFile(ISequentialOutStream *outArchiveStream,
|
||||
const UInt32 *indices, UInt32 numItems, const wchar_t *diskFilePath,
|
||||
IFolderArchiveUpdateCallback *updateCallback100)
|
||||
{
|
||||
if (!CanUpdate())
|
||||
return E_NOTIMPL;
|
||||
CRecordVector<CUpdatePair2> updatePairs;
|
||||
CDirItems dirItems;
|
||||
CUpdateCallbackAgent updateCallbackAgent;
|
||||
updateCallbackAgent.SetCallback(updateCallback100);
|
||||
CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
|
||||
|
||||
UInt32 realIndex;
|
||||
{
|
||||
CUIntVector realIndices;
|
||||
_agentFolder->GetRealIndices(indices, numItems,
|
||||
false, // includeAltStreams // we update only main stream of file
|
||||
false, // includeFolderSubItemsInFlatMode
|
||||
realIndices);
|
||||
if (realIndices.Size() != 1)
|
||||
return E_FAIL;
|
||||
realIndex = realIndices[0];
|
||||
}
|
||||
|
||||
{
|
||||
FStringVector filePaths;
|
||||
filePaths.Add(us2fs(diskFilePath));
|
||||
dirItems.EnumerateItems2(FString(), UString(), filePaths, NULL);
|
||||
if (dirItems.Items.Size() != 1)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
UInt32 numItemsInArchive;
|
||||
RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive))
|
||||
for (UInt32 i = 0; i < numItemsInArchive; i++)
|
||||
{
|
||||
CUpdatePair2 up2;
|
||||
up2.SetAs_NoChangeArcItem(i);
|
||||
if (realIndex == i)
|
||||
{
|
||||
up2.DirIndex = 0;
|
||||
up2.NewData = true;
|
||||
up2.NewProps = true;
|
||||
up2.UseArcProps = false;
|
||||
}
|
||||
updatePairs.Add(up2);
|
||||
}
|
||||
updateCallback->DirItems = &dirItems;
|
||||
updateCallback->Callback = &updateCallbackAgent;
|
||||
updateCallback->UpdatePairs = &updatePairs;
|
||||
|
||||
SetInArchiveInterfaces(this, updateCallback.ClsPtr());
|
||||
|
||||
updateCallback->KeepOriginalItemNames = true;
|
||||
return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CAgent::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))
|
||||
{
|
||||
m_PropNames.Clear();
|
||||
m_PropValues.Clear();
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
m_PropNames.Add(names[i]);
|
||||
m_PropValues.Add(values[i]);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
@@ -0,0 +1,752 @@
|
||||
// AgentProxy.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
// #include <stdio.h>
|
||||
#ifdef _WIN32
|
||||
#include <wchar.h>
|
||||
#else
|
||||
#include <ctype.h>
|
||||
#endif
|
||||
|
||||
#include "../../../../C/Sort.h"
|
||||
#include "../../../../C/CpuArch.h"
|
||||
|
||||
#include "../../../Common/UTFConvert.h"
|
||||
#include "../../../Common/Wildcard.h"
|
||||
|
||||
#include "../../../Windows/PropVariant.h"
|
||||
#include "../../../Windows/PropVariantConv.h"
|
||||
|
||||
#include "../../Archive/Common/ItemNameUtils.h"
|
||||
|
||||
#include "AgentProxy.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
int CProxyArc::FindSubDir(unsigned dirIndex, const wchar_t *name, unsigned &insertPos) const
|
||||
{
|
||||
const CRecordVector<unsigned> &subDirs = Dirs[dirIndex].SubDirs;
|
||||
unsigned left = 0, right = subDirs.Size();
|
||||
for (;;)
|
||||
{
|
||||
if (left == right)
|
||||
{
|
||||
insertPos = left;
|
||||
return -1;
|
||||
}
|
||||
const unsigned mid = (unsigned)(((size_t)left + (size_t)right) / 2);
|
||||
const unsigned dirIndex2 = subDirs[mid];
|
||||
const int comp = CompareFileNames(name, Dirs[dirIndex2].Name);
|
||||
if (comp == 0)
|
||||
return (int)dirIndex2;
|
||||
if (comp < 0)
|
||||
right = mid;
|
||||
else
|
||||
left = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
int CProxyArc::FindSubDir(unsigned dirIndex, const wchar_t *name) const
|
||||
{
|
||||
unsigned insertPos;
|
||||
return FindSubDir(dirIndex, name, insertPos);
|
||||
}
|
||||
|
||||
static const wchar_t *AllocStringAndCopy(const wchar_t *s, size_t len)
|
||||
{
|
||||
wchar_t *p = new wchar_t[len + 1];
|
||||
MyStringCopy(p, s);
|
||||
return p;
|
||||
}
|
||||
|
||||
static const wchar_t *AllocStringAndCopy(const UString &s)
|
||||
{
|
||||
return AllocStringAndCopy(s, s.Len());
|
||||
}
|
||||
|
||||
unsigned CProxyArc::AddDir(unsigned dirIndex, int arcIndex, const UString &name)
|
||||
{
|
||||
unsigned insertPos;
|
||||
int subDirIndex = FindSubDir(dirIndex, name, insertPos);
|
||||
if (subDirIndex != -1)
|
||||
{
|
||||
if (arcIndex != -1)
|
||||
{
|
||||
CProxyDir &item = Dirs[(unsigned)subDirIndex];
|
||||
if (item.ArcIndex == -1)
|
||||
item.ArcIndex = arcIndex;
|
||||
}
|
||||
return (unsigned)subDirIndex;
|
||||
}
|
||||
subDirIndex = (int)Dirs.Size();
|
||||
Dirs[dirIndex].SubDirs.Insert(insertPos, (unsigned)subDirIndex);
|
||||
CProxyDir &item = Dirs.AddNew();
|
||||
|
||||
item.NameLen = name.Len();
|
||||
item.Name = AllocStringAndCopy(name);
|
||||
|
||||
item.ArcIndex = arcIndex;
|
||||
item.ParentDir = (int)dirIndex;
|
||||
return (unsigned)subDirIndex;
|
||||
}
|
||||
|
||||
void CProxyDir::Clear()
|
||||
{
|
||||
SubDirs.Clear();
|
||||
SubFiles.Clear();
|
||||
}
|
||||
|
||||
void CProxyArc::GetDirPathParts(unsigned dirIndex, UStringVector &pathParts) const
|
||||
{
|
||||
pathParts.Clear();
|
||||
// while (dirIndex != -1)
|
||||
for (;;)
|
||||
{
|
||||
const CProxyDir &dir = Dirs[dirIndex];
|
||||
dirIndex = (unsigned)dir.ParentDir;
|
||||
if (dir.ParentDir == -1)
|
||||
break;
|
||||
pathParts.Insert(0, dir.Name);
|
||||
// 22.00: we normalize name
|
||||
NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(pathParts[0]);
|
||||
}
|
||||
}
|
||||
|
||||
UString CProxyArc::GetDirPath_as_Prefix(unsigned dirIndex) const
|
||||
{
|
||||
UString s;
|
||||
// while (dirIndex != -1)
|
||||
for (;;)
|
||||
{
|
||||
const CProxyDir &dir = Dirs[dirIndex];
|
||||
dirIndex = (unsigned)dir.ParentDir;
|
||||
if (dir.ParentDir == -1)
|
||||
break;
|
||||
s.InsertAtFront(WCHAR_PATH_SEPARATOR);
|
||||
s.Insert(0, dir.Name);
|
||||
// 22.00: we normalize name
|
||||
NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(s.GetBuf(), MyStringLen(dir.Name));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void CProxyArc::AddRealIndices(unsigned dirIndex, CUIntVector &realIndices) const
|
||||
{
|
||||
const CProxyDir &dir = Dirs[dirIndex];
|
||||
if (dir.IsLeaf())
|
||||
realIndices.Add((unsigned)dir.ArcIndex);
|
||||
unsigned i;
|
||||
for (i = 0; i < dir.SubDirs.Size(); i++)
|
||||
AddRealIndices(dir.SubDirs[i], realIndices);
|
||||
for (i = 0; i < dir.SubFiles.Size(); i++)
|
||||
realIndices.Add(dir.SubFiles[i]);
|
||||
}
|
||||
|
||||
int CProxyArc::GetRealIndex(unsigned dirIndex, unsigned index) const
|
||||
{
|
||||
const CProxyDir &dir = Dirs[dirIndex];
|
||||
const unsigned numDirItems = dir.SubDirs.Size();
|
||||
if (index < numDirItems)
|
||||
{
|
||||
const CProxyDir &f = Dirs[dir.SubDirs[index]];
|
||||
if (f.IsLeaf())
|
||||
return f.ArcIndex;
|
||||
return -1;
|
||||
}
|
||||
return (int)dir.SubFiles[index - numDirItems];
|
||||
}
|
||||
|
||||
void CProxyArc::GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const
|
||||
{
|
||||
const CProxyDir &dir = Dirs[dirIndex];
|
||||
realIndices.Clear();
|
||||
for (UInt32 i = 0; i < numItems; i++)
|
||||
{
|
||||
const UInt32 index = indices[i];
|
||||
const unsigned numDirItems = dir.SubDirs.Size();
|
||||
if (index < numDirItems)
|
||||
AddRealIndices(dir.SubDirs[index], realIndices);
|
||||
else
|
||||
realIndices.Add(dir.SubFiles[index - numDirItems]);
|
||||
}
|
||||
HeapSort(realIndices.NonConstData(), realIndices.Size());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// CProxyArc
|
||||
|
||||
static bool GetSize(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &size)
|
||||
{
|
||||
size = 0;
|
||||
NCOM::CPropVariant prop;
|
||||
if (archive->GetProperty(index, propID, &prop) != S_OK)
|
||||
throw 20120228;
|
||||
return ConvertPropVariantToUInt64(prop, size);
|
||||
}
|
||||
|
||||
void CProxyArc::CalculateSizes(unsigned dirIndex, IInArchive *archive)
|
||||
{
|
||||
CProxyDir &dir = Dirs[dirIndex];
|
||||
dir.Size = dir.PackSize = 0;
|
||||
dir.NumSubDirs = dir.SubDirs.Size();
|
||||
dir.NumSubFiles = dir.SubFiles.Size();
|
||||
dir.CrcIsDefined = true;
|
||||
dir.Crc = 0;
|
||||
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < dir.SubFiles.Size(); i++)
|
||||
{
|
||||
const UInt32 index = (UInt32)dir.SubFiles[i];
|
||||
UInt64 size, packSize;
|
||||
const bool sizeDefined = GetSize(archive, index, kpidSize, size);
|
||||
dir.Size += size;
|
||||
GetSize(archive, index, kpidPackSize, packSize);
|
||||
dir.PackSize += packSize;
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
if (archive->GetProperty(index, kpidCRC, &prop) == S_OK)
|
||||
{
|
||||
if (prop.vt == VT_UI4)
|
||||
dir.Crc += prop.ulVal;
|
||||
else if (prop.vt != VT_EMPTY || size != 0 || !sizeDefined)
|
||||
dir.CrcIsDefined = false;
|
||||
}
|
||||
else
|
||||
dir.CrcIsDefined = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < dir.SubDirs.Size(); i++)
|
||||
{
|
||||
unsigned subDirIndex = dir.SubDirs[i];
|
||||
CalculateSizes(subDirIndex, archive);
|
||||
CProxyDir &f = Dirs[subDirIndex];
|
||||
dir.Size += f.Size;
|
||||
dir.PackSize += f.PackSize;
|
||||
dir.NumSubFiles += f.NumSubFiles;
|
||||
dir.NumSubDirs += f.NumSubDirs;
|
||||
dir.Crc += f.Crc;
|
||||
if (!f.CrcIsDefined)
|
||||
dir.CrcIsDefined = false;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress)
|
||||
{
|
||||
// DWORD tickCount = GetTickCount(); for (int ttt = 0; ttt < 1; ttt++) {
|
||||
|
||||
Files.Free();
|
||||
Dirs.Clear();
|
||||
|
||||
Dirs.AddNew();
|
||||
IInArchive *archive = arc.Archive;
|
||||
|
||||
UInt32 numItems;
|
||||
RINOK(archive->GetNumberOfItems(&numItems))
|
||||
|
||||
if (progress)
|
||||
RINOK(progress->SetTotal(numItems))
|
||||
|
||||
Files.Alloc(numItems);
|
||||
|
||||
UString path;
|
||||
UString name;
|
||||
NCOM::CPropVariant prop;
|
||||
|
||||
for (UInt32 i = 0; i < numItems; i++)
|
||||
{
|
||||
if (progress && (i & 0xFFFF) == 0)
|
||||
{
|
||||
const UInt64 currentItemIndex = i;
|
||||
RINOK(progress->SetCompleted(¤tItemIndex))
|
||||
}
|
||||
|
||||
const wchar_t *s = NULL;
|
||||
unsigned len = 0;
|
||||
bool isPtrName = false;
|
||||
|
||||
#if WCHAR_PATH_SEPARATOR != L'/'
|
||||
wchar_t separatorChar = WCHAR_PATH_SEPARATOR;
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_LE) && defined(_WIN32)
|
||||
// it works only if (sizeof(wchar_t) == 2)
|
||||
if (arc.GetRawProps)
|
||||
{
|
||||
const void *p;
|
||||
UInt32 size;
|
||||
UInt32 propType;
|
||||
if (arc.GetRawProps->GetRawProp(i, kpidPath, &p, &size, &propType) == S_OK
|
||||
&& propType == NPropDataType::kUtf16z
|
||||
&& size > 2)
|
||||
{
|
||||
// is (size <= 2), it's empty name, and we call default arc.GetItemPath();
|
||||
len = size / 2 - 1;
|
||||
s = (const wchar_t *)p;
|
||||
isPtrName = true;
|
||||
#if WCHAR_PATH_SEPARATOR != L'/'
|
||||
separatorChar = L'/'; // 0
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (!s)
|
||||
#endif
|
||||
{
|
||||
prop.Clear();
|
||||
RINOK(arc.Archive->GetProperty(i, kpidPath, &prop))
|
||||
if (prop.vt == VT_BSTR)
|
||||
{
|
||||
s = prop.bstrVal;
|
||||
len = ::SysStringLen(prop.bstrVal);
|
||||
}
|
||||
else if (prop.vt != VT_EMPTY)
|
||||
return E_FAIL;
|
||||
if (len == 0)
|
||||
{
|
||||
RINOK(arc.GetItem_DefaultPath(i, path))
|
||||
len = path.Len();
|
||||
s = path;
|
||||
}
|
||||
|
||||
/*
|
||||
RINOK(arc.GetItemPath(i, path));
|
||||
len = path.Len();
|
||||
s = path;
|
||||
*/
|
||||
}
|
||||
|
||||
unsigned curItem = 0;
|
||||
|
||||
/*
|
||||
if (arc.Ask_Deleted)
|
||||
{
|
||||
bool isDeleted = false;
|
||||
RINOK(Archive_IsItem_Deleted(archive, i, isDeleted));
|
||||
if (isDeleted)
|
||||
curItem = AddDirSubItem(curItem, (UInt32)(Int32)-1, false, L"[DELETED]");
|
||||
}
|
||||
*/
|
||||
|
||||
unsigned namePos = 0;
|
||||
|
||||
unsigned numLevels = 0;
|
||||
|
||||
for (unsigned j = 0; j < len; j++)
|
||||
{
|
||||
const wchar_t c = s[j];
|
||||
if (c == L'/'
|
||||
#if WCHAR_PATH_SEPARATOR != L'/'
|
||||
|| (c == separatorChar)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
const unsigned kLevelLimit = 1 << 10;
|
||||
if (numLevels <= kLevelLimit)
|
||||
{
|
||||
if (numLevels == kLevelLimit)
|
||||
name = "[LONG_PATH]";
|
||||
else
|
||||
name.SetFrom(s + namePos, j - namePos);
|
||||
// 22.00: we can normalize dir here
|
||||
// NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(name);
|
||||
curItem = AddDir(curItem, -1, name);
|
||||
}
|
||||
namePos = j + 1;
|
||||
numLevels++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
that code must be implemeted to hide alt streams in list.
|
||||
if (arc.Ask_AltStreams)
|
||||
{
|
||||
bool isAltStream;
|
||||
RINOK(Archive_IsItem_AltStream(archive, i, isAltStream));
|
||||
if (isAltStream)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
bool isDir;
|
||||
RINOK(Archive_IsItem_Dir(archive, i, isDir))
|
||||
|
||||
CProxyFile &f = Files[i];
|
||||
|
||||
f.NameLen = len - namePos;
|
||||
s += namePos;
|
||||
|
||||
if (isPtrName)
|
||||
f.Name = s;
|
||||
else
|
||||
{
|
||||
f.Name = AllocStringAndCopy(s, f.NameLen);
|
||||
f.NeedDeleteName = true;
|
||||
}
|
||||
|
||||
if (isDir)
|
||||
{
|
||||
name = s;
|
||||
// 22.00: we can normalize dir here
|
||||
// NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(name);
|
||||
AddDir(curItem, (int)i, name);
|
||||
}
|
||||
else
|
||||
Dirs[curItem].SubFiles.Add(i);
|
||||
}
|
||||
|
||||
CalculateSizes(0, archive);
|
||||
|
||||
// } char s[128]; sprintf(s, "Load archive: %7d ms", GetTickCount() - tickCount); OutputDebugStringA(s);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------- for Tree-mode archive ----------
|
||||
|
||||
void CProxyArc2::GetDirPathParts(unsigned dirIndex, UStringVector &pathParts, bool &isAltStreamDir) const
|
||||
{
|
||||
pathParts.Clear();
|
||||
|
||||
isAltStreamDir = false;
|
||||
|
||||
if (dirIndex == k_Proxy2_RootDirIndex)
|
||||
return;
|
||||
if (dirIndex == k_Proxy2_AltRootDirIndex)
|
||||
{
|
||||
isAltStreamDir = true;
|
||||
return;
|
||||
}
|
||||
|
||||
while (dirIndex >= k_Proxy2_NumRootDirs)
|
||||
{
|
||||
const CProxyDir2 &dir = Dirs[dirIndex];
|
||||
const CProxyFile2 &file = Files[(unsigned)dir.ArcIndex];
|
||||
if (pathParts.IsEmpty() && (int)dirIndex == file.AltDirIndex)
|
||||
isAltStreamDir = true;
|
||||
pathParts.Insert(0, file.Name);
|
||||
const int par = file.Parent;
|
||||
if (par == -1)
|
||||
break;
|
||||
dirIndex = (unsigned)Files[(unsigned)par].DirIndex;
|
||||
// if ((int)dirIndex == -1) break;
|
||||
}
|
||||
}
|
||||
|
||||
bool CProxyArc2::IsAltDir(unsigned dirIndex) const
|
||||
{
|
||||
if (dirIndex == k_Proxy2_RootDirIndex)
|
||||
return false;
|
||||
if (dirIndex == k_Proxy2_AltRootDirIndex)
|
||||
return true;
|
||||
const CProxyDir2 &dir = Dirs[dirIndex];
|
||||
const CProxyFile2 &file = Files[(unsigned)dir.ArcIndex];
|
||||
return ((int)dirIndex == file.AltDirIndex);
|
||||
}
|
||||
|
||||
UString CProxyArc2::GetDirPath_as_Prefix(unsigned dirIndex, bool &isAltStreamDir) const
|
||||
{
|
||||
isAltStreamDir = false;
|
||||
const CProxyDir2 &dir = Dirs[dirIndex];
|
||||
if (dirIndex == k_Proxy2_AltRootDirIndex)
|
||||
isAltStreamDir = true;
|
||||
else if (dirIndex >= k_Proxy2_NumRootDirs)
|
||||
{
|
||||
const CProxyFile2 &file = Files[(unsigned)dir.ArcIndex];
|
||||
isAltStreamDir = ((int)dirIndex == file.AltDirIndex);
|
||||
}
|
||||
return dir.PathPrefix;
|
||||
}
|
||||
|
||||
void CProxyArc2::AddRealIndices_of_ArcItem(unsigned arcIndex, bool includeAltStreams, CUIntVector &realIndices) const
|
||||
{
|
||||
realIndices.Add(arcIndex);
|
||||
const CProxyFile2 &file = Files[arcIndex];
|
||||
if (file.DirIndex != -1)
|
||||
AddRealIndices_of_Dir((unsigned)file.DirIndex, includeAltStreams, realIndices);
|
||||
if (includeAltStreams && file.AltDirIndex != -1)
|
||||
AddRealIndices_of_Dir((unsigned)file.AltDirIndex, includeAltStreams, realIndices);
|
||||
}
|
||||
|
||||
void CProxyArc2::AddRealIndices_of_Dir(unsigned dirIndex, bool includeAltStreams, CUIntVector &realIndices) const
|
||||
{
|
||||
const CRecordVector<unsigned> &subFiles = Dirs[dirIndex].Items;
|
||||
FOR_VECTOR (i, subFiles)
|
||||
{
|
||||
AddRealIndices_of_ArcItem(subFiles[i], includeAltStreams, realIndices);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned CProxyArc2::GetRealIndex(unsigned dirIndex, unsigned index) const
|
||||
{
|
||||
return Dirs[dirIndex].Items[index];
|
||||
}
|
||||
|
||||
void CProxyArc2::GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, bool includeAltStreams, CUIntVector &realIndices) const
|
||||
{
|
||||
const CProxyDir2 &dir = Dirs[dirIndex];
|
||||
realIndices.Clear();
|
||||
for (UInt32 i = 0; i < numItems; i++)
|
||||
{
|
||||
AddRealIndices_of_ArcItem(dir.Items[indices[i]], includeAltStreams, realIndices);
|
||||
}
|
||||
HeapSort(realIndices.NonConstData(), realIndices.Size());
|
||||
}
|
||||
|
||||
void CProxyArc2::CalculateSizes(unsigned dirIndex, IInArchive *archive)
|
||||
{
|
||||
CProxyDir2 &dir = Dirs[dirIndex];
|
||||
dir.Size = dir.PackSize = 0;
|
||||
dir.NumSubDirs = 0; // dir.SubDirs.Size();
|
||||
dir.NumSubFiles = 0; // dir.Files.Size();
|
||||
dir.CrcIsDefined = true;
|
||||
dir.Crc = 0;
|
||||
|
||||
FOR_VECTOR (i, dir.Items)
|
||||
{
|
||||
UInt32 index = dir.Items[i];
|
||||
UInt64 size, packSize;
|
||||
const bool sizeDefined = GetSize(archive, index, kpidSize, size);
|
||||
dir.Size += size;
|
||||
GetSize(archive, index, kpidPackSize, packSize);
|
||||
dir.PackSize += packSize;
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
if (archive->GetProperty(index, kpidCRC, &prop) == S_OK)
|
||||
{
|
||||
if (prop.vt == VT_UI4)
|
||||
dir.Crc += prop.ulVal;
|
||||
else if (prop.vt != VT_EMPTY || size != 0 || !sizeDefined)
|
||||
dir.CrcIsDefined = false;
|
||||
}
|
||||
else
|
||||
dir.CrcIsDefined = false;
|
||||
}
|
||||
|
||||
const CProxyFile2 &subFile = Files[index];
|
||||
if (subFile.DirIndex == -1)
|
||||
{
|
||||
dir.NumSubFiles++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 22.00: we normalize name
|
||||
UString s = subFile.Name;
|
||||
NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(s);
|
||||
dir.NumSubDirs++;
|
||||
CProxyDir2 &f = Dirs[subFile.DirIndex];
|
||||
f.PathPrefix = dir.PathPrefix + s + WCHAR_PATH_SEPARATOR;
|
||||
CalculateSizes((unsigned)subFile.DirIndex, archive);
|
||||
dir.Size += f.Size;
|
||||
dir.PackSize += f.PackSize;
|
||||
dir.NumSubFiles += f.NumSubFiles;
|
||||
dir.NumSubDirs += f.NumSubDirs;
|
||||
dir.Crc += f.Crc;
|
||||
if (!f.CrcIsDefined)
|
||||
dir.CrcIsDefined = false;
|
||||
}
|
||||
|
||||
if (subFile.AltDirIndex == -1)
|
||||
{
|
||||
// dir.NumSubFiles++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// dir.NumSubDirs++;
|
||||
CProxyDir2 &f = Dirs[subFile.AltDirIndex];
|
||||
f.PathPrefix = dir.PathPrefix + subFile.Name + L':';
|
||||
CalculateSizes((unsigned)subFile.AltDirIndex, archive);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CProxyArc2::IsThere_SubDir(unsigned dirIndex, const UString &name) const
|
||||
{
|
||||
const CRecordVector<unsigned> &subFiles = Dirs[dirIndex].Items;
|
||||
FOR_VECTOR (i, subFiles)
|
||||
{
|
||||
const CProxyFile2 &file = Files[subFiles[i]];
|
||||
if (file.IsDir())
|
||||
if (CompareFileNames(name, file.Name) == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress)
|
||||
{
|
||||
if (!arc.GetRawProps)
|
||||
return E_FAIL;
|
||||
|
||||
// DWORD tickCount = GetTickCount(); for (int ttt = 0; ttt < 1; ttt++) {
|
||||
|
||||
Dirs.Clear();
|
||||
Files.Free();
|
||||
|
||||
IInArchive *archive = arc.Archive;
|
||||
|
||||
UInt32 numItems;
|
||||
RINOK(archive->GetNumberOfItems(&numItems))
|
||||
if (progress)
|
||||
RINOK(progress->SetTotal(numItems))
|
||||
UString fileName;
|
||||
|
||||
|
||||
{
|
||||
// Dirs[0] - root dir
|
||||
/* CProxyDir2 &dir = */ Dirs.AddNew();
|
||||
}
|
||||
|
||||
{
|
||||
// Dirs[1] - for alt streams of root dir
|
||||
CProxyDir2 &dir = Dirs.AddNew();
|
||||
dir.PathPrefix = ':';
|
||||
}
|
||||
|
||||
Files.Alloc(numItems);
|
||||
|
||||
UString tempUString;
|
||||
AString tempAString;
|
||||
|
||||
UInt32 i;
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
if (progress && (i & 0xFFFFF) == 0)
|
||||
{
|
||||
UInt64 currentItemIndex = i;
|
||||
RINOK(progress->SetCompleted(¤tItemIndex))
|
||||
}
|
||||
|
||||
CProxyFile2 &file = Files[i];
|
||||
|
||||
const void *p;
|
||||
UInt32 size;
|
||||
UInt32 propType;
|
||||
RINOK(arc.GetRawProps->GetRawProp(i, kpidName, &p, &size, &propType))
|
||||
|
||||
#ifdef MY_CPU_LE
|
||||
if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE)
|
||||
{
|
||||
file.Name = (const wchar_t *)p;
|
||||
file.NameLen = 0;
|
||||
if (size >= sizeof(wchar_t))
|
||||
file.NameLen = size / (unsigned)sizeof(wchar_t) - 1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (p && propType == NPropDataType::kUtf8z)
|
||||
{
|
||||
tempAString = (const char *)p;
|
||||
ConvertUTF8ToUnicode(tempAString, tempUString);
|
||||
file.NameLen = tempUString.Len();
|
||||
file.Name = AllocStringAndCopy(tempUString);
|
||||
file.NeedDeleteName = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(arc.Archive->GetProperty(i, kpidName, &prop))
|
||||
const wchar_t *s;
|
||||
if (prop.vt == VT_BSTR)
|
||||
s = prop.bstrVal;
|
||||
else if (prop.vt == VT_EMPTY)
|
||||
s = L"[Content]";
|
||||
else
|
||||
return E_FAIL;
|
||||
file.NameLen = MyStringLen(s);
|
||||
file.Name = AllocStringAndCopy(s, file.NameLen);
|
||||
file.NeedDeleteName = true;
|
||||
}
|
||||
|
||||
UInt32 parent = (UInt32)(Int32)-1;
|
||||
UInt32 parentType = 0;
|
||||
RINOK(arc.GetRawProps->GetParent(i, &parent, &parentType))
|
||||
file.Parent = (Int32)parent;
|
||||
|
||||
if (arc.Ask_Deleted)
|
||||
{
|
||||
bool isDeleted = false;
|
||||
RINOK(Archive_IsItem_Deleted(archive, i, isDeleted))
|
||||
if (isDeleted)
|
||||
{
|
||||
// continue;
|
||||
// curItem = AddDirSubItem(curItem, (UInt32)(Int32)-1, false, L"[DELETED]");
|
||||
}
|
||||
}
|
||||
|
||||
bool isDir;
|
||||
RINOK(Archive_IsItem_Dir(archive, i, isDir))
|
||||
|
||||
if (isDir)
|
||||
{
|
||||
file.DirIndex = (int)Dirs.Size();
|
||||
CProxyDir2 &dir = Dirs.AddNew();
|
||||
dir.ArcIndex = (int)i;
|
||||
}
|
||||
if (arc.Ask_AltStream)
|
||||
RINOK(Archive_IsItem_AltStream(archive, i, file.IsAltStream))
|
||||
}
|
||||
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
CProxyFile2 &file = Files[i];
|
||||
int dirIndex;
|
||||
|
||||
if (file.IsAltStream)
|
||||
{
|
||||
if (file.Parent == -1)
|
||||
dirIndex = k_Proxy2_AltRootDirIndex;
|
||||
else
|
||||
{
|
||||
int &folderIndex2 = Files[(unsigned)file.Parent].AltDirIndex;
|
||||
if (folderIndex2 == -1)
|
||||
{
|
||||
folderIndex2 = (int)Dirs.Size();
|
||||
CProxyDir2 &dir = Dirs.AddNew();
|
||||
dir.ArcIndex = file.Parent;
|
||||
}
|
||||
dirIndex = folderIndex2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (file.Parent == -1)
|
||||
dirIndex = k_Proxy2_RootDirIndex;
|
||||
else
|
||||
{
|
||||
dirIndex = Files[(unsigned)file.Parent].DirIndex;
|
||||
if (dirIndex == -1)
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
Dirs[dirIndex].Items.Add(i);
|
||||
}
|
||||
|
||||
for (i = 0; i < k_Proxy2_NumRootDirs; i++)
|
||||
CalculateSizes(i, archive);
|
||||
|
||||
// } char s[128]; sprintf(s, "Load archive: %7d ms", GetTickCount() - tickCount); OutputDebugStringA(s);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
int CProxyArc2::FindItem(unsigned dirIndex, const wchar_t *name, bool foldersOnly) const
|
||||
{
|
||||
const CProxyDir2 &dir = Dirs[dirIndex];
|
||||
FOR_VECTOR (i, dir.Items)
|
||||
{
|
||||
const CProxyFile2 &file = Files[dir.Items[i]];
|
||||
if (foldersOnly && file.DirIndex == -1)
|
||||
continue;
|
||||
if (CompareFileNames(file.Name, name) == 0)
|
||||
return (int)i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
// AgentProxy.h
|
||||
|
||||
#ifndef ZIP7_INC_AGENT_PROXY_H
|
||||
#define ZIP7_INC_AGENT_PROXY_H
|
||||
|
||||
#include "../Common/OpenArchive.h"
|
||||
|
||||
struct CProxyFile
|
||||
{
|
||||
const wchar_t *Name;
|
||||
unsigned NameLen;
|
||||
bool NeedDeleteName;
|
||||
|
||||
CProxyFile(): Name(NULL), NameLen(0), NeedDeleteName(false) {}
|
||||
~CProxyFile() { if (NeedDeleteName) delete [](wchar_t *)(void *)Name; } // delete [](wchar_t *)Name;
|
||||
};
|
||||
|
||||
const unsigned k_Proxy_RootDirIndex = 0;
|
||||
|
||||
struct CProxyDir
|
||||
{
|
||||
const wchar_t *Name;
|
||||
unsigned NameLen;
|
||||
|
||||
int ArcIndex; // index in proxy->Files[] ; -1 if there is no item for that folder
|
||||
int ParentDir; // index in proxy->Dirs[] ; -1 for root folder; ;
|
||||
CRecordVector<unsigned> SubDirs;
|
||||
CRecordVector<unsigned> SubFiles;
|
||||
|
||||
UInt64 Size;
|
||||
UInt64 PackSize;
|
||||
UInt32 Crc;
|
||||
UInt32 NumSubDirs;
|
||||
UInt32 NumSubFiles;
|
||||
bool CrcIsDefined;
|
||||
|
||||
CProxyDir(): Name(NULL), NameLen(0), ParentDir(-1) {}
|
||||
~CProxyDir() { delete [](wchar_t *)(void *)Name; }
|
||||
|
||||
void Clear();
|
||||
bool IsLeaf() const { return ArcIndex != -1; }
|
||||
};
|
||||
|
||||
class CProxyArc
|
||||
{
|
||||
int FindSubDir(unsigned dirIndex, const wchar_t *name, unsigned &insertPos) const;
|
||||
|
||||
void CalculateSizes(unsigned dirIndex, IInArchive *archive);
|
||||
unsigned AddDir(unsigned dirIndex, int arcIndex, const UString &name);
|
||||
public:
|
||||
CObjectVector<CProxyDir> Dirs; // Dirs[0] - root
|
||||
CObjArray<CProxyFile> Files; // all items from archive in same order
|
||||
|
||||
// returns index in Dirs[], or -1,
|
||||
int FindSubDir(unsigned dirIndex, const wchar_t *name) const;
|
||||
|
||||
void GetDirPathParts(unsigned dirIndex, UStringVector &pathParts) const;
|
||||
// returns full path of Dirs[dirIndex], including back slash
|
||||
UString GetDirPath_as_Prefix(unsigned dirIndex) const;
|
||||
|
||||
// AddRealIndices DOES ADD also item represented by dirIndex (if it's Leaf)
|
||||
void AddRealIndices(unsigned dirIndex, CUIntVector &realIndices) const;
|
||||
int GetRealIndex(unsigned dirIndex, unsigned index) const;
|
||||
void GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const;
|
||||
|
||||
HRESULT Load(const CArc &arc, IProgress *progress);
|
||||
};
|
||||
|
||||
|
||||
// ---------- for Tree-mode archive ----------
|
||||
|
||||
struct CProxyFile2
|
||||
{
|
||||
int DirIndex; // >= 0 for dir. (index in ProxyArchive2->Dirs)
|
||||
int AltDirIndex; // >= 0 if there are alt streams. (index in ProxyArchive2->Dirs)
|
||||
int Parent; // >= 0 if there is parent. (index in archive and in ProxyArchive2->Files)
|
||||
const wchar_t *Name;
|
||||
unsigned NameLen;
|
||||
bool NeedDeleteName;
|
||||
bool Ignore;
|
||||
bool IsAltStream;
|
||||
|
||||
int GetDirIndex(bool forAltStreams) const { return forAltStreams ? AltDirIndex : DirIndex; }
|
||||
|
||||
bool IsDir() const { return DirIndex != -1; }
|
||||
CProxyFile2():
|
||||
DirIndex(-1), AltDirIndex(-1), Parent(-1),
|
||||
Name(NULL), NameLen(0),
|
||||
NeedDeleteName(false),
|
||||
Ignore(false),
|
||||
IsAltStream(false)
|
||||
{}
|
||||
~CProxyFile2()
|
||||
{
|
||||
if (NeedDeleteName)
|
||||
delete [](wchar_t *)(void *)Name;
|
||||
}
|
||||
};
|
||||
|
||||
struct CProxyDir2
|
||||
{
|
||||
int ArcIndex; // = -1 for root folders, index in proxy->Files[]
|
||||
CRecordVector<unsigned> Items;
|
||||
UString PathPrefix;
|
||||
UInt64 Size;
|
||||
UInt64 PackSize;
|
||||
bool CrcIsDefined;
|
||||
UInt32 Crc;
|
||||
UInt32 NumSubDirs;
|
||||
UInt32 NumSubFiles;
|
||||
|
||||
CProxyDir2(): ArcIndex(-1) {}
|
||||
void AddFileSubItem(UInt32 index, const UString &name);
|
||||
void Clear();
|
||||
};
|
||||
|
||||
const unsigned k_Proxy2_RootDirIndex = k_Proxy_RootDirIndex;
|
||||
const unsigned k_Proxy2_AltRootDirIndex = 1;
|
||||
const unsigned k_Proxy2_NumRootDirs = 2;
|
||||
|
||||
class CProxyArc2
|
||||
{
|
||||
void CalculateSizes(unsigned dirIndex, IInArchive *archive);
|
||||
// AddRealIndices_of_Dir DOES NOT ADD item itself represented by dirIndex
|
||||
void AddRealIndices_of_Dir(unsigned dirIndex, bool includeAltStreams, CUIntVector &realIndices) const;
|
||||
public:
|
||||
CObjectVector<CProxyDir2> Dirs; // Dirs[0] - root folder
|
||||
// Dirs[1] - for alt streams of root dir
|
||||
CObjArray<CProxyFile2> Files; // all items from archive in same order
|
||||
|
||||
bool IsThere_SubDir(unsigned dirIndex, const UString &name) const;
|
||||
|
||||
void GetDirPathParts(unsigned dirIndex, UStringVector &pathParts, bool &isAltStreamDir) const;
|
||||
UString GetDirPath_as_Prefix(unsigned dirIndex, bool &isAltStreamDir) const;
|
||||
bool IsAltDir(unsigned dirIndex) const;
|
||||
|
||||
// AddRealIndices_of_ArcItem DOES ADD item and subItems
|
||||
void AddRealIndices_of_ArcItem(unsigned arcIndex, bool includeAltStreams, CUIntVector &realIndices) const;
|
||||
unsigned GetRealIndex(unsigned dirIndex, unsigned index) const;
|
||||
void GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, bool includeAltStreams, CUIntVector &realIndices) const;
|
||||
|
||||
HRESULT Load(const CArc &arc, IProgress *progress);
|
||||
|
||||
int GetParentDirOfFile(UInt32 arcIndex) const
|
||||
{
|
||||
const CProxyFile2 &file = Files[arcIndex];
|
||||
|
||||
if (file.Parent == -1)
|
||||
return file.IsAltStream ?
|
||||
k_Proxy2_AltRootDirIndex :
|
||||
k_Proxy2_RootDirIndex;
|
||||
|
||||
const CProxyFile2 &parentFile = Files[file.Parent];
|
||||
return file.IsAltStream ?
|
||||
parentFile.AltDirIndex :
|
||||
parentFile.DirIndex;
|
||||
}
|
||||
|
||||
int FindItem(unsigned dirIndex, const wchar_t *name, bool foldersOnly) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
// Agent/ArchiveFolder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/ComTry.h"
|
||||
|
||||
#include "../Common/ArchiveExtractCallback.h"
|
||||
|
||||
#include "Agent.h"
|
||||
|
||||
/*
|
||||
Z7_COM7F_IMF(CAgentFolder::SetReplaceAltStreamCharsMode(Int32 replaceAltStreamCharsMode))
|
||||
{
|
||||
_replaceAltStreamCharsMode = replaceAltStreamCharsMode;
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
Z7_COM7F_IMF(CAgentFolder::SetZoneIdMode(NExtract::NZoneIdMode::EEnum zoneMode))
|
||||
{
|
||||
_zoneMode = zoneMode;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CAgentFolder::SetZoneIdFile(const Byte *data, UInt32 size))
|
||||
{
|
||||
_zoneBuf.CopyFrom(data, size);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CAgentFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32 numItems,
|
||||
Int32 includeAltStreams, Int32 replaceAltStreamCharsMode,
|
||||
const wchar_t *path, IFolderOperationsExtractCallback *callback))
|
||||
{
|
||||
if (moveMode)
|
||||
return E_NOTIMPL;
|
||||
COM_TRY_BEGIN
|
||||
CMyComPtr<IFolderArchiveExtractCallback> extractCallback2;
|
||||
{
|
||||
CMyComPtr<IFolderOperationsExtractCallback> callbackWrap = callback;
|
||||
RINOK(callbackWrap.QueryInterface(IID_IFolderArchiveExtractCallback, &extractCallback2))
|
||||
}
|
||||
NExtract::NPathMode::EEnum pathMode;
|
||||
if (!_flatMode)
|
||||
pathMode = NExtract::NPathMode::kCurPaths;
|
||||
else
|
||||
pathMode = (_proxy2 && _loadAltStreams) ?
|
||||
NExtract::NPathMode::kNoPathsAlt :
|
||||
NExtract::NPathMode::kNoPaths;
|
||||
|
||||
return Extract(indices, numItems,
|
||||
includeAltStreams, replaceAltStreamCharsMode,
|
||||
pathMode, NExtract::NOverwriteMode::kAsk,
|
||||
path, BoolToInt(false), extractCallback2);
|
||||
COM_TRY_END
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
// Agent/ArchiveFolderOpen.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
// #ifdef NEW_FOLDER_INTERFACE
|
||||
|
||||
#include "../../../Common/StringToInt.h"
|
||||
#include "../../../Windows/DLL.h"
|
||||
#include "../../../Windows/ResourceString.h"
|
||||
|
||||
#include "Agent.h"
|
||||
|
||||
extern HINSTANCE g_hInstance;
|
||||
static const UINT kIconTypesResId = 100;
|
||||
|
||||
void CCodecIcons::LoadIcons(HMODULE m)
|
||||
{
|
||||
IconPairs.Clear();
|
||||
UString iconTypes;
|
||||
NWindows::MyLoadString(m, kIconTypesResId, iconTypes);
|
||||
UStringVector pairs;
|
||||
SplitString(iconTypes, pairs);
|
||||
FOR_VECTOR (i, pairs)
|
||||
{
|
||||
const UString &s = pairs[i];
|
||||
int pos = s.Find(L':');
|
||||
CIconPair iconPair;
|
||||
iconPair.IconIndex = -1;
|
||||
if (pos < 0)
|
||||
pos = (int)s.Len();
|
||||
else
|
||||
{
|
||||
const UString num = s.Ptr((unsigned)pos + 1);
|
||||
if (!num.IsEmpty())
|
||||
{
|
||||
const wchar_t *end;
|
||||
iconPair.IconIndex = (int)ConvertStringToUInt32(num, &end);
|
||||
if (*end != 0)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
iconPair.Ext = s.Left((unsigned)pos);
|
||||
IconPairs.Add(iconPair);
|
||||
}
|
||||
}
|
||||
|
||||
bool CCodecIcons::FindIconIndex(const UString &ext, int &iconIndex) const
|
||||
{
|
||||
iconIndex = -1;
|
||||
FOR_VECTOR (i, IconPairs)
|
||||
{
|
||||
const CIconPair &pair = IconPairs[i];
|
||||
if (ext.IsEqualTo_NoCase(pair.Ext))
|
||||
{
|
||||
iconIndex = pair.IconIndex;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void CArchiveFolderManager::LoadFormats()
|
||||
{
|
||||
if (WasLoaded)
|
||||
return;
|
||||
|
||||
LoadGlobalCodecs();
|
||||
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
CodecIconsVector.Clear();
|
||||
FOR_VECTOR (i, g_CodecsObj->Libs)
|
||||
{
|
||||
CCodecIcons &ci = CodecIconsVector.AddNew();
|
||||
ci.LoadIcons(g_CodecsObj->Libs[i].Lib.Get_HMODULE());
|
||||
}
|
||||
#endif
|
||||
InternalIcons.LoadIcons(g_hInstance);
|
||||
WasLoaded = true;
|
||||
}
|
||||
|
||||
/*
|
||||
int CArchiveFolderManager::FindFormat(const UString &type)
|
||||
{
|
||||
FOR_VECTOR (i, g_CodecsObj->Formats)
|
||||
if (type.IsEqualTo_NoCase(g_CodecsObj->Formats[i].Name))
|
||||
return (int)i;
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
|
||||
Z7_COM7F_IMF(CArchiveFolderManager::OpenFolderFile(IInStream *inStream,
|
||||
const wchar_t *filePath, const wchar_t *arcFormat,
|
||||
IFolderFolder **resultFolder, IProgress *progress))
|
||||
{
|
||||
CMyComPtr<IArchiveOpenCallback> openArchiveCallback;
|
||||
if (progress)
|
||||
{
|
||||
CMyComPtr<IProgress> progressWrapper = progress;
|
||||
progressWrapper.QueryInterface(IID_IArchiveOpenCallback, &openArchiveCallback);
|
||||
}
|
||||
CAgent *agent = new CAgent();
|
||||
CMyComPtr<IInFolderArchive> archive = agent;
|
||||
|
||||
const HRESULT res = archive->Open(inStream, filePath, arcFormat, NULL, openArchiveCallback);
|
||||
|
||||
if (res != S_OK)
|
||||
{
|
||||
if (res != S_FALSE)
|
||||
return res;
|
||||
/* 20.01: we create folder even for Non-Open cases, if there is NonOpen_ErrorInfo information.
|
||||
So we can get error information from that IFolderFolder later. */
|
||||
if (!agent->_archiveLink.NonOpen_ErrorInfo.IsThereErrorOrWarning())
|
||||
return res;
|
||||
}
|
||||
|
||||
RINOK(archive->BindToRootFolder(resultFolder))
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
HRESULT CAgent::FolderReOpen(
|
||||
IArchiveOpenCallback *openArchiveCallback)
|
||||
{
|
||||
return ReOpenArchive(_archive, _archiveFilePath);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Z7_COM7F_IMF(CArchiveFolderManager::GetExtensions(const wchar_t *type, BSTR *extensions))
|
||||
{
|
||||
*extensions = 0;
|
||||
int formatIndex = FindFormat(type);
|
||||
if (formatIndex < 0)
|
||||
return E_INVALIDARG;
|
||||
// Exts[0].Ext;
|
||||
return StringToBstr(g_CodecsObj.Formats[formatIndex].GetAllExtensions(), extensions);
|
||||
}
|
||||
*/
|
||||
|
||||
static void AddIconExt(const CCodecIcons &lib, UString &dest)
|
||||
{
|
||||
FOR_VECTOR (i, lib.IconPairs)
|
||||
{
|
||||
dest.Add_Space_if_NotEmpty();
|
||||
dest += lib.IconPairs[i].Ext;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CArchiveFolderManager::GetExtensions(BSTR *extensions))
|
||||
{
|
||||
*extensions = NULL;
|
||||
LoadFormats();
|
||||
UString res;
|
||||
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
/*
|
||||
FOR_VECTOR (i, g_CodecsObj->Libs)
|
||||
AddIconExt(g_CodecsObj->Libs[i].CodecIcons, res);
|
||||
*/
|
||||
FOR_VECTOR (i, CodecIconsVector)
|
||||
AddIconExt(CodecIconsVector[i], res);
|
||||
#endif
|
||||
|
||||
AddIconExt(
|
||||
// g_CodecsObj->
|
||||
InternalIcons, res);
|
||||
|
||||
return StringToBstr(res, extensions);
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CArchiveFolderManager::GetIconPath(const wchar_t *ext, BSTR *iconPath, Int32 *iconIndex))
|
||||
{
|
||||
*iconPath = NULL;
|
||||
*iconIndex = 0;
|
||||
LoadFormats();
|
||||
|
||||
#ifdef Z7_EXTERNAL_CODECS
|
||||
// FOR_VECTOR (i, g_CodecsObj->Libs)
|
||||
FOR_VECTOR (i, CodecIconsVector)
|
||||
{
|
||||
int ii;
|
||||
if (CodecIconsVector[i].FindIconIndex(ext, ii))
|
||||
{
|
||||
const CCodecLib &lib = g_CodecsObj->Libs[i];
|
||||
*iconIndex = ii;
|
||||
return StringToBstr(fs2us(lib.Path), iconPath);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int ii;
|
||||
if (InternalIcons.FindIconIndex(ext, ii))
|
||||
{
|
||||
FString path;
|
||||
if (NWindows::NDLL::MyGetModuleFileName(path))
|
||||
{
|
||||
*iconIndex = ii;
|
||||
return StringToBstr(fs2us(path), iconPath);
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
Z7_COM7F_IMF(CArchiveFolderManager::GetTypes(BSTR *types))
|
||||
{
|
||||
LoadFormats();
|
||||
UString typesStrings;
|
||||
FOR_VECTOR(i, g_CodecsObj.Formats)
|
||||
{
|
||||
const CArcInfoEx &ai = g_CodecsObj.Formats[i];
|
||||
if (ai.AssociateExts.Size() == 0)
|
||||
continue;
|
||||
if (i != 0)
|
||||
typesStrings.Add_Space();
|
||||
typesStrings += ai.Name;
|
||||
}
|
||||
return StringToBstr(typesStrings, types);
|
||||
}
|
||||
Z7_COM7F_IMF(CArchiveFolderManager::CreateFolderFile(const wchar_t * type,
|
||||
const wchar_t * filePath, IProgress progress))
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
*/
|
||||
|
||||
// #endif
|
||||
@@ -0,0 +1,456 @@
|
||||
// ArchiveFolderOut.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/ComTry.h"
|
||||
|
||||
#include "../../../Windows/FileDir.h"
|
||||
|
||||
#include "../../Common/FileStreams.h"
|
||||
#include "../../Common/LimitedStreams.h"
|
||||
|
||||
#include "../../Compress/CopyCoder.h"
|
||||
|
||||
#include "../Common/WorkDir.h"
|
||||
|
||||
#include "Agent.h"
|
||||
|
||||
using namespace NWindows;
|
||||
using namespace NFile;
|
||||
using namespace NDir;
|
||||
|
||||
void CAgentFolder::GetPathParts(UStringVector &pathParts, bool &isAltStreamFolder)
|
||||
{
|
||||
if (_proxy2)
|
||||
_proxy2->GetDirPathParts(_proxyDirIndex, pathParts, isAltStreamFolder);
|
||||
else
|
||||
_proxy->GetDirPathParts(_proxyDirIndex, pathParts);
|
||||
}
|
||||
|
||||
static bool Delete_EmptyFolder_And_EmptySubFolders(const FString &path)
|
||||
{
|
||||
{
|
||||
const FString pathPrefix = path + FCHAR_PATH_SEPARATOR;
|
||||
CObjectVector<FString> names;
|
||||
{
|
||||
NFind::CDirEntry fileInfo;
|
||||
NFind::CEnumerator enumerator;
|
||||
enumerator.SetDirPrefix(pathPrefix);
|
||||
for (;;)
|
||||
{
|
||||
bool found;
|
||||
if (!enumerator.Next(fileInfo, found))
|
||||
return false;
|
||||
if (!found)
|
||||
break;
|
||||
if (fileInfo.IsDir())
|
||||
names.Add(fileInfo.Name);
|
||||
}
|
||||
}
|
||||
bool res = true;
|
||||
FOR_VECTOR (i, names)
|
||||
{
|
||||
if (!Delete_EmptyFolder_And_EmptySubFolders(pathPrefix + names[i]))
|
||||
res = false;
|
||||
}
|
||||
if (!res)
|
||||
return false;
|
||||
}
|
||||
// we clear read-only attrib to remove read-only dir
|
||||
if (!SetFileAttrib(path, 0))
|
||||
return false;
|
||||
return RemoveDir(path);
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct C_CopyFileProgress_to_FolderCallback_MoveArc Z7_final:
|
||||
public ICopyFileProgress
|
||||
{
|
||||
IFolderArchiveUpdateCallback_MoveArc *Callback;
|
||||
HRESULT CallbackResult;
|
||||
|
||||
virtual DWORD CopyFileProgress(UInt64 total, UInt64 current) Z7_override
|
||||
{
|
||||
HRESULT res = Callback->MoveArc_Progress(total, current);
|
||||
CallbackResult = res;
|
||||
// we can ignore E_ABORT here, because we update archive,
|
||||
// and we want to get correct archive after updating
|
||||
if (res == E_ABORT)
|
||||
res = S_OK;
|
||||
return res == S_OK ? PROGRESS_CONTINUE : PROGRESS_CANCEL;
|
||||
}
|
||||
|
||||
C_CopyFileProgress_to_FolderCallback_MoveArc(
|
||||
IFolderArchiveUpdateCallback_MoveArc *callback) :
|
||||
Callback(callback),
|
||||
CallbackResult(S_OK)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
HRESULT CAgentFolder::CommonUpdateOperation(
|
||||
AGENT_OP operation,
|
||||
bool moveMode,
|
||||
const wchar_t *newItemName,
|
||||
const NUpdateArchive::CActionSet *actionSet,
|
||||
const UInt32 *indices, UInt32 numItems,
|
||||
IProgress *progress)
|
||||
{
|
||||
if (moveMode && _agentSpec->_isHashHandler)
|
||||
return E_NOTIMPL;
|
||||
|
||||
if (!_agentSpec->CanUpdate())
|
||||
return E_NOTIMPL;
|
||||
|
||||
CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
|
||||
if (progress)
|
||||
progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&updateCallback100);
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
RINOK(_agentSpec->SetFolder(this))
|
||||
|
||||
// ---------- Save FolderItem ----------
|
||||
|
||||
UStringVector pathParts;
|
||||
bool isAltStreamFolder = false;
|
||||
GetPathParts(pathParts, isAltStreamFolder);
|
||||
|
||||
FStringVector requestedPaths;
|
||||
FStringVector processedPaths;
|
||||
|
||||
CWorkDirTempFile tempFile;
|
||||
RINOK(tempFile.CreateTempFile(us2fs(_agentSpec->_archiveFilePath)))
|
||||
{
|
||||
CMyComPtr<IOutStream> tailStream;
|
||||
const CArc &arc = *_agentSpec->_archiveLink.GetArc();
|
||||
|
||||
if (arc.ArcStreamOffset == 0)
|
||||
tailStream = tempFile.OutStream;
|
||||
else
|
||||
{
|
||||
if (arc.Offset < 0)
|
||||
return E_NOTIMPL;
|
||||
RINOK(arc.InStream->Seek(0, STREAM_SEEK_SET, NULL))
|
||||
RINOK(NCompress::CopyStream_ExactSize(arc.InStream, tempFile.OutStream, arc.ArcStreamOffset, NULL))
|
||||
CTailOutStream *tailStreamSpec = new CTailOutStream;
|
||||
tailStream = tailStreamSpec;
|
||||
tailStreamSpec->Stream = tempFile.OutStream;
|
||||
tailStreamSpec->Offset = arc.ArcStreamOffset;
|
||||
tailStreamSpec->Init();
|
||||
}
|
||||
|
||||
HRESULT result;
|
||||
|
||||
switch ((int)operation)
|
||||
{
|
||||
case AGENT_OP_Delete:
|
||||
result = _agentSpec->DeleteItems(tailStream, indices, numItems, updateCallback100);
|
||||
break;
|
||||
case AGENT_OP_CreateFolder:
|
||||
result = _agentSpec->CreateFolder(tailStream, newItemName, updateCallback100);
|
||||
break;
|
||||
case AGENT_OP_Rename:
|
||||
result = _agentSpec->RenameItem(tailStream, indices, numItems, newItemName, updateCallback100);
|
||||
break;
|
||||
case AGENT_OP_Comment:
|
||||
result = _agentSpec->CommentItem(tailStream, indices, numItems, newItemName, updateCallback100);
|
||||
break;
|
||||
case AGENT_OP_CopyFromFile:
|
||||
result = _agentSpec->UpdateOneFile(tailStream, indices, numItems, newItemName, updateCallback100);
|
||||
break;
|
||||
case AGENT_OP_Uni:
|
||||
{
|
||||
Byte actionSetByte[NUpdateArchive::NPairState::kNumValues];
|
||||
for (unsigned i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
|
||||
actionSetByte[i] = (Byte)actionSet->StateActions[i];
|
||||
result = _agentSpec->DoOperation2(
|
||||
moveMode ? &requestedPaths : NULL,
|
||||
moveMode ? &processedPaths : NULL,
|
||||
tailStream, actionSetByte, NULL, updateCallback100);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
RINOK(result)
|
||||
}
|
||||
|
||||
_agentSpec->KeepModeForNextOpen();
|
||||
_agent->Close();
|
||||
|
||||
// before 9.26: if there was error for MoveToOriginal archive was closed.
|
||||
// now: we reopen archive after close
|
||||
|
||||
// m_FolderItem = NULL;
|
||||
_items.Clear();
|
||||
_proxyDirIndex = k_Proxy_RootDirIndex;
|
||||
|
||||
CMyComPtr<IFolderArchiveUpdateCallback_MoveArc> updateCallback_MoveArc;
|
||||
if (progress)
|
||||
progress->QueryInterface(IID_IFolderArchiveUpdateCallback_MoveArc, (void **)&updateCallback_MoveArc);
|
||||
|
||||
HRESULT res;
|
||||
if (updateCallback_MoveArc)
|
||||
{
|
||||
const FString &tempFilePath = tempFile.Get_TempFilePath();
|
||||
UInt64 totalSize = 0;
|
||||
{
|
||||
NFind::CFileInfo fi;
|
||||
if (fi.Find(tempFilePath))
|
||||
totalSize = fi.Size;
|
||||
}
|
||||
RINOK(updateCallback_MoveArc->MoveArc_Start(
|
||||
fs2us(tempFilePath),
|
||||
fs2us(tempFile.Get_OriginalFilePath()),
|
||||
totalSize,
|
||||
1)) // updateMode
|
||||
|
||||
C_CopyFileProgress_to_FolderCallback_MoveArc prox(updateCallback_MoveArc);
|
||||
res = tempFile.MoveToOriginal(
|
||||
true, // deleteOriginal
|
||||
&prox);
|
||||
if (res == S_OK)
|
||||
{
|
||||
res = updateCallback_MoveArc->MoveArc_Finish();
|
||||
// we don't return after E_ABORT here, because
|
||||
// we want to reopen new archive still.
|
||||
}
|
||||
else if (prox.CallbackResult != S_OK)
|
||||
res = prox.CallbackResult;
|
||||
|
||||
// if updating callback returned E_ABORT,
|
||||
// then openCallback still can return E_ABORT also.
|
||||
// So ReOpen() will return with E_ABORT.
|
||||
// But we want to open archive still.
|
||||
// And Before_ArcReopen() call will clear user break status in that case.
|
||||
RINOK(updateCallback_MoveArc->Before_ArcReopen())
|
||||
}
|
||||
else
|
||||
res = tempFile.MoveToOriginal(true); // deleteOriginal
|
||||
|
||||
// RINOK(res);
|
||||
if (res == S_OK)
|
||||
{
|
||||
if (moveMode)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < processedPaths.Size(); i++)
|
||||
{
|
||||
DeleteFileAlways(processedPaths[i]);
|
||||
}
|
||||
for (i = 0; i < requestedPaths.Size(); i++)
|
||||
{
|
||||
const FString &fs = requestedPaths[i];
|
||||
if (NFind::DoesDirExist(fs))
|
||||
Delete_EmptyFolder_And_EmptySubFolders(fs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
CMyComPtr<IArchiveOpenCallback> openCallback;
|
||||
if (updateCallback100)
|
||||
updateCallback100->QueryInterface(IID_IArchiveOpenCallback, (void **)&openCallback);
|
||||
RINOK(_agent->ReOpen(openCallback))
|
||||
}
|
||||
|
||||
// CAgent::ReOpen() deletes _proxy and _proxy2
|
||||
// _items.Clear();
|
||||
_proxy = NULL;
|
||||
_proxy2 = NULL;
|
||||
// _proxyDirIndex = k_Proxy_RootDirIndex;
|
||||
_isAltStreamFolder = false;
|
||||
|
||||
|
||||
// ---------- Restore FolderItem ----------
|
||||
|
||||
CMyComPtr<IFolderFolder> archiveFolder;
|
||||
RINOK(_agent->BindToRootFolder(&archiveFolder))
|
||||
|
||||
// CAgent::BindToRootFolder() changes _proxy and _proxy2
|
||||
_proxy = _agentSpec->_proxy;
|
||||
_proxy2 = _agentSpec->_proxy2;
|
||||
|
||||
if (_proxy)
|
||||
{
|
||||
FOR_VECTOR (i, pathParts)
|
||||
{
|
||||
const int next = _proxy->FindSubDir(_proxyDirIndex, pathParts[i]);
|
||||
if (next == -1)
|
||||
break;
|
||||
_proxyDirIndex = (unsigned)next;
|
||||
}
|
||||
}
|
||||
|
||||
if (_proxy2)
|
||||
{
|
||||
if (pathParts.IsEmpty() && isAltStreamFolder)
|
||||
{
|
||||
_proxyDirIndex = k_Proxy2_AltRootDirIndex;
|
||||
}
|
||||
else FOR_VECTOR (i, pathParts)
|
||||
{
|
||||
const bool dirOnly = (i + 1 < pathParts.Size() || !isAltStreamFolder);
|
||||
const int index = _proxy2->FindItem(_proxyDirIndex, pathParts[i], dirOnly);
|
||||
if (index == -1)
|
||||
break;
|
||||
|
||||
const CProxyFile2 &file = _proxy2->Files[_proxy2->Dirs[_proxyDirIndex].Items[index]];
|
||||
|
||||
if (dirOnly)
|
||||
_proxyDirIndex = (unsigned)file.DirIndex;
|
||||
else
|
||||
{
|
||||
if (file.AltDirIndex != -1)
|
||||
_proxyDirIndex = (unsigned)file.AltDirIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (pathParts.IsEmpty() && isAltStreamFolder)
|
||||
{
|
||||
CMyComPtr<IFolderAltStreams> folderAltStreams;
|
||||
archiveFolder.QueryInterface(IID_IFolderAltStreams, &folderAltStreams);
|
||||
if (folderAltStreams)
|
||||
{
|
||||
CMyComPtr<IFolderFolder> newFolder;
|
||||
folderAltStreams->BindToAltStreams((UInt32)(Int32)-1, &newFolder);
|
||||
if (newFolder)
|
||||
archiveFolder = newFolder;
|
||||
}
|
||||
}
|
||||
|
||||
FOR_VECTOR (i, pathParts)
|
||||
{
|
||||
CMyComPtr<IFolderFolder> newFolder;
|
||||
|
||||
if (isAltStreamFolder && i == pathParts.Size() - 1)
|
||||
{
|
||||
CMyComPtr<IFolderAltStreams> folderAltStreams;
|
||||
archiveFolder.QueryInterface(IID_IFolderAltStreams, &folderAltStreams);
|
||||
if (folderAltStreams)
|
||||
folderAltStreams->BindToAltStreams(pathParts[i], &newFolder);
|
||||
}
|
||||
else
|
||||
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));
|
||||
_proxyDirIndex = agentFolder->_proxyDirIndex;
|
||||
// _parentFolder = agentFolder->_parentFolder;
|
||||
*/
|
||||
|
||||
if (_proxy2)
|
||||
_isAltStreamFolder = _proxy2->IsAltDir(_proxyDirIndex);
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
catch(const UString &s)
|
||||
{
|
||||
if (updateCallback100)
|
||||
{
|
||||
UString s2 ("Error: ");
|
||||
s2 += s;
|
||||
RINOK(updateCallback100->UpdateErrorMessage(s2))
|
||||
return E_FAIL;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Z7_COM7F_IMF(CAgentFolder::CopyFrom(Int32 moveMode,
|
||||
const wchar_t *fromFolderPath, /* test it */
|
||||
const wchar_t * const *itemsPaths,
|
||||
UInt32 numItems,
|
||||
IProgress *progress))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
{
|
||||
RINOK(_agentSpec->SetFiles(fromFolderPath, itemsPaths, numItems))
|
||||
return CommonUpdateOperation(AGENT_OP_Uni, (moveMode != 0), NULL,
|
||||
&NUpdateArchive::k_ActionSet_Add,
|
||||
NULL, 0, progress);
|
||||
}
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CAgentFolder::CopyFromFile(UInt32 destIndex, const wchar_t *itemPath, IProgress *progress))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
return CommonUpdateOperation(AGENT_OP_CopyFromFile, false, itemPath,
|
||||
&NUpdateArchive::k_ActionSet_Add,
|
||||
&destIndex, 1, progress);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CAgentFolder::Delete(const UInt32 *indices, UInt32 numItems, IProgress *progress))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
return CommonUpdateOperation(AGENT_OP_Delete, false, NULL,
|
||||
&NUpdateArchive::k_ActionSet_Delete, indices, numItems, progress);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CAgentFolder::CreateFolder(const wchar_t *name, IProgress *progress))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
if (_isAltStreamFolder)
|
||||
return E_NOTIMPL;
|
||||
|
||||
if (_proxy2)
|
||||
{
|
||||
if (_proxy2->IsThere_SubDir(_proxyDirIndex, name))
|
||||
return ERROR_ALREADY_EXISTS;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_proxy->FindSubDir(_proxyDirIndex, name) != -1)
|
||||
return ERROR_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
return CommonUpdateOperation(AGENT_OP_CreateFolder, false, name, NULL, NULL, 0, progress);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CAgentFolder::Rename(UInt32 index, const wchar_t *newName, IProgress *progress))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
return CommonUpdateOperation(AGENT_OP_Rename, false, newName, NULL,
|
||||
&index, 1, progress);
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CAgentFolder::CreateFile(const wchar_t * /* name */, IProgress * /* progress */))
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
Z7_COM7F_IMF(CAgentFolder::SetProperty(UInt32 index, PROPID propID,
|
||||
const PROPVARIANT *value, IProgress *progress))
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
if (propID != kpidComment || value->vt != VT_BSTR)
|
||||
return E_NOTIMPL;
|
||||
if (!_agentSpec || !_agentSpec->GetTypeOfArc(_agentSpec->GetArc()).IsEqualTo_Ascii_NoCase("zip"))
|
||||
return E_NOTIMPL;
|
||||
|
||||
return CommonUpdateOperation(AGENT_OP_Comment, false, value->bstrVal, NULL,
|
||||
&index, 1, progress);
|
||||
COM_TRY_END
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
// IFolderArchive.h
|
||||
|
||||
#ifndef ZIP7_INC_IFOLDER_ARCHIVE_H
|
||||
#define ZIP7_INC_IFOLDER_ARCHIVE_H
|
||||
|
||||
#include "../../../Common/MyString.h"
|
||||
|
||||
#include "../../Archive/IArchive.h"
|
||||
#include "../../UI/Common/LoadCodecs.h"
|
||||
#include "../../UI/FileManager/IFolder.h"
|
||||
|
||||
#include "../Common/ExtractMode.h"
|
||||
#include "../Common/IFileExtractCallback.h"
|
||||
|
||||
Z7_PURE_INTERFACES_BEGIN
|
||||
|
||||
/* ---------- IArchiveFolder ----------
|
||||
IArchiveFolder is implemented by CAgentFolder (Agent/Agent.h)
|
||||
IArchiveFolder is used by:
|
||||
- FileManager/PanelCopy.cpp
|
||||
CPanel::CopyTo(), if (options->testMode)
|
||||
- FAR/PluginRead.cpp
|
||||
CPlugin::ExtractFiles
|
||||
*/
|
||||
|
||||
#define Z7_IFACEM_IArchiveFolder(x) \
|
||||
x(Extract(const UInt32 *indices, UInt32 numItems, \
|
||||
Int32 includeAltStreams, \
|
||||
Int32 replaceAltStreamCharsMode, \
|
||||
NExtract::NPathMode::EEnum pathMode, \
|
||||
NExtract::NOverwriteMode::EEnum overwriteMode, \
|
||||
const wchar_t *path, Int32 testMode, \
|
||||
IFolderArchiveExtractCallback *extractCallback2)) \
|
||||
|
||||
Z7_IFACE_CONSTR_FOLDERARC(IArchiveFolder, 0x0D)
|
||||
|
||||
|
||||
/* ---------- IInFolderArchive ----------
|
||||
IInFolderArchive is implemented by CAgent (Agent/Agent.h)
|
||||
IInFolderArchive Is used by FAR/Plugin
|
||||
*/
|
||||
|
||||
#define Z7_IFACEM_IInFolderArchive(x) \
|
||||
x(Open(IInStream *inStream, const wchar_t *filePath, const wchar_t *arcFormat, BSTR *archiveTypeRes, IArchiveOpenCallback *openArchiveCallback)) \
|
||||
x(ReOpen(IArchiveOpenCallback *openArchiveCallback)) \
|
||||
x(Close()) \
|
||||
x(GetNumberOfProperties(UInt32 *numProperties)) \
|
||||
x(GetPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)) \
|
||||
x(BindToRootFolder(IFolderFolder **resultFolder)) \
|
||||
x(Extract(NExtract::NPathMode::EEnum pathMode, \
|
||||
NExtract::NOverwriteMode::EEnum overwriteMode, const wchar_t *path, \
|
||||
Int32 testMode, IFolderArchiveExtractCallback *extractCallback2)) \
|
||||
|
||||
Z7_IFACE_CONSTR_FOLDERARC(IInFolderArchive, 0x0E)
|
||||
|
||||
#define Z7_IFACEM_IFolderArchiveUpdateCallback(x) \
|
||||
x(CompressOperation(const wchar_t *name)) \
|
||||
x(DeleteOperation(const wchar_t *name)) \
|
||||
x(OperationResult(Int32 opRes)) \
|
||||
x(UpdateErrorMessage(const wchar_t *message)) \
|
||||
x(SetNumFiles(UInt64 numFiles)) \
|
||||
|
||||
Z7_IFACE_CONSTR_FOLDERARC_SUB(IFolderArchiveUpdateCallback, IProgress, 0x0B)
|
||||
|
||||
#define Z7_IFACEM_IOutFolderArchive(x) \
|
||||
x(SetFolder(IFolderFolder *folder)) \
|
||||
x(SetFiles(const wchar_t *folderPrefix, const wchar_t * const *names, UInt32 numNames)) \
|
||||
x(DeleteItems(ISequentialOutStream *outArchiveStream, \
|
||||
const UInt32 *indices, UInt32 numItems, IFolderArchiveUpdateCallback *updateCallback)) \
|
||||
x(DoOperation( \
|
||||
FStringVector *requestedPaths, \
|
||||
FStringVector *processedPaths, \
|
||||
CCodecs *codecs, int index, \
|
||||
ISequentialOutStream *outArchiveStream, const Byte *stateActions, const wchar_t *sfxModule, \
|
||||
IFolderArchiveUpdateCallback *updateCallback)) \
|
||||
x(DoOperation2( \
|
||||
FStringVector *requestedPaths, \
|
||||
FStringVector *processedPaths, \
|
||||
ISequentialOutStream *outArchiveStream, const Byte *stateActions, const wchar_t *sfxModule, \
|
||||
IFolderArchiveUpdateCallback *updateCallback)) \
|
||||
|
||||
Z7_IFACE_CONSTR_FOLDERARC(IOutFolderArchive, 0x0F)
|
||||
|
||||
|
||||
#define Z7_IFACEM_IFolderArchiveUpdateCallback2(x) \
|
||||
x(OpenFileError(const wchar_t *path, HRESULT errorCode)) \
|
||||
x(ReadingFileError(const wchar_t *path, HRESULT errorCode)) \
|
||||
x(ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *path)) \
|
||||
x(ReportUpdateOperation(UInt32 notifyOp, const wchar_t *path, Int32 isDir)) \
|
||||
|
||||
Z7_IFACE_CONSTR_FOLDERARC(IFolderArchiveUpdateCallback2, 0x10)
|
||||
|
||||
|
||||
#define Z7_IFACEM_IFolderScanProgress(x) \
|
||||
x(ScanError(const wchar_t *path, HRESULT errorCode)) \
|
||||
x(ScanProgress(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, Int32 isDir)) \
|
||||
|
||||
Z7_IFACE_CONSTR_FOLDERARC(IFolderScanProgress, 0x11)
|
||||
|
||||
|
||||
#define Z7_IFACEM_IFolderSetZoneIdMode(x) \
|
||||
x(SetZoneIdMode(NExtract::NZoneIdMode::EEnum zoneMode)) \
|
||||
|
||||
Z7_IFACE_CONSTR_FOLDERARC(IFolderSetZoneIdMode, 0x12)
|
||||
|
||||
#define Z7_IFACEM_IFolderSetZoneIdFile(x) \
|
||||
x(SetZoneIdFile(const Byte *data, UInt32 size)) \
|
||||
|
||||
Z7_IFACE_CONSTR_FOLDERARC(IFolderSetZoneIdFile, 0x13)
|
||||
|
||||
|
||||
// if the caller calls Before_ArcReopen(), the callee must
|
||||
// clear user break status, because the caller want to open archive still.
|
||||
#define Z7_IFACEM_IFolderArchiveUpdateCallback_MoveArc(x) \
|
||||
x(MoveArc_Start(const wchar_t *srcTempPath, const wchar_t *destFinalPath, UInt64 size, Int32 updateMode)) \
|
||||
x(MoveArc_Progress(UInt64 totalSize, UInt64 currentSize)) \
|
||||
x(MoveArc_Finish()) \
|
||||
x(Before_ArcReopen()) \
|
||||
|
||||
Z7_IFACE_CONSTR_FOLDERARC(IFolderArchiveUpdateCallback_MoveArc, 0x14)
|
||||
|
||||
Z7_PURE_INTERFACES_END
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
// StdAfx.h
|
||||
|
||||
#ifndef ZIP7_INC_STDAFX_H
|
||||
#define ZIP7_INC_STDAFX_H
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1800
|
||||
#pragma warning(disable : 4464) // relative include path contains '..'
|
||||
#endif
|
||||
#include "../../../Common/Common.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,208 @@
|
||||
// UpdateCallbackAgent.h
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../Common/IntToString.h"
|
||||
|
||||
#include "../../../Windows/ErrorMsg.h"
|
||||
|
||||
#include "UpdateCallbackAgent.h"
|
||||
|
||||
using namespace NWindows;
|
||||
|
||||
void CUpdateCallbackAgent::SetCallback(IFolderArchiveUpdateCallback *callback)
|
||||
{
|
||||
Callback = callback;
|
||||
_compressProgress.Release();
|
||||
Callback2.Release();
|
||||
if (Callback)
|
||||
{
|
||||
Callback.QueryInterface(IID_ICompressProgressInfo, &_compressProgress);
|
||||
Callback.QueryInterface(IID_IFolderArchiveUpdateCallback2, &Callback2);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackAgent::SetNumItems(const CArcToDoStat &stat)
|
||||
{
|
||||
if (Callback)
|
||||
return Callback->SetNumFiles(stat.Get_NumDataItems_Total());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CUpdateCallbackAgent::WriteSfx(const wchar_t * /* name */, UInt64 /* size */)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
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::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
|
||||
{
|
||||
if (_compressProgress)
|
||||
return _compressProgress->SetRatioInfo(inSize, outSize);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackAgent::CheckBreak()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
HRESULT CUpdateCallbackAgent::Finalize()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
HRESULT CUpdateCallbackAgent::OpenFileError(const FString &path, DWORD systemError)
|
||||
{
|
||||
const HRESULT hres = HRESULT_FROM_WIN32(systemError);
|
||||
// if (systemError == ERROR_SHARING_VIOLATION)
|
||||
{
|
||||
if (Callback2)
|
||||
{
|
||||
RINOK(Callback2->OpenFileError(fs2us(path), hres))
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
if (Callback)
|
||||
{
|
||||
UString s ("WARNING: ");
|
||||
s += NError::MyFormatMessage(systemError);
|
||||
s += ": ";
|
||||
s += fs2us(path);
|
||||
RINOK(Callback->UpdateErrorMessage(s))
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
// FailedFiles.Add(name);
|
||||
return hres;
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackAgent::ReadingFileError(const FString &path, DWORD systemError)
|
||||
{
|
||||
const HRESULT hres = HRESULT_FROM_WIN32(systemError);
|
||||
|
||||
// if (systemError == ERROR_SHARING_VIOLATION)
|
||||
{
|
||||
if (Callback2)
|
||||
{
|
||||
RINOK(Callback2->ReadingFileError(fs2us(path), hres))
|
||||
}
|
||||
else if (Callback)
|
||||
{
|
||||
UString s ("ERROR: ");
|
||||
s += NError::MyFormatMessage(systemError);
|
||||
s += ": ";
|
||||
s += fs2us(path);
|
||||
RINOK(Callback->UpdateErrorMessage(s))
|
||||
}
|
||||
}
|
||||
// FailedFiles.Add(name);
|
||||
return hres;
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackAgent::GetStream(const wchar_t *name, bool isDir, bool /* isAnti */, UInt32 mode)
|
||||
{
|
||||
if (Callback2)
|
||||
return Callback2->ReportUpdateOperation(mode, name, BoolToInt(isDir));
|
||||
if (Callback)
|
||||
return Callback->CompressOperation(name);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackAgent::SetOperationResult(Int32 operationResult)
|
||||
{
|
||||
if (Callback)
|
||||
return Callback->OperationResult(operationResult);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void SetExtractErrorMessage(Int32 opRes, Int32 encrypted, const wchar_t *fileName, UString &s);
|
||||
|
||||
HRESULT CUpdateCallbackAgent::ReportExtractResult(Int32 opRes, Int32 isEncrypted, const wchar_t *name)
|
||||
{
|
||||
if (Callback2)
|
||||
{
|
||||
return Callback2->ReportExtractResult(opRes, isEncrypted, name);
|
||||
}
|
||||
/*
|
||||
if (mode != NArchive::NExtract::NOperationResult::kOK)
|
||||
{
|
||||
Int32 encrypted = 0;
|
||||
UString s;
|
||||
SetExtractErrorMessage(mode, encrypted, name, s);
|
||||
// ProgressDialog->Sync.AddError_Message(s);
|
||||
}
|
||||
*/
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackAgent::ReportUpdateOperation(UInt32 op, const wchar_t *name, bool isDir)
|
||||
{
|
||||
if (Callback2)
|
||||
{
|
||||
return Callback2->ReportUpdateOperation(op, name, BoolToInt(isDir));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
HRESULT CUpdateCallbackAgent::SetPassword(const UString &
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
password
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#ifndef Z7_NO_CRYPTO
|
||||
PasswordIsDefined = true;
|
||||
Password = password;
|
||||
#endif
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
HRESULT CUpdateCallbackAgent::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
|
||||
{
|
||||
*password = NULL;
|
||||
*passwordIsDefined = BoolToInt(false);
|
||||
if (!_cryptoGetTextPassword)
|
||||
{
|
||||
if (!Callback)
|
||||
return S_OK;
|
||||
Callback.QueryInterface(IID_ICryptoGetTextPassword2, &_cryptoGetTextPassword);
|
||||
if (!_cryptoGetTextPassword)
|
||||
return S_OK;
|
||||
}
|
||||
return _cryptoGetTextPassword->CryptoGetTextPassword2(passwordIsDefined, password);
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackAgent::CryptoGetTextPassword(BSTR *password)
|
||||
{
|
||||
*password = NULL;
|
||||
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
|
||||
Callback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
|
||||
if (!getTextPassword)
|
||||
return E_NOTIMPL;
|
||||
return getTextPassword->CryptoGetTextPassword(password);
|
||||
}
|
||||
|
||||
HRESULT CUpdateCallbackAgent::ShowDeleteFile(const wchar_t *name, bool /* isDir */)
|
||||
{
|
||||
return Callback->DeleteOperation(name);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// UpdateCallbackAgent.h
|
||||
|
||||
#ifndef ZIP7_INC_UPDATE_CALLBACK_AGENT_H
|
||||
#define ZIP7_INC_UPDATE_CALLBACK_AGENT_H
|
||||
|
||||
#include "../Common/UpdateCallback.h"
|
||||
|
||||
#include "IFolderArchive.h"
|
||||
|
||||
class CUpdateCallbackAgent Z7_final: public IUpdateCallbackUI
|
||||
{
|
||||
Z7_IFACE_IMP(IUpdateCallbackUI)
|
||||
|
||||
CMyComPtr<ICryptoGetTextPassword2> _cryptoGetTextPassword;
|
||||
CMyComPtr<IFolderArchiveUpdateCallback> Callback;
|
||||
CMyComPtr<IFolderArchiveUpdateCallback2> Callback2;
|
||||
CMyComPtr<ICompressProgressInfo> _compressProgress;
|
||||
public:
|
||||
void SetCallback(IFolderArchiveUpdateCallback *callback);
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user