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