This commit is contained in:
Igor Pavlov
2015-06-15 00:00:00 +00:00
committed by Kornel Lesiński
parent 0713a3ab80
commit 54490d51d5
591 changed files with 34932 additions and 16390 deletions

View File

File diff suppressed because it is too large Load Diff

View File

@@ -18,6 +18,10 @@
#include "AgentProxy.h"
#include "IFolderArchive.h"
extern CCodecs *g_CodecsObj;
HRESULT LoadGlobalCodecs();
void FreeGlobalCodecs();
class CAgentFolder;
DECL_INTERFACE(IArchiveFolderInternal, 0x01, 0xC)
@@ -27,7 +31,7 @@ DECL_INTERFACE(IArchiveFolderInternal, 0x01, 0xC)
struct CProxyItem
{
unsigned ProxyFolderIndex;
unsigned DirIndex;
unsigned Index;
};
@@ -44,6 +48,7 @@ enum AGENT_OP
class CAgentFolder:
public IFolderFolder,
public IFolderAltStreams,
public IFolderProperties,
public IArchiveGetRawProps,
public IGetFolderArcProps,
@@ -59,10 +64,11 @@ class CAgentFolder:
#endif
public CMyUnknownImp
{
void LoadFolder(unsigned proxyFolderIndex);
void LoadFolder(unsigned proxyDirIndex);
public:
MY_QUERYINTERFACE_BEGIN2(IFolderFolder)
MY_QUERYINTERFACE_ENTRY(IFolderAltStreams)
MY_QUERYINTERFACE_ENTRY(IFolderProperties)
MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
MY_QUERYINTERFACE_ENTRY(IGetFolderArcProps)
@@ -79,7 +85,8 @@ public:
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
HRESULT BindToFolder_Internal(unsigned proxyFolderIndex, IFolderFolder **resultFolder);
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;
@@ -87,6 +94,7 @@ public:
// INTERFACE_FolderSetReplaceAltStreamCharsMode(;)
INTERFACE_FolderFolder(;)
INTERFACE_FolderAltStreams(;)
INTERFACE_FolderProperties(;)
INTERFACE_IArchiveGetRawProps(;)
INTERFACE_IFolderGetItemName(;)
@@ -108,48 +116,57 @@ public:
STDMETHOD(SetFlatMode)(Int32 flatMode);
#endif
CAgentFolder(): _proxyFolderItem(0), _flatMode(0) /* , _replaceAltStreamCharsMode(0) */ {}
CAgentFolder():
_proxyDirIndex(0),
_isAltStreamFolder(false),
_flatMode(false),
_loadAltStreams(false) // _loadAltStreams alt streams works in flat mode, but we don't use it now
/* , _replaceAltStreamCharsMode(0) */
{}
void Init(const CProxyArchive *proxyArc, const CProxyArchive2 *proxyArc2,
unsigned proxyFolderItem,
IFolderFolder *parentFolder,
void Init(const CProxyArc *proxy, const CProxyArc2 *proxy2,
unsigned proxyDirIndex,
/* IFolderFolder *parentFolder, */
CAgent *agent)
{
_proxyArchive = proxyArc;
_proxyArchive2 = proxyArc2;
_proxyFolderItem = proxyFolderItem;
_parentFolder = parentFolder;
_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);
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,
IFolderArchiveUpdateCallback *updateCallback100);
IProgress *progress);
void GetPrefix(UInt32 index, UString &prefix) const;
UString GetName(UInt32 index) const;
UString GetFullPathPrefixPlusPrefix(UInt32 index) const;
UString GetFullPrefix(UInt32 index) const; // relative too root folder of archive
public:
const CProxyArchive *_proxyArchive;
const CProxyArchive2 *_proxyArchive2;
// const CProxyFolder *_proxyFolderItem;
unsigned _proxyFolderItem;
CMyComPtr<IFolderFolder> _parentFolder;
const CProxyArc *_proxy;
const CProxyArc2 *_proxy2;
unsigned _proxyDirIndex;
bool _isAltStreamFolder;
// CMyComPtr<IFolderFolder> _parentFolder;
CMyComPtr<IInFolderArchive> _agent;
CAgent *_agentSpec;
CRecordVector<CProxyItem> _items;
bool _flatMode;
bool _loadAltStreams; // in Flat mode
// Int32 _replaceAltStreamCharsMode;
private:
};
class CAgent:
@@ -193,29 +210,28 @@ public:
IFolderArchiveUpdateCallback *updateCallback100);
// ISetProperties
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
#endif
CCodecs *_codecs;
CMyComPtr<ICompressCodecsInfo> _compressCodecsInfo;
CAgent();
~CAgent();
private:
HRESULT ReadItems();
public:
CProxyArchive *_proxyArchive;
CProxyArchive2 *_proxyArchive2;
CProxyArc *_proxy;
CProxyArc2 *_proxy2;
CArchiveLink _archiveLink;
bool ThereIsPathProp;
// bool ThereIsAltStreamProp;
UString ArchiveType;
FStringVector _names;
FString _folderPrefix;
UString _archiveNamePrefix;
bool _updatePathPrefix_is_AltFolder;
UString _updatePathPrefix;
CAgentFolder *_agentFolder;
UString _archiveFilePath;
@@ -230,11 +246,22 @@ public:
IInArchive *GetArchive() const { if ( _archiveLink.Arcs.IsEmpty()) return 0; return GetArc().Archive; }
bool CanUpdate() const;
bool IsThereReadOnlyArc() const
{
FOR_VECTOR (i, _archiveLink.Arcs)
{
const CArc &arc = _archiveLink.Arcs[i];
if (!g_CodecsObj->Formats[arc.FormatIndex].UpdateEnabled || arc.IsReadOnly)
return true;
}
return false;
}
UString GetTypeOfArc(const CArc &arc) const
{
if (arc.FormatIndex < 0)
return L"Parser";
return _codecs->GetFormatNamePtr(arc.FormatIndex);
return g_CodecsObj->GetFormatNamePtr(arc.FormatIndex);
}
UString GetErrorMessage() const
@@ -246,25 +273,29 @@ public:
UString s2;
if (arc.ErrorInfo.ErrorFormatIndex >= 0)
s2 = L"Can not open the file as [" + _codecs->Formats[arc.ErrorInfo.ErrorFormatIndex].Name + L"] archive";
{
s2.AddAscii("Can not open the file as [");
s2 += g_CodecsObj->Formats[arc.ErrorInfo.ErrorFormatIndex].Name;
s2.AddAscii("] archive");
}
if (!arc.ErrorInfo.ErrorMessage.IsEmpty())
{
if (!s2.IsEmpty())
s2 += L"\n";
s2 += L"\n[";
s2.Add_LF();
s2.AddAscii("\n[");
s2 += GetTypeOfArc(arc);
s2 += L"]: ";
s2.AddAscii("]: ");
s2 += arc.ErrorInfo.ErrorMessage;
}
if (!s2.IsEmpty())
{
if (!s.IsEmpty())
s += L"--------------------\n";
s.AddAscii("--------------------\n");
s += arc.Path;
s += L"\n";
s.Add_LF();
s += s2;
s += L"\n";
s.Add_LF();
}
}
return s;
@@ -274,23 +305,20 @@ public:
};
#ifdef NEW_FOLDER_INTERFACE
class CArchiveFolderManager:
public IFolderManager,
public CMyUnknownImp
{
public:
MY_UNKNOWN_IMP1(IFolderManager)
INTERFACE_IFolderManager(;)
CArchiveFolderManager(): _codecs(0) {}
private:
void LoadFormats();
int FindFormat(const UString &type);
CCodecs *_codecs;
CMyComPtr<ICompressCodecsInfo> _compressCodecsInfo;
public:
MY_UNKNOWN_IMP1(IFolderManager)
INTERFACE_IFolderManager(;)
};
#endif
#endif

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h"
#include "../../../Common/Wildcard.h"
#include "../../../Windows/FileDir.h"
#include "../../../Windows/FileName.h"
#include "../../../Windows/TimeUtils.h"
@@ -18,29 +20,33 @@ using namespace NCOM;
STDMETHODIMP CAgent::SetFolder(IFolderFolder *folder)
{
_archiveNamePrefix.Empty();
if (folder == NULL)
{
_agentFolder = NULL;
_updatePathPrefix.Empty();
_updatePathPrefix_is_AltFolder = false;
_agentFolder = NULL;
if (!folder)
return S_OK;
}
{
CMyComPtr<IFolderFolder> archiveFolder = folder;
CMyComPtr<IArchiveFolderInternal> archiveFolderInternal;
RINOK(archiveFolder.QueryInterface(IID_IArchiveFolderInternal, &archiveFolderInternal));
RINOK(archiveFolderInternal->GetAgentFolder(&_agentFolder));
CMyComPtr<IArchiveFolderInternal> afi;
RINOK(folder->QueryInterface(IID_IArchiveFolderInternal, (void **)&afi));
if (afi)
{
RINOK(afi->GetAgentFolder(&_agentFolder));
}
if (!_agentFolder)
return E_FAIL;
}
if (_proxyArchive2)
_archiveNamePrefix = _proxyArchive2->GetFullPathPrefix(_agentFolder->_proxyFolderItem);
if (_proxy2)
_updatePathPrefix = _proxy2->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex, _updatePathPrefix_is_AltFolder);
else
_archiveNamePrefix = _proxyArchive->GetFullPathPrefix(_agentFolder->_proxyFolderItem);
_updatePathPrefix = _proxy->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex);
return S_OK;
}
STDMETHODIMP CAgent::SetFiles(const wchar_t *folderPrefix,
const wchar_t **names, UInt32 numNames)
const wchar_t * const *names, UInt32 numNames)
{
_folderPrefix = us2fs(folderPrefix);
_names.ClearAndReserve(numNames);
@@ -50,54 +56,57 @@ STDMETHODIMP CAgent::SetFiles(const wchar_t *folderPrefix,
}
static HRESULT EnumerateArchiveItems(CAgent *agent,
const CProxyFolder &item,
const CProxyDir &item,
const UString &prefix,
CObjectVector<CArcItem> &arcItems)
{
unsigned i;
for (i = 0; i < item.Files.Size(); i++)
for (i = 0; i < item.SubFiles.Size(); i++)
{
const CProxyFile &fileItem = item.Files[i];
unsigned arcIndex = item.SubFiles[i];
const CProxyFile &fileItem = agent->_proxy->Files[arcIndex];
CArcItem ai;
RINOK(agent->GetArc().GetItemMTime(fileItem.Index, ai.MTime, ai.MTimeDefined));
RINOK(agent->GetArc().GetItemSize(fileItem.Index, ai.Size, ai.SizeDefined));
RINOK(agent->GetArc().GetItemMTime(arcIndex, ai.MTime, ai.MTimeDefined));
RINOK(agent->GetArc().GetItemSize(arcIndex, ai.Size, ai.SizeDefined));
ai.IsDir = false;
ai.Name = prefix + fileItem.Name;
ai.Censored = true; // test it
ai.IndexInServer = fileItem.Index;
ai.IndexInServer = arcIndex;
arcItems.Add(ai);
}
for (i = 0; i < item.Folders.Size(); i++)
for (i = 0; i < item.SubDirs.Size(); i++)
{
const CProxyFolder &dirItem = agent->_proxyArchive->Folders[item.Folders[i]];
const CProxyDir &dirItem = agent->_proxy->Dirs[item.SubDirs[i]];
UString fullName = prefix + dirItem.Name;
if (dirItem.IsLeaf)
if (dirItem.IsLeaf())
{
CArcItem ai;
RINOK(agent->GetArc().GetItemMTime(dirItem.Index, ai.MTime, ai.MTimeDefined));
RINOK(agent->GetArc().GetItemMTime(dirItem.ArcIndex, ai.MTime, ai.MTimeDefined));
ai.IsDir = true;
ai.SizeDefined = false;
ai.Name = fullName;
ai.Censored = true; // test it
ai.IndexInServer = dirItem.Index;
ai.IndexInServer = dirItem.ArcIndex;
arcItems.Add(ai);
}
RINOK(EnumerateArchiveItems(agent, dirItem, fullName + UString(WCHAR_PATH_SEPARATOR), arcItems));
RINOK(EnumerateArchiveItems(agent, dirItem, fullName + WCHAR_PATH_SEPARATOR, arcItems));
}
return S_OK;
}
static HRESULT EnumerateArchiveItems2(const CAgent *agent,
const CProxyArchive2 *proxyArchive2,
unsigned folderIndex,
unsigned dirIndex,
const UString &prefix,
CObjectVector<CArcItem> &arcItems)
{
const CProxyFolder2 &folder = proxyArchive2->Folders[folderIndex];
FOR_VECTOR (i, folder.SubFiles)
const CProxyDir2 &dir = agent->_proxy2->Dirs[dirIndex];
FOR_VECTOR (i, dir.Items)
{
unsigned arcIndex = folder.SubFiles[i];
const CProxyFile2 &file = proxyArchive2->Files[arcIndex];
unsigned arcIndex = dir.Items[i];
const CProxyFile2 &file = agent->_proxy2->Files[arcIndex];
CArcItem ai;
ai.IndexInServer = arcIndex;
ai.Name = prefix + file.Name;
@@ -105,15 +114,22 @@ static HRESULT EnumerateArchiveItems2(const CAgent *agent,
RINOK(agent->GetArc().GetItemMTime(arcIndex, ai.MTime, ai.MTimeDefined));
ai.IsDir = file.IsDir();
ai.SizeDefined = false;
ai.IsAltStream = file.IsAltStream;
if (!ai.IsDir)
{
RINOK(agent->GetArc().GetItemSize(arcIndex, ai.Size, ai.SizeDefined));
ai.IsDir = false;
}
arcItems.Add(ai);
if (file.AltDirIndex >= 0)
{
RINOK(EnumerateArchiveItems2(agent, file.AltDirIndex, ai.Name + L':', arcItems));
}
if (ai.IsDir)
{
RINOK(EnumerateArchiveItems2(agent, proxyArchive2, file.FolderIndex, ai.Name + UString(WCHAR_PATH_SEPARATOR), arcItems));
RINOK(EnumerateArchiveItems2(agent, file.DirIndex, ai.Name + WCHAR_PATH_SEPARATOR, arcItems));
}
}
return S_OK;
@@ -126,10 +142,10 @@ struct CAgUpCallbackImp: public IUpdateProduceCallback
CAgUpCallbackImp(const CObjectVector<CArcItem> *a,
IFolderArchiveUpdateCallback *callback): _arcItems(a), _callback(callback) {}
HRESULT ShowDeleteFile(int arcIndex);
HRESULT ShowDeleteFile(unsigned arcIndex);
};
HRESULT CAgUpCallbackImp::ShowDeleteFile(int arcIndex)
HRESULT CAgUpCallbackImp::ShowDeleteFile(unsigned arcIndex)
{
return _callback->DeleteOperation((*_arcItems)[arcIndex].Name);
}
@@ -140,11 +156,40 @@ 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->GetRawProps = arc.GetRawProps;
upd->GetRootProps = arc.GetRootProps;
}
struct CDirItemsCallback_AgentOut: public IDirItemsCallback
{
CMyComPtr<IFolderScanProgress> FolderScanProgress;
IFolderArchiveUpdateCallback *FolderArchiveUpdateCallback;
HRESULT ErrorCode;
CDirItemsCallback_AgentOut(): ErrorCode(S_OK), FolderArchiveUpdateCallback(NULL) {}
HRESULT ScanError(const FString &name, DWORD systemError)
{
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)
{
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;
}
};
STDMETHODIMP CAgent::DoOperation(
FStringVector *requestedPaths,
FStringVector *processedPaths,
@@ -157,22 +202,43 @@ STDMETHODIMP CAgent::DoOperation(
{
if (!CanUpdate())
return E_NOTIMPL;
NUpdateArchive::CActionSet actionSet;
unsigned i;
for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
actionSet.StateActions[i] = (NUpdateArchive::NPairAction::EEnum)stateActions[i];
{
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;
NFile::NName::NormalizeDirPathPrefix(folderPrefix);
dirItems.EnumerateItems2(folderPrefix, _archiveNamePrefix, _names, requestedPaths);
if (dirItems.ErrorCodes.Size() > 0)
return dirItems.ErrorCodes.Front();
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));
@@ -182,6 +248,7 @@ STDMETHODIMP CAgent::DoOperation(
if (formatIndex < 0)
return E_FAIL;
RINOK(codecs->CreateOutArchive(formatIndex, outArchive));
#ifdef EXTERNAL_CODECS
{
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
@@ -192,7 +259,6 @@ STDMETHODIMP CAgent::DoOperation(
}
}
#endif
}
NFileTimeType::EEnum fileTimeType;
@@ -215,13 +281,14 @@ STDMETHODIMP CAgent::DoOperation(
if (GetArchive())
{
RINOK(ReadItems());
if (_proxyArchive2)
if (_proxy2)
{
RINOK(EnumerateArchiveItems2(this, _proxyArchive2, 0, L"", arcItems));
RINOK(EnumerateArchiveItems2(this, k_Proxy2_RootDirIndex, L"", arcItems));
RINOK(EnumerateArchiveItems2(this, k_Proxy2_AltRootDirIndex, L":", arcItems));
}
else
{
RINOK(EnumerateArchiveItems(this, _proxyArchive->Folders[0], L"", arcItems));
RINOK(EnumerateArchiveItems(this, _proxy->Dirs[0], L"", arcItems));
}
}
@@ -235,9 +302,11 @@ STDMETHODIMP CAgent::DoOperation(
}
UInt32 numFiles = 0;
for (i = 0; i < updatePairs2.Size(); i++)
if (updatePairs2[i].NewData)
numFiles++;
{
FOR_VECTOR (i, updatePairs2)
if (updatePairs2[i].NewData)
numFiles++;
}
if (updateCallback100)
{
@@ -262,7 +331,7 @@ STDMETHODIMP CAgent::DoOperation(
{
unsigned num = dirItems.Items.Size();
processedItems.Alloc(num);
for (i = 0; i < num; i++)
for (unsigned i = 0; i < num; i++)
processedItems[i] = 0;
updateCallbackSpec->ProcessedItemsStatuses = processedItems;
}
@@ -277,7 +346,7 @@ STDMETHODIMP CAgent::DoOperation(
else
{
CRecordVector<const wchar_t *> names;
for(i = 0; i < m_PropNames.Size(); i++)
FOR_VECTOR (i, m_PropNames)
names.Add((const wchar_t *)m_PropNames[i]);
CPropVariant *propValues = new CPropVariant[m_PropValues.Size()];
@@ -311,9 +380,9 @@ STDMETHODIMP CAgent::DoOperation(
HRESULT res = outArchive->UpdateItems(outArchiveStream, updatePairs2.Size(), updateCallback);
if (res == S_OK && processedPaths)
{
for (i = 0; i < dirItems.Items.Size(); i++)
FOR_VECTOR (i, dirItems.Items)
if (processedItems[i] != 0)
processedPaths->Add(us2fs(dirItems.GetPhyPath(i)));
processedPaths->Add(dirItems.GetPhyPath(i));
}
return res;
}
@@ -324,7 +393,7 @@ STDMETHODIMP CAgent::DoOperation2(
ISequentialOutStream *outArchiveStream,
const Byte *stateActions, const wchar_t *sfxModule, IFolderArchiveUpdateCallback *updateCallback100)
{
return DoOperation(requestedPaths, processedPaths, _codecs, -1, outArchiveStream, stateActions, sfxModule, updateCallback100);
return DoOperation(requestedPaths, processedPaths, g_CodecsObj, -1, outArchiveStream, stateActions, sfxModule, updateCallback100);
}
HRESULT CAgent::CommonUpdate(ISequentialOutStream *outArchiveStream,
@@ -357,11 +426,17 @@ STDMETHODIMP CAgent::DeleteItems(ISequentialOutStream *outArchiveStream,
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().GetItemPath2(i, deletePath));
RINOK(updateCallback100->DeleteOperation(deletePath));
curIndex++;
continue;
}
@@ -410,10 +485,12 @@ HRESULT CAgent::CreateFolder(ISequentialOutStream *outArchiveStream,
di.Attrib = FILE_ATTRIBUTE_DIRECTORY;
di.Size = 0;
if (_proxyArchive2)
di.Name = _proxyArchive2->GetFullPathPrefix(_agentFolder->_proxyFolderItem) + folderName;
bool isAltStreamFolder = false;
if (_proxy2)
di.Name = _proxy2->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex, isAltStreamFolder);
else
di.Name = _proxyArchive->GetFullPathPrefix(_agentFolder->_proxyFolderItem) + folderName;
di.Name = _proxy->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex);
di.Name += folderName;
FILETIME ft;
NTime::GetCurUtcFileTime(ft);
@@ -455,7 +532,7 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream,
int mainRealIndex = _agentFolder->GetRealIndex(indices[0]);
UString fullPrefix = _agentFolder->GetFullPathPrefixPlusPrefix(indices[0]);
UString fullPrefix = _agentFolder->GetFullPrefix(indices[0]);
UString oldItemPath = fullPrefix + _agentFolder->GetName(indices[0]);
UString newItemPath = fullPrefix + newItemName;
@@ -464,6 +541,7 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream,
unsigned curIndex = 0;
UInt32 numItemsInArchive;
RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive));
for (UInt32 i = 0; i < numItemsInArchive; i++)
{
CUpdatePair2 up2;
@@ -477,7 +555,7 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream,
UString oldFullPath;
RINOK(GetArc().GetItemPath2(i, oldFullPath));
if (MyStringCompareNoCase_N(oldFullPath, oldItemPath, oldItemPath.Len()) != 0)
if (!IsPath1PrefixedByPath2(oldFullPath, oldItemPath))
return E_INVALIDARG;
up2.NewNameIndex = newNames.Add(newItemPath + oldFullPath.Ptr(oldItemPath.Len()));
@@ -486,6 +564,7 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream,
}
updatePairs.Add(up2);
}
updateCallbackSpec->Callback = &updateCallbackAgent;
updateCallbackSpec->UpdatePairs = &updatePairs;
updateCallbackSpec->NewNames = &newNames;
@@ -553,7 +632,7 @@ HRESULT CAgent::UpdateOneFile(ISequentialOutStream *outArchiveStream,
return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
}
STDMETHODIMP CAgent::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
STDMETHODIMP CAgent::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
m_PropNames.Clear();
m_PropValues.Clear();

View File

@@ -2,6 +2,8 @@
#include "StdAfx.h"
// #include <stdio.h>
#include "../../../../C/Sort.h"
#include "../../../../C/CpuArch.h"
@@ -14,10 +16,10 @@
using namespace NWindows;
int CProxyArchive::FindDirSubItemIndex(unsigned folderIndex, const UString &name, unsigned &insertPos) const
int CProxyArc::FindSubDir(unsigned dirIndex, const wchar_t *name, unsigned &insertPos) const
{
const CRecordVector<unsigned> &subFolders = Folders[folderIndex].Folders;
unsigned left = 0, right = subFolders.Size();
const CRecordVector<unsigned> &subDirs = Dirs[dirIndex].SubDirs;
unsigned left = 0, right = subDirs.Size();
for (;;)
{
if (left == right)
@@ -26,10 +28,10 @@ int CProxyArchive::FindDirSubItemIndex(unsigned folderIndex, const UString &name
return -1;
}
unsigned mid = (left + right) / 2;
unsigned folderIndex = subFolders[mid];
int compare = CompareFileNames(name, Folders[folderIndex].Name);
unsigned dirIndex = subDirs[mid];
int compare = CompareFileNames(name, Dirs[dirIndex].Name);
if (compare == 0)
return folderIndex;
return dirIndex;
if (compare < 0)
right = mid;
else
@@ -37,120 +39,117 @@ int CProxyArchive::FindDirSubItemIndex(unsigned folderIndex, const UString &name
}
}
int CProxyArchive::FindDirSubItemIndex(unsigned folderIndex, const UString &name) const
int CProxyArc::FindSubDir(unsigned dirIndex, const wchar_t *name) const
{
unsigned insertPos;
return FindDirSubItemIndex(folderIndex, name, insertPos);
return FindSubDir(dirIndex, name, insertPos);
}
void CProxyFolder::AddFileSubItem(UInt32 index, const UString &name)
{
CProxyFile &f = Files.AddNew();
f.Index = index;
f.Name = name;
}
unsigned CProxyArchive::AddDirSubItem(unsigned folderIndex, UInt32 index, bool leaf, const UString &name)
unsigned CProxyArc::AddDir(unsigned dirIndex, int arcIndex, const UString &name)
{
unsigned insertPos;
int subFolderIndex = FindDirSubItemIndex(folderIndex, name, insertPos);
if (subFolderIndex >= 0)
int subDirIndex = FindSubDir(dirIndex, name, insertPos);
if (subDirIndex >= 0)
{
CProxyFolder &item = Folders[subFolderIndex];
if (leaf)
if (arcIndex >= 0)
{
item.Index = index;
item.IsLeaf = true;
CProxyDir &item = Dirs[subDirIndex];
if (item.ArcIndex < 0)
item.ArcIndex = arcIndex;
}
return subFolderIndex;
return subDirIndex;
}
subFolderIndex = Folders.Size();
Folders[folderIndex].Folders.Insert(insertPos, subFolderIndex);
CProxyFolder &item = Folders.AddNew();
item.Name = name;
item.Index = index;
item.Parent = folderIndex;
item.IsLeaf = leaf;
return subFolderIndex;
subDirIndex = Dirs.Size();
Dirs[dirIndex].SubDirs.Insert(insertPos, subDirIndex);
CProxyDir &item = Dirs.AddNew();
item.NameLen = name.Len();
item.Name = new wchar_t[item.NameLen + 1];
MyStringCopy((wchar_t *)item.Name, name);
item.ArcIndex = arcIndex;
item.ParentDir = dirIndex;
return subDirIndex;
}
void CProxyFolder::Clear()
void CProxyDir::Clear()
{
Folders.Clear();
Files.Clear();
SubDirs.Clear();
SubFiles.Clear();
}
void CProxyArchive::GetPathParts(int folderIndex, UStringVector &pathParts) const
void CProxyArc::GetDirPathParts(int dirIndex, UStringVector &pathParts) const
{
pathParts.Clear();
while (folderIndex >= 0)
while (dirIndex >= 0)
{
const CProxyFolder &folder = Folders[folderIndex];
folderIndex = folder.Parent;
if (folderIndex < 0)
const CProxyDir &dir = Dirs[dirIndex];
dirIndex = dir.ParentDir;
if (dirIndex < 0)
break;
pathParts.Insert(0, folder.Name);
pathParts.Insert(0, dir.Name);
}
}
UString CProxyArchive::GetFullPathPrefix(int folderIndex) const
UString CProxyArc::GetDirPath_as_Prefix(int dirIndex) const
{
UString result;
while (folderIndex >= 0)
UString s;
while (dirIndex >= 0)
{
const CProxyFolder &folder = Folders[folderIndex];
folderIndex = folder.Parent;
if (folderIndex < 0)
const CProxyDir &dir = Dirs[dirIndex];
dirIndex = dir.ParentDir;
if (dirIndex < 0)
break;
result = folder.Name + UString(WCHAR_PATH_SEPARATOR) + result;
s.InsertAtFront(WCHAR_PATH_SEPARATOR);
s.Insert(0, dir.Name);
}
return result;
return s;
}
void CProxyArchive::AddRealIndices(unsigned folderIndex, CUIntVector &realIndices) const
void CProxyArc::AddRealIndices(unsigned dirIndex, CUIntVector &realIndices) const
{
const CProxyFolder &folder = Folders[folderIndex];
if (folder.IsLeaf)
realIndices.Add(folder.Index);
const CProxyDir &dir = Dirs[dirIndex];
if (dir.IsLeaf())
realIndices.Add(dir.ArcIndex);
unsigned i;
for (i = 0; i < folder.Folders.Size(); i++)
AddRealIndices(folder.Folders[i], realIndices);
for (i = 0; i < folder.Files.Size(); i++)
realIndices.Add(folder.Files[i].Index);
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 CProxyArchive::GetRealIndex(unsigned folderIndex, unsigned index) const
int CProxyArc::GetRealIndex(unsigned dirIndex, unsigned index) const
{
const CProxyFolder &folder = Folders[folderIndex];
unsigned numDirItems = folder.Folders.Size();
const CProxyDir &dir = Dirs[dirIndex];
unsigned numDirItems = dir.SubDirs.Size();
if (index < numDirItems)
{
const CProxyFolder &f = Folders[folder.Folders[index]];
if (f.IsLeaf)
return f.Index;
const CProxyDir &f = Dirs[dir.SubDirs[index]];
if (f.IsLeaf())
return f.ArcIndex;
return -1;
}
return folder.Files[index - numDirItems].Index;
return dir.SubFiles[index - numDirItems];
}
void CProxyArchive::GetRealIndices(unsigned folderIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const
void CProxyArc::GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const
{
const CProxyFolder &folder = Folders[folderIndex];
const CProxyDir &dir = Dirs[dirIndex];
realIndices.Clear();
for (UInt32 i = 0; i < numItems; i++)
{
UInt32 index = indices[i];
unsigned numDirItems = folder.Folders.Size();
unsigned numDirItems = dir.SubDirs.Size();
if (index < numDirItems)
AddRealIndices(folder.Folders[index], realIndices);
AddRealIndices(dir.SubDirs[index], realIndices);
else
realIndices.Add(folder.Files[index - numDirItems].Index);
realIndices.Add(dir.SubFiles[index - numDirItems]);
}
HeapSort(&realIndices.Front(), realIndices.Size());
}
///////////////////////////////////////////////
// CProxyArchive
// CProxyArc
static bool GetSize(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &size)
{
@@ -161,79 +160,131 @@ static bool GetSize(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &si
return ConvertPropVariantToUInt64(prop, size);
}
void CProxyArchive::CalculateSizes(unsigned folderIndex, IInArchive *archive)
void CProxyArc::CalculateSizes(unsigned dirIndex, IInArchive *archive)
{
CProxyFolder &folder = Folders[folderIndex];
folder.Size = folder.PackSize = 0;
folder.NumSubFolders = folder.Folders.Size();
folder.NumSubFiles = folder.Files.Size();
folder.CrcIsDefined = true;
folder.Crc = 0;
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 < folder.Files.Size(); i++)
for (i = 0; i < dir.SubFiles.Size(); i++)
{
UInt32 index = folder.Files[i].Index;
UInt32 index = (UInt32)dir.SubFiles[i];
UInt64 size, packSize;
bool sizeDefined = GetSize(archive, index, kpidSize, size);
folder.Size += size;
dir.Size += size;
GetSize(archive, index, kpidPackSize, packSize);
folder.PackSize += packSize;
dir.PackSize += packSize;
{
NCOM::CPropVariant prop;
if (archive->GetProperty(index, kpidCRC, &prop) == S_OK)
{
if (prop.vt == VT_UI4)
folder.Crc += prop.ulVal;
dir.Crc += prop.ulVal;
else if (prop.vt != VT_EMPTY || size != 0 || !sizeDefined)
folder.CrcIsDefined = false;
dir.CrcIsDefined = false;
}
else
folder.CrcIsDefined = false;
dir.CrcIsDefined = false;
}
}
for (i = 0; i < folder.Folders.Size(); i++)
for (i = 0; i < dir.SubDirs.Size(); i++)
{
unsigned subFolderIndex = folder.Folders[i];
CProxyFolder &f = Folders[subFolderIndex];
CalculateSizes(subFolderIndex, archive);
folder.Size += f.Size;
folder.PackSize += f.PackSize;
folder.NumSubFiles += f.NumSubFiles;
folder.NumSubFolders += f.NumSubFolders;
folder.Crc += f.Crc;
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)
folder.CrcIsDefined = false;
dir.CrcIsDefined = false;
}
}
HRESULT CProxyArchive::Load(const CArc &arc, IProgress *progress)
HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress)
{
/*
DWORD tickCount = GetTickCount();
for (int ttt = 0; ttt < 1000; ttt++) {
*/
// DWORD tickCount = GetTickCount(); for (int ttt = 0; ttt < 1; ttt++) {
Folders.Clear();
Folders.AddNew();
Files.Free();
Dirs.Clear();
Dirs.AddNew();
IInArchive *archive = arc.Archive;
UInt32 numItems;
RINOK(archive->GetNumberOfItems(&numItems));
if (progress)
RINOK(progress->SetTotal(numItems));
UString filePath;
UString fileName;
Files.Alloc(numItems);
UString path;
UString name;
NCOM::CPropVariant prop;
for (UInt32 i = 0; i < numItems; i++)
{
if (progress && (i & 0xFFFFF) == 0)
if (progress && (i & 0xFFFF) == 0)
{
UInt64 currentItemIndex = i;
RINOK(progress->SetCompleted(&currentItemIndex));
}
RINOK(arc.GetItemPath(i, filePath));
const wchar_t *s = NULL;
unsigned len = 0;
bool isPtrName = false;
#ifdef MY_CPU_LE
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 (!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.GetDefaultItemPath(i, path));
len = path.Len();
s = path;
}
/*
RINOK(arc.GetItemPath(i, path));
len = path.Len();
s = path;
*/
}
unsigned curItem = 0;
unsigned len = filePath.Len();
fileName.Empty();
/*
if (arc.Ask_Deleted)
@@ -245,16 +296,16 @@ HRESULT CProxyArchive::Load(const CArc &arc, IProgress *progress)
}
*/
unsigned namePos = 0;
for (unsigned j = 0; j < len; j++)
{
wchar_t c = filePath[j];
wchar_t c = s[j];
if (c == WCHAR_PATH_SEPARATOR || c == L'/')
{
curItem = AddDirSubItem(curItem, (UInt32)(Int32)-1, false, fileName);
fileName.Empty();
name.SetFrom(s + namePos, j - namePos);
curItem = AddDir(curItem, -1, name);
namePos = j + 1;
}
else
fileName += c;
}
/*
@@ -270,21 +321,35 @@ HRESULT CProxyArchive::Load(const CArc &arc, IProgress *progress)
}
*/
bool isFolder;
RINOK(Archive_IsItem_Folder(archive, i, isFolder));
if (isFolder)
AddDirSubItem(curItem, i, true, fileName);
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
Folders[curItem].AddFileSubItem(i, fileName);
{
f.Name = new wchar_t[f.NameLen + 1];
f.NeedDeleteName = true;
MyStringCopy((wchar_t *)f.Name, s);
}
if (isDir)
{
name = s;
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);
*/
// } char s[128]; sprintf(s, "Load archive: %7d ms", GetTickCount() - tickCount); OutputDebugStringA(s);
return S_OK;
}
@@ -293,151 +358,162 @@ HRESULT CProxyArchive::Load(const CArc &arc, IProgress *progress)
// ---------- for Tree-mode archive ----------
void CProxyArchive2::GetPathParts(int folderIndex, UStringVector &pathParts) const
void CProxyArc2::GetDirPathParts(int dirIndex, UStringVector &pathParts, bool &isAltStreamDir) const
{
pathParts.Clear();
while (folderIndex > 0)
isAltStreamDir = false;
if (dirIndex == k_Proxy2_RootDirIndex)
return;
if (dirIndex == k_Proxy2_AltRootDirIndex)
{
const CProxyFolder2 &folder = Folders[folderIndex];
const CProxyFile2 &file = Files[folder.ArcIndex];
isAltStreamDir = true;
return;
}
while (dirIndex >= k_Proxy2_NumRootDirs)
{
const CProxyDir2 &dir = Dirs[dirIndex];
const CProxyFile2 &file = Files[dir.ArcIndex];
if (pathParts.IsEmpty() && dirIndex == file.AltDirIndex)
isAltStreamDir = true;
pathParts.Insert(0, file.Name);
int par = file.Parent;
if (par < 0)
break;
folderIndex = Files[par].FolderIndex;
dirIndex = Files[par].DirIndex;
}
}
UString CProxyArchive2::GetFullPathPrefix(unsigned folderIndex) const
bool CProxyArc2::IsAltDir(unsigned dirIndex) const
{
return Folders[folderIndex].PathPrefix;
/*
UString result;
while (folderIndex > 0)
{
const CProxyFile2 &file = Files[Folders[folderIndex].ArcIndex];
result = (UString)(file.Name) + (UString)WCHAR_PATH_SEPARATOR + result;
if (file.Parent < 0)
break;
folderIndex = Files[file.Parent].FolderIndex;
}
return result;
*/
if (dirIndex == k_Proxy2_RootDirIndex)
return false;
if (dirIndex == k_Proxy2_AltRootDirIndex)
return true;
const CProxyDir2 &dir = Dirs[dirIndex];
const CProxyFile2 &file = Files[dir.ArcIndex];
return ((int)dirIndex == file.AltDirIndex);
}
void CProxyArchive2::AddRealIndices_of_ArcItem(unsigned arcIndex, bool includeAltStreams, CUIntVector &realIndices) const
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[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.FolderIndex >= 0)
AddRealIndices_of_Folder(file.FolderIndex, includeAltStreams, realIndices);
if (includeAltStreams && file.AltStreamsFolderIndex >= 0)
AddRealIndices_of_Folder(file.AltStreamsFolderIndex, includeAltStreams, realIndices);
if (file.DirIndex >= 0)
AddRealIndices_of_Dir(file.DirIndex, includeAltStreams, realIndices);
if (includeAltStreams && file.AltDirIndex >= 0)
AddRealIndices_of_Dir(file.AltDirIndex, includeAltStreams, realIndices);
}
void CProxyArchive2::AddRealIndices_of_Folder(unsigned folderIndex, bool includeAltStreams, CUIntVector &realIndices) const
void CProxyArc2::AddRealIndices_of_Dir(unsigned dirIndex, bool includeAltStreams, CUIntVector &realIndices) const
{
const CRecordVector<unsigned> &subFiles = Folders[folderIndex].SubFiles;
const CRecordVector<unsigned> &subFiles = Dirs[dirIndex].Items;
FOR_VECTOR (i, subFiles)
{
AddRealIndices_of_ArcItem(subFiles[i], includeAltStreams, realIndices);
}
}
unsigned CProxyArchive2::GetRealIndex(unsigned folderIndex, unsigned index) const
unsigned CProxyArc2::GetRealIndex(unsigned dirIndex, unsigned index) const
{
return Folders[folderIndex].SubFiles[index];
return Dirs[dirIndex].Items[index];
}
void CProxyArchive2::GetRealIndices(unsigned folderIndex, const UInt32 *indices, UInt32 numItems, bool includeAltStreams, CUIntVector &realIndices) const
void CProxyArc2::GetRealIndices(unsigned dirIndex, const UInt32 *indices, UInt32 numItems, bool includeAltStreams, CUIntVector &realIndices) const
{
const CProxyFolder2 &folder = Folders[folderIndex];
const CProxyDir2 &dir = Dirs[dirIndex];
realIndices.Clear();
for (UInt32 i = 0; i < numItems; i++)
{
AddRealIndices_of_ArcItem(folder.SubFiles[indices[i]], includeAltStreams, realIndices);
AddRealIndices_of_ArcItem(dir.Items[indices[i]], includeAltStreams, realIndices);
}
HeapSort(&realIndices.Front(), realIndices.Size());
}
void CProxyArchive2::CalculateSizes(unsigned folderIndex, IInArchive *archive)
void CProxyArc2::CalculateSizes(unsigned dirIndex, IInArchive *archive)
{
CProxyFolder2 &folder = Folders[folderIndex];
folder.Size = folder.PackSize = 0;
folder.NumSubFolders = 0; // folder.Folders.Size();
folder.NumSubFiles = 0; // folder.Files.Size();
folder.CrcIsDefined = true;
folder.Crc = 0;
FOR_VECTOR (i, folder.SubFiles)
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 = folder.SubFiles[i];
UInt32 index = dir.Items[i];
UInt64 size, packSize;
bool sizeDefined = GetSize(archive, index, kpidSize, size);
folder.Size += size;
dir.Size += size;
GetSize(archive, index, kpidPackSize, packSize);
folder.PackSize += packSize;
dir.PackSize += packSize;
{
NCOM::CPropVariant prop;
if (archive->GetProperty(index, kpidCRC, &prop) == S_OK)
{
if (prop.vt == VT_UI4)
folder.Crc += prop.ulVal;
dir.Crc += prop.ulVal;
else if (prop.vt != VT_EMPTY || size != 0 || !sizeDefined)
folder.CrcIsDefined = false;
dir.CrcIsDefined = false;
}
else
folder.CrcIsDefined = false;
dir.CrcIsDefined = false;
}
const CProxyFile2 &subFile = Files[index];
if (subFile.FolderIndex < 0)
if (subFile.DirIndex < 0)
{
folder.NumSubFiles++;
dir.NumSubFiles++;
}
else
{
folder.NumSubFolders++;
CProxyFolder2 &f = Folders[subFile.FolderIndex];
f.PathPrefix = folder.PathPrefix + subFile.Name + WCHAR_PATH_SEPARATOR;
CalculateSizes(subFile.FolderIndex, archive);
folder.Size += f.Size;
folder.PackSize += f.PackSize;
folder.NumSubFiles += f.NumSubFiles;
folder.NumSubFolders += f.NumSubFolders;
folder.Crc += f.Crc;
dir.NumSubDirs++;
CProxyDir2 &f = Dirs[subFile.DirIndex];
f.PathPrefix = dir.PathPrefix + subFile.Name + WCHAR_PATH_SEPARATOR;
CalculateSizes(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)
folder.CrcIsDefined = false;
dir.CrcIsDefined = false;
}
if (subFile.AltStreamsFolderIndex < 0)
if (subFile.AltDirIndex < 0)
{
// folder.NumSubFiles++;
// dir.NumSubFiles++;
}
else
{
// folder.NumSubFolders++;
CProxyFolder2 &f = Folders[subFile.AltStreamsFolderIndex];
f.PathPrefix = folder.PathPrefix + subFile.Name + L":";
CalculateSizes(subFile.AltStreamsFolderIndex, archive);
/*
folder.Size += f.Size;
folder.PackSize += f.PackSize;
folder.NumSubFiles += f.NumSubFiles;
folder.NumSubFolders += f.NumSubFolders;
folder.Crc += f.Crc;
if (!f.CrcIsDefined)
folder.CrcIsDefined = false;
*/
// dir.NumSubDirs++;
CProxyDir2 &f = Dirs[subFile.AltDirIndex];
f.PathPrefix = dir.PathPrefix + subFile.Name + L':';
CalculateSizes(subFile.AltDirIndex, archive);
}
}
}
bool CProxyArchive2::IsThere_SubDir(unsigned folderIndex, const UString &name) const
bool CProxyArc2::IsThere_SubDir(unsigned dirIndex, const UString &name) const
{
const CRecordVector<unsigned> &subFiles = Folders[folderIndex].SubFiles;
const CRecordVector<unsigned> &subFiles = Dirs[dirIndex].Items;
FOR_VECTOR (i, subFiles)
{
const CProxyFile2 &file = Files[subFiles[i]];
@@ -448,14 +524,15 @@ bool CProxyArchive2::IsThere_SubDir(unsigned folderIndex, const UString &name) c
return false;
}
HRESULT CProxyArchive2::Load(const CArc &arc, IProgress *progress)
HRESULT CProxyArc2::Load(const CArc &arc, IProgress *progress)
{
if (!arc.GetRawProps)
return E_FAIL;
// DWORD tickCount = GetTickCount();
// DWORD tickCount = GetTickCount(); for (int ttt = 0; ttt < 1; ttt++) {
Folders.Clear();
Dirs.Clear();
Files.Free();
IInArchive *archive = arc.Archive;
@@ -464,9 +541,17 @@ HRESULT CProxyArchive2::Load(const CArc &arc, IProgress *progress)
if (progress)
RINOK(progress->SetTotal(numItems));
UString fileName;
{
CProxyFolder2 &folder = Folders.AddNew();
folder.ArcIndex = -1;
// Dirs[0] - root dir
/* CProxyDir2 &dir = */ Dirs.AddNew();
}
{
// Dirs[1] - for alt streams of root dir
CProxyDir2 &dir = Dirs.AddNew();
dir.PathPrefix = L':';
}
Files.Alloc(numItems);
@@ -491,9 +576,9 @@ HRESULT CProxyArchive2::Load(const CArc &arc, IProgress *progress)
if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE)
{
file.Name = (const wchar_t *)p;
file.NameSize = 0;
file.NameLen = 0;
if (size >= sizeof(wchar_t))
file.NameSize = size / sizeof(wchar_t) - 1;
file.NameLen = size / sizeof(wchar_t) - 1;
}
else
#endif
@@ -507,11 +592,12 @@ HRESULT CProxyArchive2::Load(const CArc &arc, IProgress *progress)
s = L"[Content]";
else
return E_FAIL;
file.NameSize = MyStringLen(s);
file.Name = new wchar_t[file.NameSize + 1];
file.NameLen = MyStringLen(s);
file.Name = new wchar_t[file.NameLen + 1];
file.NeedDeleteName = true;
MyStringCopy((wchar_t *)file.Name, s);
}
UInt32 parent = (UInt32)(Int32)-1;
UInt32 parentType = 0;
RINOK(arc.GetRawProps->GetParent(i, &parent, &parentType));
@@ -528,14 +614,14 @@ HRESULT CProxyArchive2::Load(const CArc &arc, IProgress *progress)
}
}
bool isFolder;
RINOK(Archive_IsItem_Folder(archive, i, isFolder));
bool isDir;
RINOK(Archive_IsItem_Dir(archive, i, isDir));
if (isFolder)
if (isDir)
{
file.FolderIndex = Folders.Size();
CProxyFolder2 &folder = Folders.AddNew();
folder.ArcIndex = i;
file.DirIndex = Dirs.Size();
CProxyDir2 &dir = Dirs.AddNew();
dir.ArcIndex = i;
}
if (arc.Ask_AltStream)
RINOK(Archive_IsItem_AltStream(archive, i, file.IsAltStream));
@@ -544,34 +630,57 @@ HRESULT CProxyArchive2::Load(const CArc &arc, IProgress *progress)
for (i = 0; i < numItems; i++)
{
CProxyFile2 &file = Files[i];
int dirIndex;
if (file.IsAltStream)
{
if (file.Parent >= 0)
if (file.Parent < 0)
dirIndex = k_Proxy2_AltRootDirIndex;
else
{
int &folderIndex = Files[file.Parent].AltStreamsFolderIndex;
if (folderIndex < 0)
int &folderIndex2 = Files[file.Parent].AltDirIndex;
if (folderIndex2 < 0)
{
folderIndex = Folders.Size();
CProxyFolder2 &folder = Folders.AddNew();
folder.ArcIndex = file.Parent; // do we need it ???
folderIndex2 = Dirs.Size();
CProxyDir2 &dir = Dirs.AddNew();
dir.ArcIndex = file.Parent;
}
Folders[folderIndex].SubFiles.Add(i);
dirIndex = folderIndex2;
}
}
else
{
int folderIndex = GetParentFolderOfFile(i);
if (folderIndex < 0)
return E_FAIL;
Folders[folderIndex].SubFiles.Add(i);
if (file.Parent < 0)
dirIndex = k_Proxy2_RootDirIndex;
else
{
dirIndex = Files[file.Parent].DirIndex;
if (dirIndex < 0)
return E_FAIL;
}
}
Dirs[dirIndex].Items.Add(i);
}
CalculateSizes(0, archive);
for (i = 0; i < k_Proxy2_NumRootDirs; i++)
CalculateSizes(i, archive);
// } char s[128]; sprintf(s, "Load archive: %7d ms", GetTickCount() - tickCount); OutputDebugStringA(s);
/*
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 < 0)
continue;
if (CompareFileNames(file.Name, name) == 0)
return i;
}
return -1;
}

View File

@@ -7,46 +7,61 @@
struct CProxyFile
{
UInt32 Index;
UString Name;
const wchar_t *Name;
unsigned NameLen;
bool NeedDeleteName;
CProxyFile(): Name(NULL), NameLen(0), NeedDeleteName(false) {}
~CProxyFile() { if (NeedDeleteName) delete [](wchar_t *)Name; }
};
class CProxyFolder: public CProxyFile
const unsigned k_Proxy_RootDirIndex = 0;
struct CProxyDir
{
public:
int Parent;
CRecordVector<unsigned> Folders;
CObjectVector<CProxyFile> Files;
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 NumSubFolders;
UInt32 NumSubDirs;
UInt32 NumSubFiles;
bool IsLeaf;
bool CrcIsDefined;
CProxyFolder(): Parent(-1) {};
void AddFileSubItem(UInt32 index, const UString &name);
CProxyDir(): Name(NULL), NameLen(0), ParentDir(-1) {};
~CProxyDir() { delete [](wchar_t *)Name; }
void Clear();
bool IsLeaf() const { return ArcIndex >= 0; }
};
class CProxyArchive
class CProxyArc
{
int FindDirSubItemIndex(unsigned folderIndex, const UString &name, unsigned &insertPos) const;
int FindSubDir(unsigned dirIndex, const wchar_t *name, unsigned &insertPos) const;
void CalculateSizes(unsigned folderIndex, IInArchive *archive);
unsigned AddDirSubItem(unsigned folderIndex, UInt32 index, bool leaf, const UString &name);
void CalculateSizes(unsigned dirIndex, IInArchive *archive);
unsigned AddDir(unsigned dirIndex, int arcIndex, const UString &name);
public:
CObjectVector<CProxyFolder> Folders; // Folders[0] - isRoot
CObjectVector<CProxyDir> Dirs; // Dirs[0] - root
CObjArray<CProxyFile> Files; // all items from archive in same order
int FindDirSubItemIndex(unsigned folderIndex, const UString &name) const;
void GetPathParts(int folderIndex, UStringVector &pathParts) const;
UString GetFullPathPrefix(int folderIndex) const;
// returns index in Dirs[], or -1,
int FindSubDir(unsigned dirIndex, const wchar_t *name) const;
void GetDirPathParts(int dirIndex, UStringVector &pathParts) const;
// returns full path of Dirs[dirIndex], including back slash
UString GetDirPath_as_Prefix(int dirIndex) const;
// AddRealIndices DOES ADD also item represented by folderIndex (if it's Leaf)
void AddRealIndices(unsigned folderIndex, CUIntVector &realIndices) const;
int GetRealIndex(unsigned folderIndex, unsigned index) const;
void GetRealIndices(unsigned folderIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) 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);
};
@@ -56,19 +71,25 @@ public:
struct CProxyFile2
{
int FolderIndex; // >= 0 for dir. (index in ProxyArchive2->Folders)
int AltStreamsFolderIndex; // >= 0 if there are alt streams. (index in ProxyArchive2->Folders)
int Parent; // >= 0 if there is parent. (index in archive and in ProxyArchive2->Files)
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 NameSize;
unsigned NameLen;
bool NeedDeleteName;
bool Ignore;
bool IsAltStream;
bool NeedDeleteName;
int GetFolderIndex(bool forAltStreams) const { return forAltStreams ? AltStreamsFolderIndex : FolderIndex; }
int GetDirIndex(bool forAltStreams) const { return forAltStreams ? AltDirIndex : DirIndex; }
bool IsDir() const { return FolderIndex >= 0; }
CProxyFile2(): FolderIndex(-1), AltStreamsFolderIndex(-1), Name(NULL), Ignore(false), IsAltStream(false), NeedDeleteName(false) {}
bool IsDir() const { return DirIndex >= 0; }
CProxyFile2():
DirIndex(-1), AltDirIndex(-1), Parent(-1),
Name(NULL), NameLen(0),
NeedDeleteName(false),
Ignore(false),
IsAltStream(false)
{}
~CProxyFile2()
{
if (NeedDeleteName)
@@ -76,53 +97,66 @@ struct CProxyFile2
}
};
class CProxyFolder2
struct CProxyDir2
{
public:
Int32 ArcIndex; // = -1 for Root folder
CRecordVector<unsigned> SubFiles;
int ArcIndex; // = -1 for root folders, index in proxy->Files[]
CRecordVector<unsigned> Items;
UString PathPrefix;
UInt64 Size;
UInt64 PackSize;
bool CrcIsDefined;
UInt32 Crc;
UInt32 NumSubFolders;
UInt32 NumSubDirs;
UInt32 NumSubFiles;
CProxyFolder2(): ArcIndex(-1) {};
CProxyDir2(): ArcIndex(-1) {};
void AddFileSubItem(UInt32 index, const UString &name);
void Clear();
};
class CProxyArchive2
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 folderIndex, IInArchive *archive);
// AddRealIndices_of_Folder DOES NOT ADD item itself represented by folderIndex
void AddRealIndices_of_Folder(unsigned folderIndex, bool includeAltStreams, CUIntVector &realIndices) const;
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<CProxyFolder2> Folders; // Folders[0] - is root folder
CObjArray<CProxyFile2> Files; // all aitems from archive in same order
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 folderIndex, const UString &name) const;
bool IsThere_SubDir(unsigned dirIndex, const UString &name) const;
void GetPathParts(int folderIndex, UStringVector &pathParts) const;
UString GetFullPathPrefix(unsigned folderIndex) const;
void GetDirPathParts(int 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 folderIndex, unsigned index) const;
void GetRealIndices(unsigned folderIndex, const UInt32 *indices, UInt32 numItems, 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 GetParentFolderOfFile(UInt32 indexInArc) const
int GetParentDirOfFile(UInt32 arcIndex) const
{
const CProxyFile2 &file = Files[indexInArc];
const CProxyFile2 &file = Files[arcIndex];
if (file.Parent < 0)
return 0;
return Files[file.Parent].FolderIndex;
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

View File

@@ -28,9 +28,14 @@ STDMETHODIMP CAgentFolder::CopyTo(Int32 moveMode, const UInt32 *indices, UInt32
CMyComPtr<IFolderOperationsExtractCallback> callbackWrap = callback;
RINOK(callbackWrap.QueryInterface(IID_IFolderArchiveExtractCallback, &extractCallback2));
}
NExtract::NPathMode::EEnum pathMode = _flatMode ?
NExtract::NPathMode::kNoPaths :
NExtract::NPathMode::kCurPaths;
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,

View File

@@ -2,21 +2,19 @@
#include "StdAfx.h"
#include "../../../Windows/DLL.h"
#include "Agent.h"
void CArchiveFolderManager::LoadFormats()
{
if (!_codecs)
{
_compressCodecsInfo = _codecs = new CCodecs;
_codecs->Load();
}
LoadGlobalCodecs();
}
int CArchiveFolderManager::FindFormat(const UString &type)
{
FOR_VECTOR (i, _codecs->Formats)
if (type.IsEqualToNoCase(_codecs->Formats[i].Name))
FOR_VECTOR (i, g_CodecsObj->Formats)
if (type.IsEqualTo_NoCase(g_CodecsObj->Formats[i].Name))
return i;
return -1;
}
@@ -54,7 +52,7 @@ STDMETHODIMP CArchiveFolderManager::GetExtensions(const wchar_t *type, BSTR *ext
if (formatIndex < 0)
return E_INVALIDARG;
// Exts[0].Ext;
return StringToBstr(_codecs.Formats[formatIndex].GetAllExtensions(), extensions);
return StringToBstr(g_CodecsObj.Formats[formatIndex].GetAllExtensions(), extensions);
}
*/
@@ -62,8 +60,7 @@ static void AddIconExt(const CCodecIcons &lib, UString &dest)
{
FOR_VECTOR (i, lib.IconPairs)
{
if (!dest.IsEmpty())
dest += L' ';
dest.Add_Space_if_NotEmpty();
dest += lib.IconPairs[i].Ext;
}
}
@@ -73,20 +70,30 @@ STDMETHODIMP CArchiveFolderManager::GetExtensions(BSTR *extensions)
LoadFormats();
*extensions = 0;
UString res;
FOR_VECTOR (i, _codecs->Libs)
AddIconExt(_codecs->Libs[i], res);
AddIconExt(_codecs->InternalIcons, res);
#ifdef EXTERNAL_CODECS
FOR_VECTOR (i, g_CodecsObj->Libs)
AddIconExt(g_CodecsObj->Libs[i], res);
#endif
AddIconExt(g_CodecsObj->InternalIcons, res);
return StringToBstr(res, extensions);
}
STDMETHODIMP CArchiveFolderManager::GetIconPath(const wchar_t *ext, BSTR *iconPath, Int32 *iconIndex)
{
LoadFormats();
*iconPath = 0;
*iconIndex = 0;
FOR_VECTOR (i, _codecs->Libs)
LoadFormats();
#ifdef EXTERNAL_CODECS
FOR_VECTOR (i, g_CodecsObj->Libs)
{
const CCodecLib &lib = _codecs->Libs[i];
const CCodecLib &lib = g_CodecsObj->Libs[i];
int ii;
if (lib.FindIconIndex(ext, ii))
{
@@ -94,8 +101,11 @@ STDMETHODIMP CArchiveFolderManager::GetIconPath(const wchar_t *ext, BSTR *iconPa
return StringToBstr(fs2us(lib.Path), iconPath);
}
}
#endif
int ii;
if (_codecs->InternalIcons.FindIconIndex(ext, ii))
if (g_CodecsObj->InternalIcons.FindIconIndex(ext, ii))
{
FString path;
if (NWindows::NDLL::MyGetModuleFileName(path))
@@ -112,13 +122,13 @@ STDMETHODIMP CArchiveFolderManager::GetTypes(BSTR *types)
{
LoadFormats();
UString typesStrings;
FOR_VECTOR(i, _codecs.Formats)
FOR_VECTOR(i, g_CodecsObj.Formats)
{
const CArcInfoEx &ai = _codecs.Formats[i];
const CArcInfoEx &ai = g_CodecsObj.Formats[i];
if (ai.AssociateExts.Size() == 0)
continue;
if (i != 0)
typesStrings += L' ';
typesStrings.Add_Space();
typesStrings += ai.Name;
}
return StringToBstr(typesStrings, types);

View File

@@ -1,4 +1,4 @@
// FolderOut.cpp
// ArchiveFolderOut.cpp
#include "StdAfx.h"
@@ -19,12 +19,12 @@ using namespace NWindows;
using namespace NFile;
using namespace NDir;
void CAgentFolder::GetPathParts(UStringVector &pathParts)
void CAgentFolder::GetPathParts(UStringVector &pathParts, bool &isAltStreamFolder)
{
if (_proxyArchive2)
_proxyArchive2->GetPathParts(_proxyFolderItem, pathParts);
if (_proxy2)
_proxy2->GetDirPathParts(_proxyDirIndex, pathParts, isAltStreamFolder);
else
_proxyArchive->GetPathParts(_proxyFolderItem, pathParts);
_proxy->GetDirPathParts(_proxyDirIndex, pathParts);
}
static bool DeleteEmptyFolderAndEmptySubFolders(const FString &path)
@@ -55,16 +55,25 @@ HRESULT CAgentFolder::CommonUpdateOperation(
const wchar_t *newItemName,
const NUpdateArchive::CActionSet *actionSet,
const UInt32 *indices, UInt32 numItems,
IFolderArchiveUpdateCallback *updateCallback100)
IProgress *progress)
{
if (!_agentSpec->CanUpdate())
return E_NOTIMPL;
////////////////////////////
// Save FolderItem;
CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
if (progress)
progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&updateCallback100);
try
{
RINOK(_agentSpec->SetFolder(this));
// ---------- Save FolderItem ----------
UStringVector pathParts;
GetPathParts(pathParts);
bool isAltStreamFolder = false;
GetPathParts(pathParts, isAltStreamFolder);
FStringVector requestedPaths;
FStringVector processedPaths;
@@ -153,25 +162,96 @@ HRESULT CAgentFolder::CommonUpdateOperation(
}
}
{
CMyComPtr<IArchiveOpenCallback> openCallback;
if (updateCallback100)
{
RINOK(updateCallback100->QueryInterface(IID_IArchiveOpenCallback, (void **)&openCallback));
}
updateCallback100->QueryInterface(IID_IArchiveOpenCallback, (void **)&openCallback);
RINOK(_agentSpec->ReOpen(openCallback));
}
// Restore FolderItem;
// CAgent::ReOpen() deletes _proxy and _proxy2
_items.Clear();
_proxy = NULL;
_proxy2 = NULL;
_proxyDirIndex = k_Proxy_RootDirIndex;
_isAltStreamFolder = false;
// ---------- Restore FolderItem ----------
CMyComPtr<IFolderFolder> archiveFolder;
RINOK(_agentSpec->BindToRootFolder(&archiveFolder));
// CAgent::BindToRootFolder() changes _proxy and _proxy2
_proxy = _agentSpec->_proxy;
_proxy2 = _agentSpec->_proxy2;
if (_proxy)
{
FOR_VECTOR (i, pathParts)
{
int next = _proxy->FindSubDir(_proxyDirIndex, pathParts[i]);
if (next < 0)
break;
_proxyDirIndex = next;
}
}
if (_proxy2)
{
if (pathParts.IsEmpty() && isAltStreamFolder)
{
_proxyDirIndex = k_Proxy2_AltRootDirIndex;
}
else FOR_VECTOR (i, pathParts)
{
bool dirOnly = (i + 1 < pathParts.Size() || !isAltStreamFolder);
int index = _proxy2->FindItem(_proxyDirIndex, pathParts[i], dirOnly);
if (index < 0)
break;
const CProxyFile2 &file = _proxy2->Files[_proxy2->Dirs[_proxyDirIndex].Items[index]];
if (dirOnly)
_proxyDirIndex = file.DirIndex;
else
{
if (file.AltDirIndex >= 0)
_proxyDirIndex = 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;
archiveFolder->BindToFolder(pathParts[i], &newFolder);
if(!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;
}
@@ -180,63 +260,56 @@ HRESULT CAgentFolder::CommonUpdateOperation(
RINOK(archiveFolder.QueryInterface(IID_IArchiveFolderInternal, &archiveFolderInternal));
CAgentFolder *agentFolder;
RINOK(archiveFolderInternal->GetAgentFolder(&agentFolder));
_proxyFolderItem = agentFolder->_proxyFolderItem;
_proxyArchive = agentFolder->_proxyArchive;
_proxyArchive2 = agentFolder->_proxyArchive2;
_parentFolder = agentFolder->_parentFolder;
_proxyDirIndex = agentFolder->_proxyDirIndex;
// _parentFolder = agentFolder->_parentFolder;
*/
if (_proxy2)
_isAltStreamFolder = _proxy2->IsAltDir(_proxyDirIndex);
return res;
}
catch(const UString &s)
{
if (updateCallback100)
{
UString s2 = L"Error: ";
s2 += s;
RINOK(updateCallback100->UpdateErrorMessage(s2));
return E_FAIL;
}
throw;
}
}
STDMETHODIMP CAgentFolder::CopyFrom(Int32 moveMode,
const wchar_t *fromFolderPath, // test it
const wchar_t **itemsPaths,
const wchar_t * const *itemsPaths,
UInt32 numItems,
IProgress *progress)
{
COM_TRY_BEGIN
CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
if (progress)
{
RINOK(progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&updateCallback100));
}
try
{
RINOK(_agentSpec->SetFiles(fromFolderPath, itemsPaths, numItems));
RINOK(_agentSpec->SetFolder(this));
return CommonUpdateOperation(AGENT_OP_Uni, (moveMode != 0), NULL,
&NUpdateArchive::k_ActionSet_Add,
0, 0, updateCallback100);
}
catch(const UString &s)
{
RINOK(updateCallback100->UpdateErrorMessage(UString(L"Error: ") + s));
return E_FAIL;
NULL, 0, progress);
}
COM_TRY_END
}
STDMETHODIMP CAgentFolder::CopyFromFile(UInt32 destIndex, const wchar_t *itemPath, IProgress * progress)
STDMETHODIMP CAgentFolder::CopyFromFile(UInt32 destIndex, const wchar_t *itemPath, IProgress *progress)
{
COM_TRY_BEGIN
CUIntVector indices;
indices.Add(destIndex);
CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
if (progress)
{
RINOK(progress->QueryInterface(IID_IFolderArchiveUpdateCallback, (void **)&updateCallback100));
}
try
{
RINOK(_agentSpec->SetFolder(this));
return CommonUpdateOperation(AGENT_OP_CopyFromFile, false, itemPath,
&NUpdateArchive::k_ActionSet_Add,
&indices.Front(), indices.Size(), updateCallback100);
}
catch(const UString &s)
{
RINOK(updateCallback100->UpdateErrorMessage(UString(L"Error: ") + s));
return E_FAIL;
&indices.Front(), indices.Size(), progress);
}
COM_TRY_END
}
@@ -244,40 +317,30 @@ STDMETHODIMP CAgentFolder::CopyFromFile(UInt32 destIndex, const wchar_t *itemPat
STDMETHODIMP CAgentFolder::Delete(const UInt32 *indices, UInt32 numItems, IProgress *progress)
{
COM_TRY_BEGIN
RINOK(_agentSpec->SetFolder(this));
CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
if (progress)
{
CMyComPtr<IProgress> progressWrapper = progress;
RINOK(progressWrapper.QueryInterface(
IID_IFolderArchiveUpdateCallback, &updateCallback100));
}
return CommonUpdateOperation(AGENT_OP_Delete, false, NULL,
&NUpdateArchive::k_ActionSet_Delete, indices, numItems, updateCallback100);
&NUpdateArchive::k_ActionSet_Delete, indices, numItems, progress);
COM_TRY_END
}
STDMETHODIMP CAgentFolder::CreateFolder(const wchar_t *name, IProgress *progress)
{
COM_TRY_BEGIN
if (_proxyArchive2)
if (_isAltStreamFolder)
return E_NOTIMPL;
if (_proxy2)
{
if (_proxyArchive2->IsThere_SubDir(_proxyFolderItem, name))
if (_proxy2->IsThere_SubDir(_proxyDirIndex, name))
return ERROR_ALREADY_EXISTS;
}
else
{
if (_proxyArchive->FindDirSubItemIndex(_proxyFolderItem, name) >= 0)
if (_proxy->FindSubDir(_proxyDirIndex, name) >= 0)
return ERROR_ALREADY_EXISTS;
}
RINOK(_agentSpec->SetFolder(this));
CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
if (progress)
{
CMyComPtr<IProgress> progressWrapper = progress;
RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100));
}
return CommonUpdateOperation(AGENT_OP_CreateFolder, false, name, NULL, NULL, 0, updateCallback100);
return CommonUpdateOperation(AGENT_OP_CreateFolder, false, name, NULL, NULL, 0, progress);
COM_TRY_END
}
@@ -286,15 +349,8 @@ STDMETHODIMP CAgentFolder::Rename(UInt32 index, const wchar_t *newName, IProgres
COM_TRY_BEGIN
CUIntVector indices;
indices.Add(index);
RINOK(_agentSpec->SetFolder(this));
CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
if (progress)
{
CMyComPtr<IProgress> progressWrapper = progress;
RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100));
}
return CommonUpdateOperation(AGENT_OP_Rename, false, newName, NULL, &indices.Front(),
indices.Size(), updateCallback100);
return CommonUpdateOperation(AGENT_OP_Rename, false, newName, NULL,
&indices.Front(), indices.Size(), progress);
COM_TRY_END
}

View File

@@ -15,6 +15,15 @@
#define FOLDER_ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 0x01, x)
#define FOLDER_ARCHIVE_INTERFACE(i, x) FOLDER_ARCHIVE_INTERFACE_SUB(i, IUnknown, x)
/* ---------- 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 INTERFACE_IArchiveFolder(x) \
STDMETHOD(Extract)(const UInt32 *indices, UInt32 numItems, \
Int32 includeAltStreams, \
@@ -29,6 +38,12 @@ FOLDER_ARCHIVE_INTERFACE(IArchiveFolder, 0x0D)
INTERFACE_IArchiveFolder(PURE)
};
/* ---------- IInFolderArchive ----------
IInFolderArchive is implemented by CAgent (Agent/Agent.h)
IInFolderArchive Is used by FAR/Plugin
*/
#define INTERFACE_IInFolderArchive(x) \
STDMETHOD(Open)(IInStream *inStream, const wchar_t *filePath, const wchar_t *arcFormat, BSTR *archiveTypeRes, IArchiveOpenCallback *openArchiveCallback) x; \
STDMETHOD(ReOpen)(IArchiveOpenCallback *openArchiveCallback) x; \
@@ -48,7 +63,7 @@ FOLDER_ARCHIVE_INTERFACE(IInFolderArchive, 0x0E)
#define INTERFACE_IFolderArchiveUpdateCallback(x) \
STDMETHOD(CompressOperation)(const wchar_t *name) x; \
STDMETHOD(DeleteOperation)(const wchar_t *name) x; \
STDMETHOD(OperationResult)(Int32 operationResult) x; \
STDMETHOD(OperationResult)(Int32 opRes) x; \
STDMETHOD(UpdateErrorMessage)(const wchar_t *message) x; \
STDMETHOD(SetNumFiles)(UInt64 numFiles) x; \
@@ -59,7 +74,7 @@ FOLDER_ARCHIVE_INTERFACE_SUB(IFolderArchiveUpdateCallback, IProgress, 0x0B)
#define INTERFACE_IOutFolderArchive(x) \
STDMETHOD(SetFolder)(IFolderFolder *folder) x; \
STDMETHOD(SetFiles)(const wchar_t *folderPrefix, const wchar_t **names, UInt32 numNames) x; \
STDMETHOD(SetFiles)(const wchar_t *folderPrefix, const wchar_t * const *names, UInt32 numNames) x; \
STDMETHOD(DeleteItems)(ISequentialOutStream *outArchiveStream, \
const UInt32 *indices, UInt32 numItems, IFolderArchiveUpdateCallback *updateCallback) x; \
STDMETHOD(DoOperation)( \
@@ -79,4 +94,26 @@ FOLDER_ARCHIVE_INTERFACE(IOutFolderArchive, 0x0F)
INTERFACE_IOutFolderArchive(PURE)
};
#define INTERFACE_IFolderArchiveUpdateCallback2(x) \
STDMETHOD(OpenFileError)(const wchar_t *path, HRESULT errorCode) x; \
STDMETHOD(ReadingFileError)(const wchar_t *path, HRESULT errorCode) x; \
STDMETHOD(ReportExtractResult)(Int32 opRes, Int32 isEncrypted, const wchar_t *path) x; \
STDMETHOD(ReportUpdateOperation)(UInt32 notifyOp, const wchar_t *path, Int32 isDir) x; \
FOLDER_ARCHIVE_INTERFACE(IFolderArchiveUpdateCallback2, 0x10)
{
INTERFACE_IFolderArchiveUpdateCallback2(PURE)
};
#define INTERFACE_IFolderScanProgress(x) \
STDMETHOD(ScanError)(const wchar_t *path, HRESULT errorCode) x; \
STDMETHOD(ScanProgress)(UInt64 numFolders, UInt64 numFiles, UInt64 totalSize, const wchar_t *path, Int32 isDir) x; \
FOLDER_ARCHIVE_INTERFACE(IFolderScanProgress, 0x11)
{
INTERFACE_IFolderScanProgress(PURE)
};
#endif

View File

@@ -14,14 +14,24 @@ 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::SetNumFiles(UInt64 numFiles)
HRESULT CUpdateCallbackAgent::SetNumItems(UInt64 numItems)
{
if (Callback)
return Callback->SetNumFiles(numFiles);
return Callback->SetNumFiles(numItems);
return S_OK;
}
HRESULT CUpdateCallbackAgent::WriteSfx(const wchar_t * /* name */, UInt64 /* size */)
{
return S_OK;
}
@@ -52,31 +62,65 @@ HRESULT CUpdateCallbackAgent::CheckBreak()
return S_OK;
}
HRESULT CUpdateCallbackAgent::Finilize()
/*
HRESULT CUpdateCallbackAgent::Finalize()
{
return S_OK;
}
*/
HRESULT CUpdateCallbackAgent::OpenFileError(const wchar_t *name, DWORD systemError)
HRESULT CUpdateCallbackAgent::OpenFileError(const FString &path, DWORD systemError)
{
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 = L"WARNING: ";
s += NError::MyFormatMessage(systemError);
s += L": ";
s += name;
s += fs2us(path);
RINOK(Callback->UpdateErrorMessage(s));
return S_FALSE;
}
}
// FailedFiles.Add(name);
return systemError;
return hres;
}
HRESULT CUpdateCallbackAgent::GetStream(const wchar_t *name, bool /* isAnti */)
HRESULT CUpdateCallbackAgent::ReadingFileError(const FString &path, DWORD systemError)
{
HRESULT hres = HRESULT_FROM_WIN32(systemError);
// if (systemError == ERROR_SHARING_VIOLATION)
{
if (Callback2)
{
RINOK(Callback2->ReadingFileError(fs2us(path), hres));
}
else if (Callback)
{
UString s = L"ERROR: ";
s += NError::MyFormatMessage(systemError);
s += L": ";
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;
@@ -89,6 +133,50 @@ HRESULT CUpdateCallbackAgent::SetOperationResult(Int32 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::ReportUpdateOpeartion(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 _NO_CRYPTO
password
#endif
)
{
#ifndef _NO_CRYPTO
PasswordIsDefined = true;
Password = password;
#endif
return S_OK;
}
*/
HRESULT CUpdateCallbackAgent::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password)
{
*password = NULL;
@@ -114,9 +202,7 @@ HRESULT CUpdateCallbackAgent::CryptoGetTextPassword(BSTR *password)
return getTextPassword->CryptoGetTextPassword(password);
}
/*
HRESULT CUpdateCallbackAgent::ShowDeleteFile(const wchar_t *name)
HRESULT CUpdateCallbackAgent::ShowDeleteFile(const wchar_t *name, bool /* isDir */)
{
return Callback->DeleteOperation(name);
}
*/

View File

@@ -10,8 +10,10 @@
class CUpdateCallbackAgent: public IUpdateCallbackUI
{
INTERFACE_IUpdateCallbackUI(;)
CMyComPtr<ICryptoGetTextPassword2> _cryptoGetTextPassword;
CMyComPtr<IFolderArchiveUpdateCallback> Callback;
CMyComPtr<IFolderArchiveUpdateCallback2> Callback2;
CMyComPtr<ICompressProgressInfo> _compressProgress;
public:
void SetCallback(IFolderArchiveUpdateCallback *callback);