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