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

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2014-11-23 03:00:00 +0300
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:16:51 +0300
commitf08f4dcc3c02464c17753b3feafcfe5243b9e236 (patch)
treeb0e1b15bc5368d92dff422e8ec0818564a2b00b8 /CPP/7zip/UI/Agent
parent83f8ddcc5b2161e1e3c49666265257fca8aeb12c (diff)
9.349.34
Diffstat (limited to 'CPP/7zip/UI/Agent')
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/Agent.cpp1184
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/Agent.h109
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/AgentOut.cpp207
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/AgentProxy.cpp565
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/AgentProxy.h107
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/ArchiveFolder.cpp29
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp14
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/ArchiveFolderOut.cpp197
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/IFolderArchive.h15
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp15
-rw-r--r--[-rwxr-xr-x]CPP/7zip/UI/Agent/UpdateCallbackAgent.h5
11 files changed, 2035 insertions, 412 deletions
diff --git a/CPP/7zip/UI/Agent/Agent.cpp b/CPP/7zip/UI/Agent/Agent.cpp
index c11bd490..e4f46f0a 100755..100644
--- a/CPP/7zip/UI/Agent/Agent.cpp
+++ b/CPP/7zip/UI/Agent/Agent.cpp
@@ -4,9 +4,12 @@
#include "../../../../C/Sort.h"
-#include "Common/ComTry.h"
+#include "../../../Common/ComTry.h"
+
+#include "../../../Windows/PropVariantConv.h"
#include "../Common/ArchiveExtractCallback.h"
+#include "../FileManager/RegistryUtils.h"
#include "Agent.h"
@@ -18,19 +21,37 @@ STDMETHODIMP CAgentFolder::GetAgentFolder(CAgentFolder **agentFolder)
return S_OK;
}
-void CAgentFolder::LoadFolder(const CProxyFolder *folder)
+void CAgentFolder::LoadFolder(unsigned proxyFolderIndex)
{
- int i;
+ unsigned i;
CProxyItem item;
- item.Folder = folder;
- for (i = 0; i < folder->Folders.Size(); i++)
+ item.ProxyFolderIndex = proxyFolderIndex;
+ if (_proxyArchive2)
+ {
+ const CProxyFolder2 &folder = _proxyArchive2->Folders[proxyFolderIndex];
+ for (i = 0; i < folder.SubFiles.Size(); i++)
+ {
+ item.Index = i;
+ _items.Add(item);
+ const CProxyFile2 &file = _proxyArchive2->Files[folder.SubFiles[i]];
+ int subFolderIndex = file.FolderIndex;
+ if (subFolderIndex >= 0)
+ LoadFolder(subFolderIndex);
+ subFolderIndex = file.AltStreamsFolderIndex;
+ if (subFolderIndex >= 0)
+ LoadFolder(subFolderIndex);
+ }
+ return;
+ }
+ const CProxyFolder &folder = _proxyArchive->Folders[proxyFolderIndex];
+ for (i = 0; i < folder.Folders.Size(); i++)
{
item.Index = i;
_items.Add(item);
- LoadFolder(&folder->Folders[i]);
+ LoadFolder(folder.Folders[i]);
}
- int start = folder->Folders.Size();
- for (i = 0; i < folder->Files.Size(); i++)
+ unsigned start = folder.Folders.Size();
+ for (i = 0; i < folder.Files.Size(); i++)
{
item.Index = start + i;
_items.Add(item);
@@ -51,58 +72,210 @@ STDMETHODIMP CAgentFolder::GetNumberOfItems(UInt32 *numItems)
{
if (_flatMode)
*numItems = _items.Size();
+ else if (_proxyArchive2)
+ *numItems = _proxyArchive2->Folders[_proxyFolderItem].SubFiles.Size();
else
- *numItems = _proxyFolderItem->Folders.Size() +_proxyFolderItem->Files.Size();
+ {
+ const CProxyFolder *folder = &_proxyArchive->Folders[_proxyFolderItem];
+ *numItems = folder->Folders.Size() + folder ->Files.Size();
+ }
return S_OK;
}
#define SET_realIndex_AND_folder \
UInt32 realIndex; const CProxyFolder *folder; \
- if (_flatMode) { const CProxyItem &item = _items[index]; folder = item.Folder; realIndex = item.Index; } \
- else { folder = _proxyFolderItem; realIndex = index; }
+ if (_flatMode) { const CProxyItem &item = _items[index]; folder = &_proxyArchive->Folders[item.ProxyFolderIndex]; realIndex = item.Index; } \
+ else { folder = &_proxyArchive->Folders[_proxyFolderItem]; realIndex = index; }
+#define SET_realIndex_AND_folder_2 \
+ UInt32 realIndex; const CProxyFolder2 *folder; \
+ if (_flatMode) { const CProxyItem &item = _items[index]; folder = &_proxyArchive2->Folders[item.ProxyFolderIndex]; realIndex = item.Index; } \
+ else { folder = &_proxyArchive2->Folders[_proxyFolderItem]; realIndex = index; }
UString CAgentFolder::GetName(UInt32 index) const
{
+ if (_proxyArchive2)
+ {
+ SET_realIndex_AND_folder_2
+ return _proxyArchive2->Files[folder->SubFiles[realIndex]].Name;
+ }
SET_realIndex_AND_folder
if (realIndex < (UInt32)folder->Folders.Size())
- return folder->Folders[realIndex].Name;
+ return _proxyArchive->Folders[folder->Folders[realIndex]].Name;
return folder->Files[realIndex - folder->Folders.Size()].Name;
}
-UString CAgentFolder::GetPrefix(UInt32 index) const
+void CAgentFolder::GetPrefix(UInt32 index, UString &prefix) const
{
if (!_flatMode)
- return UString();
+ {
+ prefix.Empty();
+ return;
+ }
const CProxyItem &item = _items[index];
- const CProxyFolder *folder = item.Folder;
- UString path;
- while (folder != _proxyFolderItem)
+ unsigned proxyIndex = item.ProxyFolderIndex;
+ unsigned totalLen;
+ if (_proxyArchive2)
{
- path = folder->Name + UString(WCHAR_PATH_SEPARATOR) + path;
- folder = folder->Parent;
+ unsigned len = 0;
+ while (proxyIndex != _proxyFolderItem)
+ {
+ const CProxyFile2 &file = _proxyArchive2->Files[_proxyArchive2->Folders[proxyIndex].ArcIndex];
+ len += file.NameSize + 1;
+ proxyIndex = (file.Parent < 0) ? 0 : _proxyArchive2->Files[file.Parent].GetFolderIndex(file.IsAltStream);
+ }
+ totalLen = len;
+
+ wchar_t *p = prefix.GetBuffer(len);
+ proxyIndex = item.ProxyFolderIndex;
+ while (proxyIndex != _proxyFolderItem)
+ {
+ const CProxyFile2 &file = _proxyArchive2->Files[_proxyArchive2->Folders[proxyIndex].ArcIndex];
+ MyStringCopy(p + len - file.NameSize - 1, file.Name);
+ p[--len] = WCHAR_PATH_SEPARATOR;
+ len -= file.NameSize;
+ proxyIndex = (file.Parent < 0) ? 0 : _proxyArchive2->Files[file.Parent].GetFolderIndex(file.IsAltStream);
+ }
+ }
+ else
+ {
+ unsigned len = 0;
+ while (proxyIndex != _proxyFolderItem)
+ {
+ const CProxyFolder *folder = &_proxyArchive->Folders[proxyIndex];
+ len += folder->Name.Len() + 1;
+ proxyIndex = folder->Parent;
+ }
+ totalLen = len;
+
+ wchar_t *p = prefix.GetBuffer(len);
+ proxyIndex = item.ProxyFolderIndex;
+ while (proxyIndex != _proxyFolderItem)
+ {
+ const CProxyFolder *folder = &_proxyArchive->Folders[proxyIndex];
+ MyStringCopy(p + len - folder->Name.Len() - 1, (const wchar_t *)folder->Name);
+ p[--len] = WCHAR_PATH_SEPARATOR;
+ len -= folder->Name.Len();
+ proxyIndex = folder->Parent;
+ }
}
- return path;
+ prefix.ReleaseBuffer(totalLen);
}
UString CAgentFolder::GetFullPathPrefixPlusPrefix(UInt32 index) const
{
- return _proxyFolderItem->GetFullPathPrefix() + GetPrefix(index);
+ UString prefix;
+ GetPrefix(index, prefix);
+ if (_proxyArchive2)
+ return _proxyArchive2->GetFullPathPrefix(_proxyFolderItem) + prefix;
+ else
+ return _proxyArchive->GetFullPathPrefix(_proxyFolderItem) + prefix;
+}
+
+STDMETHODIMP_(UInt64) CAgentFolder::GetItemSize(UInt32 index)
+{
+ unsigned arcIndex;
+ if (_proxyArchive2)
+ {
+ SET_realIndex_AND_folder_2
+ arcIndex = folder->SubFiles[realIndex];
+ const CProxyFile2 &item = _proxyArchive2->Files[arcIndex];
+ if (item.IsDir())
+ {
+ const CProxyFolder2 &itemFolder = _proxyArchive2->Folders[item.FolderIndex];
+ if (!_flatMode)
+ return itemFolder.Size;
+ }
+ }
+ else
+ {
+ SET_realIndex_AND_folder
+ if (realIndex < (UInt32)folder->Folders.Size())
+ {
+ const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]];
+ if (!_flatMode)
+ return item.Size;
+ arcIndex = item.Index;
+ }
+ else
+ {
+ const CProxyFile &item = folder->Files[realIndex - folder->Folders.Size()];
+ arcIndex = item.Index;
+ }
+ }
+ NCOM::CPropVariant prop;
+ _agentSpec->GetArchive()->GetProperty(arcIndex, kpidSize, &prop);
+ if (prop.vt == VT_UI8)
+ return prop.uhVal.QuadPart;
+ else
+ return 0;
}
STDMETHODIMP CAgentFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NCOM::CPropVariant prop;
- SET_realIndex_AND_folder
+
if (propID == kpidPrefix)
{
if (_flatMode)
- prop = GetPrefix(index);
+ {
+ UString prefix;
+ GetPrefix(index, prefix);
+ prop = prefix;
+ }
+ }
+ else if (_proxyArchive2)
+ {
+ SET_realIndex_AND_folder_2
+ unsigned arcIndex = folder->SubFiles[realIndex];
+ const CProxyFile2 &item = _proxyArchive2->Files[arcIndex];
+ if (!item.IsDir())
+ {
+ switch (propID)
+ {
+ case kpidIsDir: prop = false; break;
+ case kpidName: prop = item.Name; break;
+ default: return _agentSpec->GetArchive()->GetProperty(arcIndex, propID, value);
+ }
+ }
+ else
+ {
+ const CProxyFolder2 &itemFolder = _proxyArchive2->Folders[item.FolderIndex];
+ if (!_flatMode && propID == kpidSize)
+ prop = itemFolder.Size;
+ else if (!_flatMode && propID == kpidPackSize)
+ prop = itemFolder.PackSize;
+ else switch (propID)
+ {
+ case kpidIsDir: prop = true; break;
+ case kpidNumSubDirs: prop = itemFolder.NumSubFolders; break;
+ case kpidNumSubFiles: prop = itemFolder.NumSubFiles; break;
+ case kpidName: prop = item.Name; break;
+ case kpidCRC:
+ {
+ // if (itemFolder.IsLeaf)
+ if (!item.Ignore)
+ {
+ RINOK(_agentSpec->GetArchive()->GetProperty(arcIndex, propID, value));
+ }
+ if (itemFolder.CrcIsDefined && value->vt == VT_EMPTY)
+ prop = itemFolder.Crc;
+ break;
+ }
+ default:
+ // if (itemFolder.IsLeaf)
+ if (!item.Ignore)
+ return _agentSpec->GetArchive()->GetProperty(arcIndex, propID, value);
+ }
+ }
}
- else if (realIndex < (UInt32)folder->Folders.Size())
+ else
{
- const CProxyFolder &item = folder->Folders[realIndex];
+ SET_realIndex_AND_folder
+ if (realIndex < (UInt32)folder->Folders.Size())
+ {
+ const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]];
if (!_flatMode && propID == kpidSize)
prop = item.Size;
else if (!_flatMode && propID == kpidPackSize)
@@ -140,23 +313,457 @@ STDMETHODIMP CAgentFolder::GetProperty(UInt32 index, PROPID propID, PROPVARIANT
return _agentSpec->GetArchive()->GetProperty(item.Index, propID, value);
}
}
+ }
prop.Detach(value);
return S_OK;
COM_TRY_END
}
-HRESULT CAgentFolder::BindToFolder(const CProxyFolder *folder, IFolderFolder **resultFolder)
+static UInt64 GetUInt64Prop(IInArchive *archive, UInt32 index, PROPID propID)
+{
+ NCOM::CPropVariant prop;
+ if (archive->GetProperty(index, propID, &prop) != S_OK)
+ throw 111233443;
+ UInt64 v = 0;
+ if (ConvertPropVariantToUInt64(prop, v))
+ return v;
+ return 0;
+}
+
+STDMETHODIMP CAgentFolder::GetItemName(UInt32 index, const wchar_t **name, unsigned *len)
+{
+ if (_proxyArchive2)
+ {
+ SET_realIndex_AND_folder_2
+ unsigned arcIndex = folder->SubFiles[realIndex];
+ const CProxyFile2 &item = _proxyArchive2->Files[arcIndex];
+ *name = item.Name;
+ *len = item.NameSize;
+ return S_OK;
+ }
+ else
+ {
+ SET_realIndex_AND_folder
+ if (realIndex < (UInt32)folder->Folders.Size())
+ {
+ const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]];
+ *name = item.Name;
+ *len = item.Name.Len();
+ return S_OK;
+ }
+ else
+ {
+ const CProxyFile &item = folder->Files[realIndex - folder->Folders.Size()];
+ *name = item.Name;
+ *len = item.Name.Len();
+ return S_OK;
+ }
+ }
+}
+
+STDMETHODIMP CAgentFolder::GetItemPrefix(UInt32 index, const wchar_t **name, unsigned *len)
+{
+ *name = 0;
+ *len = 0;
+ if (!_flatMode)
+ return S_OK;
+ if (_proxyArchive2)
+ {
+ SET_realIndex_AND_folder_2
+
+ unsigned arcIndex = folder->SubFiles[realIndex];
+ const CProxyFile2 &item = _proxyArchive2->Files[arcIndex];
+ if (item.Parent >= 0)
+ {
+ const CProxyFile2 &item2 = _proxyArchive2->Files[item.Parent];
+ int foldInd = item2.GetFolderIndex(item.IsAltStream);
+ if (foldInd >= 0)
+ {
+ const UString &s = _proxyArchive2->Folders[foldInd].PathPrefix;
+ unsigned baseLen = _proxyArchive2->Folders[_proxyFolderItem].PathPrefix.Len();
+ if (baseLen <= s.Len())
+ {
+ *name = (const wchar_t *)s + baseLen;
+ *len = s.Len() - baseLen;
+ }
+ }
+ }
+ }
+ return S_OK;
+}
+
+static int CompareRawProps(IArchiveGetRawProps *rawProps, int arcIndex1, int arcIndex2, PROPID propID)
+{
+ // if (propID == kpidSha1)
+ if (rawProps)
+ {
+ const void *p1, *p2;
+ UInt32 size1, size2;
+ UInt32 propType1, propType2;
+ HRESULT res1 = rawProps->GetRawProp(arcIndex1, propID, &p1, &size1, &propType1);
+ HRESULT res2 = rawProps->GetRawProp(arcIndex2, propID, &p2, &size2, &propType2);
+ if (res1 == S_OK && res2 == S_OK)
+ {
+ for (UInt32 i = 0; i < size1 && i < size2; i++)
+ {
+ Byte b1 = ((const Byte *)p1)[i];
+ Byte b2 = ((const Byte *)p2)[i];
+ if (b1 < b2) return -1;
+ if (b1 > b2) return 1;
+ }
+ if (size1 < size2) return -1;
+ if (size1 > size2) return 1;
+ return 0;
+ }
+ }
+ return 0;
+}
+
+// returns pointer to extension including '.'
+
+static const wchar_t *GetExtension(const wchar_t *name)
+{
+ for (const wchar_t *dotPtr = NULL;; name++)
+ {
+ wchar_t c = *name;
+ if (c == 0)
+ return dotPtr ? dotPtr : name;
+ if (c == '.')
+ dotPtr = name;
+ }
+}
+
+int CAgentFolder::CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw)
+{
+ UInt32 realIndex1, realIndex2;
+ const CProxyFolder2 *folder1, *folder2;
+
+ if (_flatMode)
+ {
+ const CProxyItem &item1 = _items[index1];
+ const CProxyItem &item2 = _items[index2];
+ folder1 = &_proxyArchive2->Folders[item1.ProxyFolderIndex];
+ folder2 = &_proxyArchive2->Folders[item2.ProxyFolderIndex];
+ realIndex1 = item1.Index;
+ realIndex2 = item2.Index;
+ }
+ else
+ {
+ folder2 = folder1 = &_proxyArchive2->Folders[_proxyFolderItem];
+ realIndex1 = index1;
+ realIndex2 = index2;
+ }
+
+ UInt32 arcIndex1;
+ UInt32 arcIndex2;
+ bool isDir1, isDir2;
+ arcIndex1 = folder1->SubFiles[realIndex1];
+ arcIndex2 = folder2->SubFiles[realIndex2];
+ const CProxyFile2 &prox1 = _proxyArchive2->Files[arcIndex1];
+ const CProxyFile2 &prox2 = _proxyArchive2->Files[arcIndex2];
+
+ if (propID == kpidName)
+ {
+ return CompareFileNames_ForFolderList(prox1.Name, prox2.Name);
+ }
+
+ if (propID == kpidPrefix)
+ {
+ if (!_flatMode)
+ return 0;
+ if (prox1.Parent < 0) return prox2.Parent < 0 ? 0 : -1;
+ if (prox2.Parent < 0) return 1;
+
+ const CProxyFile2 &proxPar1 = _proxyArchive2->Files[prox1.Parent];
+ const CProxyFile2 &proxPar2 = _proxyArchive2->Files[prox2.Parent];
+ return CompareFileNames_ForFolderList(
+ _proxyArchive2->Folders[proxPar1.GetFolderIndex(prox1.IsAltStream)].PathPrefix,
+ _proxyArchive2->Folders[proxPar2.GetFolderIndex(prox2.IsAltStream)].PathPrefix);
+ }
+
+ if (propID == kpidExtension)
+ {
+ return CompareFileNames_ForFolderList(
+ GetExtension(prox1.Name),
+ GetExtension(prox2.Name));
+ }
+
+ isDir1 = prox1.IsDir();
+ isDir2 = prox2.IsDir();
+
+ if (propID == kpidIsDir)
+ {
+ if (isDir1 == isDir2)
+ return 0;
+ return isDir1 ? -1 : 1;
+ }
+
+ const CProxyFolder2 *proxFolder1 = NULL;
+ const CProxyFolder2 *proxFolder2 = NULL;
+ if (isDir1) proxFolder1 = &_proxyArchive2->Folders[prox1.FolderIndex];
+ if (isDir2) proxFolder2 = &_proxyArchive2->Folders[prox2.FolderIndex];
+
+ if (propID == kpidNumSubDirs)
+ {
+ UInt32 n1 = 0;
+ UInt32 n2 = 0;
+ if (isDir1) n1 = proxFolder1->NumSubFolders;
+ if (isDir2) n2 = proxFolder2->NumSubFolders;
+ return MyCompare(n1, n2);
+ }
+
+ if (propID == kpidNumSubFiles)
+ {
+ UInt32 n1 = 0;
+ UInt32 n2 = 0;
+ if (isDir1) n1 = proxFolder1->NumSubFiles;
+ if (isDir2) n2 = proxFolder2->NumSubFiles;
+ return MyCompare(n1, n2);
+ }
+
+ if (propID == kpidSize)
+ {
+ UInt64 n1, n2;
+ if (isDir1)
+ n1 = _flatMode ? 0 : proxFolder1->Size;
+ else
+ n1 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex1, kpidSize);
+ if (isDir2)
+ n2 = _flatMode ? 0 : proxFolder2->Size;
+ else
+ n2 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex2, kpidSize);
+ return MyCompare(n1, n2);
+ }
+
+ if (propID == kpidPackSize)
+ {
+ UInt64 n1, n2;
+ if (isDir1)
+ n1 = _flatMode ? 0 : proxFolder1->PackSize;
+ else
+ n1 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex1, kpidPackSize);
+ if (isDir2)
+ n2 = _flatMode ? 0 : proxFolder2->PackSize;
+ else
+ n2 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex2, kpidPackSize);
+ return MyCompare(n1, n2);
+ }
+
+ if (propID == kpidCRC)
+ {
+ UInt64 n1, n2;
+ if (!isDir1 || !prox1.Ignore)
+ n1 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex1, kpidCRC);
+ else
+ n1 = proxFolder1->Crc;
+ if (!isDir2 || !prox2.Ignore)
+ n2 = GetUInt64Prop(_agentSpec->GetArchive(), arcIndex2, kpidCRC);
+ else
+ n2 = proxFolder2->Crc;
+ return MyCompare(n1, n2);
+ }
+
+ if (propIsRaw)
+ return CompareRawProps(_agentSpec->_archiveLink.GetArchiveGetRawProps(), arcIndex1, arcIndex2, propID);
+
+ NCOM::CPropVariant prop1, prop2;
+ // Name must be first property
+ GetProperty(index1, propID, &prop1);
+ GetProperty(index2, propID, &prop2);
+ if (prop1.vt != prop2.vt)
+ {
+ return MyCompare(prop1.vt, prop2.vt);
+ }
+ if (prop1.vt == VT_BSTR)
+ {
+ return _wcsicmp(prop1.bstrVal, prop2.bstrVal);
+ }
+ return prop1.Compare(prop2);
+}
+
+STDMETHODIMP_(Int32) CAgentFolder::CompareItems(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw)
+{
+ COM_TRY_BEGIN
+ if (_proxyArchive2)
+ return CompareItems2(index1, index2, propID, propIsRaw);
+ UInt32 realIndex1, realIndex2;
+ const CProxyFolder *folder1, *folder2;
+
+ if (_flatMode)
+ {
+ const CProxyItem &item1 = _items[index1];
+ const CProxyItem &item2 = _items[index2];
+ folder1 = &_proxyArchive->Folders[item1.ProxyFolderIndex];
+ folder2 = &_proxyArchive->Folders[item2.ProxyFolderIndex];
+ realIndex1 = item1.Index;
+ realIndex2 = item2.Index;
+ }
+ else
+ {
+ folder2 = folder1 = &_proxyArchive->Folders[_proxyFolderItem];
+ realIndex1 = index1;
+ realIndex2 = index2;
+ }
+ if (propID == kpidPrefix)
+ {
+ if (!_flatMode)
+ return 0;
+ UString prefix1, prefix2;
+ GetPrefix(index1, prefix1);
+ GetPrefix(index2, prefix2);
+ return CompareFileNames_ForFolderList(prefix1, prefix2);
+ }
+ const CProxyFile *prox1;
+ const CProxyFile *prox2;
+ const CProxyFolder *proxFolder1 = NULL;
+ const CProxyFolder *proxFolder2 = NULL;
+ bool isDir1, isDir2;
+ if (realIndex1 < (UInt32)folder1->Folders.Size())
+ {
+ isDir1 = true;
+ prox1 = proxFolder1 = &_proxyArchive->Folders[folder1->Folders[realIndex1]];
+ }
+ else
+ {
+ isDir1 = false;
+ prox1 = &folder1->Files[realIndex1 - folder1->Folders.Size()];
+ }
+
+ if (realIndex2 < (UInt32)folder2->Folders.Size())
+ {
+ isDir2 = true;
+ prox2 = proxFolder2 = &_proxyArchive->Folders[folder2->Folders[realIndex2]];
+ }
+ else
+ {
+ isDir2 = false;
+ prox2 = &folder2->Files[realIndex2 - folder2->Folders.Size()];
+ }
+
+ if (propID == kpidName)
+ {
+ return CompareFileNames_ForFolderList(prox1->Name, prox2->Name);
+ }
+ if (propID == kpidExtension)
+ {
+ return CompareFileNames_ForFolderList(
+ GetExtension(prox1->Name),
+ GetExtension(prox2->Name));
+ }
+
+ if (propID == kpidIsDir)
+ {
+ if (isDir1 == isDir2)
+ return 0;
+ return isDir1 ? -1 : 1;
+ }
+ if (propID == kpidNumSubDirs)
+ {
+ UInt32 n1 = 0;
+ UInt32 n2 = 0;
+ if (isDir1) n1 = proxFolder1->NumSubFolders;
+ if (isDir2) n2 = proxFolder2->NumSubFolders;
+ return MyCompare(n1, n2);
+ }
+ if (propID == kpidNumSubFiles)
+ {
+ UInt32 n1 = 0;
+ UInt32 n2 = 0;
+ if (isDir1) n1 = proxFolder1->NumSubFiles;
+ if (isDir2) n2 = proxFolder2->NumSubFiles;
+ return MyCompare(n1, n2);
+ }
+ if (propID == kpidSize)
+ {
+ UInt64 n1, n2;
+ if (isDir1)
+ n1 = _flatMode ? 0 : proxFolder1->Size;
+ else
+ n1 = GetUInt64Prop(_agentSpec->GetArchive(), prox1->Index, kpidSize);
+ if (isDir2)
+ n2 = _flatMode ? 0 : proxFolder2->Size;
+ else
+ n2 = GetUInt64Prop(_agentSpec->GetArchive(), prox2->Index, kpidSize);
+ return MyCompare(n1, n2);
+ }
+ if (propID == kpidPackSize)
+ {
+ UInt64 n1, n2;
+ if (isDir1)
+ n1 = _flatMode ? 0 : proxFolder1->PackSize;
+ else
+ n1 = GetUInt64Prop(_agentSpec->GetArchive(), prox1->Index, kpidPackSize);
+ if (isDir2)
+ n2 = _flatMode ? 0 : proxFolder2->PackSize;
+ else
+ n2 = GetUInt64Prop(_agentSpec->GetArchive(), prox2->Index, kpidPackSize);
+ return MyCompare(n1, n2);
+ }
+
+ if (propID == kpidCRC)
+ {
+ UInt64 n1, n2;
+ if (!isDir1 || proxFolder1->IsLeaf)
+ n1 = GetUInt64Prop(_agentSpec->GetArchive(), prox1->Index, kpidCRC);
+ else
+ n1 = proxFolder1->Crc;
+ if (!isDir2 || proxFolder2->IsLeaf)
+ n2 = GetUInt64Prop(_agentSpec->GetArchive(), prox2->Index, kpidCRC);
+ else
+ n2 = proxFolder2->Crc;
+ return MyCompare(n1, n2);
+ }
+
+ if (propIsRaw)
+ return CompareRawProps(_agentSpec->_archiveLink.GetArchiveGetRawProps(), prox1->Index, prox2->Index, propID);
+
+ NCOM::CPropVariant prop1, prop2;
+ // Name must be first property
+ GetProperty(index1, propID, &prop1);
+ GetProperty(index2, propID, &prop2);
+ if (prop1.vt != prop2.vt)
+ {
+ return MyCompare(prop1.vt, prop2.vt);
+ }
+ if (prop1.vt == VT_BSTR)
+ {
+ return _wcsicmp(prop1.bstrVal, prop2.bstrVal);
+ }
+ return prop1.Compare(prop2);
+
+ COM_TRY_END
+}
+
+HRESULT CAgentFolder::BindToFolder_Internal(unsigned proxyFolderIndex, IFolderFolder **resultFolder)
{
CMyComPtr<IFolderFolder> parentFolder;
- if (folder->Parent != _proxyFolderItem)
+
+ if (_proxyArchive2)
{
- RINOK(BindToFolder(folder->Parent, &parentFolder));
+ parentFolder = NULL; // Change it;
+ const CProxyFolder2 &folder = _proxyArchive2->Folders[proxyFolderIndex];
+ int par = _proxyArchive2->GetParentFolderOfFile(folder.ArcIndex);
+ if (par != (int)_proxyFolderItem)
+ {
+ // return E_FAIL;
+ RINOK(BindToFolder_Internal(par, &parentFolder));
+ }
+ else
+ parentFolder = this;
}
else
- parentFolder = this;
+ {
+ const CProxyFolder &folder = _proxyArchive->Folders[proxyFolderIndex];
+ if (folder.Parent != (int)_proxyFolderItem)
+ {
+ RINOK(BindToFolder_Internal(folder.Parent, &parentFolder));
+ }
+ else
+ parentFolder = this;
+ }
CAgentFolder *folderSpec = new CAgentFolder;
CMyComPtr<IFolderFolder> agentFolder = folderSpec;
- folderSpec->Init(_proxyArchive, folder, parentFolder, _agentSpec);
+ folderSpec->Init(_proxyArchive, _proxyArchive2, proxyFolderIndex, parentFolder, _agentSpec);
*resultFolder = agentFolder.Detach();
return S_OK;
}
@@ -164,30 +771,51 @@ HRESULT CAgentFolder::BindToFolder(const CProxyFolder *folder, IFolderFolder **r
STDMETHODIMP CAgentFolder::BindToFolder(UInt32 index, IFolderFolder **resultFolder)
{
COM_TRY_BEGIN
+ if (_proxyArchive2)
+ {
+ SET_realIndex_AND_folder_2
+ unsigned arcIndex = folder->SubFiles[realIndex];
+ const CProxyFile2 &item = _proxyArchive2->Files[arcIndex];
+ if (!item.IsDir())
+ return E_INVALIDARG;
+ return BindToFolder_Internal(item.FolderIndex, resultFolder);
+ }
SET_realIndex_AND_folder
if (realIndex >= (UInt32)folder->Folders.Size())
return E_INVALIDARG;
- return BindToFolder(&folder->Folders[realIndex], resultFolder);
+ return BindToFolder_Internal(folder->Folders[realIndex], resultFolder);
COM_TRY_END
}
STDMETHODIMP CAgentFolder::BindToFolder(const wchar_t *name, IFolderFolder **resultFolder)
{
COM_TRY_BEGIN
- int index = _proxyFolderItem->FindDirSubItemIndex(name);
+ if (_proxyArchive2)
+ {
+ const CProxyFolder2 &folder = _proxyArchive2->Folders[_proxyFolderItem];
+ FOR_VECTOR (i, folder.SubFiles)
+ {
+ const CProxyFile2 &file = _proxyArchive2->Files[folder.SubFiles[i]];
+ if (file.FolderIndex >= 0)
+ if (StringsAreEqualNoCase(file.Name, name))
+ return BindToFolder_Internal(file.FolderIndex, resultFolder);
+ }
+ return E_INVALIDARG;
+ }
+ int index = _proxyArchive->FindDirSubItemIndex(_proxyFolderItem, name);
if (index < 0)
return E_INVALIDARG;
- return BindToFolder(index, resultFolder);
+ return BindToFolder_Internal(index, resultFolder);
COM_TRY_END
}
STDMETHODIMP CAgentFolder::BindToParentFolder(IFolderFolder **resultFolder)
{
- COM_TRY_BEGIN
+ // COM_TRY_BEGIN
CMyComPtr<IFolderFolder> parentFolder = _parentFolder;
*resultFolder = parentFolder.Detach();
return S_OK;
- COM_TRY_END
+ // COM_TRY_END
}
STDMETHODIMP CAgentFolder::GetStream(UInt32 index, ISequentialInStream **stream)
@@ -197,30 +825,36 @@ STDMETHODIMP CAgentFolder::GetStream(UInt32 index, ISequentialInStream **stream)
if (!getStream)
return S_OK;
+ UInt32 indexInArchive;
+ if (_proxyArchive2)
+ {
+ SET_realIndex_AND_folder_2
+ indexInArchive = folder->SubFiles[realIndex];
+ }
+ else
+ {
SET_realIndex_AND_folder
- UInt32 indexInArchive;
if (realIndex < (UInt32)folder->Folders.Size())
{
- const CProxyFolder &item = folder->Folders[realIndex];
+ const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]];
if (!item.IsLeaf)
return S_OK;
indexInArchive = item.Index;
}
else
indexInArchive = folder->Files[realIndex - folder->Folders.Size()].Index;
+ }
return getStream->GetStream(indexInArchive, stream);
}
-static const STATPROPSTG kProperties[] =
+static const PROPID kProps[] =
{
- { NULL, kpidNumSubDirs, VT_UI4},
- { NULL, kpidNumSubFiles, VT_UI4},
- { NULL, kpidPrefix, VT_BSTR}
+ kpidNumSubDirs,
+ kpidNumSubFiles,
+ kpidPrefix
};
-static const UInt32 kNumProperties = sizeof(kProperties) / sizeof(kProperties[0]);
-
struct CArchiveItemPropertyTemp
{
UString Name;
@@ -232,10 +866,18 @@ STDMETHODIMP CAgentFolder::GetNumberOfProperties(UInt32 *numProps)
{
COM_TRY_BEGIN
RINOK(_agentSpec->GetArchive()->GetNumberOfProperties(numProps));
- *numProps += kNumProperties;
+ *numProps += ARRAY_SIZE(kProps);
if (!_flatMode)
(*numProps)--;
- if (!_agentSpec->_proxyArchive->ThereIsPathProp)
+ /*
+ bool thereIsPathProp = _proxyArchive2 ?
+ _agentSpec->_proxyArchive2->ThereIsPathProp :
+ _agentSpec->_proxyArchive->ThereIsPathProp;
+ */
+
+ // if there is kpidPath, we change kpidPath to kpidName
+ // if there is no kpidPath, we add kpidName.
+ if (!_agentSpec->ThereIsPathProp)
(*numProps)++;
return S_OK;
COM_TRY_END
@@ -246,7 +888,14 @@ STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *pro
COM_TRY_BEGIN
UInt32 numProps;
_agentSpec->GetArchive()->GetNumberOfProperties(&numProps);
- if (!_agentSpec->_proxyArchive->ThereIsPathProp)
+
+ /*
+ bool thereIsPathProp = _proxyArchive2 ?
+ _agentSpec->_proxyArchive2->ThereIsPathProp :
+ _agentSpec->_proxyArchive->ThereIsPathProp;
+ */
+
+ if (!_agentSpec->ThereIsPathProp)
{
if (index == 0)
{
@@ -266,40 +915,68 @@ STDMETHODIMP CAgentFolder::GetPropertyInfo(UInt32 index, BSTR *name, PROPID *pro
}
else
{
- const STATPROPSTG &srcItem = kProperties[index - numProps];
- *propID = srcItem.propid;
- *varType = srcItem.vt;
+ *propID = kProps[index - numProps];
+ *varType = k7z_PROPID_To_VARTYPE[(unsigned)*propID];
*name = 0;
}
return S_OK;
COM_TRY_END
}
-static const STATPROPSTG kFolderProps[] =
+static const PROPID kFolderProps[] =
{
- { NULL, kpidSize, VT_UI8},
- { NULL, kpidPackSize, VT_UI8},
- { NULL, kpidNumSubDirs, VT_UI4},
- { NULL, kpidNumSubFiles, VT_UI4},
- { NULL, kpidCRC, VT_UI4}
+ kpidSize,
+ kpidPackSize,
+ kpidNumSubDirs,
+ kpidNumSubFiles,
+ kpidCRC
};
-static const UInt32 kNumFolderProps = sizeof(kFolderProps) / sizeof(kFolderProps[0]);
-
STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
+
NWindows::NCOM::CPropVariant prop;
+
+ if (_proxyArchive2)
+ {
+ const CProxyFolder2 &folder = _proxyArchive2->Folders[_proxyFolderItem];
+ if (propID == kpidName)
+ {
+ if (folder.ArcIndex >= 0)
+ prop = _proxyArchive2->Files[folder.ArcIndex].Name;
+ }
+ else if (propID == kpidPath)
+ {
+ prop = _proxyArchive2->GetFullPathPrefix(_proxyFolderItem);
+ }
+ else switch (propID)
+ {
+ case kpidSize: prop = folder.Size; break;
+ case kpidPackSize: prop = folder.PackSize; break;
+ case kpidNumSubDirs: prop = folder.NumSubFolders; break;
+ case kpidNumSubFiles: prop = folder.NumSubFiles; break;
+ // case kpidName: prop = folder.Name; break;
+ // case kpidPath: prop = _proxyArchive2->GetFullPathPrefix(_proxyFolderItem); break;
+ case kpidType: prop = UString(L"7-Zip.") + _agentSpec->ArchiveType; break;
+ case kpidCRC: if (folder.CrcIsDefined) prop = folder.Crc; break;
+ }
+
+ }
+ else
+ {
+ const CProxyFolder &folder = _proxyArchive->Folders[_proxyFolderItem];
switch (propID)
{
- case kpidSize: prop = _proxyFolderItem->Size; break;
- case kpidPackSize: prop = _proxyFolderItem->PackSize; break;
- case kpidNumSubDirs: prop = _proxyFolderItem->NumSubFolders; break;
- case kpidNumSubFiles: prop = _proxyFolderItem->NumSubFiles; break;
- case kpidName: prop = _proxyFolderItem->Name; break;
- case kpidPath: prop = _proxyFolderItem->GetFullPathPrefix(); break;
+ case kpidSize: prop = folder.Size; break;
+ case kpidPackSize: prop = folder.PackSize; break;
+ case kpidNumSubDirs: prop = folder.NumSubFolders; break;
+ case kpidNumSubFiles: prop = folder.NumSubFiles; break;
+ case kpidName: prop = folder.Name; break;
+ case kpidPath: prop = _proxyArchive->GetFullPathPrefix(_proxyFolderItem); break;
case kpidType: prop = UString(L"7-Zip.") + _agentSpec->ArchiveType; break;
- case kpidCRC: if (_proxyFolderItem->CrcIsDefined) prop = _proxyFolderItem->Crc; break;
+ case kpidCRC: if (folder.CrcIsDefined) prop = folder.Crc; break;
+ }
}
prop.Detach(value);
return S_OK;
@@ -308,20 +985,73 @@ STDMETHODIMP CAgentFolder::GetFolderProperty(PROPID propID, PROPVARIANT *value)
STDMETHODIMP CAgentFolder::GetNumberOfFolderProperties(UInt32 *numProps)
{
- *numProps = kNumFolderProps;
+ *numProps = ARRAY_SIZE(kFolderProps);
return S_OK;
}
-STDMETHODIMP CAgentFolder::GetFolderPropertyInfo(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType)
+STDMETHODIMP CAgentFolder::GetFolderPropertyInfo IMP_IFolderFolder_GetProp(kFolderProps)
+
+STDMETHODIMP CAgentFolder::GetParent(UInt32 /* index */, UInt32 * /* parent */, UInt32 * /* parentType */)
{
- // if (index < kNumFolderProps)
+ return E_FAIL;
+}
+
+
+STDMETHODIMP CAgentFolder::GetNumRawProps(UInt32 *numProps)
+{
+ IArchiveGetRawProps *rawProps = _agentSpec->_archiveLink.GetArchiveGetRawProps();
+ if (rawProps)
+ return rawProps->GetNumRawProps(numProps);
+ *numProps = 0;
+ return S_OK;
+}
+
+STDMETHODIMP CAgentFolder::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID)
+{
+ IArchiveGetRawProps *rawProps = _agentSpec->_archiveLink.GetArchiveGetRawProps();
+ if (rawProps)
+ return rawProps->GetRawPropInfo(index, name, propID);
+ return E_FAIL;
+}
+
+STDMETHODIMP CAgentFolder::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)
+{
+ IArchiveGetRawProps *rawProps = _agentSpec->_archiveLink.GetArchiveGetRawProps();
+ if (rawProps)
{
- const STATPROPSTG &srcItem = kFolderProps[index];
- *propID = srcItem.propid;
- *varType = srcItem.vt;
- *name = 0;
- return S_OK;
+ unsigned arcIndex;
+ if (_proxyArchive2)
+ {
+ SET_realIndex_AND_folder_2
+ arcIndex = folder->SubFiles[realIndex];
+ }
+ else
+ {
+ SET_realIndex_AND_folder
+ if (realIndex < (UInt32)folder->Folders.Size())
+ {
+ const CProxyFolder &item = _proxyArchive->Folders[folder->Folders[realIndex]];
+ if (!item.IsLeaf)
+ {
+ *data = NULL;
+ *dataSize = 0;
+ *propType = 0;
+ return S_OK;
+ }
+ arcIndex = item.Index;
+ }
+ else
+ {
+ const CProxyFile &item = folder->Files[realIndex - folder->Folders.Size()];
+ arcIndex = item.Index;
+ }
+ }
+ return rawProps->GetRawProp(arcIndex, propID, data, dataSize, propType);
}
+ *data = NULL;
+ *dataSize = 0;
+ *propType = 0;
+ return S_OK;
}
STDMETHODIMP CAgentFolder::GetFolderArcProps(IFolderArcProps **object)
@@ -341,28 +1071,86 @@ STDMETHODIMP CAgentFolder::SetFlatMode(Int32 flatMode)
#endif
-void CAgentFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const
+int CAgentFolder::GetRealIndex(unsigned index) const
{
if (!_flatMode)
{
- _proxyFolderItem->GetRealIndices(indices, numItems, realIndices);
+ if (_proxyArchive2)
+ return _proxyArchive2->GetRealIndex(_proxyFolderItem, index);
+ else
+ return _proxyArchive->GetRealIndex(_proxyFolderItem, index);
+ }
+ {
+ const CProxyItem &item = _items[index];
+ if (_proxyArchive2)
+ {
+ const CProxyFolder2 *folder = &_proxyArchive2->Folders[item.ProxyFolderIndex];
+ return folder->SubFiles[item.Index];
+ }
+ else
+ {
+ const CProxyFolder *folder = &_proxyArchive->Folders[item.ProxyFolderIndex];
+ unsigned realIndex = item.Index;
+ if (realIndex < folder->Folders.Size())
+ {
+ const CProxyFolder &f = _proxyArchive->Folders[folder->Folders[realIndex]];
+ if (!f.IsLeaf)
+ return -1;
+ return f.Index;
+ }
+ return folder->Files[realIndex - folder->Folders.Size()].Index;
+ }
+ }
+}
+
+void CAgentFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, bool includeAltStreams, bool includeFolderSubItemsInFlatMode, CUIntVector &realIndices) const
+{
+ if (!_flatMode)
+ {
+ if (_proxyArchive2)
+ _proxyArchive2->GetRealIndices(_proxyFolderItem, indices, numItems, includeAltStreams, realIndices);
+ else
+ _proxyArchive->GetRealIndices(_proxyFolderItem, indices, numItems, realIndices);
return;
}
realIndices.Clear();
for (UInt32 i = 0; i < numItems; i++)
{
const CProxyItem &item = _items[indices[i]];
- const CProxyFolder *folder = item.Folder;
- UInt32 realIndex = item.Index;
- if (realIndex < (UInt32)folder->Folders.Size())
+ if (_proxyArchive2)
+ {
+ const CProxyFolder2 *folder = &_proxyArchive2->Folders[item.ProxyFolderIndex];
+ _proxyArchive2->AddRealIndices_of_ArcItem(folder->SubFiles[item.Index], includeAltStreams, realIndices);
continue;
- realIndices.Add(folder->Files[realIndex - folder->Folders.Size()].Index);
+ }
+ UInt32 arcIndex;
+ {
+ const CProxyFolder *folder = &_proxyArchive->Folders[item.ProxyFolderIndex];
+ unsigned realIndex = item.Index;
+ if (realIndex < folder->Folders.Size())
+ {
+ if (includeFolderSubItemsInFlatMode)
+ {
+ _proxyArchive->AddRealIndices(folder->Folders[realIndex], realIndices);
+ continue;
+ }
+ const CProxyFolder &f = _proxyArchive->Folders[folder->Folders[realIndex]];
+ if (!f.IsLeaf)
+ continue;
+ arcIndex = f.Index;
+ }
+ else
+ arcIndex = folder->Files[realIndex - folder->Folders.Size()].Index;
+ }
+ realIndices.Add(arcIndex);
}
HeapSort(&realIndices.Front(), realIndices.Size());
}
STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices,
UInt32 numItems,
+ Int32 includeAltStreams,
+ Int32 replaceAltStreamColon,
NExtract::NPathMode::EEnum pathMode,
NExtract::NOverwriteMode::EEnum overwriteMode,
const wchar_t *path,
@@ -373,7 +1161,10 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices,
CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
UStringVector pathParts;
- _proxyFolderItem->GetPathParts(pathParts);
+ if (_proxyArchive2)
+ _proxyArchive2->GetPathParts(_proxyFolderItem, pathParts);
+ else
+ _proxyArchive->GetPathParts(_proxyFolderItem, pathParts);
/*
if (_flatMode)
@@ -385,16 +1176,45 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices,
FString pathU;
if (path)
pathU = us2fs(path);
- extractCallbackSpec->Init(NULL, &_agentSpec->GetArc(),
+
+ CExtractNtOptions extractNtOptions;
+ extractNtOptions.AltStreams.Val = IntToBool(includeAltStreams); // change it!!!
+ extractNtOptions.AltStreams.Def = true;
+
+ extractNtOptions.ReplaceColonForAltStream = IntToBool(replaceAltStreamColon);
+
+ extractCallbackSpec->Init(
+ extractNtOptions,
+ NULL, &_agentSpec->GetArc(),
extractCallback2,
- false, testMode ? true : false, false,
+ false, // stdOutMode
+ IntToBool(testMode),
path ? pathU : FTEXT(""),
pathParts,
(UInt64)(Int64)-1);
+
+ if (_proxyArchive2)
+ extractCallbackSpec->SetBaseParentFolderIndex(_proxyArchive2->Folders[_proxyFolderItem].ArcIndex);
+
CUIntVector realIndices;
- GetRealIndices(indices, numItems, realIndices);
- return _agentSpec->GetArchive()->Extract(&realIndices.Front(),
+ GetRealIndices(indices, numItems, IntToBool(includeAltStreams),
+ false, // includeFolderSubItemsInFlatMode
+ realIndices); //
+
+ #ifdef SUPPORT_LINKS
+
+ if (!testMode)
+ {
+ RINOK(extractCallbackSpec->PrepareHardLinks(&realIndices));
+ }
+
+ #endif
+
+ HRESULT result = _agentSpec->GetArchive()->Extract(&realIndices.Front(),
realIndices.Size(), testMode, extractCallback);
+ if (result == S_OK)
+ result = extractCallbackSpec->SetDirsTimes();
+ return result;
COM_TRY_END
}
@@ -403,14 +1223,32 @@ STDMETHODIMP CAgentFolder::Extract(const UInt32 *indices,
CAgent::CAgent():
_proxyArchive(NULL),
+ _proxyArchive2(NULL),
+ _isDeviceFile(false),
_codecs(0)
{
}
CAgent::~CAgent()
{
- if (_proxyArchive != NULL)
+ if (_proxyArchive)
delete _proxyArchive;
+ if (_proxyArchive2)
+ delete _proxyArchive2;
+}
+
+bool CAgent::CanUpdate() const
+{
+ // FAR plugin uses empty agent to create new archive !!!
+ if (_archiveLink.Arcs.Size() == 0)
+ return true;
+ if (_isDeviceFile)
+ return false;
+ if (_archiveLink.Arcs.Size() != 1)
+ return false;
+ if (_archiveLink.Arcs[0].ErrorInfo.ThereIsTail)
+ return false;
+ return true;
}
STDMETHODIMP CAgent::Open(
@@ -423,12 +1261,14 @@ STDMETHODIMP CAgent::Open(
COM_TRY_BEGIN
_archiveFilePath = filePath;
NFile::NFind::CFileInfo fi;
+ _isDeviceFile = false;
if (!inStream)
{
if (!fi.Find(us2fs(_archiveFilePath)))
return ::GetLastError();
if (fi.IsDir())
return E_FAIL;
+ _isDeviceFile = fi.IsDevice;
}
CArcInfoEx archiverInfo0, archiverInfo1;
@@ -437,11 +1277,33 @@ STDMETHODIMP CAgent::Open(
_compressCodecsInfo = _codecs;
RINOK(_codecs->Load());
- CIntVector formatIndices;
- if (!_codecs->FindFormatForArchiveType(arcFormat, formatIndices))
+ CObjectVector<COpenType> types;
+ if (!ParseOpenTypes(*_codecs, arcFormat, types))
return S_FALSE;
- RINOK(_archiveLink.Open(_codecs, formatIndices, false, inStream, _archiveFilePath, openArchiveCallback));
+ /*
+ CObjectVector<COptionalOpenProperties> optProps;
+ if (Read_ShowDeleted())
+ {
+ COptionalOpenProperties &optPair = optProps.AddNew();
+ optPair.FormatName = L"ntfs";
+ // optPair.Props.AddNew().Name = L"LS";
+ optPair.Props.AddNew().Name = L"LD";
+ }
+ */
+
+ COpenOptions options;
+ options.props = NULL;
+ options.codecs = _codecs;
+ options.types = &types;
+ CIntVector exl;
+ options.excludedFormats = &exl;
+ options.stdInMode = false;
+ options.stream = inStream;
+ options.filePath = _archiveFilePath;
+ options.callback = openArchiveCallback;
+
+ RINOK(_archiveLink.Open(options));
CArc &arc = _archiveLink.Arcs.Back();
if (!inStream)
@@ -450,22 +1312,42 @@ STDMETHODIMP CAgent::Open(
arc.MTime = fi.MTime;
}
- ArchiveType = _codecs->Formats[arc.FormatIndex].Name;
- if (archiveType == 0)
- return S_OK;
- return StringToBstr(ArchiveType, archiveType);
+ ArchiveType = GetTypeOfArc(arc);
+ if (archiveType)
+ {
+ RINOK(StringToBstr(ArchiveType, archiveType));
+ }
+ return S_OK;
COM_TRY_END
}
STDMETHODIMP CAgent::ReOpen(IArchiveOpenCallback *openArchiveCallback)
{
COM_TRY_BEGIN
- if (_proxyArchive != NULL)
+ if (_proxyArchive2)
+ {
+ delete _proxyArchive2;
+ _proxyArchive2 = NULL;
+ }
+ if (_proxyArchive)
{
delete _proxyArchive;
_proxyArchive = NULL;
}
- RINOK(_archiveLink.ReOpen(_codecs, _archiveFilePath, openArchiveCallback));
+
+ CObjectVector<COpenType> incl;
+ CIntVector exl;
+
+ COpenOptions options;
+ options.props = NULL;
+ options.codecs = _codecs;
+ options.types = &incl;
+ options.excludedFormats = &exl;
+ options.stdInMode = false;
+ options.filePath = _archiveFilePath;
+ options.callback = openArchiveCallback;
+
+ RINOK(_archiveLink.ReOpen(options));
return ReadItems();
COM_TRY_END
}
@@ -486,9 +1368,38 @@ STDMETHODIMP CAgent::EnumProperties(IEnumSTATPROPSTG **EnumProperties)
HRESULT CAgent::ReadItems()
{
- if (_proxyArchive != NULL)
+ if (_proxyArchive || _proxyArchive2)
return S_OK;
- _proxyArchive = new CProxyArchive();
+
+ const CArc &arc = GetArc();
+ bool useProxy2 = (arc.GetRawProps && arc.IsTree);
+ // useProxy2 = false;
+
+ if (useProxy2)
+ _proxyArchive2 = new CProxyArchive2();
+ else
+ _proxyArchive = new CProxyArchive();
+
+ {
+ ThereIsPathProp = false;
+ UInt32 numProps;
+ arc.Archive->GetNumberOfProperties(&numProps);
+ for (UInt32 i = 0; i < numProps; i++)
+ {
+ CMyComBSTR name;
+ PROPID propID;
+ VARTYPE varType;
+ RINOK(arc.Archive->GetPropertyInfo(i, &name, &propID, &varType));
+ if (propID == kpidPath)
+ {
+ ThereIsPathProp = true;
+ break;
+ }
+ }
+ }
+
+ if (_proxyArchive2)
+ return _proxyArchive2->Load(GetArc(), NULL);
return _proxyArchive->Load(GetArc(), NULL);
}
@@ -498,13 +1409,12 @@ STDMETHODIMP CAgent::BindToRootFolder(IFolderFolder **resultFolder)
RINOK(ReadItems());
CAgentFolder *folderSpec = new CAgentFolder;
CMyComPtr<IFolderFolder> rootFolder = folderSpec;
- folderSpec->Init(_proxyArchive, &_proxyArchive->RootFolder, NULL, this);
+ folderSpec->Init(_proxyArchive, _proxyArchive2, 0, NULL, this);
*resultFolder = rootFolder.Detach();
return S_OK;
COM_TRY_END
}
-
STDMETHODIMP CAgent::Extract(
NExtract::NPathMode::EEnum pathMode,
NExtract::NOverwriteMode::EEnum overwriteMode,
@@ -516,12 +1426,31 @@ STDMETHODIMP CAgent::Extract(
CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback;
CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
extractCallbackSpec->InitForMulti(false, pathMode, overwriteMode);
- extractCallbackSpec->Init(NULL, &GetArc(),
+
+ CExtractNtOptions extractNtOptions;
+ extractNtOptions.AltStreams.Val = true; // change it!!!
+ extractNtOptions.AltStreams.Def = true; // change it!!!
+ extractNtOptions.ReplaceColonForAltStream = false; // change it!!!
+
+ extractCallbackSpec->Init(
+ extractNtOptions,
+ NULL, &GetArc(),
extractCallback2,
- false, testMode ? true : false, false,
+ false, // stdOutMode
+ IntToBool(testMode),
us2fs(path),
UStringVector(),
(UInt64)(Int64)-1);
+
+ #ifdef SUPPORT_LINKS
+
+ if (!testMode)
+ {
+ RINOK(extractCallbackSpec->PrepareHardLinks(NULL)); // NULL means all items
+ }
+
+ #endif
+
return GetArchive()->Extract(0, (UInt32)(Int32)-1, testMode, extractCallback);
COM_TRY_END
}
@@ -554,12 +1483,59 @@ STDMETHODIMP CAgent::GetArcProp(UInt32 level, PROPID propID, PROPVARIANT *value)
{
COM_TRY_BEGIN
NWindows::NCOM::CPropVariant prop;
- CArc &arc = _archiveLink.Arcs[level];
- switch (propID)
+ if (level > (UInt32)_archiveLink.Arcs.Size())
+ return E_INVALIDARG;
+ if (level == (UInt32)_archiveLink.Arcs.Size())
+ {
+ switch (propID)
+ {
+ case kpidPath:
+ if (!_archiveLink.NonOpen_ArcPath.IsEmpty())
+ prop = _archiveLink.NonOpen_ArcPath;
+ break;
+ case kpidErrorType:
+ if (_archiveLink.NonOpen_ErrorInfo.ErrorFormatIndex >= 0)
+ prop = _codecs->Formats[_archiveLink.NonOpen_ErrorInfo.ErrorFormatIndex].Name;
+ break;
+ }
+ }
+ else
{
- case kpidType: prop = GetTypeOfArc(arc); break;
- case kpidPath: prop = arc.Path; break;
- default: return arc.Archive->GetArchiveProperty(propID, value);
+ const CArc &arc = _archiveLink.Arcs[level];
+ switch (propID)
+ {
+ case kpidType: prop = GetTypeOfArc(arc); break;
+ case kpidPath: prop = arc.Path; break;
+ case kpidErrorType: if (arc.ErrorInfo.ErrorFormatIndex >= 0) prop = _codecs->Formats[arc.ErrorInfo.ErrorFormatIndex].Name; break;
+ case kpidErrorFlags:
+ {
+ UInt32 flags = arc.ErrorInfo.GetErrorFlags();
+ if (flags != 0)
+ prop = flags;
+ break;
+ }
+ case kpidWarningFlags:
+ {
+ UInt32 flags = arc.ErrorInfo.GetWarningFlags();
+ if (flags != 0)
+ prop = flags;
+ break;
+ }
+ case kpidOffset:
+ {
+ Int64 v = arc.GetGlobalOffset();
+ if (v != 0)
+ prop = v;
+ break;
+ }
+ case kpidTailSize:
+ {
+ if (arc.ErrorInfo.TailSize != 0)
+ prop = arc.ErrorInfo.TailSize;
+ break;
+ }
+ default: return arc.Archive->GetArchiveProperty(propID, value);
+ }
}
prop.Detach(value);
return S_OK;
diff --git a/CPP/7zip/UI/Agent/Agent.h b/CPP/7zip/UI/Agent/Agent.h
index cc92b0dd..e06f8576 100755..100644
--- a/CPP/7zip/UI/Agent/Agent.h
+++ b/CPP/7zip/UI/Agent/Agent.h
@@ -3,9 +3,9 @@
#ifndef __AGENT_AGENT_H
#define __AGENT_AGENT_H
-#include "Common/MyCom.h"
+#include "../../../Common/MyCom.h"
-#include "Windows/PropVariant.h"
+#include "../../../Windows/PropVariant.h"
#include "../Common/OpenArchive.h"
#include "../Common/UpdateAction.h"
@@ -27,8 +27,8 @@ DECL_INTERFACE(IArchiveFolderInternal, 0x01, 0xC)
struct CProxyItem
{
- const CProxyFolder *Folder;
- UInt32 Index;
+ unsigned ProxyFolderIndex;
+ unsigned Index;
};
class CAgent;
@@ -45,25 +45,33 @@ enum AGENT_OP
class CAgentFolder:
public IFolderFolder,
public IFolderProperties,
+ public IArchiveGetRawProps,
public IGetFolderArcProps,
+ public IFolderCompare,
+ public IFolderGetItemName,
public IArchiveFolder,
public IArchiveFolderInternal,
public IInArchiveGetStream,
+ // public IFolderSetReplaceAltStreamCharsMode,
#ifdef NEW_FOLDER_INTERFACE
public IFolderOperations,
public IFolderSetFlatMode,
#endif
public CMyUnknownImp
{
- void LoadFolder(const CProxyFolder *folder);
+ void LoadFolder(unsigned proxyFolderIndex);
public:
MY_QUERYINTERFACE_BEGIN2(IFolderFolder)
MY_QUERYINTERFACE_ENTRY(IFolderProperties)
+ MY_QUERYINTERFACE_ENTRY(IArchiveGetRawProps)
MY_QUERYINTERFACE_ENTRY(IGetFolderArcProps)
+ MY_QUERYINTERFACE_ENTRY(IFolderCompare)
+ MY_QUERYINTERFACE_ENTRY(IFolderGetItemName)
MY_QUERYINTERFACE_ENTRY(IArchiveFolder)
MY_QUERYINTERFACE_ENTRY(IArchiveFolderInternal)
MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream)
+ // MY_QUERYINTERFACE_ENTRY(IFolderSetReplaceAltStreamCharsMode)
#ifdef NEW_FOLDER_INTERFACE
MY_QUERYINTERFACE_ENTRY(IFolderOperations)
MY_QUERYINTERFACE_ENTRY(IFolderSetFlatMode)
@@ -71,21 +79,24 @@ public:
MY_QUERYINTERFACE_END
MY_ADDREF_RELEASE
- HRESULT BindToFolder(const CProxyFolder *folder, IFolderFolder **resultFolder);
- void GetRealIndices(const UINT32 *indices, UINT32 numItems, CUIntVector &realIndices) const;
+ HRESULT BindToFolder_Internal(unsigned proxyFolderIndex, IFolderFolder **resultFolder);
+ int GetRealIndex(unsigned index) const;
+ void GetRealIndices(const UInt32 *indices, UInt32 numItems,
+ bool includeAltStreams, bool includeFolderSubItemsInFlatMode, CUIntVector &realIndices) const;
+
+ // INTERFACE_FolderSetReplaceAltStreamCharsMode(;)
INTERFACE_FolderFolder(;)
INTERFACE_FolderProperties(;)
+ INTERFACE_IArchiveGetRawProps(;)
+ INTERFACE_IFolderGetItemName(;)
STDMETHOD(GetFolderArcProps)(IFolderArcProps **object);
+ STDMETHOD_(Int32, CompareItems)(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw);
+ int CompareItems2(UInt32 index1, UInt32 index2, PROPID propID, Int32 propIsRaw);
// IArchiveFolder
- STDMETHOD(Extract)(const UINT32 *indices, UINT32 numItems,
- NExtract::NPathMode::EEnum pathMode,
- NExtract::NOverwriteMode::EEnum overwriteMode,
- const wchar_t *path,
- Int32 testMode,
- IFolderArchiveExtractCallback *extractCallback);
+ INTERFACE_IArchiveFolder(;)
STDMETHOD(GetAgentFolder)(CAgentFolder **agentFolder);
@@ -97,14 +108,15 @@ public:
STDMETHOD(SetFlatMode)(Int32 flatMode);
#endif
- CAgentFolder(): _proxyFolderItem(NULL), _flatMode(0) {}
+ CAgentFolder(): _proxyFolderItem(0), _flatMode(0) /* , _replaceAltStreamCharsMode(0) */ {}
- void Init(const CProxyArchive *proxyHandler,
- const CProxyFolder *proxyFolderItem,
+ void Init(const CProxyArchive *proxyArc, const CProxyArchive2 *proxyArc2,
+ unsigned proxyFolderItem,
IFolderFolder *parentFolder,
CAgent *agent)
{
- _proxyArchive = proxyHandler;
+ _proxyArchive = proxyArc;
+ _proxyArchive2 = proxyArc2;
_proxyFolderItem = proxyFolderItem;
_parentFolder = parentFolder;
_agent = (IInFolderArchive *)agent;
@@ -114,25 +126,29 @@ public:
void GetPathParts(UStringVector &pathParts);
HRESULT CommonUpdateOperation(
AGENT_OP operation,
+ bool moveMode,
const wchar_t *newItemName,
const NUpdateArchive::CActionSet *actionSet,
- const UINT32 *indices, UINT32 numItems,
+ const UInt32 *indices, UInt32 numItems,
IFolderArchiveUpdateCallback *updateCallback100);
- UString GetPrefix(UInt32 index) const;
+ void GetPrefix(UInt32 index, UString &prefix) const;
UString GetName(UInt32 index) const;
UString GetFullPathPrefixPlusPrefix(UInt32 index) const;
public:
const CProxyArchive *_proxyArchive;
- const CProxyFolder *_proxyFolderItem;
+ const CProxyArchive2 *_proxyArchive2;
+ // const CProxyFolder *_proxyFolderItem;
+ unsigned _proxyFolderItem;
CMyComPtr<IFolderFolder> _parentFolder;
CMyComPtr<IInFolderArchive> _agent;
CAgent *_agentSpec;
CRecordVector<CProxyItem> _items;
bool _flatMode;
+ // Int32 _replaceAltStreamCharsMode;
private:
};
@@ -163,7 +179,7 @@ public:
INTERFACE_IOutFolderArchive(;)
HRESULT CommonUpdate(ISequentialOutStream *outArchiveStream,
- int numUpdateItems, IArchiveUpdateCallback *updateCallback);
+ unsigned numUpdateItems, IArchiveUpdateCallback *updateCallback);
HRESULT CreateFolder(ISequentialOutStream *outArchiveStream,
const wchar_t *folderName, IFolderArchiveUpdateCallback *updateCallback100);
@@ -177,7 +193,7 @@ public:
IFolderArchiveUpdateCallback *updateCallback100);
// ISetProperties
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties);
+ STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
#endif
CCodecs *_codecs;
@@ -189,8 +205,10 @@ private:
HRESULT ReadItems();
public:
CProxyArchive *_proxyArchive;
+ CProxyArchive2 *_proxyArchive2;
CArchiveLink _archiveLink;
+ bool ThereIsPathProp;
UString ArchiveType;
@@ -201,6 +219,7 @@ public:
CAgentFolder *_agentFolder;
UString _archiveFilePath;
+ bool _isDeviceFile;
#ifndef EXTRACT_ONLY
CObjectVector<UString> m_PropNames;
@@ -209,28 +228,50 @@ public:
const CArc &GetArc() const { return _archiveLink.Arcs.Back(); }
IInArchive *GetArchive() const { if ( _archiveLink.Arcs.IsEmpty()) return 0; return GetArc().Archive; }
- bool CanUpdate() const { return _archiveLink.Arcs.Size() <= 1; }
+ bool CanUpdate() const;
+
+ UString GetTypeOfArc(const CArc &arc) const
+ {
+ if (arc.FormatIndex < 0)
+ return L"Parser";
+ return _codecs->GetFormatNamePtr(arc.FormatIndex);
+ }
- UString GetTypeOfArc(const CArc &arc) const { return _codecs->Formats[arc.FormatIndex].Name; }
UString GetErrorMessage() const
{
UString s;
for (int i = _archiveLink.Arcs.Size() - 1; i >= 0; i--)
{
const CArc &arc = _archiveLink.Arcs[i];
- if (arc.ErrorMessage.IsEmpty())
- continue;
- if (!s.IsEmpty())
- s += L"--------------------\n";
- s += arc.ErrorMessage;
- s += L"\n\n[";
- s += GetTypeOfArc(arc);
- s += L"] ";
- s += arc.Path;
- s += L"\n";
+
+ UString s2;
+ if (arc.ErrorInfo.ErrorFormatIndex >= 0)
+ s2 = L"Can not open the file as [" + _codecs->Formats[arc.ErrorInfo.ErrorFormatIndex].Name + L"] archive";
+
+ if (!arc.ErrorInfo.ErrorMessage.IsEmpty())
+ {
+ if (!s2.IsEmpty())
+ s2 += L"\n";
+ s2 += L"\n[";
+ s2 += GetTypeOfArc(arc);
+ s2 += L"]: ";
+ s2 += arc.ErrorInfo.ErrorMessage;
+ }
+ if (!s2.IsEmpty())
+ {
+ if (!s.IsEmpty())
+ s += L"--------------------\n";
+ s += arc.Path;
+ s += L"\n";
+ s += s2;
+ s += L"\n";
+ }
}
return s;
}
+
+ void KeepModeForNextOpen() { _archiveLink.KeepModeForNextOpen(); }
+
};
#ifdef NEW_FOLDER_INTERFACE
diff --git a/CPP/7zip/UI/Agent/AgentOut.cpp b/CPP/7zip/UI/Agent/AgentOut.cpp
index 17f5443a..3fd25670 100755..100644
--- a/CPP/7zip/UI/Agent/AgentOut.cpp
+++ b/CPP/7zip/UI/Agent/AgentOut.cpp
@@ -2,9 +2,9 @@
#include "StdAfx.h"
-#include "Windows/FileDir.h"
-#include "Windows/FileName.h"
-#include "Windows/Time.h"
+#include "../../../Windows/FileDir.h"
+#include "../../../Windows/FileName.h"
+#include "../../../Windows/TimeUtils.h"
#include "../../Compress/CopyCoder.h"
@@ -32,7 +32,10 @@ STDMETHODIMP CAgent::SetFolder(IFolderFolder *folder)
RINOK(archiveFolderInternal->GetAgentFolder(&_agentFolder));
}
- _archiveNamePrefix = _agentFolder->_proxyFolderItem->GetFullPathPrefix();
+ if (_proxyArchive2)
+ _archiveNamePrefix = _proxyArchive2->GetFullPathPrefix(_agentFolder->_proxyFolderItem);
+ else
+ _archiveNamePrefix = _proxyArchive->GetFullPathPrefix(_agentFolder->_proxyFolderItem);
return S_OK;
}
@@ -40,10 +43,9 @@ STDMETHODIMP CAgent::SetFiles(const wchar_t *folderPrefix,
const wchar_t **names, UInt32 numNames)
{
_folderPrefix = us2fs(folderPrefix);
- _names.Clear();
- _names.Reserve(numNames);
+ _names.ClearAndReserve(numNames);
for (UInt32 i = 0; i < numNames; i++)
- _names.Add(us2fs(names[i]));
+ _names.AddInReserved(us2fs(names[i]));
return S_OK;
}
@@ -52,7 +54,7 @@ static HRESULT EnumerateArchiveItems(CAgent *agent,
const UString &prefix,
CObjectVector<CArcItem> &arcItems)
{
- int i;
+ unsigned i;
for (i = 0; i < item.Files.Size(); i++)
{
const CProxyFile &fileItem = item.Files[i];
@@ -67,7 +69,7 @@ static HRESULT EnumerateArchiveItems(CAgent *agent,
}
for (i = 0; i < item.Folders.Size(); i++)
{
- const CProxyFolder &dirItem = item.Folders[i];
+ const CProxyFolder &dirItem = agent->_proxyArchive->Folders[item.Folders[i]];
UString fullName = prefix + dirItem.Name;
if (dirItem.IsLeaf)
{
@@ -85,6 +87,38 @@ static HRESULT EnumerateArchiveItems(CAgent *agent,
return S_OK;
}
+static HRESULT EnumerateArchiveItems2(const CAgent *agent,
+ const CProxyArchive2 *proxyArchive2,
+ unsigned folderIndex,
+ const UString &prefix,
+ CObjectVector<CArcItem> &arcItems)
+{
+ const CProxyFolder2 &folder = proxyArchive2->Folders[folderIndex];
+ FOR_VECTOR (i, folder.SubFiles)
+ {
+ unsigned arcIndex = folder.SubFiles[i];
+ const CProxyFile2 &file = proxyArchive2->Files[arcIndex];
+ CArcItem ai;
+ ai.IndexInServer = arcIndex;
+ ai.Name = prefix + file.Name;
+ ai.Censored = true; // test it
+ RINOK(agent->GetArc().GetItemMTime(arcIndex, ai.MTime, ai.MTimeDefined));
+ ai.IsDir = file.IsDir();
+ ai.SizeDefined = false;
+ if (!ai.IsDir)
+ {
+ RINOK(agent->GetArc().GetItemSize(arcIndex, ai.Size, ai.SizeDefined));
+ ai.IsDir = false;
+ }
+ arcItems.Add(ai);
+ if (ai.IsDir)
+ {
+ RINOK(EnumerateArchiveItems2(agent, proxyArchive2, file.FolderIndex, ai.Name + UString(WCHAR_PATH_SEPARATOR), arcItems));
+ }
+ }
+ return S_OK;
+}
+
struct CAgUpCallbackImp: public IUpdateProduceCallback
{
const CObjectVector<CArcItem> *_arcItems;
@@ -100,7 +134,20 @@ HRESULT CAgUpCallbackImp::ShowDeleteFile(int 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->Archive = arc.Archive;
+ upd->GetRawProps = arc.GetRawProps;
+ upd->GetRootProps = arc.GetRootProps;
+}
+
STDMETHODIMP CAgent::DoOperation(
+ FStringVector *requestedPaths,
+ FStringVector *processedPaths,
CCodecs *codecs,
int formatIndex,
ISequentialOutStream *outArchiveStream,
@@ -111,7 +158,7 @@ STDMETHODIMP CAgent::DoOperation(
if (!CanUpdate())
return E_NOTIMPL;
NUpdateArchive::CActionSet actionSet;
- int i;
+ unsigned i;
for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
actionSet.StateActions[i] = (NUpdateArchive::NPairAction::EEnum)stateActions[i];
@@ -120,11 +167,9 @@ STDMETHODIMP CAgent::DoOperation(
{
FString folderPrefix = _folderPrefix;
NFile::NName::NormalizeDirPathPrefix(folderPrefix);
- FStringVector errorPaths;
- CRecordVector<DWORD> errorCodes;
- dirItems.EnumerateDirItems2(folderPrefix, _archiveNamePrefix, _names, errorPaths, errorCodes);
- if (errorCodes.Size() > 0)
- return errorCodes.Front();
+ dirItems.EnumerateItems2(folderPrefix, _archiveNamePrefix, _names, requestedPaths);
+ if (dirItems.ErrorCodes.Size() > 0)
+ return dirItems.ErrorCodes.Front();
}
CMyComPtr<IOutArchive> outArchive;
@@ -170,7 +215,14 @@ STDMETHODIMP CAgent::DoOperation(
if (GetArchive())
{
RINOK(ReadItems());
- EnumerateArchiveItems(this, _proxyArchive->RootFolder, L"", arcItems);
+ if (_proxyArchive2)
+ {
+ RINOK(EnumerateArchiveItems2(this, _proxyArchive2, 0, L"", arcItems));
+ }
+ else
+ {
+ RINOK(EnumerateArchiveItems(this, _proxyArchive->Folders[0], L"", arcItems));
+ }
}
CRecordVector<CUpdatePair2> updatePairs2;
@@ -200,9 +252,21 @@ STDMETHODIMP CAgent::DoOperation(
updateCallbackSpec->DirItems = &dirItems;
updateCallbackSpec->ArcItems = &arcItems;
updateCallbackSpec->UpdatePairs = &updatePairs2;
- updateCallbackSpec->Archive = GetArchive();
+
+ SetInArchiveInterfaces(this, updateCallbackSpec);
+
updateCallbackSpec->Callback = &updateCallbackAgent;
+ CByteBuffer processedItems;
+ if (processedPaths)
+ {
+ unsigned num = dirItems.Items.Size();
+ processedItems.Alloc(num);
+ for (i = 0; i < num; i++)
+ processedItems[i] = 0;
+ updateCallbackSpec->ProcessedItemsStatuses = processedItems;
+ }
+
CMyComPtr<ISetProperties> setProperties;
if (outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties) == S_OK)
{
@@ -219,7 +283,7 @@ STDMETHODIMP CAgent::DoOperation(
CPropVariant *propValues = new CPropVariant[m_PropValues.Size()];
try
{
- for (int i = 0; i < m_PropValues.Size(); i++)
+ FOR_VECTOR (i, m_PropValues)
propValues[i] = m_PropValues[i];
RINOK(setProperties->SetProperties(&names.Front(), propValues, names.Size()));
}
@@ -244,17 +308,27 @@ STDMETHODIMP CAgent::DoOperation(
RINOK(NCompress::CopyStream(sfxStream, outArchiveStream, NULL));
}
- return outArchive->UpdateItems(outArchiveStream, updatePairs2.Size(),updateCallback);
+ HRESULT res = outArchive->UpdateItems(outArchiveStream, updatePairs2.Size(), updateCallback);
+ if (res == S_OK && processedPaths)
+ {
+ for (i = 0; i < dirItems.Items.Size(); i++)
+ if (processedItems[i] != 0)
+ processedPaths->Add(us2fs(dirItems.GetPhyPath(i)));
+ }
+ return res;
}
-STDMETHODIMP CAgent::DoOperation2(ISequentialOutStream *outArchiveStream,
+STDMETHODIMP CAgent::DoOperation2(
+ FStringVector *requestedPaths,
+ FStringVector *processedPaths,
+ ISequentialOutStream *outArchiveStream,
const Byte *stateActions, const wchar_t *sfxModule, IFolderArchiveUpdateCallback *updateCallback100)
{
- return DoOperation(_codecs, -1, outArchiveStream, stateActions, sfxModule, updateCallback100);
+ return DoOperation(requestedPaths, processedPaths, _codecs, -1, outArchiveStream, stateActions, sfxModule, updateCallback100);
}
HRESULT CAgent::CommonUpdate(ISequentialOutStream *outArchiveStream,
- int numUpdateItems, IArchiveUpdateCallback *updateCallback)
+ unsigned numUpdateItems, IArchiveUpdateCallback *updateCallback)
{
if (!CanUpdate())
return E_NOTIMPL;
@@ -276,8 +350,11 @@ STDMETHODIMP CAgent::DeleteItems(ISequentialOutStream *outArchiveStream,
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
CUIntVector realIndices;
- _agentFolder->GetRealIndices(indices, numItems, realIndices);
- int curIndex = 0;
+ _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));
for (UInt32 i = 0; i < numItemsInArchive; i++)
@@ -289,13 +366,13 @@ STDMETHODIMP CAgent::DeleteItems(ISequentialOutStream *outArchiveStream,
continue;
}
CUpdatePair2 up2;
- up2.NewData = up2.NewProps = false;
- up2.IsAnti = false; // check it. Maybe it can be undefined
- up2.ArcIndex = i;
+ up2.SetAs_NoChangeArcItem(i);
updatePairs.Add(up2);
}
updateCallbackSpec->UpdatePairs = &updatePairs;
- updateCallbackSpec->Archive = GetArchive();
+
+ SetInArchiveInterfaces(this, updateCallbackSpec);
+
updateCallbackSpec->Callback = &updateCallbackAgent;
return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
}
@@ -317,14 +394,12 @@ HRESULT CAgent::CreateFolder(ISequentialOutStream *outArchiveStream,
for (UInt32 i = 0; i < numItemsInArchive; i++)
{
CUpdatePair2 up2;
- up2.NewData = up2.NewProps = false;
- up2.IsAnti = false; // check it.
- up2.ArcIndex = i;
+ up2.SetAs_NoChangeArcItem(i);
updatePairs.Add(up2);
}
CUpdatePair2 up2;
up2.NewData = up2.NewProps = true;
- up2.IsAnti = false;
+ up2.UseArcProps = false;
up2.DirIndex = 0;
updatePairs.Add(up2);
@@ -335,7 +410,10 @@ HRESULT CAgent::CreateFolder(ISequentialOutStream *outArchiveStream,
di.Attrib = FILE_ATTRIBUTE_DIRECTORY;
di.Size = 0;
- di.Name = _agentFolder->_proxyFolderItem->GetFullPathPrefix() + folderName;
+ if (_proxyArchive2)
+ di.Name = _proxyArchive2->GetFullPathPrefix(_agentFolder->_proxyFolderItem) + folderName;
+ else
+ di.Name = _proxyArchive->GetFullPathPrefix(_agentFolder->_proxyFolderItem) + folderName;
FILETIME ft;
NTime::GetCurUtcFileTime(ft);
@@ -346,7 +424,9 @@ HRESULT CAgent::CreateFolder(ISequentialOutStream *outArchiveStream,
updateCallbackSpec->Callback = &updateCallbackAgent;
updateCallbackSpec->DirItems = &dirItems;
updateCallbackSpec->UpdatePairs = &updatePairs;
- updateCallbackSpec->Archive = GetArchive();
+
+ SetInArchiveInterfaces(this, updateCallbackSpec);
+
return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
}
@@ -359,6 +439,8 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream,
return E_NOTIMPL;
if (numItems != 1)
return E_INVALIDARG;
+ if (!_archiveLink.IsOpen)
+ return E_FAIL;
CRecordVector<CUpdatePair2> updatePairs;
CUpdateCallbackAgent updateCallbackAgent;
updateCallbackAgent.SetCallback(updateCallback100);
@@ -366,7 +448,12 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream,
CMyComPtr<IArchiveUpdateCallback> updateCallback(updateCallbackSpec);
CUIntVector realIndices;
- _agentFolder->GetRealIndices(indices, numItems, realIndices);
+ _agentFolder->GetRealIndices(indices, numItems,
+ true, // includeAltStreams
+ true, // includeFolderSubItemsInFlatMode
+ realIndices);
+
+ int mainRealIndex = _agentFolder->GetRealIndex(indices[0]);
UString fullPrefix = _agentFolder->GetFullPathPrefixPlusPrefix(indices[0]);
UString oldItemPath = fullPrefix + _agentFolder->GetName(indices[0]);
@@ -374,41 +461,37 @@ HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream,
UStringVector newNames;
- int curIndex = 0;
+ 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)
{
- CUpdatePair2 up2;
- up2.NewData = false;
up2.NewProps = true;
- RINOK(GetArc().IsItemAnti(i, up2.IsAnti));
- up2.ArcIndex = i;
+ RINOK(GetArc().IsItemAnti(i, up2.IsAnti)); // it must work without that line too.
UString oldFullPath;
- RINOK(GetArc().GetItemPath(i, oldFullPath));
+ RINOK(GetArc().GetItemPath2(i, oldFullPath));
- if (oldItemPath.CompareNoCase(oldFullPath.Left(oldItemPath.Length())) != 0)
+ if (MyStringCompareNoCase_N(oldFullPath, oldItemPath, oldItemPath.Len()) != 0)
return E_INVALIDARG;
- up2.NewNameIndex = newNames.Add(newItemPath + oldFullPath.Mid(oldItemPath.Length()));
- updatePairs.Add(up2);
+ up2.NewNameIndex = newNames.Add(newItemPath + oldFullPath.Ptr(oldItemPath.Len()));
+ up2.IsMainRenameItem = (mainRealIndex == (int)i);
curIndex++;
- continue;
}
- CUpdatePair2 up2;
- up2.NewData = up2.NewProps = false;
- up2.IsAnti = false;
- up2.ArcIndex = i;
updatePairs.Add(up2);
}
updateCallbackSpec->Callback = &updateCallbackAgent;
updateCallbackSpec->UpdatePairs = &updatePairs;
updateCallbackSpec->NewNames = &newNames;
- updateCallbackSpec->Archive = GetArchive();
+
+ SetInArchiveInterfaces(this, updateCallbackSpec);
+
return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
}
@@ -428,7 +511,10 @@ HRESULT CAgent::UpdateOneFile(ISequentialOutStream *outArchiveStream,
UInt32 realIndex;
{
CUIntVector realIndices;
- _agentFolder->GetRealIndices(indices, numItems, 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];
@@ -437,9 +523,7 @@ HRESULT CAgent::UpdateOneFile(ISequentialOutStream *outArchiveStream,
{
FStringVector filePaths;
filePaths.Add(us2fs(diskFilePath));
- FStringVector errorPaths;
- CRecordVector<DWORD> errorCodes;
- dirItems.EnumerateDirItems2(FString(), UString(), filePaths, errorPaths, errorCodes);
+ dirItems.EnumerateItems2(FString(), UString(), filePaths, NULL);
if (dirItems.Items.Size() != 1)
return E_FAIL;
}
@@ -449,32 +533,31 @@ HRESULT CAgent::UpdateOneFile(ISequentialOutStream *outArchiveStream,
for (UInt32 i = 0; i < numItemsInArchive; i++)
{
CUpdatePair2 up2;
- up2.ArcIndex = i;
- up2.IsAnti = false;
- up2.NewData = false;
- up2.NewProps = false;
+ up2.SetAs_NoChangeArcItem(i);
if (realIndex == i)
{
up2.DirIndex = 0;
up2.NewData = true;
up2.NewProps = true;
+ up2.UseArcProps = false;
}
updatePairs.Add(up2);
}
updateCallbackSpec->DirItems = &dirItems;
updateCallbackSpec->Callback = &updateCallbackAgent;
updateCallbackSpec->UpdatePairs = &updatePairs;
- updateCallbackSpec->Archive = GetArchive();
+
+ SetInArchiveInterfaces(this, updateCallbackSpec);
+
updateCallbackSpec->KeepOriginalItemNames = true;
return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
}
-STDMETHODIMP CAgent::SetProperties(const wchar_t **names,
- const PROPVARIANT *values, Int32 numProperties)
+STDMETHODIMP CAgent::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
{
m_PropNames.Clear();
m_PropValues.Clear();
- for (int i = 0; i < numProperties; i++)
+ for (UInt32 i = 0; i < numProps; i++)
{
m_PropNames.Add(names[i]);
m_PropValues.Add(values[i]);
diff --git a/CPP/7zip/UI/Agent/AgentProxy.cpp b/CPP/7zip/UI/Agent/AgentProxy.cpp
index ce9b3bfb..a31a904b 100755..100644
--- a/CPP/7zip/UI/Agent/AgentProxy.cpp
+++ b/CPP/7zip/UI/Agent/AgentProxy.cpp
@@ -3,17 +3,21 @@
#include "StdAfx.h"
#include "../../../../C/Sort.h"
+#include "../../../../C/CpuArch.h"
-#include "Windows/PropVariant.h"
-#include "Windows/PropVariantConversions.h"
+#include "../../../Common/Wildcard.h"
+
+#include "../../../Windows/PropVariant.h"
+#include "../../../Windows/PropVariantConv.h"
#include "AgentProxy.h"
using namespace NWindows;
-int CProxyFolder::FindDirSubItemIndex(const UString &name, int &insertPos) const
+int CProxyArchive::FindDirSubItemIndex(unsigned folderIndex, const UString &name, unsigned &insertPos) const
{
- int left = 0, right = Folders.Size();
+ const CRecordVector<unsigned> &subFolders = Folders[folderIndex].Folders;
+ unsigned left = 0, right = subFolders.Size();
for (;;)
{
if (left == right)
@@ -21,10 +25,11 @@ int CProxyFolder::FindDirSubItemIndex(const UString &name, int &insertPos) const
insertPos = left;
return -1;
}
- int mid = (left + right) / 2;
- int compare = name.CompareNoCase(Folders[mid].Name);
+ unsigned mid = (left + right) / 2;
+ unsigned folderIndex = subFolders[mid];
+ int compare = CompareFileNames(name, Folders[folderIndex].Name);
if (compare == 0)
- return mid;
+ return folderIndex;
if (compare < 0)
right = mid;
else
@@ -32,40 +37,41 @@ int CProxyFolder::FindDirSubItemIndex(const UString &name, int &insertPos) const
}
}
-int CProxyFolder::FindDirSubItemIndex(const UString &name) const
+int CProxyArchive::FindDirSubItemIndex(unsigned folderIndex, const UString &name) const
{
- int insertPos;
- return FindDirSubItemIndex(name, insertPos);
+ unsigned insertPos;
+ return FindDirSubItemIndex(folderIndex, name, insertPos);
}
void CProxyFolder::AddFileSubItem(UInt32 index, const UString &name)
{
- Files.Add(CProxyFile());
- Files.Back().Name = name;
- Files.Back().Index = index;
+ CProxyFile &f = Files.AddNew();
+ f.Index = index;
+ f.Name = name;
}
-CProxyFolder* CProxyFolder::AddDirSubItem(UInt32 index, bool leaf, const UString &name)
+unsigned CProxyArchive::AddDirSubItem(unsigned folderIndex, UInt32 index, bool leaf, const UString &name)
{
- int insertPos;
- int folderIndex = FindDirSubItemIndex(name, insertPos);
- if (folderIndex >= 0)
+ unsigned insertPos;
+ int subFolderIndex = FindDirSubItemIndex(folderIndex, name, insertPos);
+ if (subFolderIndex >= 0)
{
- CProxyFolder *item = &Folders[folderIndex];
+ CProxyFolder &item = Folders[subFolderIndex];
if (leaf)
{
- item->Index = index;
- item->IsLeaf = true;
+ item.Index = index;
+ item.IsLeaf = true;
}
- return item;
+ return subFolderIndex;
}
- Folders.Insert(insertPos, CProxyFolder());
- CProxyFolder *item = &Folders[insertPos];
- item->Name = name;
- item->Index = index;
- item->Parent = this;
- item->IsLeaf = leaf;
- return item;
+ 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;
}
void CProxyFolder::Clear()
@@ -74,51 +80,71 @@ void CProxyFolder::Clear()
Files.Clear();
}
-void CProxyFolder::GetPathParts(UStringVector &pathParts) const
+void CProxyArchive::GetPathParts(int folderIndex, UStringVector &pathParts) const
{
pathParts.Clear();
- const CProxyFolder *current = this;
- while (current->Parent != NULL)
+ while (folderIndex >= 0)
{
- pathParts.Insert(0, current->Name);
- current = current->Parent;
+ const CProxyFolder &folder = Folders[folderIndex];
+ folderIndex = folder.Parent;
+ if (folderIndex < 0)
+ break;
+ pathParts.Insert(0, folder.Name);
}
}
-UString CProxyFolder::GetFullPathPrefix() const
+UString CProxyArchive::GetFullPathPrefix(int folderIndex) const
{
UString result;
- const CProxyFolder *current = this;
- while (current->Parent != NULL)
+ while (folderIndex >= 0)
{
- result = current->Name + UString(WCHAR_PATH_SEPARATOR) + result;
- current = current->Parent;
+ const CProxyFolder &folder = Folders[folderIndex];
+ folderIndex = folder.Parent;
+ if (folderIndex < 0)
+ break;
+ result = folder.Name + UString(WCHAR_PATH_SEPARATOR) + result;
}
return result;
}
-void CProxyFolder::AddRealIndices(CUIntVector &realIndices) const
+void CProxyArchive::AddRealIndices(unsigned folderIndex, CUIntVector &realIndices) const
{
- if (IsLeaf)
- realIndices.Add(Index);
- int i;
- for (i = 0; i < Folders.Size(); i++)
- Folders[i].AddRealIndices(realIndices);
- for (i = 0; i < Files.Size(); i++)
- realIndices.Add(Files[i].Index);
+ const CProxyFolder &folder = Folders[folderIndex];
+ if (folder.IsLeaf)
+ realIndices.Add(folder.Index);
+ 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);
+}
+
+int CProxyArchive::GetRealIndex(unsigned folderIndex, unsigned index) const
+{
+ const CProxyFolder &folder = Folders[folderIndex];
+ unsigned numDirItems = folder.Folders.Size();
+ if (index < numDirItems)
+ {
+ const CProxyFolder &f = Folders[folder.Folders[index]];
+ if (f.IsLeaf)
+ return f.Index;
+ return -1;
+ }
+ return folder.Files[index - numDirItems].Index;
}
-void CProxyFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const
+void CProxyArchive::GetRealIndices(unsigned folderIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const
{
+ const CProxyFolder &folder = Folders[folderIndex];
realIndices.Clear();
for (UInt32 i = 0; i < numItems; i++)
{
- int index = indices[i];
- int numDirItems = Folders.Size();
+ UInt32 index = indices[i];
+ unsigned numDirItems = folder.Folders.Size();
if (index < numDirItems)
- Folders[index].AddRealIndices(realIndices);
+ AddRealIndices(folder.Folders[index], realIndices);
else
- realIndices.Add(Files[index - numDirItems].Index);
+ realIndices.Add(folder.Files[index - numDirItems].Index);
}
HeapSort(&realIndices.Front(), realIndices.Size());
}
@@ -126,111 +152,426 @@ void CProxyFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntV
///////////////////////////////////////////////
// CProxyArchive
-static UInt64 GetSize(IInArchive *archive, UInt32 index, PROPID propID)
+static bool GetSize(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &size)
{
+ size = 0;
NCOM::CPropVariant prop;
- if (archive->GetProperty(index, propID, &prop) == S_OK)
- if (prop.vt != VT_EMPTY)
- return ConvertPropVariantToUInt64(prop);
- return 0;
+ if (archive->GetProperty(index, propID, &prop) != S_OK)
+ throw 20120228;
+ return ConvertPropVariantToUInt64(prop, size);
}
-void CProxyFolder::CalculateSizes(IInArchive *archive)
+void CProxyArchive::CalculateSizes(unsigned folderIndex, IInArchive *archive)
{
- Size = PackSize = 0;
- NumSubFolders = Folders.Size();
- NumSubFiles = Files.Size();
- CrcIsDefined = true;
- Crc = 0;
- int i;
- for (i = 0; i < Files.Size(); i++)
+ 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;
+ unsigned i;
+ for (i = 0; i < folder.Files.Size(); i++)
{
- UInt32 index = Files[i].Index;
- Size += GetSize(archive, index, kpidSize);
- PackSize += GetSize(archive, index, kpidPackSize);
+ UInt32 index = folder.Files[i].Index;
+ UInt64 size, packSize;
+ bool sizeDefined = GetSize(archive, index, kpidSize, size);
+ folder.Size += size;
+ GetSize(archive, index, kpidPackSize, packSize);
+ folder.PackSize += packSize;
{
NCOM::CPropVariant prop;
- if (archive->GetProperty(index, kpidCRC, &prop) == S_OK && prop.vt == VT_UI4)
- Crc += prop.ulVal;
+ if (archive->GetProperty(index, kpidCRC, &prop) == S_OK)
+ {
+ if (prop.vt == VT_UI4)
+ folder.Crc += prop.ulVal;
+ else if (prop.vt != VT_EMPTY || size != 0 || !sizeDefined)
+ folder.CrcIsDefined = false;
+ }
else
- CrcIsDefined = false;
+ folder.CrcIsDefined = false;
}
}
- for (i = 0; i < Folders.Size(); i++)
+ for (i = 0; i < folder.Folders.Size(); i++)
{
- CProxyFolder &f = Folders[i];
- f.CalculateSizes(archive);
- Size += f.Size;
- PackSize += f.PackSize;
- NumSubFiles += f.NumSubFiles;
- NumSubFolders += f.NumSubFolders;
- Crc += f.Crc;
+ 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;
if (!f.CrcIsDefined)
- CrcIsDefined = false;
+ folder.CrcIsDefined = false;
}
}
HRESULT CProxyArchive::Load(const CArc &arc, IProgress *progress)
{
- RootFolder.Clear();
+ /*
+ DWORD tickCount = GetTickCount();
+ for (int ttt = 0; ttt < 1000; ttt++) {
+ */
+
+ Folders.Clear();
+ Folders.AddNew();
IInArchive *archive = arc.Archive;
- {
- ThereIsPathProp = false;
- UInt32 numProps;
- archive->GetNumberOfProperties(&numProps);
- for (UInt32 i = 0; i < numProps; i++)
- {
- CMyComBSTR name;
- PROPID propID;
- VARTYPE varType;
- RINOK(archive->GetPropertyInfo(i, &name, &propID, &varType));
- if (propID == kpidPath)
- {
- ThereIsPathProp = true;
- break;
- }
- }
- }
UInt32 numItems;
RINOK(archive->GetNumberOfItems(&numItems));
- if (progress != NULL)
- {
- UInt64 totalItems = numItems;
- RINOK(progress->SetTotal(totalItems));
- }
+ if (progress)
+ RINOK(progress->SetTotal(numItems));
+ UString filePath;
UString fileName;
for (UInt32 i = 0; i < numItems; i++)
{
- if (progress != NULL && (i & 0xFFFFF) == 0)
+ if (progress && (i & 0xFFFFF) == 0)
{
UInt64 currentItemIndex = i;
RINOK(progress->SetCompleted(&currentItemIndex));
}
- UString filePath;
RINOK(arc.GetItemPath(i, filePath));
- CProxyFolder *curItem = &RootFolder;
- int len = filePath.Length();
+ unsigned curItem = 0;
+ unsigned len = filePath.Len();
fileName.Empty();
- for (int j = 0; j < len; j++)
+
+ /*
+ 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]");
+ }
+ */
+
+ for (unsigned j = 0; j < len; j++)
{
wchar_t c = filePath[j];
if (c == WCHAR_PATH_SEPARATOR || c == L'/')
{
- curItem = curItem->AddDirSubItem((UInt32)(Int32)-1, false, fileName);
+ curItem = AddDirSubItem(curItem, (UInt32)(Int32)-1, false, fileName);
fileName.Empty();
}
else
fileName += c;
}
+ /*
+ 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 isFolder;
- RINOK(IsArchiveItemFolder(archive, i, isFolder));
+ RINOK(Archive_IsItem_Folder(archive, i, isFolder));
if (isFolder)
- curItem->AddDirSubItem(i, true, fileName);
+ AddDirSubItem(curItem, i, true, fileName);
else
- curItem->AddFileSubItem(i, fileName);
+ Folders[curItem].AddFileSubItem(i, fileName);
+ }
+ CalculateSizes(0, archive);
+
+ /*
+ }
+ char s[128];
+ sprintf(s, "load archive %7d ms", GetTickCount() - tickCount);
+ OutputDebugStringA(s);
+ */
+
+ return S_OK;
+}
+
+
+
+// ---------- for Tree-mode archive ----------
+
+void CProxyArchive2::GetPathParts(int folderIndex, UStringVector &pathParts) const
+{
+ pathParts.Clear();
+ while (folderIndex > 0)
+ {
+ const CProxyFolder2 &folder = Folders[folderIndex];
+ const CProxyFile2 &file = Files[folder.ArcIndex];
+ pathParts.Insert(0, file.Name);
+ int par = file.Parent;
+ if (par < 0)
+ break;
+ folderIndex = Files[par].FolderIndex;
+ }
+}
+
+UString CProxyArchive2::GetFullPathPrefix(unsigned folderIndex) 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;
+ */
+}
+
+void CProxyArchive2::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);
+}
+
+void CProxyArchive2::AddRealIndices_of_Folder(unsigned folderIndex, bool includeAltStreams, CUIntVector &realIndices) const
+{
+ const CRecordVector<unsigned> &subFiles = Folders[folderIndex].SubFiles;
+ FOR_VECTOR (i, subFiles)
+ {
+ AddRealIndices_of_ArcItem(subFiles[i], includeAltStreams, realIndices);
}
- RootFolder.CalculateSizes(archive);
+}
+
+unsigned CProxyArchive2::GetRealIndex(unsigned folderIndex, unsigned index) const
+{
+ return Folders[folderIndex].SubFiles[index];
+}
+
+void CProxyArchive2::GetRealIndices(unsigned folderIndex, const UInt32 *indices, UInt32 numItems, bool includeAltStreams, CUIntVector &realIndices) const
+{
+ const CProxyFolder2 &folder = Folders[folderIndex];
+ realIndices.Clear();
+ for (UInt32 i = 0; i < numItems; i++)
+ {
+ AddRealIndices_of_ArcItem(folder.SubFiles[indices[i]], includeAltStreams, realIndices);
+ }
+ HeapSort(&realIndices.Front(), realIndices.Size());
+}
+
+void CProxyArchive2::CalculateSizes(unsigned folderIndex, 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)
+ {
+ UInt32 index = folder.SubFiles[i];
+ UInt64 size, packSize;
+ bool sizeDefined = GetSize(archive, index, kpidSize, size);
+ folder.Size += size;
+ GetSize(archive, index, kpidPackSize, packSize);
+ folder.PackSize += packSize;
+ {
+ NCOM::CPropVariant prop;
+ if (archive->GetProperty(index, kpidCRC, &prop) == S_OK)
+ {
+ if (prop.vt == VT_UI4)
+ folder.Crc += prop.ulVal;
+ else if (prop.vt != VT_EMPTY || size != 0 || !sizeDefined)
+ folder.CrcIsDefined = false;
+ }
+ else
+ folder.CrcIsDefined = false;
+ }
+
+ const CProxyFile2 &subFile = Files[index];
+ if (subFile.FolderIndex < 0)
+ {
+ folder.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;
+ if (!f.CrcIsDefined)
+ folder.CrcIsDefined = false;
+ }
+
+ if (subFile.AltStreamsFolderIndex < 0)
+ {
+ // folder.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;
+ */
+ }
+
+
+ }
+}
+
+
+bool CProxyArchive2::IsThere_SubDir(unsigned folderIndex, const UString &name) const
+{
+ const CRecordVector<unsigned> &subFiles = Folders[folderIndex].SubFiles;
+ FOR_VECTOR (i, subFiles)
+ {
+ const CProxyFile2 &file = Files[subFiles[i]];
+ if (file.IsDir())
+ if (CompareFileNames(name, file.Name) == 0)
+ return true;
+ }
+ return false;
+}
+
+HRESULT CProxyArchive2::Load(const CArc &arc, IProgress *progress)
+{
+ if (!arc.GetRawProps)
+ return E_FAIL;
+
+ // DWORD tickCount = GetTickCount();
+
+ Folders.Clear();
+
+ IInArchive *archive = arc.Archive;
+
+ UInt32 numItems;
+ RINOK(archive->GetNumberOfItems(&numItems));
+ if (progress)
+ RINOK(progress->SetTotal(numItems));
+ UString fileName;
+ {
+ CProxyFolder2 &folder = Folders.AddNew();
+ folder.ArcIndex = -1;
+ }
+
+ Files.Alloc(numItems);
+
+ UInt32 i;
+ for (i = 0; i < numItems; i++)
+ {
+ if (progress && (i & 0xFFFFF) == 0)
+ {
+ UInt64 currentItemIndex = i;
+ RINOK(progress->SetCompleted(&currentItemIndex));
+ }
+
+ CProxyFile2 &file = Files[i];
+
+ #ifdef MY_CPU_LE
+ const void *p;
+ UInt32 size;
+ UInt32 propType;
+ RINOK(arc.GetRawProps->GetRawProp(i, kpidName, &p, &size, &propType));
+
+ if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE)
+ {
+ file.Name = (const wchar_t *)p;
+ file.NameSize = 0;
+ if (size >= 2)
+ file.NameSize = size / 2 - 1;
+ }
+ else
+ #endif
+ {
+ 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.NameSize = MyStringLen(s);
+ file.Name = new wchar_t[file.NameSize + 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));
+ 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 isFolder;
+ RINOK(Archive_IsItem_Folder(archive, i, isFolder));
+
+ if (isFolder)
+ {
+ file.FolderIndex = Folders.Size();
+ CProxyFolder2 &folder = Folders.AddNew();
+ folder.ArcIndex = i;
+ }
+ if (arc.Ask_AltStream)
+ RINOK(Archive_IsItem_AltStream(archive, i, file.IsAltStream));
+ }
+
+ for (i = 0; i < numItems; i++)
+ {
+ CProxyFile2 &file = Files[i];
+ if (file.IsAltStream)
+ {
+ if (file.Parent >= 0)
+ {
+ int &folderIndex = Files[file.Parent].AltStreamsFolderIndex;
+ if (folderIndex < 0)
+ {
+ folderIndex = Folders.Size();
+ CProxyFolder2 &folder = Folders.AddNew();
+ folder.ArcIndex = file.Parent; // do we need it ???
+ }
+ Folders[folderIndex].SubFiles.Add(i);
+ }
+ }
+ else
+ {
+ int folderIndex = GetParentFolderOfFile(i);
+ if (folderIndex < 0)
+ return E_FAIL;
+ Folders[folderIndex].SubFiles.Add(i);
+ }
+ }
+ CalculateSizes(0, archive);
+
+ /*
+ char s[128];
+ sprintf(s, "load archive %7d ms", GetTickCount() - tickCount);
+ OutputDebugStringA(s);
+ */
return S_OK;
}
diff --git a/CPP/7zip/UI/Agent/AgentProxy.h b/CPP/7zip/UI/Agent/AgentProxy.h
index dcf52f04..1755d444 100755..100644
--- a/CPP/7zip/UI/Agent/AgentProxy.h
+++ b/CPP/7zip/UI/Agent/AgentProxy.h
@@ -13,39 +13,116 @@ struct CProxyFile
class CProxyFolder: public CProxyFile
{
- int FindDirSubItemIndex(const UString &name, int &insertPos) const;
- void AddRealIndices(CUIntVector &realIndices) const;
public:
- CProxyFolder *Parent;
- CObjectVector<CProxyFolder> Folders;
+ int Parent;
+ CRecordVector<unsigned> Folders;
CObjectVector<CProxyFile> Files;
+ UInt64 Size;
+ UInt64 PackSize;
+ UInt32 Crc;
+ UInt32 NumSubFolders;
+ UInt32 NumSubFiles;
bool IsLeaf;
-
bool CrcIsDefined;
+
+ CProxyFolder(): Parent(-1) {};
+ void AddFileSubItem(UInt32 index, const UString &name);
+ void Clear();
+};
+
+class CProxyArchive
+{
+ int FindDirSubItemIndex(unsigned folderIndex, const UString &name, unsigned &insertPos) const;
+
+ void CalculateSizes(unsigned folderIndex, IInArchive *archive);
+ unsigned AddDirSubItem(unsigned folderIndex, UInt32 index, bool leaf, const UString &name);
+public:
+ CObjectVector<CProxyFolder> Folders; // Folders[0] - isRoot
+
+ int FindDirSubItemIndex(unsigned folderIndex, const UString &name) const;
+ void GetPathParts(int folderIndex, UStringVector &pathParts) const;
+ UString GetFullPathPrefix(int folderIndex) 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;
+
+ HRESULT Load(const CArc &arc, IProgress *progress);
+};
+
+
+// ---------- for Tree-mode archive ----------
+
+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)
+ const wchar_t *Name;
+ unsigned NameSize;
+ bool Ignore;
+ bool IsAltStream;
+ bool NeedDeleteName;
+
+ int GetFolderIndex(bool forAltStreams) const { return forAltStreams ? AltStreamsFolderIndex : FolderIndex; }
+
+ bool IsDir() const { return FolderIndex >= 0; }
+ CProxyFile2(): FolderIndex(-1), AltStreamsFolderIndex(-1), Name(NULL), Ignore(false), IsAltStream(false), NeedDeleteName(false) {}
+ ~CProxyFile2()
+ {
+ if (NeedDeleteName)
+ delete [](wchar_t *)Name;
+ }
+};
+
+class CProxyFolder2
+{
+public:
+ Int32 ArcIndex; // = -1 for Root folder
+ CRecordVector<unsigned> SubFiles;
+ UString PathPrefix;
UInt64 Size;
UInt64 PackSize;
+ bool CrcIsDefined;
UInt32 Crc;
UInt32 NumSubFolders;
UInt32 NumSubFiles;
- CProxyFolder(): Parent(NULL) {};
- int FindDirSubItemIndex(const UString &name) const;
- CProxyFolder* AddDirSubItem(UInt32 index, bool leaf, const UString &name);
+ CProxyFolder2(): ArcIndex(-1) {};
void AddFileSubItem(UInt32 index, const UString &name);
void Clear();
- void GetPathParts(UStringVector &pathParts) const;
- UString GetFullPathPrefix() const;
- void GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const;
- void CalculateSizes(IInArchive *archive);
};
-struct CProxyArchive
+class CProxyArchive2
{
- CProxyFolder RootFolder;
- bool ThereIsPathProp;
+ 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;
+public:
+ CObjectVector<CProxyFolder2> Folders; // Folders[0] - is root folder
+ CObjArray<CProxyFile2> Files; // all aitems from archive in same order
+
+ bool IsThere_SubDir(unsigned folderIndex, const UString &name) const;
+
+ void GetPathParts(int folderIndex, UStringVector &pathParts) const;
+ UString GetFullPathPrefix(unsigned folderIndex) 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;
HRESULT Load(const CArc &arc, IProgress *progress);
+
+ int GetParentFolderOfFile(UInt32 indexInArc) const
+ {
+ const CProxyFile2 &file = Files[indexInArc];
+ if (file.Parent < 0)
+ return 0;
+ return Files[file.Parent].FolderIndex;
+ }
};
#endif
diff --git a/CPP/7zip/UI/Agent/ArchiveFolder.cpp b/CPP/7zip/UI/Agent/ArchiveFolder.cpp
index 237afa05..81291f44 100755..100644
--- a/CPP/7zip/UI/Agent/ArchiveFolder.cpp
+++ b/CPP/7zip/UI/Agent/ArchiveFolder.cpp
@@ -2,15 +2,26 @@
#include "StdAfx.h"
-#include "Common/ComTry.h"
+#include "../../../Common/ComTry.h"
#include "../Common/ArchiveExtractCallback.h"
#include "Agent.h"
-STDMETHODIMP CAgentFolder::CopyTo(const UInt32 *indices, UInt32 numItems,
+/*
+STDMETHODIMP CAgentFolder::SetReplaceAltStreamCharsMode(Int32 replaceAltStreamCharsMode)
+{
+ _replaceAltStreamCharsMode = replaceAltStreamCharsMode;
+ return S_OK;
+}
+*/
+
+STDMETHODIMP 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;
{
@@ -18,15 +29,11 @@ STDMETHODIMP CAgentFolder::CopyTo(const UInt32 *indices, UInt32 numItems,
RINOK(callbackWrap.QueryInterface(IID_IFolderArchiveExtractCallback, &extractCallback2));
}
NExtract::NPathMode::EEnum pathMode = _flatMode ?
- NExtract::NPathMode::kNoPathnames :
- NExtract::NPathMode::kCurrentPathnames;
- return Extract(indices,numItems, pathMode, NExtract::NOverwriteMode::kAskBefore,
+ NExtract::NPathMode::kNoPaths :
+ NExtract::NPathMode::kCurPaths;
+ return Extract(indices, numItems,
+ includeAltStreams, replaceAltStreamCharsMode,
+ pathMode, NExtract::NOverwriteMode::kAsk,
path, BoolToInt(false), extractCallback2);
COM_TRY_END
}
-
-STDMETHODIMP CAgentFolder::MoveTo(const UInt32 * /* indices */, UInt32 /* numItems */,
- const wchar_t * /* path */, IFolderOperationsExtractCallback * /* callback */)
-{
- return E_NOTIMPL;
-}
diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp
index 3a16a667..13d94bdf 100755..100644
--- a/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp
+++ b/CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp
@@ -15,8 +15,8 @@ void CArchiveFolderManager::LoadFormats()
int CArchiveFolderManager::FindFormat(const UString &type)
{
- for (int i = 0; i < _codecs->Formats.Size(); i++)
- if (type.CompareNoCase(_codecs->Formats[i].Name) == 0)
+ FOR_VECTOR (i, _codecs->Formats)
+ if (type.IsEqualToNoCase(_codecs->Formats[i].Name))
return i;
return -1;
}
@@ -60,11 +60,11 @@ STDMETHODIMP CArchiveFolderManager::GetExtensions(const wchar_t *type, BSTR *ext
static void AddIconExt(const CCodecIcons &lib, UString &dest)
{
- for (int j = 0; j < lib.IconPairs.Size(); j++)
+ FOR_VECTOR (i, lib.IconPairs)
{
if (!dest.IsEmpty())
dest += L' ';
- dest += lib.IconPairs[j].Ext;
+ dest += lib.IconPairs[i].Ext;
}
}
@@ -73,7 +73,7 @@ STDMETHODIMP CArchiveFolderManager::GetExtensions(BSTR *extensions)
LoadFormats();
*extensions = 0;
UString res;
- for (int i = 0; i < _codecs->Libs.Size(); i++)
+ FOR_VECTOR (i, _codecs->Libs)
AddIconExt(_codecs->Libs[i], res);
AddIconExt(_codecs->InternalIcons, res);
return StringToBstr(res, extensions);
@@ -84,7 +84,7 @@ STDMETHODIMP CArchiveFolderManager::GetIconPath(const wchar_t *ext, BSTR *iconPa
LoadFormats();
*iconPath = 0;
*iconIndex = 0;
- for (int i = 0; i < _codecs->Libs.Size(); i++)
+ FOR_VECTOR (i, _codecs->Libs)
{
const CCodecLib &lib = _codecs->Libs[i];
int ii;
@@ -112,7 +112,7 @@ STDMETHODIMP CArchiveFolderManager::GetTypes(BSTR *types)
{
LoadFormats();
UString typesStrings;
- for(int i = 0; i < _codecs.Formats.Size(); i++)
+ FOR_VECTOR(i, _codecs.Formats)
{
const CArcInfoEx &ai = _codecs.Formats[i];
if (ai.AssociateExts.Size() == 0)
diff --git a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp
index 656602cb..003f6d98 100755..100644
--- a/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp
+++ b/CPP/7zip/UI/Agent/ArchiveFolderOut.cpp
@@ -2,79 +2,157 @@
#include "StdAfx.h"
-#include "Common/ComTry.h"
+#include "../../../Common/ComTry.h"
-#include "Windows/FileDir.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 NDirectory;
+using namespace NDir;
void CAgentFolder::GetPathParts(UStringVector &pathParts)
{
- _proxyFolderItem->GetPathParts(pathParts);
+ if (_proxyArchive2)
+ _proxyArchive2->GetPathParts(_proxyFolderItem, pathParts);
+ else
+ _proxyArchive->GetPathParts(_proxyFolderItem, pathParts);
+}
+
+static bool DeleteEmptyFolderAndEmptySubFolders(const FString &path)
+{
+ NFind::CFileInfo fileInfo;
+ FString pathPrefix = path + FCHAR_PATH_SEPARATOR;
+ {
+ NFind::CEnumerator enumerator(pathPrefix + FCHAR_ANY_MASK);
+ while (enumerator.Next(fileInfo))
+ {
+ if (fileInfo.IsDir())
+ if (!DeleteEmptyFolderAndEmptySubFolders(pathPrefix + fileInfo.Name))
+ return false;
+ }
+ }
+ /*
+ // we don't need clear readonly for folders
+ if (!SetFileAttrib(path, 0))
+ return false;
+ */
+ return RemoveDir(path);
}
+
HRESULT CAgentFolder::CommonUpdateOperation(
AGENT_OP operation,
+ bool moveMode,
const wchar_t *newItemName,
const NUpdateArchive::CActionSet *actionSet,
- const UINT32 *indices, UINT32 numItems,
+ const UInt32 *indices, UInt32 numItems,
IFolderArchiveUpdateCallback *updateCallback100)
{
- CWorkDirTempFile tempFile;
- RINOK(tempFile.CreateTempFile(us2fs(_agentSpec->_archiveFilePath)));
+ if (!_agentSpec->CanUpdate())
+ return E_NOTIMPL;
- /*
- if (SetOutProperties(anOutArchive, aCompressionInfo.Method) != S_OK)
- return NFileOperationReturnCode::kError;
- */
-
////////////////////////////
// Save FolderItem;
UStringVector pathParts;
GetPathParts(pathParts);
- HRESULT result;
- switch (operation)
+ FStringVector requestedPaths;
+ FStringVector processedPaths;
+
+ CWorkDirTempFile tempFile;
+ RINOK(tempFile.CreateTempFile(us2fs(_agentSpec->_archiveFilePath)));
{
- case AGENT_OP_Delete:
- result = _agentSpec->DeleteItems(tempFile.OutStream, indices, numItems, updateCallback100);
- break;
- case AGENT_OP_CreateFolder:
- result = _agentSpec->CreateFolder(tempFile.OutStream, newItemName, updateCallback100);
- break;
- case AGENT_OP_Rename:
- result = _agentSpec->RenameItem(tempFile.OutStream, indices, numItems, newItemName, updateCallback100);
- break;
- case AGENT_OP_CopyFromFile:
- result = _agentSpec->UpdateOneFile(tempFile.OutStream, indices, numItems, newItemName, updateCallback100);
- break;
- case AGENT_OP_Uni:
+ CMyComPtr<IOutStream> tailStream;
+ const CArc &arc = *_agentSpec->_archiveLink.GetArc();
+
+ if (arc.ArcStreamOffset == 0)
+ tailStream = tempFile.OutStream;
+ else
{
- Byte actionSetByte[NUpdateArchive::NPairState::kNumValues];
- for (int i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
- actionSetByte[i] = (Byte)actionSet->StateActions[i];
- result = _agentSpec->DoOperation2(tempFile.OutStream, actionSetByte, NULL, updateCallback100);
- break;
+ 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();
}
- default:
- return E_FAIL;
+
+ HRESULT result;
+
+ switch (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_CopyFromFile:
+ result = _agentSpec->UpdateOneFile(tailStream, indices, numItems, newItemName, updateCallback100);
+ break;
+ case AGENT_OP_Uni:
+ {
+ Byte actionSetByte[NUpdateArchive::NPairState::kNumValues];
+ for (int 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);
}
-
- RINOK(result);
+ _agentSpec->KeepModeForNextOpen();
_agentSpec->Close();
+ // before 9.26: if there was error for MoveToOriginal archive was closed.
+ // now: we reopen archive after close
+
// m_FolderItem = NULL;
- RINOK(tempFile.MoveToOriginal(true));
+ HRESULT res = tempFile.MoveToOriginal(true);
+
+ // 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))
+ DeleteEmptyFolderAndEmptySubFolders(fs);
+ }
+ }
+ }
+
{
CMyComPtr<IArchiveOpenCallback> openCallback;
@@ -85,12 +163,11 @@ HRESULT CAgentFolder::CommonUpdateOperation(
RINOK(_agentSpec->ReOpen(openCallback));
}
- ////////////////////////////
// Restore FolderItem;
CMyComPtr<IFolderFolder> archiveFolder;
RINOK(_agentSpec->BindToRootFolder(&archiveFolder));
- for (int i = 0; i < pathParts.Size(); i++)
+ FOR_VECTOR (i, pathParts)
{
CMyComPtr<IFolderFolder> newFolder;
archiveFolder->BindToFolder(pathParts[i], &newFolder);
@@ -105,15 +182,16 @@ HRESULT CAgentFolder::CommonUpdateOperation(
RINOK(archiveFolderInternal->GetAgentFolder(&agentFolder));
_proxyFolderItem = agentFolder->_proxyFolderItem;
_proxyArchive = agentFolder->_proxyArchive;
+ _proxyArchive2 = agentFolder->_proxyArchive2;
_parentFolder = agentFolder->_parentFolder;
- return S_OK;
+ return res;
}
-STDMETHODIMP CAgentFolder::CopyFrom(
+STDMETHODIMP CAgentFolder::CopyFrom(Int32 moveMode,
const wchar_t *fromFolderPath, // test it
const wchar_t **itemsPaths,
- UINT32 numItems,
+ UInt32 numItems,
IProgress *progress)
{
COM_TRY_BEGIN
@@ -126,8 +204,9 @@ STDMETHODIMP CAgentFolder::CopyFrom(
{
RINOK(_agentSpec->SetFiles(fromFolderPath, itemsPaths, numItems));
RINOK(_agentSpec->SetFolder(this));
- return CommonUpdateOperation(AGENT_OP_Uni, NULL,
- &NUpdateArchive::kAddActionSet, 0, 0, updateCallback100);
+ return CommonUpdateOperation(AGENT_OP_Uni, (moveMode != 0), NULL,
+ &NUpdateArchive::k_ActionSet_Add,
+ 0, 0, updateCallback100);
}
catch(const UString &s)
{
@@ -150,8 +229,8 @@ STDMETHODIMP CAgentFolder::CopyFromFile(UInt32 destIndex, const wchar_t *itemPat
try
{
RINOK(_agentSpec->SetFolder(this));
- return CommonUpdateOperation(AGENT_OP_CopyFromFile, itemPath,
- &NUpdateArchive::kAddActionSet,
+ return CommonUpdateOperation(AGENT_OP_CopyFromFile, false, itemPath,
+ &NUpdateArchive::k_ActionSet_Add,
&indices.Front(), indices.Size(), updateCallback100);
}
catch(const UString &s)
@@ -162,7 +241,7 @@ STDMETHODIMP CAgentFolder::CopyFromFile(UInt32 destIndex, const wchar_t *itemPat
COM_TRY_END
}
-STDMETHODIMP CAgentFolder::Delete(const UINT32 *indices, UINT32 numItems, IProgress *progress)
+STDMETHODIMP CAgentFolder::Delete(const UInt32 *indices, UInt32 numItems, IProgress *progress)
{
COM_TRY_BEGIN
RINOK(_agentSpec->SetFolder(this));
@@ -173,16 +252,24 @@ STDMETHODIMP CAgentFolder::Delete(const UINT32 *indices, UINT32 numItems, IProgr
RINOK(progressWrapper.QueryInterface(
IID_IFolderArchiveUpdateCallback, &updateCallback100));
}
- return CommonUpdateOperation(AGENT_OP_Delete, NULL,
- &NUpdateArchive::kDeleteActionSet, indices, numItems, updateCallback100);
+ return CommonUpdateOperation(AGENT_OP_Delete, false, NULL,
+ &NUpdateArchive::k_ActionSet_Delete, indices, numItems, updateCallback100);
COM_TRY_END
}
STDMETHODIMP CAgentFolder::CreateFolder(const wchar_t *name, IProgress *progress)
{
COM_TRY_BEGIN
- if (_proxyFolderItem->FindDirSubItemIndex(name) >= 0)
- return ERROR_ALREADY_EXISTS;
+ if (_proxyArchive2)
+ {
+ if (_proxyArchive2->IsThere_SubDir(_proxyFolderItem, name))
+ return ERROR_ALREADY_EXISTS;
+ }
+ else
+ {
+ if (_proxyArchive->FindDirSubItemIndex(_proxyFolderItem, name) >= 0)
+ return ERROR_ALREADY_EXISTS;
+ }
RINOK(_agentSpec->SetFolder(this));
CMyComPtr<IFolderArchiveUpdateCallback> updateCallback100;
if (progress)
@@ -190,11 +277,11 @@ STDMETHODIMP CAgentFolder::CreateFolder(const wchar_t *name, IProgress *progress
CMyComPtr<IProgress> progressWrapper = progress;
RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100));
}
- return CommonUpdateOperation(AGENT_OP_CreateFolder, name, NULL, NULL, 0, updateCallback100);
+ return CommonUpdateOperation(AGENT_OP_CreateFolder, false, name, NULL, NULL, 0, updateCallback100);
COM_TRY_END
}
-STDMETHODIMP CAgentFolder::Rename(UINT32 index, const wchar_t *newName, IProgress *progress)
+STDMETHODIMP CAgentFolder::Rename(UInt32 index, const wchar_t *newName, IProgress *progress)
{
COM_TRY_BEGIN
CUIntVector indices;
@@ -206,7 +293,7 @@ STDMETHODIMP CAgentFolder::Rename(UINT32 index, const wchar_t *newName, IProgres
CMyComPtr<IProgress> progressWrapper = progress;
RINOK(progressWrapper.QueryInterface(IID_IFolderArchiveUpdateCallback, &updateCallback100));
}
- return CommonUpdateOperation(AGENT_OP_Rename, newName, NULL, &indices.Front(),
+ return CommonUpdateOperation(AGENT_OP_Rename, false, newName, NULL, &indices.Front(),
indices.Size(), updateCallback100);
COM_TRY_END
}
@@ -216,7 +303,7 @@ STDMETHODIMP CAgentFolder::CreateFile(const wchar_t * /* name */, IProgress * /*
return E_NOTIMPL;
}
-STDMETHODIMP CAgentFolder::SetProperty(UINT32 /* index */, PROPID /* propID */,
+STDMETHODIMP CAgentFolder::SetProperty(UInt32 /* index */, PROPID /* propID */,
const PROPVARIANT * /* value */, IProgress * /* progress */)
{
return E_NOTIMPL;
diff --git a/CPP/7zip/UI/Agent/IFolderArchive.h b/CPP/7zip/UI/Agent/IFolderArchive.h
index 2357af31..0f87cb55 100755..100644
--- a/CPP/7zip/UI/Agent/IFolderArchive.h
+++ b/CPP/7zip/UI/Agent/IFolderArchive.h
@@ -3,6 +3,8 @@
#ifndef __IFOLDER_ARCHIVE_H
#define __IFOLDER_ARCHIVE_H
+#include "../../../Common/MyString.h"
+
#include "../../Archive/IArchive.h"
#include "../../UI/Common/LoadCodecs.h"
#include "../../UI/FileManager/IFolder.h"
@@ -15,12 +17,14 @@
#define INTERFACE_IArchiveFolder(x) \
STDMETHOD(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) x; \
-FOLDER_ARCHIVE_INTERFACE(IArchiveFolder, 0x05)
+FOLDER_ARCHIVE_INTERFACE(IArchiveFolder, 0x0D)
{
INTERFACE_IArchiveFolder(PURE)
};
@@ -58,14 +62,19 @@ FOLDER_ARCHIVE_INTERFACE_SUB(IFolderArchiveUpdateCallback, IProgress, 0x0B)
STDMETHOD(SetFiles)(const wchar_t *folderPrefix, const wchar_t **names, UInt32 numNames) x; \
STDMETHOD(DeleteItems)(ISequentialOutStream *outArchiveStream, \
const UInt32 *indices, UInt32 numItems, IFolderArchiveUpdateCallback *updateCallback) x; \
- STDMETHOD(DoOperation)(CCodecs *codecs, int index, \
+ STDMETHOD(DoOperation)( \
+ FStringVector *requestedPaths, \
+ FStringVector *processedPaths, \
+ CCodecs *codecs, int index, \
ISequentialOutStream *outArchiveStream, const Byte *stateActions, const wchar_t *sfxModule, \
IFolderArchiveUpdateCallback *updateCallback) x; \
STDMETHOD(DoOperation2)( \
+ FStringVector *requestedPaths, \
+ FStringVector *processedPaths, \
ISequentialOutStream *outArchiveStream, const Byte *stateActions, const wchar_t *sfxModule, \
IFolderArchiveUpdateCallback *updateCallback) x; \
-FOLDER_ARCHIVE_INTERFACE(IOutFolderArchive, 0x0A)
+FOLDER_ARCHIVE_INTERFACE(IOutFolderArchive, 0x0F)
{
INTERFACE_IOutFolderArchive(PURE)
};
diff --git a/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp
index 3687c3d0..cfdacb2f 100755..100644
--- a/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp
+++ b/CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp
@@ -2,8 +2,9 @@
#include "StdAfx.h"
-#include "Windows/Error.h"
-#include "Common/IntToString.h"
+#include "../../../Common/IntToString.h"
+
+#include "../../../Windows/ErrorMsg.h"
#include "UpdateCallbackAgent.h"
@@ -62,11 +63,11 @@ HRESULT CUpdateCallbackAgent::OpenFileError(const wchar_t *name, DWORD systemErr
{
if (Callback)
{
- RINOK(Callback->UpdateErrorMessage(
- UString(L"WARNING: ") +
- NError::MyFormatMessageW(systemError) +
- UString(L": ") +
- name));
+ UString s = L"WARNING: ";
+ s += NError::MyFormatMessage(systemError);
+ s += L": ";
+ s += name;
+ RINOK(Callback->UpdateErrorMessage(s));
return S_FALSE;
}
}
diff --git a/CPP/7zip/UI/Agent/UpdateCallbackAgent.h b/CPP/7zip/UI/Agent/UpdateCallbackAgent.h
index 1d5ed17a..3707a93c 100755..100644
--- a/CPP/7zip/UI/Agent/UpdateCallbackAgent.h
+++ b/CPP/7zip/UI/Agent/UpdateCallbackAgent.h
@@ -1,9 +1,10 @@
// UpdateCallbackAgent.h
-#ifndef __UPDATECALLBACKAGENT_H
-#define __UPDATECALLBACKAGENT_H
+#ifndef __UPDATE_CALLBACK_AGENT_H
+#define __UPDATE_CALLBACK_AGENT_H
#include "../Common/UpdateCallback.h"
+
#include "IFolderArchive.h"
class CUpdateCallbackAgent: public IUpdateCallbackUI