Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(134)

Side by Side Diff: third_party/lzma/v4_65/files/CPP/7zip/UI/Common/ArchiveCommandLine.cpp

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // ArchiveCommandLine.cpp
2
3 #include "StdAfx.h"
4
5 #ifdef _WIN32
6 #include <io.h>
7 #endif
8 #include <stdio.h>
9
10 #include "Common/ListFileUtils.h"
11 #include "Common/StringConvert.h"
12 #include "Common/StringToInt.h"
13
14 #include "Windows/FileName.h"
15 #include "Windows/FileDir.h"
16 #ifdef _WIN32
17 #include "Windows/FileMapping.h"
18 #include "Windows/Synchronization.h"
19 #endif
20
21 #include "ArchiveCommandLine.h"
22 #include "UpdateAction.h"
23 #include "Update.h"
24 #include "SortUtils.h"
25 #include "EnumDirItems.h"
26
27 extern bool g_CaseSensitive;
28
29 #if _MSC_VER >= 1400
30 #define MY_isatty_fileno(x) _isatty(_fileno(x))
31 #else
32 #define MY_isatty_fileno(x) isatty(fileno(x))
33 #endif
34
35 #define MY_IS_TERMINAL(x) (MY_isatty_fileno(x) != 0);
36
37 using namespace NCommandLineParser;
38 using namespace NWindows;
39 using namespace NFile;
40
41 namespace NKey {
42 enum Enum
43 {
44 kHelp1 = 0,
45 kHelp2,
46 kHelp3,
47 kDisableHeaders,
48 kDisablePercents,
49 kArchiveType,
50 kYes,
51 #ifndef _NO_CRYPTO
52 kPassword,
53 #endif
54 kProperty,
55 kOutputDir,
56 kWorkingDir,
57 kInclude,
58 kExclude,
59 kArInclude,
60 kArExclude,
61 kNoArName,
62 kUpdate,
63 kVolume,
64 kRecursed,
65 kSfx,
66 kStdIn,
67 kStdOut,
68 kOverwrite,
69 kEmail,
70 kShowDialog,
71 kLargePages,
72 kCharSet,
73 kTechMode,
74 kShareForWrite,
75 kCaseSensitive
76 };
77
78 }
79
80
81 static const wchar_t kRecursedIDChar = 'R';
82 static const wchar_t *kRecursedPostCharSet = L"0-";
83
84 namespace NRecursedPostCharIndex {
85 enum EEnum
86 {
87 kWildCardRecursionOnly = 0,
88 kNoRecursion = 1
89 };
90 }
91
92 static const char kImmediateNameID = '!';
93 static const char kMapNameID = '#';
94 static const char kFileListID = '@';
95
96 static const char kSomeCludePostStringMinSize = 2; // at least <@|!><N>ame must be
97 static const char kSomeCludeAfterRecursedPostStringMinSize = 2; // at least <@|! ><N>ame must be
98
99 static const wchar_t *kOverwritePostCharSet = L"asut";
100
101 NExtract::NOverwriteMode::EEnum k_OverwriteModes[] =
102 {
103 NExtract::NOverwriteMode::kWithoutPrompt,
104 NExtract::NOverwriteMode::kSkipExisting,
105 NExtract::NOverwriteMode::kAutoRename,
106 NExtract::NOverwriteMode::kAutoRenameExisting
107 };
108
109 static const CSwitchForm kSwitchForms[] =
110 {
111 { L"?", NSwitchType::kSimple, false },
112 { L"H", NSwitchType::kSimple, false },
113 { L"-HELP", NSwitchType::kSimple, false },
114 { L"BA", NSwitchType::kSimple, false },
115 { L"BD", NSwitchType::kSimple, false },
116 { L"T", NSwitchType::kUnLimitedPostString, false, 1 },
117 { L"Y", NSwitchType::kSimple, false },
118 #ifndef _NO_CRYPTO
119 { L"P", NSwitchType::kUnLimitedPostString, false, 0 },
120 #endif
121 { L"M", NSwitchType::kUnLimitedPostString, true, 1 },
122 { L"O", NSwitchType::kUnLimitedPostString, false, 1 },
123 { L"W", NSwitchType::kUnLimitedPostString, false, 0 },
124 { L"I", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSiz e},
125 { L"X", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSiz e},
126 { L"AI", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSiz e},
127 { L"AX", NSwitchType::kUnLimitedPostString, true, kSomeCludePostStringMinSiz e},
128 { L"AN", NSwitchType::kSimple, false },
129 { L"U", NSwitchType::kUnLimitedPostString, true, 1},
130 { L"V", NSwitchType::kUnLimitedPostString, true, 1},
131 { L"R", NSwitchType::kPostChar, false, 0, 0, kRecursedPostCharSet },
132 { L"SFX", NSwitchType::kUnLimitedPostString, false, 0 },
133 { L"SI", NSwitchType::kUnLimitedPostString, false, 0 },
134 { L"SO", NSwitchType::kSimple, false, 0 },
135 { L"AO", NSwitchType::kPostChar, false, 1, 1, kOverwritePostCharSet},
136 { L"SEML", NSwitchType::kUnLimitedPostString, false, 0},
137 { L"AD", NSwitchType::kSimple, false },
138 { L"SLP", NSwitchType::kUnLimitedPostString, false, 0},
139 { L"SCS", NSwitchType::kUnLimitedPostString, false, 0},
140 { L"SLT", NSwitchType::kSimple, false },
141 { L"SSW", NSwitchType::kSimple, false },
142 { L"SSC", NSwitchType::kPostChar, false, 0, 0, L"-" }
143 };
144
145 static const CCommandForm g_CommandForms[] =
146 {
147 { L"A", false },
148 { L"U", false },
149 { L"D", false },
150 { L"T", false },
151 { L"E", false },
152 { L"X", false },
153 { L"L", false },
154 { L"B", false },
155 { L"I", false }
156 };
157
158 static const int kNumCommandForms = sizeof(g_CommandForms) / sizeof(g_CommandFo rms[0]);
159
160 static const wchar_t *kUniversalWildcard = L"*";
161 static const int kMinNonSwitchWords = 1;
162 static const int kCommandIndex = 0;
163
164 // ---------------------------
165 // exception messages
166
167 static const char *kUserErrorMessage = "Incorrect command line";
168 static const char *kIncorrectListFile = "Incorrect item in listfile.\nCheck char set encoding and -scs switch.";
169 static const char *kIncorrectWildCardInListFile = "Incorrect wildcard in listfil e";
170 static const char *kIncorrectWildCardInCommandLine = "Incorrect wildcard in com mand line";
171 static const char *kTerminalOutError = "I won't write compressed data to a termi nal";
172 static const char *kSameTerminalError = "I won't write data and program's messag es to same terminal";
173
174 static void ThrowException(const char *errorMessage)
175 {
176 throw CArchiveCommandLineException(errorMessage);
177 };
178
179 static void ThrowUserErrorException()
180 {
181 ThrowException(kUserErrorMessage);
182 };
183
184 // ---------------------------
185
186 bool CArchiveCommand::IsFromExtractGroup() const
187 {
188 switch(CommandType)
189 {
190 case NCommandType::kTest:
191 case NCommandType::kExtract:
192 case NCommandType::kFullExtract:
193 return true;
194 default:
195 return false;
196 }
197 }
198
199 NExtract::NPathMode::EEnum CArchiveCommand::GetPathMode() const
200 {
201 switch(CommandType)
202 {
203 case NCommandType::kTest:
204 case NCommandType::kFullExtract:
205 return NExtract::NPathMode::kFullPathnames;
206 default:
207 return NExtract::NPathMode::kNoPathnames;
208 }
209 }
210
211 bool CArchiveCommand::IsFromUpdateGroup() const
212 {
213 return (CommandType == NCommandType::kAdd ||
214 CommandType == NCommandType::kUpdate ||
215 CommandType == NCommandType::kDelete);
216 }
217
218 static NRecursedType::EEnum GetRecursedTypeFromIndex(int index)
219 {
220 switch (index)
221 {
222 case NRecursedPostCharIndex::kWildCardRecursionOnly:
223 return NRecursedType::kWildCardOnlyRecursed;
224 case NRecursedPostCharIndex::kNoRecursion:
225 return NRecursedType::kNonRecursed;
226 default:
227 return NRecursedType::kRecursed;
228 }
229 }
230
231 static bool ParseArchiveCommand(const UString &commandString, CArchiveCommand &c ommand)
232 {
233 UString commandStringUpper = commandString;
234 commandStringUpper.MakeUpper();
235 UString postString;
236 int commandIndex = ParseCommand(kNumCommandForms, g_CommandForms, commandStrin gUpper,
237 postString) ;
238 if (commandIndex < 0)
239 return false;
240 command.CommandType = (NCommandType::EEnum)commandIndex;
241 return true;
242 }
243
244 // ------------------------------------------------------------------
245 // filenames functions
246
247 static bool AddNameToCensor(NWildcard::CCensor &wildcardCensor,
248 const UString &name, bool include, NRecursedType::EEnum type)
249 {
250 bool isWildCard = DoesNameContainWildCard(name);
251 bool recursed = false;
252
253 switch (type)
254 {
255 case NRecursedType::kWildCardOnlyRecursed:
256 recursed = isWildCard;
257 break;
258 case NRecursedType::kRecursed:
259 recursed = true;
260 break;
261 case NRecursedType::kNonRecursed:
262 recursed = false;
263 break;
264 }
265 wildcardCensor.AddItem(include, name, recursed);
266 return true;
267 }
268
269 static void AddToCensorFromListFile(NWildcard::CCensor &wildcardCensor,
270 LPCWSTR fileName, bool include, NRecursedType::EEnum type, UINT codePage)
271 {
272 UStringVector names;
273 if (!ReadNamesFromListFile(fileName, names, codePage))
274 throw kIncorrectListFile;
275 for (int i = 0; i < names.Size(); i++)
276 if (!AddNameToCensor(wildcardCensor, names[i], include, type))
277 throw kIncorrectWildCardInListFile;
278 }
279
280 static void AddCommandLineWildCardToCensr(NWildcard::CCensor &wildcardCensor,
281 const UString &name, bool include, NRecursedType::EEnum recursedType)
282 {
283 if (!AddNameToCensor(wildcardCensor, name, include, recursedType))
284 throw kIncorrectWildCardInCommandLine;
285 }
286
287 static void AddToCensorFromNonSwitchesStrings(
288 int startIndex,
289 NWildcard::CCensor &wildcardCensor,
290 const UStringVector &nonSwitchStrings, NRecursedType::EEnum type,
291 bool thereAreSwitchIncludes, UINT codePage)
292 {
293 if (nonSwitchStrings.Size() == startIndex && (!thereAreSwitchIncludes))
294 AddCommandLineWildCardToCensr(wildcardCensor, kUniversalWildcard, true, type );
295 for (int i = startIndex; i < nonSwitchStrings.Size(); i++)
296 {
297 const UString &s = nonSwitchStrings[i];
298 if (s[0] == kFileListID)
299 AddToCensorFromListFile(wildcardCensor, s.Mid(1), true, type, codePage);
300 else
301 AddCommandLineWildCardToCensr(wildcardCensor, s, true, type);
302 }
303 }
304
305 #ifdef _WIN32
306 static void ParseMapWithPaths(NWildcard::CCensor &wildcardCensor,
307 const UString &switchParam, bool include,
308 NRecursedType::EEnum commonRecursedType)
309 {
310 int splitPos = switchParam.Find(L':');
311 if (splitPos < 0)
312 ThrowUserErrorException();
313 UString mappingName = switchParam.Left(splitPos);
314
315 UString switchParam2 = switchParam.Mid(splitPos + 1);
316 splitPos = switchParam2.Find(L':');
317 if (splitPos < 0)
318 ThrowUserErrorException();
319
320 UString mappingSize = switchParam2.Left(splitPos);
321 UString eventName = switchParam2.Mid(splitPos + 1);
322
323 UInt64 dataSize64 = ConvertStringToUInt64(mappingSize, NULL);
324 UInt32 dataSize = (UInt32)dataSize64;
325 {
326 CFileMapping fileMapping;
327 if (!fileMapping.Open(FILE_MAP_READ, false, GetSystemString(mappingName)))
328 ThrowException("Can not open mapping");
329 LPVOID data = fileMapping.MapViewOfFile(FILE_MAP_READ, 0, dataSize);
330 if (data == NULL)
331 ThrowException("MapViewOfFile error");
332 try
333 {
334 const wchar_t *curData = (const wchar_t *)data;
335 if (*curData != 0)
336 ThrowException("Incorrect mapping data");
337 UInt32 numChars = dataSize / sizeof(wchar_t);
338 UString name;
339 for (UInt32 i = 1; i < numChars; i++)
340 {
341 wchar_t c = curData[i];
342 if (c == L'\0')
343 {
344 AddCommandLineWildCardToCensr(wildcardCensor,
345 name, include, commonRecursedType);
346 name.Empty();
347 }
348 else
349 name += c;
350 }
351 if (!name.IsEmpty())
352 ThrowException("data error");
353 }
354 catch(...)
355 {
356 UnmapViewOfFile(data);
357 throw;
358 }
359 UnmapViewOfFile(data);
360 }
361
362 {
363 NSynchronization::CManualResetEvent event;
364 if (event.Open(EVENT_MODIFY_STATE, false, GetSystemString(eventName)) == S_O K)
365 event.Set();
366 }
367 }
368 #endif
369
370 static void AddSwitchWildCardsToCensor(NWildcard::CCensor &wildcardCensor,
371 const UStringVector &strings, bool include,
372 NRecursedType::EEnum commonRecursedType, UINT codePage)
373 {
374 for (int i = 0; i < strings.Size(); i++)
375 {
376 const UString &name = strings[i];
377 NRecursedType::EEnum recursedType;
378 int pos = 0;
379 if (name.Length() < kSomeCludePostStringMinSize)
380 ThrowUserErrorException();
381 if (::MyCharUpper(name[pos]) == kRecursedIDChar)
382 {
383 pos++;
384 int index = UString(kRecursedPostCharSet).Find(name[pos]);
385 recursedType = GetRecursedTypeFromIndex(index);
386 if (index >= 0)
387 pos++;
388 }
389 else
390 recursedType = commonRecursedType;
391 if (name.Length() < pos + kSomeCludeAfterRecursedPostStringMinSize)
392 ThrowUserErrorException();
393 UString tail = name.Mid(pos + 1);
394 if (name[pos] == kImmediateNameID)
395 AddCommandLineWildCardToCensr(wildcardCensor, tail, include, recursedType) ;
396 else if (name[pos] == kFileListID)
397 AddToCensorFromListFile(wildcardCensor, tail, include, recursedType, codeP age);
398 #ifdef _WIN32
399 else if (name[pos] == kMapNameID)
400 ParseMapWithPaths(wildcardCensor, tail, include, recursedType);
401 #endif
402 else
403 ThrowUserErrorException();
404 }
405 }
406
407 #ifdef _WIN32
408
409 // This code converts all short file names to long file names.
410
411 static void ConvertToLongName(const UString &prefix, UString &name)
412 {
413 if (name.IsEmpty() || DoesNameContainWildCard(name))
414 return;
415 NFind::CFileInfoW fileInfo;
416 if (NFind::FindFile(prefix + name, fileInfo))
417 name = fileInfo.Name;
418 }
419
420 static void ConvertToLongNames(const UString &prefix, CObjectVector<NWildcard::C Item> &items)
421 {
422 for (int i = 0; i < items.Size(); i++)
423 {
424 NWildcard::CItem &item = items[i];
425 if (item.Recursive || item.PathParts.Size() != 1)
426 continue;
427 ConvertToLongName(prefix, item.PathParts.Front());
428 }
429 }
430
431 static void ConvertToLongNames(const UString &prefix, NWildcard::CCensorNode &no de)
432 {
433 ConvertToLongNames(prefix, node.IncludeItems);
434 ConvertToLongNames(prefix, node.ExcludeItems);
435 int i;
436 for (i = 0; i < node.SubNodes.Size(); i++)
437 ConvertToLongName(prefix, node.SubNodes[i].Name);
438 // mix folders with same name
439 for (i = 0; i < node.SubNodes.Size(); i++)
440 {
441 NWildcard::CCensorNode &nextNode1 = node.SubNodes[i];
442 for (int j = i + 1; j < node.SubNodes.Size();)
443 {
444 const NWildcard::CCensorNode &nextNode2 = node.SubNodes[j];
445 if (nextNode1.Name.CompareNoCase(nextNode2.Name) == 0)
446 {
447 nextNode1.IncludeItems += nextNode2.IncludeItems;
448 nextNode1.ExcludeItems += nextNode2.ExcludeItems;
449 node.SubNodes.Delete(j);
450 }
451 else
452 j++;
453 }
454 }
455 for (i = 0; i < node.SubNodes.Size(); i++)
456 {
457 NWildcard::CCensorNode &nextNode = node.SubNodes[i];
458 ConvertToLongNames(prefix + nextNode.Name + wchar_t(NFile::NName::kDirDelimi ter), nextNode);
459 }
460 }
461
462 static void ConvertToLongNames(NWildcard::CCensor &censor)
463 {
464 for (int i = 0; i < censor.Pairs.Size(); i++)
465 {
466 NWildcard::CPair &pair = censor.Pairs[i];
467 ConvertToLongNames(pair.Prefix, pair.Head);
468 }
469 }
470
471 #endif
472
473 static NUpdateArchive::NPairAction::EEnum GetUpdatePairActionType(int i)
474 {
475 switch(i)
476 {
477 case NUpdateArchive::NPairAction::kIgnore: return NUpdateArchive::NPairActio n::kIgnore;
478 case NUpdateArchive::NPairAction::kCopy: return NUpdateArchive::NPairAction: :kCopy;
479 case NUpdateArchive::NPairAction::kCompress: return NUpdateArchive::NPairAct ion::kCompress;
480 case NUpdateArchive::NPairAction::kCompressAsAnti: return NUpdateArchive::NP airAction::kCompressAsAnti;
481 }
482 throw 98111603;
483 }
484
485 const UString kUpdatePairStateIDSet = L"PQRXYZW";
486 const int kUpdatePairStateNotSupportedActions[] = {2, 2, 1, -1, -1, -1, -1};
487
488 const UString kUpdatePairActionIDSet = L"0123"; //Ignore, Copy, Compress, Create Anti
489
490 const wchar_t *kUpdateIgnoreItselfPostStringID = L"-";
491 const wchar_t kUpdateNewArchivePostCharID = '!';
492
493
494 static bool ParseUpdateCommandString2(const UString &command,
495 NUpdateArchive::CActionSet &actionSet, UString &postString)
496 {
497 for (int i = 0; i < command.Length();)
498 {
499 wchar_t c = MyCharUpper(command[i]);
500 int statePos = kUpdatePairStateIDSet.Find(c);
501 if (statePos < 0)
502 {
503 postString = command.Mid(i);
504 return true;
505 }
506 i++;
507 if (i >= command.Length())
508 return false;
509 int actionPos = kUpdatePairActionIDSet.Find(::MyCharUpper(command[i]));
510 if (actionPos < 0)
511 return false;
512 actionSet.StateActions[statePos] = GetUpdatePairActionType(actionPos);
513 if (kUpdatePairStateNotSupportedActions[statePos] == actionPos)
514 return false;
515 i++;
516 }
517 postString.Empty();
518 return true;
519 }
520
521 static void ParseUpdateCommandString(CUpdateOptions &options,
522 const UStringVector &updatePostStrings,
523 const NUpdateArchive::CActionSet &defaultActionSet)
524 {
525 for (int i = 0; i < updatePostStrings.Size(); i++)
526 {
527 const UString &updateString = updatePostStrings[i];
528 if (updateString.CompareNoCase(kUpdateIgnoreItselfPostStringID) == 0)
529 {
530 if (options.UpdateArchiveItself)
531 {
532 options.UpdateArchiveItself = false;
533 options.Commands.Delete(0);
534 }
535 }
536 else
537 {
538 NUpdateArchive::CActionSet actionSet = defaultActionSet;
539
540 UString postString;
541 if (!ParseUpdateCommandString2(updateString, actionSet, postString))
542 ThrowUserErrorException();
543 if (postString.IsEmpty())
544 {
545 if (options.UpdateArchiveItself)
546 options.Commands[0].ActionSet = actionSet;
547 }
548 else
549 {
550 if (MyCharUpper(postString[0]) != kUpdateNewArchivePostCharID)
551 ThrowUserErrorException();
552 CUpdateArchiveCommand uc;
553 UString archivePath = postString.Mid(1);
554 if (archivePath.IsEmpty())
555 ThrowUserErrorException();
556 uc.UserArchivePath = archivePath;
557 uc.ActionSet = actionSet;
558 options.Commands.Add(uc);
559 }
560 }
561 }
562 }
563
564 static const char kByteSymbol = 'B';
565 static const char kKiloSymbol = 'K';
566 static const char kMegaSymbol = 'M';
567 static const char kGigaSymbol = 'G';
568
569 static bool ParseComplexSize(const UString &src, UInt64 &result)
570 {
571 UString s = src;
572 s.MakeUpper();
573
574 const wchar_t *start = s;
575 const wchar_t *end;
576 UInt64 number = ConvertStringToUInt64(start, &end);
577 int numDigits = (int)(end - start);
578 if (numDigits == 0 || s.Length() > numDigits + 1)
579 return false;
580 if (s.Length() == numDigits)
581 {
582 result = number;
583 return true;
584 }
585 int numBits;
586 switch (s[numDigits])
587 {
588 case kByteSymbol:
589 result = number;
590 return true;
591 case kKiloSymbol:
592 numBits = 10;
593 break;
594 case kMegaSymbol:
595 numBits = 20;
596 break;
597 case kGigaSymbol:
598 numBits = 30;
599 break;
600 default:
601 return false;
602 }
603 if (number >= ((UInt64)1 << (64 - numBits)))
604 return false;
605 result = number << numBits;
606 return true;
607 }
608
609 static void SetAddCommandOptions(
610 NCommandType::EEnum commandType,
611 const CParser &parser,
612 CUpdateOptions &options)
613 {
614 NUpdateArchive::CActionSet defaultActionSet;
615 switch(commandType)
616 {
617 case NCommandType::kAdd:
618 defaultActionSet = NUpdateArchive::kAddActionSet;
619 break;
620 case NCommandType::kDelete:
621 defaultActionSet = NUpdateArchive::kDeleteActionSet;
622 break;
623 default:
624 defaultActionSet = NUpdateArchive::kUpdateActionSet;
625 }
626
627 options.UpdateArchiveItself = true;
628
629 options.Commands.Clear();
630 CUpdateArchiveCommand updateMainCommand;
631 updateMainCommand.ActionSet = defaultActionSet;
632 options.Commands.Add(updateMainCommand);
633 if (parser[NKey::kUpdate].ThereIs)
634 ParseUpdateCommandString(options, parser[NKey::kUpdate].PostStrings,
635 defaultActionSet);
636 if (parser[NKey::kWorkingDir].ThereIs)
637 {
638 const UString &postString = parser[NKey::kWorkingDir].PostStrings[0];
639 if (postString.IsEmpty())
640 NDirectory::MyGetTempPath(options.WorkingDir);
641 else
642 options.WorkingDir = postString;
643 }
644 options.SfxMode = parser[NKey::kSfx].ThereIs;
645 if (options.SfxMode)
646 options.SfxModule = parser[NKey::kSfx].PostStrings[0];
647
648 if (parser[NKey::kVolume].ThereIs)
649 {
650 const UStringVector &sv = parser[NKey::kVolume].PostStrings;
651 for (int i = 0; i < sv.Size(); i++)
652 {
653 UInt64 size;
654 if (!ParseComplexSize(sv[i], size))
655 ThrowException("Incorrect volume size");
656 options.VolumesSizes.Add(size);
657 }
658 }
659 }
660
661 static void SetMethodOptions(const CParser &parser, CObjectVector<CProperty> &pr operties)
662 {
663 if (parser[NKey::kProperty].ThereIs)
664 {
665 // options.MethodMode.Properties.Clear();
666 for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++)
667 {
668 CProperty property;
669 const UString &postString = parser[NKey::kProperty].PostStrings[i];
670 int index = postString.Find(L'=');
671 if (index < 0)
672 property.Name = postString;
673 else
674 {
675 property.Name = postString.Left(index);
676 property.Value = postString.Mid(index + 1);
677 }
678 properties.Add(property);
679 }
680 }
681 }
682
683 CArchiveCommandLineParser::CArchiveCommandLineParser():
684 parser(sizeof(kSwitchForms) / sizeof(kSwitchForms[0])) {}
685
686 void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings,
687 CArchiveCommandLineOptions &options)
688 {
689 try
690 {
691 parser.ParseStrings(kSwitchForms, commandStrings);
692 }
693 catch(...)
694 {
695 ThrowUserErrorException();
696 }
697
698 options.IsInTerminal = MY_IS_TERMINAL(stdin);
699 options.IsStdOutTerminal = MY_IS_TERMINAL(stdout);
700 options.IsStdErrTerminal = MY_IS_TERMINAL(stderr);
701 options.StdOutMode = parser[NKey::kStdOut].ThereIs;
702 options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs;
703 options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereI s || parser[NKey::kHelp3].ThereIs;
704
705 #ifdef _WIN32
706 options.LargePages = false;
707 if (parser[NKey::kLargePages].ThereIs)
708 {
709 const UString &postString = parser[NKey::kLargePages].PostStrings.Front();
710 if (postString.IsEmpty())
711 options.LargePages = true;
712 }
713 #endif
714 }
715
716 struct CCodePagePair
717 {
718 const wchar_t *Name;
719 UINT CodePage;
720 };
721
722 static CCodePagePair g_CodePagePairs[] =
723 {
724 { L"UTF-8", CP_UTF8 },
725 { L"WIN", CP_ACP },
726 { L"DOS", CP_OEMCP }
727 };
728
729 static const int kNumCodePages = sizeof(g_CodePagePairs) / sizeof(g_CodePagePair s[0]);
730
731 static bool ConvertStringToUInt32(const wchar_t *s, UInt32 &v)
732 {
733 const wchar_t *end;
734 UInt64 number = ConvertStringToUInt64(s, &end);
735 if (*end != 0)
736 return false;
737 if (number > (UInt32)0xFFFFFFFF)
738 return false;
739 v = (UInt32)number;
740 return true;
741 }
742
743 void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options)
744 {
745 const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
746 int numNonSwitchStrings = nonSwitchStrings.Size();
747 if (numNonSwitchStrings < kMinNonSwitchWords)
748 ThrowUserErrorException();
749
750 if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command))
751 ThrowUserErrorException();
752
753 options.TechMode = parser[NKey::kTechMode].ThereIs;
754
755 if (parser[NKey::kCaseSensitive].ThereIs)
756 g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0);
757
758 NRecursedType::EEnum recursedType;
759 if (parser[NKey::kRecursed].ThereIs)
760 recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharInde x);
761 else
762 recursedType = NRecursedType::kNonRecursed;
763
764 UINT codePage = CP_UTF8;
765 if (parser[NKey::kCharSet].ThereIs)
766 {
767 UString name = parser[NKey::kCharSet].PostStrings.Front();
768 name.MakeUpper();
769 int i;
770 for (i = 0; i < kNumCodePages; i++)
771 {
772 const CCodePagePair &pair = g_CodePagePairs[i];
773 if (name.Compare(pair.Name) == 0)
774 {
775 codePage = pair.CodePage;
776 break;
777 }
778 }
779 if (i >= kNumCodePages)
780 ThrowUserErrorException();
781 }
782
783 bool thereAreSwitchIncludes = false;
784 if (parser[NKey::kInclude].ThereIs)
785 {
786 thereAreSwitchIncludes = true;
787 AddSwitchWildCardsToCensor(options.WildcardCensor,
788 parser[NKey::kInclude].PostStrings, true, recursedType, codePage);
789 }
790 if (parser[NKey::kExclude].ThereIs)
791 AddSwitchWildCardsToCensor(options.WildcardCensor,
792 parser[NKey::kExclude].PostStrings, false, recursedType, codePage);
793
794 int curCommandIndex = kCommandIndex + 1;
795 bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs &&
796 options.Command.CommandType != NCommandType::kBenchmark &&
797 options.Command.CommandType != NCommandType::kInfo;
798 if (thereIsArchiveName)
799 {
800 if (curCommandIndex >= numNonSwitchStrings)
801 ThrowUserErrorException();
802 options.ArchiveName = nonSwitchStrings[curCommandIndex++];
803 }
804
805 AddToCensorFromNonSwitchesStrings(
806 curCommandIndex, options.WildcardCensor,
807 nonSwitchStrings, recursedType, thereAreSwitchIncludes, codePage);
808
809 options.YesToAll = parser[NKey::kYes].ThereIs;
810
811 bool isExtractGroupCommand = options.Command.IsFromExtractGroup();
812
813 #ifndef _NO_CRYPTO
814 options.PasswordEnabled = parser[NKey::kPassword].ThereIs;
815 if (options.PasswordEnabled)
816 options.Password = parser[NKey::kPassword].PostStrings[0];
817 #endif
818
819 options.StdInMode = parser[NKey::kStdIn].ThereIs;
820 options.ShowDialog = parser[NKey::kShowDialog].ThereIs;
821
822 if (parser[NKey::kArchiveType].ThereIs)
823 options.ArcType = parser[NKey::kArchiveType].PostStrings[0];
824
825 if (isExtractGroupCommand || options.Command.CommandType == NCommandType::kLis t)
826 {
827 if (options.StdInMode)
828 ThrowException("Reading archives from stdin is not implemented");
829 if (!options.WildcardCensor.AllAreRelative())
830 ThrowException("Cannot use absolute pathnames for this command");
831
832 NWildcard::CCensor archiveWildcardCensor;
833
834 if (parser[NKey::kArInclude].ThereIs)
835 {
836 AddSwitchWildCardsToCensor(archiveWildcardCensor,
837 parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, codePage);
838 }
839 if (parser[NKey::kArExclude].ThereIs)
840 AddSwitchWildCardsToCensor(archiveWildcardCensor,
841 parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, codePage);
842
843 if (thereIsArchiveName)
844 AddCommandLineWildCardToCensr(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed);
845
846 #ifdef _WIN32
847 ConvertToLongNames(archiveWildcardCensor);
848 #endif
849
850 archiveWildcardCensor.ExtendExclude();
851
852 UStringVector archivePaths;
853
854 {
855 CDirItems dirItems;
856 {
857 UStringVector errorPaths;
858 CRecordVector<DWORD> errorCodes;
859 HRESULT res = EnumerateItems(archiveWildcardCensor, dirItems, NULL, erro rPaths, errorCodes);
860 if (res != S_OK || errorPaths.Size() > 0)
861 throw "cannot find archive";
862 }
863 for (int i = 0; i < dirItems.Items.Size(); i++)
864 {
865 const CDirItem &dirItem = dirItems.Items[i];
866 if (!dirItem.IsDir())
867 archivePaths.Add(dirItems.GetPhyPath(i));
868 }
869 }
870
871 if (archivePaths.Size() == 0)
872 throw "there is no such archive";
873
874 UStringVector archivePathsFull;
875
876 int i;
877 for (i = 0; i < archivePaths.Size(); i++)
878 {
879 UString fullPath;
880 NFile::NDirectory::MyGetFullPathName(archivePaths[i], fullPath);
881 archivePathsFull.Add(fullPath);
882 }
883 CIntVector indices;
884 SortFileNames(archivePathsFull, indices);
885 options.ArchivePathsSorted.Reserve(indices.Size());
886 options.ArchivePathsFullSorted.Reserve(indices.Size());
887 for (i = 0; i < indices.Size(); i++)
888 {
889 options.ArchivePathsSorted.Add(archivePaths[indices[i]]);
890 options.ArchivePathsFullSorted.Add(archivePathsFull[indices[i]]);
891 }
892
893 if (isExtractGroupCommand)
894 {
895 SetMethodOptions(parser, options.ExtractProperties);
896 if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerm inal)
897 throw kSameTerminalError;
898 if (parser[NKey::kOutputDir].ThereIs)
899 {
900 options.OutputDir = parser[NKey::kOutputDir].PostStrings[0];
901 NFile::NName::NormalizeDirPathPrefix(options.OutputDir);
902 }
903
904 options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore;
905 if (parser[NKey::kOverwrite].ThereIs)
906 options.OverwriteMode =
907 k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex];
908 else if (options.YesToAll)
909 options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;
910 }
911 }
912 else if (options.Command.IsFromUpdateGroup())
913 {
914 CUpdateOptions &updateOptions = options.UpdateOptions;
915
916 SetAddCommandOptions(options.Command.CommandType, parser, updateOptions);
917
918 SetMethodOptions(parser, updateOptions.MethodMode.Properties);
919
920 if (parser[NKey::kShareForWrite].ThereIs)
921 updateOptions.OpenShareForWrite = true;
922
923 options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs;
924
925 if (options.EnablePercents)
926 {
927 if ((options.StdOutMode && !options.IsStdErrTerminal) ||
928 (!options.StdOutMode && !options.IsStdOutTerminal))
929 options.EnablePercents = false;
930 }
931
932 updateOptions.EMailMode = parser[NKey::kEmail].ThereIs;
933 if (updateOptions.EMailMode)
934 {
935 updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front();
936 if (updateOptions.EMailAddress.Length() > 0)
937 if (updateOptions.EMailAddress[0] == L'.')
938 {
939 updateOptions.EMailRemoveAfter = true;
940 updateOptions.EMailAddress.Delete(0);
941 }
942 }
943
944 updateOptions.StdOutMode = options.StdOutMode;
945 updateOptions.StdInMode = options.StdInMode;
946
947 if (updateOptions.StdOutMode && updateOptions.EMailMode)
948 throw "stdout mode and email mode cannot be combined";
949 if (updateOptions.StdOutMode && options.IsStdOutTerminal)
950 throw kTerminalOutError;
951 if (updateOptions.StdInMode)
952 updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front();
953
954 #ifdef _WIN32
955 ConvertToLongNames(options.WildcardCensor);
956 #endif
957 }
958 else if (options.Command.CommandType == NCommandType::kBenchmark)
959 {
960 options.NumThreads = (UInt32)-1;
961 options.DictionarySize = (UInt32)-1;
962 options.NumIterations = 1;
963 if (curCommandIndex < numNonSwitchStrings)
964 {
965 if (!ConvertStringToUInt32(nonSwitchStrings[curCommandIndex++], options.Nu mIterations))
966 ThrowUserErrorException();
967 }
968 for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++)
969 {
970 UString postString = parser[NKey::kProperty].PostStrings[i];
971 postString.MakeUpper();
972 if (postString.Length() < 2)
973 ThrowUserErrorException();
974 if (postString[0] == 'D')
975 {
976 int pos = 1;
977 if (postString[pos] == '=')
978 pos++;
979 UInt32 logSize;
980 if (!ConvertStringToUInt32((const wchar_t *)postString + pos, logSize))
981 ThrowUserErrorException();
982 if (logSize > 31)
983 ThrowUserErrorException();
984 options.DictionarySize = 1 << logSize;
985 }
986 else if (postString[0] == 'M' && postString[1] == 'T' )
987 {
988 int pos = 2;
989 if (postString[pos] == '=')
990 pos++;
991 if (postString[pos] != 0)
992 if (!ConvertStringToUInt32((const wchar_t *)postString + pos, options. NumThreads))
993 ThrowUserErrorException();
994 }
995 else if (postString[0] == 'M' && postString[1] == '=' )
996 {
997 int pos = 2;
998 if (postString[pos] != 0)
999 options.Method = postString.Mid(2);
1000 }
1001 else
1002 ThrowUserErrorException();
1003 }
1004 }
1005 else if (options.Command.CommandType == NCommandType::kInfo)
1006 {
1007 }
1008 else
1009 ThrowUserErrorException();
1010 options.WildcardCensor.ExtendExclude();
1011 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698