Imported Upstream version 9.20
[platform/upstream/7zip.git] / CPP / 7zip / UI / GUI / UpdateGUI.cpp
1 // UpdateGUI.cpp\r
2 \r
3 #include "StdAfx.h"\r
4 \r
5 #include "UpdateGUI.h"\r
6 \r
7 #include "Common/IntToString.h"\r
8 #include "Common/StringConvert.h"\r
9 #include "Common/StringToInt.h"\r
10 \r
11 #include "Windows/Error.h"\r
12 #include "Windows/FileDir.h"\r
13 #include "Windows/Thread.h"\r
14 \r
15 #include "../Common/WorkDir.h"\r
16 \r
17 #include "../Explorer/MyMessages.h"\r
18 \r
19 #include "../FileManager/LangUtils.h"\r
20 #include "../FileManager/ProgramLocation.h"\r
21 #include "../FileManager/StringUtils.h"\r
22 #include "../FileManager/resourceGui.h"\r
23 \r
24 #include "CompressDialog.h"\r
25 #include "UpdateGUI.h"\r
26 \r
27 #include "resource2.h"\r
28 \r
29 using namespace NWindows;\r
30 using namespace NFile;\r
31 \r
32 static const wchar_t *kDefaultSfxModule = L"7z.sfx";\r
33 static const wchar_t *kSFXExtension = L"exe";\r
34 \r
35 extern void AddMessageToString(UString &dest, const UString &src);\r
36 \r
37 UString HResultToMessage(HRESULT errorCode);\r
38 \r
39 class CThreadUpdating: public CProgressThreadVirt\r
40 {\r
41   HRESULT ProcessVirt();\r
42 public:\r
43   CCodecs *codecs;\r
44   CUpdateCallbackGUI *UpdateCallbackGUI;\r
45   const NWildcard::CCensor *WildcardCensor;\r
46   CUpdateOptions *Options;\r
47 };\r
48  \r
49 HRESULT CThreadUpdating::ProcessVirt()\r
50 {\r
51   CUpdateErrorInfo ei;\r
52   HRESULT res = UpdateArchive(codecs, *WildcardCensor, *Options,\r
53      ei, UpdateCallbackGUI, UpdateCallbackGUI);\r
54   ErrorMessage = ei.Message;\r
55   ErrorPath1 = ei.FileName;\r
56   ErrorPath2 = ei.FileName2;\r
57   if (ei.SystemError != S_OK && ei.SystemError != E_FAIL && ei.SystemError != E_ABORT)\r
58     return ei.SystemError;\r
59   return res;\r
60 }\r
61 \r
62 static void AddProp(CObjectVector<CProperty> &properties, const UString &name, const UString &value)\r
63 {\r
64   CProperty prop;\r
65   prop.Name = name;\r
66   prop.Value = value;\r
67   properties.Add(prop);\r
68 }\r
69 \r
70 static void AddProp(CObjectVector<CProperty> &properties, const UString &name, UInt32 value)\r
71 {\r
72   wchar_t tmp[32];\r
73   ConvertUInt64ToString(value, tmp);\r
74   AddProp(properties, name, tmp);\r
75 }\r
76 \r
77 static void AddProp(CObjectVector<CProperty> &properties, const UString &name, bool value)\r
78 {\r
79   AddProp(properties, name, value ? UString(L"on"): UString(L"off"));\r
80 }\r
81 \r
82 static bool IsThereMethodOverride(bool is7z, const UString &propertiesString)\r
83 {\r
84   UStringVector strings;\r
85   SplitString(propertiesString, strings);\r
86   for (int i = 0; i < strings.Size(); i++)\r
87   {\r
88     const UString &s = strings[i];\r
89     if (is7z)\r
90     {\r
91       const wchar_t *end;\r
92       UInt64 n = ConvertStringToUInt64(s, &end);\r
93       if (n == 0 && *end == L'=')\r
94         return true;\r
95     }\r
96     else\r
97     {\r
98       if (s.Length() > 0)\r
99         if (s[0] == L'm' && s[1] == L'=')\r
100           return true;\r
101     }\r
102   }\r
103   return false;\r
104 }\r
105 \r
106 static void ParseAndAddPropertires(CObjectVector<CProperty> &properties,\r
107     const UString &propertiesString)\r
108 {\r
109   UStringVector strings;\r
110   SplitString(propertiesString, strings);\r
111   for (int i = 0; i < strings.Size(); i++)\r
112   {\r
113     const UString &s = strings[i];\r
114     CProperty property;\r
115     int index = s.Find(L'=');\r
116     if (index < 0)\r
117       property.Name = s;\r
118     else\r
119     {\r
120       property.Name = s.Left(index);\r
121       property.Value = s.Mid(index + 1);\r
122     }\r
123     properties.Add(property);\r
124   }\r
125 }\r
126 \r
127 static UString GetNumInBytesString(UInt64 v)\r
128 {\r
129   wchar_t s[32];\r
130   ConvertUInt64ToString(v, s);\r
131   size_t len = wcslen(s);\r
132   s[len++] = L'B';\r
133   s[len] = L'\0';\r
134   return s;\r
135 }\r
136 \r
137 static void SetOutProperties(\r
138     CObjectVector<CProperty> &properties,\r
139     bool is7z,\r
140     UInt32 level,\r
141     bool setMethod,\r
142     const UString &method,\r
143     UInt32 dictionary,\r
144     bool orderMode,\r
145     UInt32 order,\r
146     bool solidIsSpecified, UInt64 solidBlockSize,\r
147     bool multiThreadIsAllowed, UInt32 numThreads,\r
148     const UString &encryptionMethod,\r
149     bool encryptHeadersIsAllowed, bool encryptHeaders,\r
150     bool /* sfxMode */)\r
151 {\r
152   if (level != (UInt32)(Int32)-1)\r
153     AddProp(properties, L"x", (UInt32)level);\r
154   if (setMethod)\r
155   {\r
156     if (!method.IsEmpty())\r
157       AddProp(properties, is7z ? L"0": L"m", method);\r
158     if (dictionary != (UInt32)(Int32)-1)\r
159     {\r
160       UString name;\r
161       if (is7z)\r
162         name = L"0";\r
163       if (orderMode)\r
164         name += L"mem";\r
165       else\r
166         name += L"d";\r
167       AddProp(properties, name, GetNumInBytesString(dictionary));\r
168     }\r
169     if (order != (UInt32)(Int32)-1)\r
170     {\r
171       UString name;\r
172       if (is7z)\r
173         name = L"0";\r
174       if (orderMode)\r
175         name += L"o";\r
176       else\r
177         name += L"fb";\r
178       AddProp(properties, name, (UInt32)order);\r
179     }\r
180   }\r
181     \r
182   if (!encryptionMethod.IsEmpty())\r
183     AddProp(properties, L"em", encryptionMethod);\r
184 \r
185   if (encryptHeadersIsAllowed)\r
186     AddProp(properties, L"he", encryptHeaders);\r
187   if (solidIsSpecified)\r
188     AddProp(properties, L"s", GetNumInBytesString(solidBlockSize));\r
189   if (multiThreadIsAllowed)\r
190     AddProp(properties, L"mt", numThreads);\r
191 }\r
192 \r
193 static HRESULT ShowDialog(\r
194     CCodecs *codecs,\r
195     const NWildcard::CCensor &censor,\r
196     CUpdateOptions &options, CUpdateCallbackGUI *callback, HWND hwndParent)\r
197 {\r
198   if (options.Commands.Size() != 1)\r
199     throw "It must be one command";\r
200   UString currentDirPrefix;\r
201   #ifndef UNDER_CE\r
202   {\r
203     if (!NDirectory::MyGetCurrentDirectory(currentDirPrefix))\r
204       return E_FAIL;\r
205     NName::NormalizeDirPathPrefix(currentDirPrefix);\r
206   }\r
207   #endif\r
208 \r
209   bool oneFile = false;\r
210   NFind::CFileInfoW fileInfo;\r
211   UString name;\r
212   if (censor.Pairs.Size() > 0)\r
213   {\r
214     const NWildcard::CPair &pair = censor.Pairs[0];\r
215     if (pair.Head.IncludeItems.Size() > 0)\r
216     {\r
217       const NWildcard::CItem &item = pair.Head.IncludeItems[0];\r
218       if (item.ForFile)\r
219       {\r
220         name = pair.Prefix;\r
221         for (int i = 0; i < item.PathParts.Size(); i++)\r
222         {\r
223           if (i > 0)\r
224             name += WCHAR_PATH_SEPARATOR;\r
225           name += item.PathParts[i];\r
226         }\r
227         if (fileInfo.Find(name))\r
228         {\r
229           if (censor.Pairs.Size() == 1 && pair.Head.IncludeItems.Size() == 1)\r
230             oneFile = !fileInfo.IsDir();\r
231         }\r
232       }\r
233     }\r
234   }\r
235     \r
236   CCompressDialog dialog;\r
237   NCompressDialog::CInfo &di = dialog.Info;\r
238   dialog.ArcFormats = &codecs->Formats;\r
239   for (int i = 0; i < codecs->Formats.Size(); i++)\r
240   {\r
241     const CArcInfoEx &ai = codecs->Formats[i];\r
242     if (ai.Name.CompareNoCase(L"swfc") == 0)\r
243       if (!oneFile || name.Right(4).CompareNoCase(L".swf") != 0)\r
244         continue;\r
245     if (ai.UpdateEnabled && (oneFile || !ai.KeepName))\r
246       dialog.ArcIndices.Add(i);\r
247   }\r
248   if (dialog.ArcIndices.Size() == 0)\r
249   {\r
250     ShowErrorMessage(L"No Update Engines");\r
251     return E_FAIL;\r
252   }\r
253 \r
254   // di.ArchiveName = options.ArchivePath.GetFinalPath();\r
255   di.ArchiveName = options.ArchivePath.GetPathWithoutExt();\r
256   dialog.OriginalFileName = options.ArchivePath.Prefix + fileInfo.Name;\r
257     \r
258   di.CurrentDirPrefix = currentDirPrefix;\r
259   di.SFXMode = options.SfxMode;\r
260   di.OpenShareForWrite = options.OpenShareForWrite;\r
261   \r
262   if (callback->PasswordIsDefined)\r
263     di.Password = callback->Password;\r
264     \r
265   di.KeepName = !oneFile;\r
266     \r
267   if (dialog.Create(hwndParent) != IDOK)\r
268     return E_ABORT;\r
269     \r
270   options.VolumesSizes = di.VolumeSizes;\r
271   /*\r
272   if (di.VolumeSizeIsDefined)\r
273   {\r
274     MyMessageBox(L"Splitting to volumes is not supported");\r
275     return E_FAIL;\r
276   }\r
277   */\r
278   \r
279   NUpdateArchive::CActionSet &actionSet = options.Commands.Front().ActionSet;\r
280   \r
281   switch(di.UpdateMode)\r
282   {\r
283     case NCompressDialog::NUpdateMode::kAdd:\r
284       actionSet = NUpdateArchive::kAddActionSet;\r
285       break;\r
286     case NCompressDialog::NUpdateMode::kUpdate:\r
287       actionSet = NUpdateArchive::kUpdateActionSet;\r
288       break;\r
289     case NCompressDialog::NUpdateMode::kFresh:\r
290       actionSet = NUpdateArchive::kFreshActionSet;\r
291       break;\r
292     case NCompressDialog::NUpdateMode::kSynchronize:\r
293       actionSet = NUpdateArchive::kSynchronizeActionSet;\r
294       break;\r
295     default:\r
296       throw 1091756;\r
297   }\r
298   const CArcInfoEx &archiverInfo = codecs->Formats[di.FormatIndex];\r
299   callback->PasswordIsDefined = (!di.Password.IsEmpty());\r
300   if (callback->PasswordIsDefined)\r
301     callback->Password = di.Password;\r
302 \r
303   options.MethodMode.Properties.Clear();\r
304 \r
305   bool is7z = archiverInfo.Name.CompareNoCase(L"7z") == 0;\r
306   bool methodOverride = IsThereMethodOverride(is7z, di.Options);\r
307 \r
308   SetOutProperties(\r
309       options.MethodMode.Properties,\r
310       is7z,\r
311       di.Level,\r
312       !methodOverride,\r
313       di.Method,\r
314       di.Dictionary,\r
315       di.OrderMode, di.Order,\r
316       di.SolidIsSpecified, di.SolidBlockSize,\r
317       di.MultiThreadIsAllowed, di.NumThreads,\r
318       di.EncryptionMethod,\r
319       di.EncryptHeadersIsAllowed, di.EncryptHeaders,\r
320       di.SFXMode);\r
321   \r
322   options.OpenShareForWrite = di.OpenShareForWrite;\r
323   ParseAndAddPropertires(options.MethodMode.Properties, di.Options);\r
324 \r
325   if (di.SFXMode)\r
326     options.SfxMode = true;\r
327   options.MethodMode.FormatIndex = di.FormatIndex;\r
328 \r
329   options.ArchivePath.VolExtension = archiverInfo.GetMainExt();\r
330   if (di.SFXMode)\r
331     options.ArchivePath.BaseExtension = kSFXExtension;\r
332   else\r
333     options.ArchivePath.BaseExtension = options.ArchivePath.VolExtension;\r
334   options.ArchivePath.ParseFromPath(di.ArchiveName);\r
335 \r
336   NWorkDir::CInfo workDirInfo;\r
337   workDirInfo.Load();\r
338   options.WorkingDir.Empty();\r
339   if (workDirInfo.Mode != NWorkDir::NMode::kCurrent)\r
340   {\r
341     UString fullPath;\r
342     NDirectory::MyGetFullPathName(di.ArchiveName, fullPath);\r
343     options.WorkingDir = GetWorkDir(workDirInfo, fullPath);\r
344     NDirectory::CreateComplexDirectory(options.WorkingDir);\r
345   }\r
346   return S_OK;\r
347 }\r
348 \r
349 HRESULT UpdateGUI(\r
350     CCodecs *codecs,\r
351     const NWildcard::CCensor &censor,\r
352     CUpdateOptions &options,\r
353     bool showDialog,\r
354     bool &messageWasDisplayed,\r
355     CUpdateCallbackGUI *callback,\r
356     HWND hwndParent)\r
357 {\r
358   messageWasDisplayed = false;\r
359   if (showDialog)\r
360   {\r
361     RINOK(ShowDialog(codecs, censor, options, callback, hwndParent));\r
362   }\r
363   if (options.SfxMode && options.SfxModule.IsEmpty())\r
364   {\r
365     UString folder;\r
366     if (!GetProgramFolderPath(folder))\r
367       folder.Empty();\r
368     options.SfxModule = folder + kDefaultSfxModule;\r
369   }\r
370 \r
371   CThreadUpdating tu;\r
372 \r
373   tu.codecs = codecs;\r
374 \r
375   tu.UpdateCallbackGUI = callback;\r
376   tu.UpdateCallbackGUI->ProgressDialog = &tu.ProgressDialog;\r
377   tu.UpdateCallbackGUI->Init();\r
378 \r
379   UString title = LangString(IDS_PROGRESS_COMPRESSING, 0x02000DC0);\r
380 \r
381   /*\r
382   if (hwndParent != 0)\r
383   {\r
384     tu.ProgressDialog.MainWindow = hwndParent;\r
385     // tu.ProgressDialog.MainTitle = fileName;\r
386     tu.ProgressDialog.MainAddTitle = title + L" ";\r
387   }\r
388   */\r
389 \r
390   tu.WildcardCensor = &censor;\r
391   tu.Options = &options;\r
392   tu.ProgressDialog.IconID = IDI_ICON;\r
393 \r
394   RINOK(tu.Create(title, hwndParent));\r
395 \r
396   messageWasDisplayed = tu.ThreadFinishedOK &\r
397       tu.ProgressDialog.MessagesDisplayed;\r
398   return tu.Result;\r
399 }\r