• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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