1 // Main.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../Common/MyInitGuid.h"
6
7 #include "../../../Common/CommandLineParser.h"
8 #include "../../../Common/MyException.h"
9
10 #ifdef _WIN32
11 #include "../../../Windows/DLL.h"
12 #include "../../../Windows/FileDir.h"
13 #endif
14 #include "../../../Windows/FileName.h"
15
16 #include "../../UI/Common/ExitCode.h"
17 #include "../../UI/Common/Extract.h"
18
19 #include "../../UI/Console/ExtractCallbackConsole.h"
20 #include "../../UI/Console/List.h"
21 #include "../../UI/Console/OpenCallbackConsole.h"
22
23 #include "../../MyVersion.h"
24
25 using namespace NWindows;
26 using namespace NFile;
27 using namespace NDir;
28 using namespace NCommandLineParser;
29
30 #ifdef _WIN32
31 HINSTANCE g_hInstance = 0;
32 #endif
33 int g_CodePage = -1;
34 extern CStdOutStream *g_StdStream;
35
36 static const char *kCopyrightString =
37 "\n7-Zip SFX " MY_VERSION_COPYRIGHT_DATE "\n";
38
39 static const int kNumSwitches = 6;
40
41 namespace NKey {
42 enum Enum
43 {
44 kHelp1 = 0,
45 kHelp2,
46 kDisablePercents,
47 kYes,
48 kPassword,
49 kOutputDir
50 };
51
52 }
53
54 namespace NRecursedType {
55 enum EEnum
56 {
57 kRecursed,
58 kWildcardOnlyRecursed,
59 kNonRecursed
60 };
61 }
62 /*
63 static const char kRecursedIDChar = 'R';
64 static const wchar_t *kRecursedPostCharSet = L"0-";
65
66 namespace NRecursedPostCharIndex {
67 enum EEnum
68 {
69 kWildcardRecursionOnly = 0,
70 kNoRecursion = 1
71 };
72 }
73
74 static const char kFileListID = '@';
75 static const char kImmediateNameID = '!';
76
77 static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be
78 static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|!><N>ame must be
79 */
80 static const CSwitchForm kSwitchForms[kNumSwitches] =
81 {
82 { "?", NSwitchType::kSimple },
83 { "H", NSwitchType::kSimple },
84 { "BD", NSwitchType::kSimple },
85 { "Y", NSwitchType::kSimple },
86 { "P", NSwitchType::kString, false, 1 },
87 { "O", NSwitchType::kString, false, 1 },
88 };
89
90 static const int kNumCommandForms = 3;
91
92 static const NRecursedType::EEnum kCommandRecursedDefault[kNumCommandForms] =
93 {
94 NRecursedType::kRecursed
95 };
96
97 // static const bool kTestExtractRecursedDefault = true;
98 // static const bool kAddRecursedDefault = false;
99
100 static const wchar_t *kUniversalWildcard = L"*";
101 static const int kCommandIndex = 0;
102
103 static const char *kHelpString =
104 "\nUsage: 7zSFX [<command>] [<switches>...]\n"
105 "\n"
106 "<Commands>\n"
107 " l: List contents of archive\n"
108 " t: Test integrity of archive\n"
109 " x: eXtract files with full pathname (default)\n"
110 "<Switches>\n"
111 // " -bd Disable percentage indicator\n"
112 " -o{Directory}: set Output directory\n"
113 " -p{Password}: set Password\n"
114 " -y: assume Yes on all queries\n";
115
116
117 // ---------------------------
118 // exception messages
119
120 static const char *kUserErrorMessage = "Incorrect command line"; // NExitCode::kUserError
121 // static const char *kIncorrectListFile = "Incorrect wildcard in listfile";
122 static const char *kIncorrectWildcardInCommandLine = "Incorrect wildcard in command line";
123
124 // static const CSysString kFileIsNotArchiveMessageBefore = "File \"";
125 // static const CSysString kFileIsNotArchiveMessageAfter = "\" is not archive";
126
127 // static const char *kProcessArchiveMessage = " archive: ";
128
129 static const char *kCantFindSFX = " cannot find sfx";
130
131 namespace NCommandType
132 {
133 enum EEnum
134 {
135 kTest = 0,
136 kFullExtract,
137 kList
138 };
139 }
140
141 static const char *g_Commands = "txl";
142
143 struct CArchiveCommand
144 {
145 NCommandType::EEnum CommandType;
146
147 NRecursedType::EEnum DefaultRecursedType() const;
148 };
149
ParseArchiveCommand(const UString & commandString,CArchiveCommand & command)150 bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &command)
151 {
152 UString s = commandString;
153 s.MakeLower_Ascii();
154 if (s.Len() != 1)
155 return false;
156 if (s[0] >= 0x80)
157 return false;
158 int index = FindCharPosInString(g_Commands, (char)s[0]);
159 if (index < 0)
160 return false;
161 command.CommandType = (NCommandType::EEnum)index;
162 return true;
163 }
164
DefaultRecursedType() const165 NRecursedType::EEnum CArchiveCommand::DefaultRecursedType() const
166 {
167 return kCommandRecursedDefault[CommandType];
168 }
169
PrintHelp(void)170 void PrintHelp(void)
171 {
172 g_StdOut << kHelpString;
173 }
174
ShowMessageAndThrowException(const char * message,NExitCode::EEnum code)175 static void ShowMessageAndThrowException(const char *message, NExitCode::EEnum code)
176 {
177 g_StdOut << message << endl;
178 throw code;
179 }
180
PrintHelpAndExit()181 static void PrintHelpAndExit() // yyy
182 {
183 PrintHelp();
184 ShowMessageAndThrowException(kUserErrorMessage, NExitCode::kUserError);
185 }
186
187 // ------------------------------------------------------------------
188 // filenames functions
189
AddNameToCensor(NWildcard::CCensor & wildcardCensor,const UString & name,bool include,NRecursedType::EEnum type)190 static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor,
191 const UString &name, bool include, NRecursedType::EEnum type)
192 {
193 /*
194 if (!IsWildcardFilePathLegal(name))
195 return false;
196 */
197 bool isWildcard = DoesNameContainWildcard(name);
198 bool recursed = false;
199
200 switch (type)
201 {
202 case NRecursedType::kWildcardOnlyRecursed:
203 recursed = isWildcard;
204 break;
205 case NRecursedType::kRecursed:
206 recursed = true;
207 break;
208 case NRecursedType::kNonRecursed:
209 recursed = false;
210 break;
211 }
212 wildcardCensor.AddPreItem(include, name, recursed, true);
213 return true;
214 }
215
AddCommandLineWildcardToCensor(NWildcard::CCensor & wildcardCensor,const UString & name,bool include,NRecursedType::EEnum type)216 void AddCommandLineWildcardToCensor(NWildcard::CCensor &wildcardCensor,
217 const UString &name, bool include, NRecursedType::EEnum type)
218 {
219 if (!AddNameToCensor(wildcardCensor, name, include, type))
220 ShowMessageAndThrowException(kIncorrectWildcardInCommandLine, NExitCode::kUserError);
221 }
222
AddToCensorFromNonSwitchesStrings(NWildcard::CCensor & wildcardCensor,const UStringVector &,NRecursedType::EEnum type,bool)223 void AddToCensorFromNonSwitchesStrings(NWildcard::CCensor &wildcardCensor,
224 const UStringVector & /* nonSwitchStrings */, NRecursedType::EEnum type,
225 bool /* thereAreSwitchIncludeWildcards */)
226 {
227 AddCommandLineWildcardToCensor(wildcardCensor, kUniversalWildcard, true, type);
228 }
229
230
231 #ifndef _WIN32
GetArguments(int numArgs,const char * args[],UStringVector & parts)232 static void GetArguments(int numArgs, const char *args[], UStringVector &parts)
233 {
234 parts.Clear();
235 for (int i = 0; i < numArgs; i++)
236 {
237 UString s = MultiByteToUnicodeString(args[i]);
238 parts.Add(s);
239 }
240 }
241 #endif
242
Main2(int numArgs,const char * args[])243 int Main2(
244 #ifndef _WIN32
245 int numArgs, const char *args[]
246 #endif
247 )
248 {
249 #if defined(_WIN32) && !defined(UNDER_CE)
250 SetFileApisToOEM();
251 #endif
252
253 g_StdOut << kCopyrightString;
254
255 UStringVector commandStrings;
256 #ifdef _WIN32
257 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings);
258 #else
259 GetArguments(numArgs, args, commandStrings);
260 #endif
261
262 #ifdef _WIN32
263
264 FString arcPath;
265 {
266 FString path;
267 NDLL::MyGetModuleFileName(path);
268 if (!MyGetFullPathName(path, arcPath))
269 {
270 g_StdOut << "GetFullPathName Error";
271 return NExitCode::kFatalError;
272 }
273 }
274
275 #else
276
277 UString arcPath = commandStrings.Front();
278
279 #endif
280
281 commandStrings.Delete(0);
282
283 NCommandLineParser::CParser parser(kNumSwitches);
284 try
285 {
286 parser.ParseStrings(kSwitchForms, commandStrings);
287 }
288 catch(...)
289 {
290 PrintHelpAndExit();
291 }
292
293 if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs)
294 {
295 PrintHelp();
296 return 0;
297 }
298 const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
299
300 int numNonSwitchStrings = nonSwitchStrings.Size();
301
302 CArchiveCommand command;
303 if (numNonSwitchStrings == 0)
304 command.CommandType = NCommandType::kFullExtract;
305 else
306 {
307 if (numNonSwitchStrings > 1)
308 PrintHelpAndExit();
309 if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], command))
310 PrintHelpAndExit();
311 }
312
313
314 NRecursedType::EEnum recursedType;
315 recursedType = command.DefaultRecursedType();
316
317 NWildcard::CCensor wildcardCensor;
318
319 bool thereAreSwitchIncludeWildcards;
320 thereAreSwitchIncludeWildcards = false;
321
322 AddToCensorFromNonSwitchesStrings(wildcardCensor, nonSwitchStrings, recursedType,
323 thereAreSwitchIncludeWildcards);
324
325 bool yesToAll = parser[NKey::kYes].ThereIs;
326
327 // NExtractMode::EEnum extractMode;
328 // bool isExtractGroupCommand = command.IsFromExtractGroup(extractMode);
329
330 bool passwordEnabled = parser[NKey::kPassword].ThereIs;
331
332 UString password;
333 if (passwordEnabled)
334 password = parser[NKey::kPassword].PostStrings[0];
335
336 if (!NFind::DoesFileExist(arcPath))
337 throw kCantFindSFX;
338
339 FString outputDir;
340 if (parser[NKey::kOutputDir].ThereIs)
341 {
342 outputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]);
343 NName::NormalizeDirPathPrefix(outputDir);
344 }
345
346
347 wildcardCensor.AddPathsToCensor(NWildcard::k_RelatPath);
348
349 {
350 UStringVector v1, v2;
351 v1.Add(fs2us(arcPath));
352 v2.Add(fs2us(arcPath));
353 const NWildcard::CCensorNode &wildcardCensorHead =
354 wildcardCensor.Pairs.Front().Head;
355
356 CCodecs *codecs = new CCodecs;
357 CMyComPtr<
358 #ifdef EXTERNAL_CODECS
359 ICompressCodecsInfo
360 #else
361 IUnknown
362 #endif
363 > compressCodecsInfo = codecs;
364 HRESULT result = codecs->Load();
365 if (result != S_OK)
366 throw CSystemException(result);
367
368 if (command.CommandType != NCommandType::kList)
369 {
370 CExtractCallbackConsole *ecs = new CExtractCallbackConsole;
371 CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs;
372 ecs->OutStream = g_StdStream;
373
374 #ifndef _NO_CRYPTO
375 ecs->PasswordIsDefined = passwordEnabled;
376 ecs->Password = password;
377 #endif
378
379 ecs->Init();
380
381 COpenCallbackConsole openCallback;
382 openCallback.OutStream = g_StdStream;
383
384 #ifndef _NO_CRYPTO
385 openCallback.PasswordIsDefined = passwordEnabled;
386 openCallback.Password = password;
387 #endif
388
389 CExtractOptions eo;
390 eo.StdOutMode = false;
391 eo.YesToAll = yesToAll;
392 eo.TestMode = command.CommandType == NCommandType::kTest;
393 eo.PathMode = NExtract::NPathMode::kFullPaths;
394 eo.OverwriteMode = yesToAll ?
395 NExtract::NOverwriteMode::kOverwrite :
396 NExtract::NOverwriteMode::kAsk;
397 eo.OutputDir = outputDir;
398
399 UString errorMessage;
400 CDecompressStat stat;
401 HRESULT result = Extract(
402 codecs, CObjectVector<COpenType>(), CIntVector(),
403 v1, v2,
404 wildcardCensorHead,
405 eo, &openCallback, ecs,
406 // NULL, // hash
407 errorMessage, stat);
408 if (!errorMessage.IsEmpty())
409 {
410 (*g_StdStream) << endl << "Error: " << errorMessage;;
411 if (result == S_OK)
412 result = E_FAIL;
413 }
414
415 if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0)
416 {
417 if (ecs->NumArcsWithError != 0)
418 (*g_StdStream) << endl << "Archive Errors" << endl;
419 if (ecs->NumFileErrors != 0)
420 (*g_StdStream) << endl << "Sub items Errors: " << ecs->NumFileErrors << endl;
421 return NExitCode::kFatalError;
422 }
423 if (result != S_OK)
424 throw CSystemException(result);
425 }
426 else
427 {
428 UInt64 numErrors = 0;
429 UInt64 numWarnings = 0;
430 HRESULT result = ListArchives(
431 codecs, CObjectVector<COpenType>(), CIntVector(),
432 false, // stdInMode
433 v1, v2,
434 true, // processAltStreams
435 false, // showAltStreams
436 wildcardCensorHead,
437 true, // enableHeaders
438 false, // techMode
439 #ifndef _NO_CRYPTO
440 passwordEnabled, password,
441 #endif
442 numErrors, numWarnings);
443 if (numErrors > 0)
444 {
445 g_StdOut << endl << "Errors: " << numErrors;
446 return NExitCode::kFatalError;
447 }
448 if (result != S_OK)
449 throw CSystemException(result);
450 }
451 }
452 return 0;
453 }
454