xref: /aosp_15_r20/external/lzma/CPP/7zip/UI/Agent/AgentOut.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // AgentOut.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "../../../Common/Wildcard.h"
6 
7 #include "../../../Windows/FileDir.h"
8 #include "../../../Windows/FileName.h"
9 #include "../../../Windows/TimeUtils.h"
10 
11 #include "../../Compress/CopyCoder.h"
12 
13 #include "../../Common/FileStreams.h"
14 
15 #include "../../Archive/Common/ItemNameUtils.h"
16 
17 #include "Agent.h"
18 #include "UpdateCallbackAgent.h"
19 
20 using namespace NWindows;
21 using namespace NCOM;
22 
Z7_COM7F_IMF(CAgent::SetFolder (IFolderFolder * folder))23 Z7_COM7F_IMF(CAgent::SetFolder(IFolderFolder *folder))
24 {
25   _updatePathPrefix.Empty();
26   _updatePathPrefix_is_AltFolder = false;
27   _agentFolder = NULL;
28 
29   if (!folder)
30     return S_OK;
31 
32   {
33     Z7_DECL_CMyComPtr_QI_FROM(
34         IArchiveFolderInternal,
35         afi, folder)
36     if (afi)
37     {
38       RINOK(afi->GetAgentFolder(&_agentFolder))
39     }
40     if (!_agentFolder)
41       return E_FAIL;
42   }
43 
44   if (_proxy2)
45     _updatePathPrefix = _proxy2->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex, _updatePathPrefix_is_AltFolder);
46   else
47     _updatePathPrefix = _proxy->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex);
48   return S_OK;
49 }
50 
Z7_COM7F_IMF(CAgent::SetFiles (const wchar_t * folderPrefix,const wchar_t * const * names,UInt32 numNames))51 Z7_COM7F_IMF(CAgent::SetFiles(const wchar_t *folderPrefix,
52     const wchar_t * const *names, UInt32 numNames))
53 {
54   _folderPrefix = us2fs(folderPrefix);
55   _names.ClearAndReserve(numNames);
56   for (UInt32 i = 0; i < numNames; i++)
57     _names.AddInReserved(us2fs(names[i]));
58   return S_OK;
59 }
60 
EnumerateArchiveItems(CAgent * agent,const CProxyDir & item,const UString & prefix,CObjectVector<CArcItem> & arcItems)61 static HRESULT EnumerateArchiveItems(CAgent *agent,
62     const CProxyDir &item,
63     const UString &prefix,
64     CObjectVector<CArcItem> &arcItems)
65 {
66   unsigned i;
67 
68   for (i = 0; i < item.SubFiles.Size(); i++)
69   {
70     unsigned arcIndex = item.SubFiles[i];
71     const CProxyFile &fileItem = agent->_proxy->Files[arcIndex];
72     CArcItem ai;
73     RINOK(agent->GetArc().GetItem_MTime(arcIndex, ai.MTime))
74     RINOK(agent->GetArc().GetItem_Size(arcIndex, ai.Size, ai.Size_Defined))
75     ai.IsDir = false;
76     ai.Name = prefix + fileItem.Name;
77     ai.Censored = true; // test it
78     ai.IndexInServer = arcIndex;
79     arcItems.Add(ai);
80   }
81 
82   for (i = 0; i < item.SubDirs.Size(); i++)
83   {
84     const CProxyDir &dirItem = agent->_proxy->Dirs[item.SubDirs[i]];
85     UString fullName = prefix + dirItem.Name;
86     if (dirItem.IsLeaf())
87     {
88       CArcItem ai;
89       RINOK(agent->GetArc().GetItem_MTime((unsigned)dirItem.ArcIndex, ai.MTime))
90       ai.IsDir = true;
91       ai.Size_Defined = false;
92       ai.Name = fullName;
93       ai.Censored = true; // test it
94       ai.IndexInServer = (unsigned)dirItem.ArcIndex;
95       arcItems.Add(ai);
96     }
97     RINOK(EnumerateArchiveItems(agent, dirItem, fullName + WCHAR_PATH_SEPARATOR, arcItems))
98   }
99 
100   return S_OK;
101 }
102 
EnumerateArchiveItems2(const CAgent * agent,unsigned dirIndex,const UString & prefix,CObjectVector<CArcItem> & arcItems)103 static HRESULT EnumerateArchiveItems2(const CAgent *agent,
104     unsigned dirIndex,
105     const UString &prefix,
106     CObjectVector<CArcItem> &arcItems)
107 {
108   const CProxyDir2 &dir = agent->_proxy2->Dirs[dirIndex];
109   FOR_VECTOR (i, dir.Items)
110   {
111     unsigned arcIndex = dir.Items[i];
112     const CProxyFile2 &file = agent->_proxy2->Files[arcIndex];
113     CArcItem ai;
114     ai.IndexInServer = arcIndex;
115     ai.Name = prefix + file.Name;
116     ai.Censored = true; // test it
117     RINOK(agent->GetArc().GetItem_MTime(arcIndex, ai.MTime))
118     ai.IsDir = file.IsDir();
119     ai.Size_Defined = false;
120     ai.IsAltStream = file.IsAltStream;
121     if (!ai.IsDir)
122     {
123       RINOK(agent->GetArc().GetItem_Size(arcIndex, ai.Size, ai.Size_Defined))
124       ai.IsDir = false;
125     }
126     arcItems.Add(ai);
127 
128     if (file.AltDirIndex != -1)
129     {
130       RINOK(EnumerateArchiveItems2(agent, (unsigned)file.AltDirIndex, ai.Name + L':', arcItems))
131     }
132 
133     if (ai.IsDir)
134     {
135       RINOK(EnumerateArchiveItems2(agent, (unsigned)file.DirIndex, ai.Name + WCHAR_PATH_SEPARATOR, arcItems))
136     }
137   }
138   return S_OK;
139 }
140 
141 struct CAgUpCallbackImp Z7_final: public IUpdateProduceCallback
142 {
143   const CObjectVector<CArcItem> *_arcItems;
144   IFolderArchiveUpdateCallback *_callback;
145 
CAgUpCallbackImpZ7_final146   CAgUpCallbackImp(const CObjectVector<CArcItem> *a,
147       IFolderArchiveUpdateCallback *callback): _arcItems(a), _callback(callback) {}
148   HRESULT ShowDeleteFile(unsigned arcIndex) Z7_override;
149 };
150 
ShowDeleteFile(unsigned arcIndex)151 HRESULT CAgUpCallbackImp::ShowDeleteFile(unsigned arcIndex)
152 {
153   return _callback->DeleteOperation((*_arcItems)[arcIndex].Name);
154 }
155 
156 
SetInArchiveInterfaces(CAgent * agent,CArchiveUpdateCallback * upd)157 static void SetInArchiveInterfaces(CAgent *agent, CArchiveUpdateCallback *upd)
158 {
159   if (agent->_archiveLink.Arcs.IsEmpty())
160     return;
161   const CArc &arc = agent->GetArc();
162   upd->Arc = &arc;
163   upd->Archive = arc.Archive;
164 
165   upd->ArcFileName = ExtractFileNameFromPath(arc.Path);
166 }
167 
168 struct CDirItemsCallback_AgentOut Z7_final: public IDirItemsCallback
169 {
170   CMyComPtr<IFolderScanProgress> FolderScanProgress;
171   IFolderArchiveUpdateCallback *FolderArchiveUpdateCallback;
172   HRESULT ErrorCode;
173 
CDirItemsCallback_AgentOutZ7_final174   CDirItemsCallback_AgentOut(): FolderArchiveUpdateCallback(NULL), ErrorCode(S_OK) {}
175 
ScanErrorZ7_final176   HRESULT ScanError(const FString &name, DWORD systemError) Z7_override
177   {
178     const HRESULT hres = HRESULT_FROM_WIN32(systemError);
179     if (FolderArchiveUpdateCallback)
180       return FolderScanProgress->ScanError(fs2us(name), hres);
181     ErrorCode = hres;
182     return ErrorCode;
183   }
184 
ScanProgressZ7_final185   HRESULT ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir) Z7_override
186   {
187     if (FolderScanProgress)
188       return FolderScanProgress->ScanProgress(st.NumDirs, st.NumFiles + st.NumAltStreams,
189           st.GetTotalBytes(), fs2us(path), BoolToInt(isDir));
190     if (FolderArchiveUpdateCallback)
191       return FolderArchiveUpdateCallback->SetNumFiles(st.NumFiles);
192     return S_OK;
193   }
194 };
195 
196 
Z7_COM7F_IMF(CAgent::DoOperation (FStringVector * requestedPaths,FStringVector * processedPaths,CCodecs * codecs,int formatIndex,ISequentialOutStream * outArchiveStream,const Byte * stateActions,const wchar_t * sfxModule,IFolderArchiveUpdateCallback * updateCallback100))197 Z7_COM7F_IMF(CAgent::DoOperation(
198     FStringVector *requestedPaths,
199     FStringVector *processedPaths,
200     CCodecs *codecs,
201     int formatIndex,
202     ISequentialOutStream *outArchiveStream,
203     const Byte *stateActions,
204     const wchar_t *sfxModule,
205     IFolderArchiveUpdateCallback *updateCallback100))
206 {
207   if (!CanUpdate())
208     return E_NOTIMPL;
209 
210   NUpdateArchive::CActionSet actionSet;
211   {
212     for (unsigned i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
213       actionSet.StateActions[i] = (NUpdateArchive::NPairAction::EEnum)stateActions[i];
214   }
215 
216   CDirItemsCallback_AgentOut enumCallback;
217   if (updateCallback100)
218   {
219     enumCallback.FolderArchiveUpdateCallback = updateCallback100;
220     updateCallback100->QueryInterface(IID_IFolderScanProgress, (void **)&enumCallback.FolderScanProgress);
221   }
222 
223   CDirItems dirItems;
224   dirItems.Callback = &enumCallback;
225 
226   {
227     FString folderPrefix = _folderPrefix;
228     if (!NFile::NName::IsAltStreamPrefixWithColon(fs2us(folderPrefix)))
229       NFile::NName::NormalizeDirPathPrefix(folderPrefix);
230 
231     RINOK(dirItems.EnumerateItems2(folderPrefix, _updatePathPrefix, _names, requestedPaths))
232 
233     if (_updatePathPrefix_is_AltFolder)
234     {
235       FOR_VECTOR(i, dirItems.Items)
236       {
237         CDirItem &item = dirItems.Items[i];
238         if (item.IsDir())
239           return E_NOTIMPL;
240         item.IsAltStream = true;
241       }
242     }
243   }
244 
245   CMyComPtr<IOutArchive> outArchive;
246 
247   if (GetArchive())
248   {
249     RINOK(GetArchive()->QueryInterface(IID_IOutArchive, (void **)&outArchive))
250   }
251   else
252   {
253     if (formatIndex < 0)
254       return E_FAIL;
255     RINOK(codecs->CreateOutArchive((unsigned)formatIndex, outArchive))
256 
257     #ifdef Z7_EXTERNAL_CODECS
258     {
259       CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
260       outArchive.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
261       if (setCompressCodecsInfo)
262       {
263         RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecs))
264       }
265     }
266     #endif
267   }
268 
269   NFileTimeType::EEnum fileTimeType = NFileTimeType::kNotDefined;
270   UInt32 value;
271   RINOK(outArchive->GetFileTimeType(&value))
272   // we support any future fileType here.
273   // 22.00:
274   fileTimeType = (NFileTimeType::EEnum)value;
275   /*
276   switch (value)
277   {
278     case NFileTimeType::kWindows:
279     case NFileTimeType::kDOS:
280     case NFileTimeType::kUnix:
281       fileTimeType = NFileTimeType::EEnum(value);
282       break;
283     default:
284     {
285       return E_FAIL;
286     }
287   }
288   */
289 
290 
291   CObjectVector<CArcItem> arcItems;
292   if (GetArchive())
293   {
294     RINOK(ReadItems())
295     if (_proxy2)
296     {
297       RINOK(EnumerateArchiveItems2(this, k_Proxy2_RootDirIndex, L"", arcItems))
298       RINOK(EnumerateArchiveItems2(this, k_Proxy2_AltRootDirIndex, L":", arcItems))
299     }
300     else
301     {
302       RINOK(EnumerateArchiveItems(this, _proxy->Dirs[0], L"", arcItems))
303     }
304   }
305 
306   CRecordVector<CUpdatePair2> updatePairs2;
307 
308   {
309     CRecordVector<CUpdatePair> updatePairs;
310     GetUpdatePairInfoList(dirItems, arcItems, fileTimeType, updatePairs);
311     CAgUpCallbackImp upCallback(&arcItems, updateCallback100);
312     UpdateProduce(updatePairs, actionSet, updatePairs2, &upCallback);
313   }
314 
315   UInt32 numFiles = 0;
316   {
317     FOR_VECTOR (i, updatePairs2)
318       if (updatePairs2[i].NewData)
319         numFiles++;
320   }
321 
322   if (updateCallback100)
323   {
324     RINOK(updateCallback100->SetNumFiles(numFiles))
325   }
326 
327   CUpdateCallbackAgent updateCallbackAgent;
328   updateCallbackAgent.SetCallback(updateCallback100);
329   CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
330 
331   updateCallback->DirItems = &dirItems;
332   updateCallback->ArcItems = &arcItems;
333   updateCallback->UpdatePairs = &updatePairs2;
334 
335   SetInArchiveInterfaces(this, updateCallback.ClsPtr());
336 
337   updateCallback->Callback = &updateCallbackAgent;
338 
339   CByteBuffer processedItems;
340   if (processedPaths)
341   {
342     unsigned num = dirItems.Items.Size();
343     processedItems.Alloc(num);
344     for (unsigned i = 0; i < num; i++)
345       processedItems[i] = 0;
346     updateCallback->ProcessedItemsStatuses = processedItems;
347   }
348 
349   Z7_DECL_CMyComPtr_QI_FROM(
350       ISetProperties,
351       setProperties, outArchive)
352   if (setProperties)
353   {
354     if (m_PropNames.Size() == 0)
355     {
356       RINOK(setProperties->SetProperties(NULL, NULL, 0))
357     }
358     else
359     {
360       CRecordVector<const wchar_t *> names;
361       FOR_VECTOR (i, m_PropNames)
362         names.Add((const wchar_t *)m_PropNames[i]);
363 
364       CPropVariant *propValues = new CPropVariant[m_PropValues.Size()];
365       try
366       {
367         FOR_VECTOR (i, m_PropValues)
368           propValues[i] = m_PropValues[i];
369         RINOK(setProperties->SetProperties(names.ConstData(), propValues, names.Size()))
370       }
371       catch(...)
372       {
373         delete []propValues;
374         return E_FAIL;
375       }
376       delete []propValues;
377     }
378   }
379   m_PropNames.Clear();
380   m_PropValues.Clear();
381 
382   if (sfxModule != NULL)
383   {
384     CMyComPtr2_Create<IInStream, CInFileStream> sfxStream;
385     if (!sfxStream->Open(us2fs(sfxModule)))
386       return E_FAIL;
387       // throw "Can't open sfx module";
388     RINOK(NCompress::CopyStream(sfxStream, outArchiveStream, NULL))
389   }
390 
391   const HRESULT res = outArchive->UpdateItems(outArchiveStream, updatePairs2.Size(), updateCallback);
392   if (res == S_OK && processedPaths)
393   {
394     {
395       /* OutHandler for 7z archives doesn't report compression operation for empty files.
396          So we must include these files manually */
397       FOR_VECTOR(i, updatePairs2)
398       {
399         const CUpdatePair2 &up = updatePairs2[i];
400         if (up.DirIndex != -1 && up.NewData)
401         {
402           const CDirItem &di = dirItems.Items[(unsigned)up.DirIndex];
403           if (!di.IsDir() && di.Size == 0)
404             processedItems[(unsigned)up.DirIndex] = 1;
405         }
406       }
407     }
408 
409     FOR_VECTOR (i, dirItems.Items)
410       if (processedItems[i] != 0)
411         processedPaths->Add(dirItems.GetPhyPath(i));
412   }
413   return res;
414 }
415 
Z7_COM7F_IMF(CAgent::DoOperation2 (FStringVector * requestedPaths,FStringVector * processedPaths,ISequentialOutStream * outArchiveStream,const Byte * stateActions,const wchar_t * sfxModule,IFolderArchiveUpdateCallback * updateCallback100))416 Z7_COM7F_IMF(CAgent::DoOperation2(
417     FStringVector *requestedPaths,
418     FStringVector *processedPaths,
419     ISequentialOutStream *outArchiveStream,
420     const Byte *stateActions, const wchar_t *sfxModule, IFolderArchiveUpdateCallback *updateCallback100))
421 {
422   return DoOperation(requestedPaths, processedPaths, g_CodecsObj, -1, outArchiveStream, stateActions, sfxModule, updateCallback100);
423 }
424 
CommonUpdate(ISequentialOutStream * outArchiveStream,unsigned numUpdateItems,IArchiveUpdateCallback * updateCallback)425 HRESULT CAgent::CommonUpdate(ISequentialOutStream *outArchiveStream,
426     unsigned numUpdateItems, IArchiveUpdateCallback *updateCallback)
427 {
428   if (!CanUpdate())
429     return E_NOTIMPL;
430   CMyComPtr<IOutArchive> outArchive;
431   RINOK(GetArchive()->QueryInterface(IID_IOutArchive, (void **)&outArchive))
432   return outArchive->UpdateItems(outArchiveStream, numUpdateItems, updateCallback);
433 }
434 
Z7_COM7F_IMF(CAgent::DeleteItems (ISequentialOutStream * outArchiveStream,const UInt32 * indices,UInt32 numItems,IFolderArchiveUpdateCallback * updateCallback100))435 Z7_COM7F_IMF(CAgent::DeleteItems(ISequentialOutStream *outArchiveStream,
436     const UInt32 *indices, UInt32 numItems,
437     IFolderArchiveUpdateCallback *updateCallback100))
438 {
439   if (!CanUpdate())
440     return E_NOTIMPL;
441   CRecordVector<CUpdatePair2> updatePairs;
442   CUpdateCallbackAgent updateCallbackAgent;
443   updateCallbackAgent.SetCallback(updateCallback100);
444   CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
445 
446   CUIntVector realIndices;
447   _agentFolder->GetRealIndices(indices, numItems,
448       true, // includeAltStreams
449       false, // includeFolderSubItemsInFlatMode, we don't want to delete subItems in Flat Mode
450       realIndices);
451   unsigned curIndex = 0;
452   UInt32 numItemsInArchive;
453   RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive))
454 
455   UString deletePath;
456 
457   for (UInt32 i = 0; i < numItemsInArchive; i++)
458   {
459     if (curIndex < realIndices.Size())
460       if (realIndices[curIndex] == i)
461       {
462         RINOK(GetArc().GetItem_Path2(i, deletePath))
463         RINOK(updateCallback100->DeleteOperation(deletePath))
464 
465         curIndex++;
466         continue;
467       }
468     CUpdatePair2 up2;
469     up2.SetAs_NoChangeArcItem(i);
470     updatePairs.Add(up2);
471   }
472   updateCallback->UpdatePairs = &updatePairs;
473 
474   SetInArchiveInterfaces(this, updateCallback.ClsPtr());
475 
476   updateCallback->Callback = &updateCallbackAgent;
477   return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
478 }
479 
CreateFolder(ISequentialOutStream * outArchiveStream,const wchar_t * folderName,IFolderArchiveUpdateCallback * updateCallback100)480 HRESULT CAgent::CreateFolder(ISequentialOutStream *outArchiveStream,
481     const wchar_t *folderName, IFolderArchiveUpdateCallback *updateCallback100)
482 {
483   if (!CanUpdate())
484     return E_NOTIMPL;
485   CRecordVector<CUpdatePair2> updatePairs;
486   CDirItems dirItems;
487   CUpdateCallbackAgent updateCallbackAgent;
488   updateCallbackAgent.SetCallback(updateCallback100);
489   CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
490 
491   UInt32 numItemsInArchive;
492   RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive))
493   for (UInt32 i = 0; i < numItemsInArchive; i++)
494   {
495     CUpdatePair2 up2;
496     up2.SetAs_NoChangeArcItem(i);
497     updatePairs.Add(up2);
498   }
499   CUpdatePair2 up2;
500   up2.NewData = up2.NewProps = true;
501   up2.UseArcProps = false;
502   up2.DirIndex = 0;
503 
504   updatePairs.Add(up2);
505 
506   updatePairs.ReserveDown();
507 
508   CDirItem di;
509 
510   di.Attrib = FILE_ATTRIBUTE_DIRECTORY;
511   di.Size = 0;
512   bool isAltStreamFolder = false;
513   if (_proxy2)
514     di.Name = _proxy2->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex, isAltStreamFolder);
515   else
516     di.Name = _proxy->GetDirPath_as_Prefix(_agentFolder->_proxyDirIndex);
517   di.Name += folderName;
518 
519   FILETIME ft;
520   NTime::GetCurUtcFileTime(ft);
521   di.CTime = di.ATime = di.MTime = ft;
522 
523   dirItems.Items.Add(di);
524 
525   updateCallback->Callback = &updateCallbackAgent;
526   updateCallback->DirItems = &dirItems;
527   updateCallback->UpdatePairs = &updatePairs;
528 
529   SetInArchiveInterfaces(this, updateCallback.ClsPtr());
530 
531   return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
532 }
533 
534 
RenameItem(ISequentialOutStream * outArchiveStream,const UInt32 * indices,UInt32 numItems,const wchar_t * newItemName,IFolderArchiveUpdateCallback * updateCallback100)535 HRESULT CAgent::RenameItem(ISequentialOutStream *outArchiveStream,
536     const UInt32 *indices, UInt32 numItems, const wchar_t *newItemName,
537     IFolderArchiveUpdateCallback *updateCallback100)
538 {
539   if (!CanUpdate())
540     return E_NOTIMPL;
541   if (numItems != 1)
542     return E_INVALIDARG;
543   if (!_archiveLink.IsOpen)
544     return E_FAIL;
545   CRecordVector<CUpdatePair2> updatePairs;
546   CUpdateCallbackAgent updateCallbackAgent;
547   updateCallbackAgent.SetCallback(updateCallback100);
548   CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
549 
550   CUIntVector realIndices;
551   _agentFolder->GetRealIndices(indices, numItems,
552       true, // includeAltStreams
553       true, // includeFolderSubItemsInFlatMode
554       realIndices);
555 
556   const UInt32 ind0 = indices[0];
557   const int mainRealIndex = _agentFolder->GetRealIndex(ind0);
558   const UString fullPrefix = _agentFolder->GetFullPrefix(ind0);
559   UString name = _agentFolder->GetName(ind0);
560   // 22.00 : we normalize name
561   NArchive::NItemName::NormalizeSlashes_in_FileName_for_OsPath(name);
562   const UString oldItemPath = fullPrefix + name;
563   const UString newItemPath = fullPrefix + newItemName;
564 
565   UStringVector newNames;
566 
567   unsigned curIndex = 0;
568   UInt32 numItemsInArchive;
569   RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive))
570 
571   for (UInt32 i = 0; i < numItemsInArchive; i++)
572   {
573     CUpdatePair2 up2;
574     up2.SetAs_NoChangeArcItem(i);
575     if (curIndex < realIndices.Size())
576       if (realIndices[curIndex] == i)
577       {
578         up2.NewProps = true;
579         RINOK(GetArc().IsItem_Anti(i, up2.IsAnti)) // it must work without that line too.
580 
581         UString oldFullPath;
582         RINOK(GetArc().GetItem_Path2(i, oldFullPath))
583 
584         if (!IsPath1PrefixedByPath2(oldFullPath, oldItemPath))
585           return E_INVALIDARG;
586 
587         up2.NewNameIndex = (int)newNames.Add(newItemPath + oldFullPath.Ptr(oldItemPath.Len()));
588         up2.IsMainRenameItem = (mainRealIndex == (int)i);
589         curIndex++;
590       }
591     updatePairs.Add(up2);
592   }
593 
594   updateCallback->Callback = &updateCallbackAgent;
595   updateCallback->UpdatePairs = &updatePairs;
596   updateCallback->NewNames = &newNames;
597 
598   SetInArchiveInterfaces(this, updateCallback.ClsPtr());
599 
600   return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
601 }
602 
603 
CommentItem(ISequentialOutStream * outArchiveStream,const UInt32 * indices,UInt32 numItems,const wchar_t * newItemName,IFolderArchiveUpdateCallback * updateCallback100)604 HRESULT CAgent::CommentItem(ISequentialOutStream *outArchiveStream,
605     const UInt32 *indices, UInt32 numItems, const wchar_t *newItemName,
606     IFolderArchiveUpdateCallback *updateCallback100)
607 {
608   if (!CanUpdate())
609     return E_NOTIMPL;
610   if (numItems != 1)
611     return E_INVALIDARG;
612   if (!_archiveLink.IsOpen)
613     return E_FAIL;
614 
615   CRecordVector<CUpdatePair2> updatePairs;
616   CUpdateCallbackAgent updateCallbackAgent;
617   updateCallbackAgent.SetCallback(updateCallback100);
618   CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
619 
620   const int mainRealIndex = _agentFolder->GetRealIndex(indices[0]);
621 
622   if (mainRealIndex < 0)
623     return E_NOTIMPL;
624 
625   UInt32 numItemsInArchive;
626   RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive))
627 
628   UString newName = newItemName;
629 
630   for (UInt32 i = 0; i < numItemsInArchive; i++)
631   {
632     CUpdatePair2 up2;
633     up2.SetAs_NoChangeArcItem(i);
634     if ((int)i == mainRealIndex)
635       up2.NewProps = true;
636     updatePairs.Add(up2);
637   }
638 
639   updateCallback->Callback = &updateCallbackAgent;
640   updateCallback->UpdatePairs = &updatePairs;
641   updateCallback->CommentIndex = mainRealIndex;
642   updateCallback->Comment = &newName;
643 
644   SetInArchiveInterfaces(this, updateCallback.ClsPtr());
645 
646   return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
647 }
648 
649 
650 
UpdateOneFile(ISequentialOutStream * outArchiveStream,const UInt32 * indices,UInt32 numItems,const wchar_t * diskFilePath,IFolderArchiveUpdateCallback * updateCallback100)651 HRESULT CAgent::UpdateOneFile(ISequentialOutStream *outArchiveStream,
652     const UInt32 *indices, UInt32 numItems, const wchar_t *diskFilePath,
653     IFolderArchiveUpdateCallback *updateCallback100)
654 {
655   if (!CanUpdate())
656     return E_NOTIMPL;
657   CRecordVector<CUpdatePair2> updatePairs;
658   CDirItems dirItems;
659   CUpdateCallbackAgent updateCallbackAgent;
660   updateCallbackAgent.SetCallback(updateCallback100);
661   CMyComPtr2_Create<IArchiveUpdateCallback, CArchiveUpdateCallback> updateCallback;
662 
663   UInt32 realIndex;
664   {
665     CUIntVector realIndices;
666     _agentFolder->GetRealIndices(indices, numItems,
667         false, // includeAltStreams // we update only main stream of file
668         false, // includeFolderSubItemsInFlatMode
669         realIndices);
670     if (realIndices.Size() != 1)
671       return E_FAIL;
672     realIndex = realIndices[0];
673   }
674 
675   {
676     FStringVector filePaths;
677     filePaths.Add(us2fs(diskFilePath));
678     dirItems.EnumerateItems2(FString(), UString(), filePaths, NULL);
679     if (dirItems.Items.Size() != 1)
680       return E_FAIL;
681   }
682 
683   UInt32 numItemsInArchive;
684   RINOK(GetArchive()->GetNumberOfItems(&numItemsInArchive))
685   for (UInt32 i = 0; i < numItemsInArchive; i++)
686   {
687     CUpdatePair2 up2;
688     up2.SetAs_NoChangeArcItem(i);
689     if (realIndex == i)
690     {
691       up2.DirIndex = 0;
692       up2.NewData = true;
693       up2.NewProps = true;
694       up2.UseArcProps = false;
695     }
696     updatePairs.Add(up2);
697   }
698   updateCallback->DirItems = &dirItems;
699   updateCallback->Callback = &updateCallbackAgent;
700   updateCallback->UpdatePairs = &updatePairs;
701 
702   SetInArchiveInterfaces(this, updateCallback.ClsPtr());
703 
704   updateCallback->KeepOriginalItemNames = true;
705   return CommonUpdate(outArchiveStream, updatePairs.Size(), updateCallback);
706 }
707 
Z7_COM7F_IMF(CAgent::SetProperties (const wchar_t * const * names,const PROPVARIANT * values,UInt32 numProps))708 Z7_COM7F_IMF(CAgent::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))
709 {
710   m_PropNames.Clear();
711   m_PropValues.Clear();
712   for (UInt32 i = 0; i < numProps; i++)
713   {
714     m_PropNames.Add(names[i]);
715     m_PropValues.Add(values[i]);
716   }
717   return S_OK;
718 }
719