1 // PluginRead.cpp
2
3 #include "StdAfx.h"
4
5 #include "Plugin.h"
6
7 #include "Messages.h"
8
9 #include "../../../Common/StringConvert.h"
10
11 #include "../../../Windows/FileName.h"
12 #include "../../../Windows/FileFind.h"
13 #include "../../../Windows/FileDir.h"
14
15 #include "../Common/ZipRegistry.h"
16
17 #include "ExtractEngine.h"
18
19 using namespace NWindows;
20 using namespace NFile;
21 using namespace NDir;
22 using namespace NFar;
23
24 static const char * const kHelpTopicExtrFromSevenZip = "Extract";
25
26 static const char kDirDelimiter = CHAR_PATH_SEPARATOR;
27
28 static const char * const kExractPathHistoryName = "7-ZipExtractPath";
29
ExtractFiles(bool decompressAllItems,const UInt32 * indices,UInt32 numIndices,bool silent,NExtract::NPathMode::EEnum pathMode,NExtract::NOverwriteMode::EEnum overwriteMode,const UString & destPath,bool passwordIsDefined,const UString & password)30 HRESULT CPlugin::ExtractFiles(
31 bool decompressAllItems,
32 const UInt32 *indices,
33 UInt32 numIndices,
34 bool silent,
35 NExtract::NPathMode::EEnum pathMode,
36 NExtract::NOverwriteMode::EEnum overwriteMode,
37 const UString &destPath,
38 bool passwordIsDefined, const UString &password)
39 {
40 if (_agent->_isHashHandler)
41 {
42 g_StartupInfo.ShowMessage(NMessageID::kMoveIsNotSupported);
43 return NFileOperationReturnCode::kError;
44 }
45
46 CScreenRestorer screenRestorer;
47 CProgressBox progressBox;
48 CProgressBox *progressBoxPointer = NULL;
49 if (!silent)
50 {
51 screenRestorer.Save();
52
53 progressBoxPointer = &progressBox;
54 progressBox.Init(
55 // g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),
56 g_StartupInfo.GetMsgString(NMessageID::kExtracting));
57 }
58
59
60 CExtractCallbackImp *extractCallbackSpec = new CExtractCallbackImp;
61 CMyComPtr<IFolderArchiveExtractCallback> extractCallback(extractCallbackSpec);
62
63 extractCallbackSpec->Init(
64 CP_OEMCP,
65 progressBoxPointer,
66 /*
67 GetDefaultName(m_FileName, m_ArchiverInfo.Extension),
68 m_FileInfo.MTime, m_FileInfo.Attributes,
69 */
70 passwordIsDefined, password);
71
72 if (decompressAllItems)
73 return m_ArchiveHandler->Extract(pathMode, overwriteMode,
74 destPath, BoolToInt(false), extractCallback);
75 else
76 {
77 CMyComPtr<IArchiveFolder> archiveFolder;
78 _folder.QueryInterface(IID_IArchiveFolder, &archiveFolder);
79
80 return archiveFolder->Extract(indices, numIndices,
81 BoolToInt(true), // includeAltStreams
82 BoolToInt(false), // replaceAltStreamChars
83 pathMode, overwriteMode,
84 destPath, BoolToInt(false), extractCallback);
85 }
86 }
87
GetFiles(struct PluginPanelItem * panelItems,unsigned itemsNumber,int move,char * destPath,int opMode)88 NFileOperationReturnCode::EEnum CPlugin::GetFiles(struct PluginPanelItem *panelItems,
89 unsigned itemsNumber, int move, char *destPath, int opMode)
90 {
91 return GetFilesReal(panelItems, itemsNumber, move,
92 destPath, opMode, (opMode & OPM_SILENT) == 0);
93 }
94
GetFilesReal(struct PluginPanelItem * panelItems,unsigned itemsNumber,int move,const char * destPathLoc,int opMode,bool showBox)95 NFileOperationReturnCode::EEnum CPlugin::GetFilesReal(struct PluginPanelItem *panelItems,
96 unsigned itemsNumber, int move, const char *destPathLoc, int opMode, bool showBox)
97 {
98 if (move != 0)
99 {
100 g_StartupInfo.ShowMessage(NMessageID::kMoveIsNotSupported);
101 return NFileOperationReturnCode::kError;
102 }
103
104 AString destPath (destPathLoc);
105 UString destPathU = GetUnicodeString(destPath, CP_OEMCP);
106 NName::NormalizeDirPathPrefix(destPathU);
107 destPath = UnicodeStringToMultiByte(destPathU, CP_OEMCP);
108
109 // bool extractSelectedFiles = true;
110
111 NExtract::CInfo extractionInfo;
112 extractionInfo.PathMode = NExtract::NPathMode::kCurPaths;
113 extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kOverwrite;
114
115 const bool silent = (opMode & OPM_SILENT) != 0;
116 bool decompressAllItems = false;
117 UString password = Password;
118 bool passwordIsDefined = PasswordIsDefined;
119
120 if (!silent)
121 {
122 const int kPathIndex = 2;
123
124 extractionInfo.Load();
125
126 const int kPathModeRadioIndex = 4;
127 const int kOverwriteModeRadioIndex = kPathModeRadioIndex + 4;
128 const int kNumOverwriteOptions = 6;
129 const int kFilesModeIndex = kOverwriteModeRadioIndex + kNumOverwriteOptions;
130 const int kXSize = 76;
131 const int kYSize = 19;
132 const int kPasswordYPos = 12;
133
134 const int kXMid = kXSize / 2;
135
136 AString oemPassword (UnicodeStringToMultiByte(password, CP_OEMCP));
137
138 struct CInitDialogItem initItems[]={
139 { DI_DOUBLEBOX, 3, 1, kXSize - 4, kYSize - 2, false, false, 0, false, NMessageID::kExtractTitle, NULL, NULL },
140 { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, NMessageID::kExtractTo, NULL, NULL },
141
142 { DI_EDIT, 5, 3, kXSize - 6, 3, true, false, DIF_HISTORY, false, -1, destPath, kExractPathHistoryName},
143 // { DI_EDIT, 5, 3, kXSize - 6, 3, true, false, 0, false, -1, destPath, NULL},
144
145 { DI_SINGLEBOX, 4, 5, kXMid - 2, 5 + 4, false, false, 0, false, NMessageID::kExtractPathMode, NULL, NULL },
146 { DI_RADIOBUTTON, 6, 6, 0, 0, false,
147 extractionInfo.PathMode == NExtract::NPathMode::kFullPaths,
148 DIF_GROUP, false, NMessageID::kExtractPathFull, NULL, NULL },
149 { DI_RADIOBUTTON, 6, 7, 0, 0, false,
150 extractionInfo.PathMode == NExtract::NPathMode::kCurPaths,
151 0, false, NMessageID::kExtractPathCurrent, NULL, NULL },
152 { DI_RADIOBUTTON, 6, 8, 0, 0, false,
153 extractionInfo.PathMode == NExtract::NPathMode::kNoPaths,
154 false, 0, NMessageID::kExtractPathNo, NULL, NULL },
155
156 { DI_SINGLEBOX, kXMid, 5, kXSize - 6, 5 + kNumOverwriteOptions, false, false, 0, false, NMessageID::kExtractOwerwriteMode, NULL, NULL },
157 { DI_RADIOBUTTON, kXMid + 2, 6, 0, 0, false,
158 extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kAsk,
159 DIF_GROUP, false, NMessageID::kExtractOwerwriteAsk, NULL, NULL },
160 { DI_RADIOBUTTON, kXMid + 2, 7, 0, 0, false,
161 extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kOverwrite,
162 0, false, NMessageID::kExtractOwerwritePrompt, NULL, NULL },
163 { DI_RADIOBUTTON, kXMid + 2, 8, 0, 0, false,
164 extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kSkip,
165 0, false, NMessageID::kExtractOwerwriteSkip, NULL, NULL },
166 { DI_RADIOBUTTON, kXMid + 2, 9, 0, 0, false,
167 extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kRename,
168 0, false, NMessageID::kExtractOwerwriteAutoRename, NULL, NULL },
169 { DI_RADIOBUTTON, kXMid + 2, 10, 0, 0, false,
170 extractionInfo.OverwriteMode == NExtract::NOverwriteMode::kRenameExisting,
171 0, false, NMessageID::kExtractOwerwriteAutoRenameExisting, NULL, NULL },
172
173 { DI_SINGLEBOX, 4, 10, kXMid- 2, 10 + 3, false, false, 0, false, NMessageID::kExtractFilesMode, NULL, NULL },
174 { DI_RADIOBUTTON, 6, 11, 0, 0, false, true, DIF_GROUP, false, NMessageID::kExtractFilesSelected, NULL, NULL },
175 { DI_RADIOBUTTON, 6, 12, 0, 0, false, false, 0, false, NMessageID::kExtractFilesAll, NULL, NULL },
176
177 { DI_SINGLEBOX, kXMid, kPasswordYPos, kXSize - 6, kPasswordYPos + 2, false, false, 0, false, NMessageID::kExtractPassword, NULL, NULL },
178 { DI_PSWEDIT, kXMid + 2, kPasswordYPos + 1, kXSize - 8, 12, false, false, 0, false, -1, oemPassword, NULL},
179
180 { DI_TEXT, 3, kYSize - 4, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL },
181
182
183 { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, true, NMessageID::kExtractExtract, NULL, NULL },
184 { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kExtractCancel, NULL, NULL }
185 };
186
187 const unsigned kNumDialogItems = Z7_ARRAY_SIZE(initItems);
188 const unsigned kOkButtonIndex = kNumDialogItems - 2;
189 const unsigned kPasswordIndex = kNumDialogItems - 4;
190
191 FarDialogItem dialogItems[kNumDialogItems];
192 g_StartupInfo.InitDialogItems(initItems, dialogItems, kNumDialogItems);
193 for (;;)
194 {
195 int askCode = g_StartupInfo.ShowDialog(kXSize, kYSize,
196 kHelpTopicExtrFromSevenZip, dialogItems, kNumDialogItems);
197 if (askCode != kOkButtonIndex)
198 return NFileOperationReturnCode::kInterruptedByUser;
199 destPath = dialogItems[kPathIndex].Data;
200 destPathU = GetUnicodeString(destPath, CP_OEMCP);
201 destPathU.Trim();
202 if (destPathU.IsEmpty())
203 {
204 #ifdef UNDER_CE
205 destPathU = "\\";
206 #else
207 FString destPathF = us2fs(destPathU);
208 if (!GetCurrentDir(destPathF))
209 throw 318016;
210 NName::NormalizeDirPathPrefix(destPathF);
211 destPathU = fs2us(destPathF);
212 #endif
213 break;
214 }
215 else
216 {
217 if (destPathU.Back() == kDirDelimiter)
218 break;
219 }
220 g_StartupInfo.ShowErrorMessage("You must specify directory path");
221 }
222
223 if (dialogItems[kPathModeRadioIndex].Selected)
224 extractionInfo.PathMode = NExtract::NPathMode::kFullPaths;
225 else if (dialogItems[kPathModeRadioIndex + 1].Selected)
226 extractionInfo.PathMode = NExtract::NPathMode::kCurPaths;
227 else if (dialogItems[kPathModeRadioIndex + 2].Selected)
228 extractionInfo.PathMode = NExtract::NPathMode::kNoPaths;
229 else
230 throw 31806;
231
232 if (dialogItems[kOverwriteModeRadioIndex].Selected)
233 extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kAsk;
234 else if (dialogItems[kOverwriteModeRadioIndex + 1].Selected)
235 extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kOverwrite;
236 else if (dialogItems[kOverwriteModeRadioIndex + 2].Selected)
237 extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kSkip;
238 else if (dialogItems[kOverwriteModeRadioIndex + 3].Selected)
239 extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kRename;
240 else if (dialogItems[kOverwriteModeRadioIndex + 4].Selected)
241 extractionInfo.OverwriteMode = NExtract::NOverwriteMode::kRenameExisting;
242 else
243 throw 31806;
244
245 if (dialogItems[kFilesModeIndex].Selected)
246 decompressAllItems = false;
247 else if (dialogItems[kFilesModeIndex + 1].Selected)
248 decompressAllItems = true;
249 else
250 throw 31806;
251
252 extractionInfo.Save();
253
254 if (dialogItems[kFilesModeIndex].Selected)
255 {
256 // extractSelectedFiles = true;
257 }
258 else if (dialogItems[kFilesModeIndex + 1].Selected)
259 {
260 // extractSelectedFiles = false;
261 }
262 else
263 throw 31806;
264
265 oemPassword = dialogItems[kPasswordIndex].Data;
266 password = MultiByteToUnicodeString(oemPassword, CP_OEMCP);
267 passwordIsDefined = !password.IsEmpty();
268 }
269
270 CreateComplexDir(us2fs(destPathU));
271
272 /*
273 vector<int> realIndices;
274 if (!decompressAllItems)
275 GetRealIndexes(panelItems, itemsNumber, realIndices);
276 */
277 CObjArray<UInt32> indices(itemsNumber);
278 for (unsigned i = 0; i < itemsNumber; i++)
279 indices[i] = (UInt32)panelItems[i].UserData;
280
281 const HRESULT result = ExtractFiles(decompressAllItems, indices, itemsNumber,
282 !showBox, extractionInfo.PathMode, extractionInfo.OverwriteMode,
283 destPathU,
284 passwordIsDefined, password);
285 // HRESULT result = ExtractFiles(decompressAllItems, realIndices, !showBox,
286 // extractionInfo, destPath, passwordIsDefined, password);
287 if (result != S_OK)
288 {
289 if (result == E_ABORT)
290 return NFileOperationReturnCode::kInterruptedByUser;
291 ShowSysErrorMessage(result);
292 return NFileOperationReturnCode::kError;
293 }
294
295 // if (move != 0)
296 // {
297 // if (DeleteFiles(panelItems, itemsNumber, opMode) == FALSE)
298 // return NFileOperationReturnCode::kError;
299 // }
300 return NFileOperationReturnCode::kSuccess;
301 }
302