diff options
Diffstat (limited to 'CPP/7zip/UI/Agent')
-rw-r--r--[-rwxr-xr-x] | CPP/7zip/UI/Agent/Agent.cpp | 1184 | ||||
-rw-r--r--[-rwxr-xr-x] | CPP/7zip/UI/Agent/Agent.h | 109 | ||||
-rw-r--r--[-rwxr-xr-x] | CPP/7zip/UI/Agent/AgentOut.cpp | 207 | ||||
-rw-r--r--[-rwxr-xr-x] | CPP/7zip/UI/Agent/AgentProxy.cpp | 565 | ||||
-rw-r--r--[-rwxr-xr-x] | CPP/7zip/UI/Agent/AgentProxy.h | 107 | ||||
-rw-r--r--[-rwxr-xr-x] | CPP/7zip/UI/Agent/ArchiveFolder.cpp | 29 | ||||
-rw-r--r--[-rwxr-xr-x] | CPP/7zip/UI/Agent/ArchiveFolderOpen.cpp | 14 | ||||
-rw-r--r--[-rwxr-xr-x] | CPP/7zip/UI/Agent/ArchiveFolderOut.cpp | 197 | ||||
-rw-r--r--[-rwxr-xr-x] | CPP/7zip/UI/Agent/IFolderArchive.h | 15 | ||||
-rw-r--r--[-rwxr-xr-x] | CPP/7zip/UI/Agent/UpdateCallbackAgent.cpp | 15 | ||||
-rw-r--r--[-rwxr-xr-x] | CPP/7zip/UI/Agent/UpdateCallbackAgent.h | 5 |
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(¤tItemIndex)); } - 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(¤tItemIndex)); + } + + 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 |