1 // PluginWrite.cpp
2
3 #include "StdAfx.h"
4
5 #include <stdio.h>
6
7 #include "Plugin.h"
8
9 #include "../../../Common/StringConvert.h"
10 #include "../../../Common/Wildcard.h"
11
12 #include "../../../Windows/FileName.h"
13 #include "../../../Windows/FileFind.h"
14
15 #include "../Common/ZipRegistry.h"
16
17 #include "../Agent/Agent.h"
18
19 #include "ProgressBox.h"
20 #include "Messages.h"
21 #include "UpdateCallbackFar.h"
22
23 using namespace NWindows;
24 using namespace NFile;
25 using namespace NDir;
26 using namespace NFar;
27
28 using namespace NUpdateArchive;
29
30 static const char * const kHelpTopic = "Update";
31
32 static const char * const kArchiveHistoryKeyName = "7-ZipArcName";
33
34 static const UInt32 g_MethodMap[] = { 0, 1, 3, 5, 7, 9 };
35
SetOutProperties(IOutFolderArchive * outArchive,UInt32 method)36 static HRESULT SetOutProperties(IOutFolderArchive *outArchive, UInt32 method)
37 {
38 CMyComPtr<ISetProperties> setProperties;
39 if (outArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties) == S_OK)
40 {
41 /*
42 UStringVector realNames;
43 realNames.Add(UString("x"));
44 NCOM::CPropVariant value = (UInt32)method;
45 CRecordVector<const wchar_t *> names;
46 FOR_VECTOR (i, realNames)
47 names.Add(realNames[i]);
48 RINOK(setProperties->SetProperties(&names.Front(), &value, names.Size()));
49 */
50 NCOM::CPropVariant value = (UInt32)method;
51 const wchar_t *name = L"x";
52 RINOK(setProperties->SetProperties(&name, &value, 1))
53 }
54 return S_OK;
55 }
56
57 /*
58 HRESULT CPlugin::AfterUpdate(CWorkDirTempFile &tempFile, const UStringVector &pathVector)
59 {
60 _folder.Release();
61 m_ArchiveHandler->Close();
62
63 RINOK(tempFile.MoveToOriginal(true));
64
65 RINOK(m_ArchiveHandler->ReOpen(NULL)); // check it
66
67 m_ArchiveHandler->BindToRootFolder(&_folder);
68 FOR_VECTOR (i, pathVector)
69 {
70 CMyComPtr<IFolderFolder> newFolder;
71 _folder->BindToFolder(pathVector[i], &newFolder);
72 if (!newFolder)
73 break;
74 _folder = newFolder;
75 }
76 return S_OK;
77 }
78 */
79
PutFiles(struct PluginPanelItem * panelItems,unsigned numItems,int moveMode,int opMode)80 NFileOperationReturnCode::EEnum CPlugin::PutFiles(
81 struct PluginPanelItem *panelItems, unsigned numItems,
82 int moveMode, int opMode)
83 {
84 if (moveMode != 0
85 && _agent->_isHashHandler)
86 {
87 g_StartupInfo.ShowMessage(NMessageID::kMoveIsNotSupported);
88 return NFileOperationReturnCode::kError;
89 }
90
91 if (numItems <= 0)
92 return NFileOperationReturnCode::kError;
93
94 if (_agent->IsThere_ReadOnlyArc())
95 {
96 g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);
97 return NFileOperationReturnCode::kError;
98 }
99
100 const int kYSize = 14;
101 const int kXMid = 38;
102
103 NCompression::CInfo compressionInfo;
104 compressionInfo.Load();
105
106 unsigned methodIndex = 0;
107
108 unsigned i;
109 for (i = Z7_ARRAY_SIZE(g_MethodMap); i != 0;)
110 {
111 i--;
112 if (compressionInfo.Level >= g_MethodMap[i])
113 {
114 methodIndex = i;
115 break;
116 }
117 }
118
119 const int kMethodRadioIndex = 2;
120 const int kModeRadioIndex = kMethodRadioIndex + 7;
121
122 struct CInitDialogItem initItems[]={
123 { DI_DOUBLEBOX, 3, 1, 72, kYSize - 2, false, false, 0, false, NMessageID::kUpdateTitle, NULL, NULL },
124
125 { DI_SINGLEBOX, 4, 2, kXMid - 2, 2 + 7, false, false, 0, false, NMessageID::kUpdateMethod, NULL, NULL },
126
127 { DI_RADIOBUTTON, 6, 3, 0, 0, methodIndex == 0, methodIndex == 0, DIF_GROUP, false, NMessageID::kUpdateMethod_Store, NULL, NULL },
128 { DI_RADIOBUTTON, 6, 4, 0, 0, methodIndex == 1, methodIndex == 1, 0, false, NMessageID::kUpdateMethod_Fastest, NULL, NULL },
129 { DI_RADIOBUTTON, 6, 5, 0, 0, methodIndex == 2, methodIndex == 2, 0, false, NMessageID::kUpdateMethod_Fast, NULL, NULL },
130 { DI_RADIOBUTTON, 6, 6, 0, 0, methodIndex == 3, methodIndex == 3, 0, false, NMessageID::kUpdateMethod_Normal, NULL, NULL },
131 { DI_RADIOBUTTON, 6, 7, 0, 0, methodIndex == 4, methodIndex == 4, 0, false, NMessageID::kUpdateMethod_Maximum, NULL, NULL },
132 { DI_RADIOBUTTON, 6, 8, 0, 0, methodIndex == 5, methodIndex == 5, 0, false, NMessageID::kUpdateMethod_Ultra, NULL, NULL },
133
134 { DI_SINGLEBOX, kXMid, 2, 70, 2 + 5, false, false, 0, false, NMessageID::kUpdateMode, NULL, NULL },
135
136 { DI_RADIOBUTTON, kXMid + 2, 3, 0, 0, false, true, DIF_GROUP, false, NMessageID::kUpdateMode_Add, NULL, NULL },
137 { DI_RADIOBUTTON, kXMid + 2, 4, 0, 0, false, false, 0, false, NMessageID::kUpdateMode_Update, NULL, NULL },
138 { DI_RADIOBUTTON, kXMid + 2, 5, 0, 0, false, false, 0, false, NMessageID::kUpdateMode_Fresh, NULL, NULL },
139 { DI_RADIOBUTTON, kXMid + 2, 6, 0, 0, false, false, 0, false, NMessageID::kUpdateMode_Sync, NULL, NULL },
140
141 { DI_TEXT, 3, kYSize - 4, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL },
142
143 { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kUpdateAdd, NULL, NULL },
144 { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kCancel, NULL, NULL }
145 };
146
147 const int kNumDialogItems = Z7_ARRAY_SIZE(initItems);
148 const int kOkButtonIndex = kNumDialogItems - 2;
149 FarDialogItem dialogItems[kNumDialogItems];
150 g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems);
151 const int askCode = g_StartupInfo.ShowDialog(76, kYSize,
152 kHelpTopic, dialogItems, kNumDialogItems);
153 if (askCode != kOkButtonIndex)
154 return NFileOperationReturnCode::kInterruptedByUser;
155
156 compressionInfo.Level = g_MethodMap[0];
157 for (i = 0; i < Z7_ARRAY_SIZE(g_MethodMap); i++)
158 if (dialogItems[kMethodRadioIndex + i].Selected)
159 compressionInfo.Level = g_MethodMap[i];
160
161 const CActionSet *actionSet;
162
163 if (dialogItems[kModeRadioIndex ].Selected) actionSet = &k_ActionSet_Add;
164 else if (dialogItems[kModeRadioIndex + 1].Selected) actionSet = &k_ActionSet_Update;
165 else if (dialogItems[kModeRadioIndex + 2].Selected) actionSet = &k_ActionSet_Fresh;
166 else if (dialogItems[kModeRadioIndex + 3].Selected) actionSet = &k_ActionSet_Sync;
167 else throw 51751;
168
169 compressionInfo.Save();
170
171 CWorkDirTempFile tempFile;
172 if (tempFile.CreateTempFile(m_FileName) != S_OK)
173 return NFileOperationReturnCode::kError;
174
175
176 /*
177 CSysStringVector fileNames;
178 for (int i = 0; i < numItems; i++)
179 {
180 const PluginPanelItem &panelItem = panelItems[i];
181 CSysString fullName;
182 if (!MyGetFullPathName(panelItem.FindData.cFileName, fullName))
183 return NFileOperationReturnCode::kError;
184 fileNames.Add(fullName);
185 }
186 */
187
188 CScreenRestorer screenRestorer;
189 CProgressBox progressBox;
190 CProgressBox *progressBoxPointer = NULL;
191 if ((opMode & OPM_SILENT) == 0 && (opMode & OPM_FIND ) == 0)
192 {
193 screenRestorer.Save();
194
195 progressBoxPointer = &progressBox;
196 progressBox.Init(
197 // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),
198 g_StartupInfo.GetMsgString(NMessageID::kUpdating));
199 }
200
201 UStringVector pathVector;
202 GetPathParts(pathVector);
203
204 UStringVector fileNames;
205 fileNames.ClearAndReserve(numItems);
206 for (i = 0; i < (unsigned)numItems; i++)
207 fileNames.AddInReserved(MultiByteToUnicodeString(panelItems[i].FindData.cFileName, CP_OEMCP));
208 CObjArray<const wchar_t *> fileNamePointers(numItems);
209 for (i = 0; i < (unsigned)numItems; i++)
210 fileNamePointers[i] = fileNames[i];
211
212 CMyComPtr<IOutFolderArchive> outArchive;
213 HRESULT result = m_ArchiveHandler.QueryInterface(IID_IOutFolderArchive, &outArchive);
214 if (result != S_OK)
215 {
216 g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);
217 return NFileOperationReturnCode::kError;
218 }
219
220 /*
221 BYTE actionSetByte[NUpdateArchive::NPairState::kNumValues];
222 for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
223 actionSetByte[i] = (BYTE)actionSet->StateActions[i];
224 */
225
226 CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp;
227 CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec );
228
229 updateCallbackSpec->Init(/* m_ArchiveHandler, */ progressBoxPointer);
230 updateCallbackSpec->PasswordIsDefined = PasswordIsDefined;
231 updateCallbackSpec->Password = Password;
232
233 if (!_agent->_isHashHandler)
234 {
235 if (SetOutProperties(outArchive, compressionInfo.Level) != S_OK)
236 return NFileOperationReturnCode::kError;
237 }
238
239 /*
240 outArchive->SetFolder(_folder);
241 outArchive->SetFiles(L"", fileNamePointers, numItems);
242 // FStringVector requestedPaths;
243 // FStringVector processedPaths;
244 result = outArchive->DoOperation2(
245 // &requestedPaths, &processedPaths,
246 NULL, NULL,
247 tempFile.OutStream, actionSetByte, NULL, updateCallback);
248 updateCallback.Release();
249 outArchive.Release();
250
251 if (result == S_OK)
252 {
253 result = AfterUpdate(tempFile, pathVector);
254 }
255 */
256
257 {
258 result = _agent->SetFiles(L"", fileNamePointers, numItems);
259 if (result == S_OK)
260 {
261 CAgentFolder *agentFolder = NULL;
262 {
263 CMyComPtr<IArchiveFolderInternal> afi;
264 _folder.QueryInterface(IID_IArchiveFolderInternal, &afi);
265 if (afi)
266 afi->GetAgentFolder(&agentFolder);
267 }
268 if (agentFolder)
269 result = agentFolder->CommonUpdateOperation(AGENT_OP_Uni,
270 (moveMode != 0), NULL, actionSet, NULL, 0, updateCallback);
271 else
272 result = E_FAIL;
273 }
274 }
275
276 if (result != S_OK)
277 {
278 ShowSysErrorMessage(result);
279 return NFileOperationReturnCode::kError;
280 }
281
282 return NFileOperationReturnCode::kSuccess;
283 }
284
285 namespace NPathType
286 {
287 enum EEnum
288 {
289 kLocal,
290 kUNC
291 };
292 EEnum GetPathType(const UString &path);
293 }
294
295 struct CParsedPath
296 {
297 UString Prefix; // Disk or UNC with slash
298 UStringVector PathParts;
299 void ParsePath(const UString &path);
300 UString MergePath() const;
301 };
302
303 static const char kDirDelimiter = CHAR_PATH_SEPARATOR;
304 static const wchar_t kDiskDelimiter = L':';
305
306 namespace NPathType
307 {
GetPathType(const UString & path)308 EEnum GetPathType(const UString &path)
309 {
310 if (path.Len() <= 2)
311 return kLocal;
312 if (path[0] == kDirDelimiter && path[1] == kDirDelimiter)
313 return kUNC;
314 return kLocal;
315 }
316 }
317
ParsePath(const UString & path)318 void CParsedPath::ParsePath(const UString &path)
319 {
320 int curPos = 0;
321 switch (NPathType::GetPathType(path))
322 {
323 case NPathType::kLocal:
324 {
325 const int posDiskDelimiter = path.Find(kDiskDelimiter);
326 if (posDiskDelimiter >= 0)
327 {
328 curPos = posDiskDelimiter + 1;
329 if ((int)path.Len() > curPos)
330 if (path[curPos] == kDirDelimiter)
331 curPos++;
332 }
333 break;
334 }
335 case NPathType::kUNC:
336 {
337 // the bug was fixed:
338 curPos = path.Find((wchar_t)kDirDelimiter, 2);
339 if (curPos < 0)
340 curPos = (int)path.Len();
341 else
342 curPos++;
343 }
344 }
345 Prefix = path.Left(curPos);
346 SplitPathToParts(path.Ptr(curPos), PathParts);
347 }
348
MergePath() const349 UString CParsedPath::MergePath() const
350 {
351 UString result = Prefix;
352 FOR_VECTOR (i, PathParts)
353 {
354 if (i != 0)
355 // result += kDirDelimiter;
356 result.Add_PathSepar();
357 result += PathParts[i];
358 }
359 return result;
360 }
361
362
SetArcName(UString & arcName,const CArcInfoEx & arcInfo)363 static void SetArcName(UString &arcName, const CArcInfoEx &arcInfo)
364 {
365 if (!arcInfo.Flags_KeepName())
366 {
367 int dotPos = arcName.ReverseFind_Dot();
368 int slashPos = arcName.ReverseFind_PathSepar();
369 if (dotPos > slashPos + 1)
370 arcName.DeleteFrom(dotPos);
371 }
372 arcName.Add_Dot();
373 arcName += arcInfo.GetMainExt();
374 }
375
CompressFiles(const CObjectVector<PluginPanelItem> & pluginPanelItems)376 HRESULT CompressFiles(const CObjectVector<PluginPanelItem> &pluginPanelItems)
377 {
378 if (pluginPanelItems.Size() == 0)
379 return E_FAIL;
380
381 UStringVector fileNames;
382 {
383 FOR_VECTOR (i, pluginPanelItems)
384 {
385 const PluginPanelItem &panelItem = pluginPanelItems[i];
386 if (strcmp(panelItem.FindData.cFileName, "..") == 0 &&
387 NFind::NAttributes::IsDir(panelItem.FindData.dwFileAttributes))
388 return E_FAIL;
389 if (strcmp(panelItem.FindData.cFileName, ".") == 0 &&
390 NFind::NAttributes::IsDir(panelItem.FindData.dwFileAttributes))
391 return E_FAIL;
392 FString fullPath;
393 FString fileNameUnicode = us2fs(MultiByteToUnicodeString(panelItem.FindData.cFileName, CP_OEMCP));
394 if (!MyGetFullPathName(fileNameUnicode, fullPath))
395 return E_FAIL;
396 fileNames.Add(fs2us(fullPath));
397 }
398 }
399
400 NCompression::CInfo compressionInfo;
401 compressionInfo.Load();
402
403 int archiverIndex = -1;
404
405 /*
406 CCodecs *codecs = new CCodecs;
407 CMyComPtr<ICompressCodecsInfo> compressCodecsInfo = codecs;
408 if (codecs->Load() != S_OK)
409 throw "Can't load 7-Zip codecs";
410 */
411
412 if (LoadGlobalCodecs() != S_OK)
413 throw "Can't load 7-Zip codecs";
414
415 CCodecs *codecs = g_CodecsObj;
416
417 {
418 FOR_VECTOR (i, codecs->Formats)
419 {
420 const CArcInfoEx &arcInfo = codecs->Formats[i];
421 if (arcInfo.UpdateEnabled)
422 {
423 if (archiverIndex == -1)
424 archiverIndex = (int)i;
425 if (MyStringCompareNoCase(arcInfo.Name, compressionInfo.ArcType) == 0)
426 archiverIndex = (int)i;
427 }
428 }
429 }
430
431 if (archiverIndex < 0)
432 throw "there is no output handler";
433
434 UString resultPath;
435 {
436 CParsedPath parsedPath;
437 parsedPath.ParsePath(fileNames.Front());
438 if (parsedPath.PathParts.Size() == 0)
439 return E_FAIL;
440 if (fileNames.Size() == 1 || parsedPath.PathParts.Size() == 1)
441 {
442 // CSysString pureName, dot, extension;
443 resultPath = parsedPath.PathParts.Back();
444 }
445 else
446 {
447 parsedPath.PathParts.DeleteBack();
448 resultPath = parsedPath.PathParts.Back();
449 }
450 }
451 UString archiveNameSrc = resultPath;
452 UString arcName = archiveNameSrc;
453
454 int prevFormat = archiverIndex;
455 SetArcName(arcName, codecs->Formats[archiverIndex]);
456
457 const CActionSet *actionSet = &k_ActionSet_Add;
458
459 for (;;)
460 {
461 AString archiveNameA (UnicodeStringToMultiByte(arcName, CP_OEMCP));
462 const int kYSize = 16;
463 const int kXMid = 38;
464
465 const int kArchiveNameIndex = 2;
466 const int kMethodRadioIndex = kArchiveNameIndex + 2;
467 const int kModeRadioIndex = kMethodRadioIndex + 7;
468
469 // char updateAddToArchiveString[512];
470 AString str1;
471 {
472 const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex];
473 const AString s (UnicodeStringToMultiByte(arcInfo.Name, CP_OEMCP));
474 str1 = g_StartupInfo.GetMsgString(NMessageID::kUpdateAddToArchive);
475 str1.Replace(AString ("%s"), s);
476 /*
477 sprintf(updateAddToArchiveString,
478 g_StartupInfo.GetMsgString(NMessageID::kUpdateAddToArchive), (const char *)s);
479 */
480 }
481
482 unsigned methodIndex = 0;
483 unsigned i;
484 for (i = Z7_ARRAY_SIZE(g_MethodMap); i != 0;)
485 {
486 i--;
487 if (compressionInfo.Level >= g_MethodMap[i])
488 {
489 methodIndex = i;
490 break;
491 }
492 }
493
494 const struct CInitDialogItem initItems[]=
495 {
496 { DI_DOUBLEBOX, 3, 1, 72, kYSize - 2, false, false, 0, false, NMessageID::kUpdateTitle, NULL, NULL },
497
498 { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, -1, str1, NULL },
499
500 { DI_EDIT, 5, 3, 70, 3, true, false, DIF_HISTORY, false, -1, archiveNameA, kArchiveHistoryKeyName},
501 // { DI_EDIT, 5, 3, 70, 3, true, false, 0, false, -1, arcName, NULL},
502
503 { DI_SINGLEBOX, 4, 4, kXMid - 2, 4 + 7, false, false, 0, false, NMessageID::kUpdateMethod, NULL, NULL },
504
505 { DI_RADIOBUTTON, 6, 5, 0, 0, false, methodIndex == 0, DIF_GROUP, false, NMessageID::kUpdateMethod_Store, NULL, NULL },
506 { DI_RADIOBUTTON, 6, 6, 0, 0, false, methodIndex == 1, 0, false, NMessageID::kUpdateMethod_Fastest, NULL, NULL },
507 { DI_RADIOBUTTON, 6, 7, 0, 0, false, methodIndex == 2, 0, false, NMessageID::kUpdateMethod_Fast, NULL, NULL },
508 { DI_RADIOBUTTON, 6, 8, 0, 0, false, methodIndex == 3, 0, false, NMessageID::kUpdateMethod_Normal, NULL, NULL },
509 { DI_RADIOBUTTON, 6, 9, 0, 0, false, methodIndex == 4, 0, false, NMessageID::kUpdateMethod_Maximum, NULL, NULL },
510 { DI_RADIOBUTTON, 6,10, 0, 0, false, methodIndex == 5, 0, false, NMessageID::kUpdateMethod_Ultra, NULL, NULL },
511
512 { DI_SINGLEBOX, kXMid, 4, 70, 4 + 5, false, false, 0, false, NMessageID::kUpdateMode, NULL, NULL },
513
514 { DI_RADIOBUTTON, kXMid + 2, 5, 0, 0, false, actionSet == &k_ActionSet_Add, DIF_GROUP, false, NMessageID::kUpdateMode_Add, NULL, NULL },
515 { DI_RADIOBUTTON, kXMid + 2, 6, 0, 0, false, actionSet == &k_ActionSet_Update, 0, false, NMessageID::kUpdateMode_Update, NULL, NULL },
516 { DI_RADIOBUTTON, kXMid + 2, 7, 0, 0, false, actionSet == &k_ActionSet_Fresh, 0, false, NMessageID::kUpdateMode_Fresh, NULL, NULL },
517 { DI_RADIOBUTTON, kXMid + 2, 8, 0, 0, false, actionSet == &k_ActionSet_Sync, 0, false, NMessageID::kUpdateMode_Sync, NULL, NULL },
518
519 { DI_TEXT, 3, kYSize - 4, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL },
520
521 { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kUpdateAdd, NULL, NULL },
522 { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kUpdateSelectArchiver, NULL, NULL },
523 { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kCancel, NULL, NULL }
524 };
525
526 const int kNumDialogItems = Z7_ARRAY_SIZE(initItems);
527
528 const int kOkButtonIndex = kNumDialogItems - 3;
529 const int kSelectarchiverButtonIndex = kNumDialogItems - 2;
530
531 FarDialogItem dialogItems[kNumDialogItems];
532 g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems);
533 int askCode = g_StartupInfo.ShowDialog(76, kYSize,
534 kHelpTopic, dialogItems, kNumDialogItems);
535
536 archiveNameA = dialogItems[kArchiveNameIndex].Data;
537 archiveNameA.Trim();
538 MultiByteToUnicodeString2(arcName, archiveNameA, CP_OEMCP);
539
540 compressionInfo.Level = g_MethodMap[0];
541 for (i = 0; i < Z7_ARRAY_SIZE(g_MethodMap); i++)
542 if (dialogItems[kMethodRadioIndex + i].Selected)
543 compressionInfo.Level = g_MethodMap[i];
544
545 if (dialogItems[kModeRadioIndex ].Selected) actionSet = &k_ActionSet_Add;
546 else if (dialogItems[kModeRadioIndex + 1].Selected) actionSet = &k_ActionSet_Update;
547 else if (dialogItems[kModeRadioIndex + 2].Selected) actionSet = &k_ActionSet_Fresh;
548 else if (dialogItems[kModeRadioIndex + 3].Selected) actionSet = &k_ActionSet_Sync;
549 else throw 51751;
550
551 if (askCode == kSelectarchiverButtonIndex)
552 {
553 CUIntVector indices;
554 AStringVector archiverNames;
555 FOR_VECTOR (k, codecs->Formats)
556 {
557 const CArcInfoEx &arc = codecs->Formats[k];
558 if (arc.UpdateEnabled)
559 {
560 indices.Add(k);
561 archiverNames.Add(GetOemString(arc.Name));
562 }
563 }
564
565 const int index = g_StartupInfo.Menu(FMENU_AUTOHIGHLIGHT,
566 g_StartupInfo.GetMsgString(NMessageID::kUpdateSelectArchiverMenuTitle),
567 NULL, archiverNames, archiverIndex);
568 if (index >= 0)
569 {
570 const CArcInfoEx &prevArchiverInfo = codecs->Formats[prevFormat];
571 if (prevArchiverInfo.Flags_KeepName())
572 {
573 const UString &prevExtension = prevArchiverInfo.GetMainExt();
574 const unsigned prevExtensionLen = prevExtension.Len();
575 if (arcName.Len() >= prevExtensionLen &&
576 MyStringCompareNoCase(arcName.RightPtr(prevExtensionLen), prevExtension) == 0)
577 {
578 const unsigned pos = arcName.Len() - prevExtensionLen;
579 if (pos > 2)
580 {
581 if (arcName[pos - 1] == '.')
582 arcName.DeleteFrom(pos - 1);
583 }
584 }
585 }
586
587 archiverIndex = (int)indices[index];
588 const CArcInfoEx &arcInfo = codecs->Formats[archiverIndex];
589 prevFormat = archiverIndex;
590
591 if (arcInfo.Flags_KeepName())
592 arcName = archiveNameSrc;
593 SetArcName(arcName, arcInfo);
594 }
595 continue;
596 }
597
598 if (askCode != kOkButtonIndex)
599 return E_ABORT;
600
601 break;
602 }
603
604 const CArcInfoEx &archiverInfoFinal = codecs->Formats[archiverIndex];
605 compressionInfo.ArcType = archiverInfoFinal.Name;
606 compressionInfo.Save();
607
608 NWorkDir::CInfo workDirInfo;
609 workDirInfo.Load();
610
611 FString fullArcName;
612 if (!MyGetFullPathName(us2fs(arcName), fullArcName))
613 return E_FAIL;
614
615 CWorkDirTempFile tempFile;
616 RINOK(tempFile.CreateTempFile(fullArcName))
617 CScreenRestorer screenRestorer;
618 CProgressBox progressBox;
619 CProgressBox *progressBoxPointer = NULL;
620
621 screenRestorer.Save();
622
623 progressBoxPointer = &progressBox;
624 progressBox.Init(
625 // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),
626 g_StartupInfo.GetMsgString(NMessageID::kUpdating));
627
628
629 NFind::CFileInfo fileInfo;
630
631 CMyComPtr<IOutFolderArchive> outArchive;
632
633 CMyComPtr<IInFolderArchive> archiveHandler;
634 if (fileInfo.Find(fullArcName))
635 {
636 if (fileInfo.IsDir())
637 throw "There is Directory with such name";
638
639 CAgent *agentSpec = new CAgent;
640 archiveHandler = agentSpec;
641 // CLSID realClassID;
642 CMyComBSTR archiveType;
643 RINOK(archiveHandler->Open(NULL,
644 GetUnicodeString(fullArcName, CP_OEMCP), UString(),
645 // &realClassID,
646 &archiveType,
647 NULL))
648
649 if (MyStringCompareNoCase(archiverInfoFinal.Name, (const wchar_t *)archiveType) != 0)
650 throw "Type of existing archive differs from specified type";
651 const HRESULT result = archiveHandler.QueryInterface(
652 IID_IOutFolderArchive, &outArchive);
653 if (result != S_OK)
654 {
655 g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);
656 return E_FAIL;
657 }
658 }
659 else
660 {
661 // HRESULT result = outArchive.CoCreateInstance(classID);
662 CAgent *agentSpec = new CAgent;
663 outArchive = agentSpec;
664
665 /*
666 HRESULT result = outArchive.CoCreateInstance(CLSID_CAgentArchiveHandler);
667 if (result != S_OK)
668 {
669 g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);
670 return E_FAIL;
671 }
672 */
673 }
674
675 CObjArray<const wchar_t *> fileNamePointers(fileNames.Size());
676
677 unsigned i;
678 for (i = 0; i < fileNames.Size(); i++)
679 fileNamePointers[i] = fileNames[i];
680
681 outArchive->SetFolder(NULL);
682 outArchive->SetFiles(L"", fileNamePointers, fileNames.Size());
683 BYTE actionSetByte[NUpdateArchive::NPairState::kNumValues];
684 for (i = 0; i < NUpdateArchive::NPairState::kNumValues; i++)
685 actionSetByte[i] = (BYTE)actionSet->StateActions[i];
686
687 CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp;
688 CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec );
689
690 updateCallbackSpec->Init(/* archiveHandler, */ progressBoxPointer);
691
692
693 RINOK(SetOutProperties(outArchive, compressionInfo.Level))
694
695 // FStringVector requestedPaths;
696 // FStringVector processedPaths;
697 HRESULT result = outArchive->DoOperation(
698 // &requestedPaths, &processedPaths,
699 NULL, NULL,
700 codecs, archiverIndex,
701 tempFile.OutStream, actionSetByte,
702 NULL, updateCallback);
703 updateCallback.Release();
704 outArchive.Release();
705
706 if (result != S_OK)
707 {
708 ShowSysErrorMessage(result);
709 return result;
710 }
711
712 if (archiveHandler)
713 {
714 archiveHandler->Close();
715 }
716
717 result = tempFile.MoveToOriginal(archiveHandler != NULL);
718 if (result != S_OK)
719 {
720 ShowSysErrorMessage(result);
721 return result;
722 }
723 return S_OK;
724 }
725
726
727 static const char * const k_CreateFolder_History = "NewFolder"; // we use default FAR folder name
728
CreateFolder()729 HRESULT CPlugin::CreateFolder()
730 {
731 if (_agent->IsThere_ReadOnlyArc())
732 {
733 g_StartupInfo.ShowMessage(NMessageID::kUpdateNotSupportedForThisArchive);
734 return TRUE;
735 }
736
737 UString destPathU;
738 {
739 const int kXSize = 60;
740 const int kYSize = 8;
741 const int kPathIndex = 2;
742
743 AString destPath ("New Folder");
744
745 const struct CInitDialogItem initItems[]={
746 { DI_DOUBLEBOX, 3, 1, kXSize - 4, kYSize - 2, false, false, 0, false,
747 -1, "Create Folder", NULL },
748
749 { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, -1, "Folder name:", NULL },
750
751 { DI_EDIT, 5, 3, kXSize - 6, 3, true, false, DIF_HISTORY, false, -1, destPath, k_CreateFolder_History },
752
753 { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kOk, NULL, NULL },
754 { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kCancel, NULL, NULL }
755 };
756
757 const int kNumDialogItems = Z7_ARRAY_SIZE(initItems);
758 const int kOkButtonIndex = kNumDialogItems - 2;
759
760 FarDialogItem dialogItems[kNumDialogItems];
761 g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems);
762 for (;;)
763 {
764 int askCode = g_StartupInfo.ShowDialog(kXSize, kYSize,
765 NULL, // kHelpTopic
766 dialogItems, kNumDialogItems);
767 if (askCode != kOkButtonIndex)
768 return E_ABORT;
769 destPath = dialogItems[kPathIndex].Data;
770 destPathU = GetUnicodeString(destPath, CP_OEMCP);
771 destPathU.Trim();
772 if (!destPathU.IsEmpty())
773 break;
774 g_StartupInfo.ShowErrorMessage("You must specify folder name");
775 }
776
777 }
778
779 CScreenRestorer screenRestorer;
780 CProgressBox progressBox;
781 CProgressBox *progressBoxPointer = NULL;
782 // if ((opMode & OPM_SILENT) == 0 && (opMode & OPM_FIND ) == 0)
783 {
784 screenRestorer.Save();
785
786 progressBoxPointer = &progressBox;
787 progressBox.Init(
788 // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),
789 g_StartupInfo.GetMsgString(NMessageID::kDeleting));
790 }
791
792 CUpdateCallback100Imp *updateCallbackSpec = new CUpdateCallback100Imp;
793 CMyComPtr<IFolderArchiveUpdateCallback> updateCallback(updateCallbackSpec);
794
795 updateCallbackSpec->Init(/* m_ArchiveHandler, */ progressBoxPointer);
796 updateCallbackSpec->PasswordIsDefined = PasswordIsDefined;
797 updateCallbackSpec->Password = Password;
798
799 HRESULT result;
800 {
801 CMyComPtr<IFolderOperations> folderOperations;
802 result = _folder.QueryInterface(IID_IFolderOperations, &folderOperations);
803 if (folderOperations)
804 result = folderOperations->CreateFolder(destPathU, updateCallback);
805 else if (result != S_OK)
806 result = E_FAIL;
807 }
808
809 if (result != S_OK)
810 {
811 ShowSysErrorMessage(result);
812 return result;
813 }
814
815 g_StartupInfo.Control(this, FCTL_UPDATEPANEL, (void *)1);
816 g_StartupInfo.Control(this, FCTL_REDRAWPANEL, NULL);
817
818 PanelInfo panelInfo;
819
820 if (g_StartupInfo.ControlGetActivePanelInfo(panelInfo))
821 {
822 const AString destPath (GetOemString(destPathU));
823
824 for (int i = 0; i < panelInfo.ItemsNumber; i++)
825 {
826 const PluginPanelItem &pi = panelInfo.PanelItems[i];
827 if (strcmp(destPath, pi.FindData.cFileName) == 0)
828 {
829 PanelRedrawInfo panelRedrawInfo;
830 panelRedrawInfo.CurrentItem = i;
831 panelRedrawInfo.TopPanelItem = 0;
832 g_StartupInfo.Control(this, FCTL_REDRAWPANEL, &panelRedrawInfo);
833 break;
834 }
835 }
836 }
837
838 SetCurrentDirVar();
839 return S_OK;
840 }
841