HRESULT DecompressArchives( UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &optionsSpec, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback) { CExtractOptions options = optionsSpec; for (int i = 0; i < archivePaths.Size(); i++) { const UString &archivePath = archivePaths[i]; NFile::NFind::CFileInfoW archiveFileInfo; if (!NFile::NFind::FindFile(archivePath, archiveFileInfo)) throw "there is no such archive"; if (archiveFileInfo.IsDirectory()) throw "there is no such archive"; options.ArchiveFileInfo = archiveFileInfo; RINOK(extractCallback->BeforeOpen(archivePath)); CArchiveLink archiveLink; HRESULT result = MyOpenArchive(archivePath, archiveLink, openCallback); RINOK(extractCallback->OpenResult(archivePath, result)); if (result != S_OK) continue; for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { archivePaths.Delete(index); archivePathsFull.Delete(index); } } #ifndef _NO_CRYPTO UString password; RINOK(openCallback->GetPasswordIfAny(password)); if (!password.IsEmpty()) { RINOK(extractCallback->SetPassword(password)); } #endif options.DefaultItemName = archiveLink.GetDefaultItemName(); RINOK(DecompressArchive( archiveLink.GetArchive(), archiveLink.GetDefaultItemName(), wildcardCensor, options, extractCallback)); } return S_OK; }
void AddUniqueStringToHeadOfList(UStringVector &list, const UString &s) { for (unsigned i = 0; i < list.Size();) if (s.IsEqualTo_NoCase(list[i])) list.Delete(i); else i++; list.Insert(0, s); }
void CCensor::AddItem(bool include, const UString &path, bool recursive) { UStringVector pathParts; SplitPathToParts(path, pathParts); bool forFile = true; if (pathParts.Back().IsEmpty()) { forFile = false; pathParts.DeleteBack(); } const UString &front = pathParts.Front(); bool isAbs = false; if (front.IsEmpty()) isAbs = true; else if (front.Length() == 2 && front[1] == L':') isAbs = true; else { for (int i = 0; i < pathParts.Size(); i++) { const UString &part = pathParts[i]; if (part == L".." || part == L".") { isAbs = true; break; } } } int numAbsParts = 0; if (isAbs) if (pathParts.Size() > 1) numAbsParts = pathParts.Size() - 1; else numAbsParts = 1; UString prefix; for (int i = 0; i < numAbsParts; i++) { const UString &front = pathParts.Front(); if (DoesNameContainWildCard(front)) break; prefix += front; prefix += WCHAR_PATH_SEPARATOR; pathParts.Delete(0); } int index = FindPrefix(prefix); if (index < 0) index = Pairs.Add(CPair(prefix)); CItem item; item.PathParts = pathParts; item.ForDir = true; item.ForFile = forFile; item.Recursive = recursive; Pairs[index].Head.AddItem(include, item); }
void MakeCorrectPath(UStringVector &pathParts) { for (int i = 0; i < pathParts.Size();) { UString &s = pathParts[i]; s = GetCorrectFileName(s); if (s.IsEmpty()) pathParts.Delete(i); else i++; } }
void MakeCorrectPath(UStringVector &pathParts) { for (int i = 0; i < pathParts.Size();) { UString &s = pathParts[i]; s = GetCorrectFileName(s); if (s.IsEmpty()) pathParts.Delete(i); else { #ifdef _WIN32 if (!IsSupportedName(s)) s = (UString)L"_" + s; #endif i++; } } }
HRESULT DecompressArchives( CCodecs *codecs, const CIntVector &formatIndices, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &optionsSpec, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, UString &errorMessage, CDecompressStat &stat) { stat.Clear(); CExtractOptions options = optionsSpec; int i; UInt64 totalPackSize = 0; CRecordVector<UInt64> archiveSizes; for (i = 0; i < archivePaths.Size(); i++) { const UString &archivePath = archivePaths[i]; NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(archivePath, fi)) throw "there is no such archive"; if (fi.IsDir()) throw "can't decompress folder"; archiveSizes.Add(fi.Size); totalPackSize += fi.Size; } CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec); bool multi = (archivePaths.Size() > 1); extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode); if (multi) { RINOK(extractCallback->SetTotal(totalPackSize)); } for (i = 0; i < archivePaths.Size(); i++) { const UString &archivePath = archivePaths[i]; NFile::NFind::CFileInfoW fi; if (!NFile::NFind::FindFile(archivePath, fi)) throw "there is no such archive"; if (fi.IsDir()) throw "there is no such archive"; options.ArchiveFileInfo = fi; #ifndef _NO_CRYPTO openCallback->Open_ClearPasswordWasAskedFlag(); #endif RINOK(extractCallback->BeforeOpen(archivePath)); CArchiveLink archiveLink; CIntVector formatIndices2 = formatIndices; #ifndef _SFX if (formatIndices.IsEmpty()) { int pos = archivePath.ReverseFind(L'.'); if (pos >= 0) { UString s = archivePath.Mid(pos + 1); int index = codecs->FindFormatForExtension(s); if (index >= 0 && s == L"001") { s = archivePath.Left(pos); pos = s.ReverseFind(L'.'); if (pos >= 0) { int index2 = codecs->FindFormatForExtension(s.Mid(pos + 1)); if (index2 >= 0 && s.CompareNoCase(L"rar") != 0) { formatIndices2.Add(index2); formatIndices2.Add(index); } } } } } #endif HRESULT result = MyOpenArchive(codecs, formatIndices2, archivePath, archiveLink, openCallback); if (result == E_ABORT) return result; bool crypted = false; #ifndef _NO_CRYPTO crypted = openCallback->Open_WasPasswordAsked(); #endif RINOK(extractCallback->OpenResult(archivePath, result, crypted)); if (result != S_OK) continue; for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { archivePaths.Delete(index); archivePathsFull.Delete(index); totalPackSize -= archiveSizes[index]; archiveSizes.Delete(index); } } if (archiveLink.VolumePaths.Size() != 0) { totalPackSize += archiveLink.VolumesSize; RINOK(extractCallback->SetTotal(totalPackSize)); } #ifndef _NO_CRYPTO UString password; RINOK(openCallback->Open_GetPasswordIfAny(password)); if (!password.IsEmpty()) { RINOK(extractCallback->SetPassword(password)); } #endif options.DefaultItemName = archiveLink.GetDefaultItemName(); RINOK(DecompressArchive( archiveLink.GetArchive(), fi.Size + archiveLink.VolumesSize, wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage)); extractCallbackSpec->LocalProgressSpec->InSize += fi.Size + archiveLink.VolumesSize; extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize; if (!errorMessage.IsEmpty()) return E_FAIL; } stat.NumFolders = extractCallbackSpec->NumFolders; stat.NumFiles = extractCallbackSpec->NumFiles; stat.UnpackSize = extractCallbackSpec->UnpackSize; stat.NumArchives = archivePaths.Size(); stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize; return S_OK; }
HRESULT ListArchives(CCodecs *codecs, const CIntVector &formatIndices, bool stdInMode, UStringVector &arcPaths, UStringVector &arcPathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, #ifndef _NO_CRYPTO bool &passwordEnabled, UString &password, #endif UInt64 &numErrors) { numErrors = 0; CFieldPrinter fieldPrinter; if (!techMode) fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0])); UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0; UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0; int numArcs = /* stdInMode ? 1 : */ arcPaths.Size(); for (int i = 0; i < numArcs; i++) { const UString &archiveName = arcPaths[i]; UInt64 arcPackSize = 0; if (!stdInMode) { NFile::NFind::CFileInfoW fi; if (!fi.Find(archiveName) || fi.IsDir()) { g_StdOut << endl << "Error: " << archiveName << " is not file" << endl; numErrors++; continue; } arcPackSize = fi.Size; } CArchiveLink archiveLink; COpenCallbackConsole openCallback; openCallback.OutStream = &g_StdOut; #ifndef _NO_CRYPTO openCallback.PasswordIsDefined = passwordEnabled; openCallback.Password = password; #endif HRESULT result = archiveLink.Open2(codecs, formatIndices, stdInMode, NULL, archiveName, &openCallback); if (result != S_OK) { if (result == E_ABORT) return result; g_StdOut << endl << "Error: " << archiveName << ": "; if (result == S_FALSE) { #ifndef _NO_CRYPTO if (openCallback.Open_WasPasswordAsked()) g_StdOut << "Can not open encrypted archive. Wrong password?"; else #endif g_StdOut << "Can not open file as archive"; } else if (result == E_OUTOFMEMORY) g_StdOut << "Can't allocate required memory"; else g_StdOut << NError::MyFormatMessage(result); g_StdOut << endl; numErrors++; continue; } if (!stdInMode) for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { arcPaths.Delete(index); arcPathsFull.Delete(index); numArcs = arcPaths.Size(); } } if (enableHeaders) { g_StdOut << endl << kListing << archiveName << endl << endl; for (int i = 0; i < archiveLink.Arcs.Size(); i++) { const CArc &arc = archiveLink.Arcs[i]; g_StdOut << "--\n"; PrintPropPair(L"Path", arc.Path); PrintPropPair(L"Type", codecs->Formats[arc.FormatIndex].Name); if (!arc.ErrorMessage.IsEmpty()) PrintPropPair(L"Error", arc.ErrorMessage); UInt32 numProps; IInArchive *archive = arc.Archive; if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK) { for (UInt32 j = 0; j < numProps; j++) { CMyComBSTR name; PROPID propID; VARTYPE vt; RINOK(archive->GetArchivePropertyInfo(j, &name, &propID, &vt)); NCOM::CPropVariant prop; RINOK(archive->GetArchiveProperty(propID, &prop)); UString s = ConvertPropertyToString(prop, propID); if (!s.IsEmpty()) PrintPropPair(GetPropName(propID, name), s); } } if (i != archiveLink.Arcs.Size() - 1) { UInt32 numProps; g_StdOut << "----\n"; if (archive->GetNumberOfProperties(&numProps) == S_OK) { UInt32 mainIndex = archiveLink.Arcs[i + 1].SubfileIndex; for (UInt32 j = 0; j < numProps; j++) { CMyComBSTR name; PROPID propID; VARTYPE vt; RINOK(archive->GetPropertyInfo(j, &name, &propID, &vt)); NCOM::CPropVariant prop; RINOK(archive->GetProperty(mainIndex, propID, &prop)); UString s = ConvertPropertyToString(prop, propID); if (!s.IsEmpty()) PrintPropPair(GetPropName(propID, name), s); } } } } g_StdOut << endl; if (techMode) g_StdOut << "----------\n"; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitle(); g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; } const CArc &arc = archiveLink.Arcs.Back(); IInArchive *archive = arc.Archive; if (techMode) { RINOK(fieldPrinter.Init(archive)); } UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0; UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); for (UInt32 i = 0; i < numItems; i++) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; UString filePath; HRESULT res = arc.GetItemPath(i, filePath); if (stdInMode && res == E_INVALIDARG) break; RINOK(res); bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); if (!wildcardCensor.CheckPath(filePath, !isFolder)) continue; fieldPrinter.PrintItemInfo(arc, i, techMode); UInt64 packSize, unpackSize; if (!GetUInt64Value(archive, i, kpidSize, unpackSize)) unpackSize = 0; else totalUnPackSizePointer = &totalUnPackSize; if (!GetUInt64Value(archive, i, kpidPackSize, packSize)) packSize = 0; else totalPackSizePointer = &totalPackSize; g_StdOut << endl; if (isFolder) numDirs++; else numFiles++; totalPackSize += packSize; totalUnPackSize += unpackSize; } if (!stdInMode && totalPackSizePointer == 0) { if (archiveLink.VolumePaths.Size() != 0) arcPackSize += archiveLink.VolumesSize; totalPackSize = (numFiles == 0) ? 0 : arcPackSize; totalPackSizePointer = &totalPackSize; } if (totalUnPackSizePointer == 0 && numFiles == 0) { totalUnPackSize = 0; totalUnPackSizePointer = &totalUnPackSize; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer); g_StdOut << endl; } if (totalPackSizePointer != 0) { totalPackSizePointer2 = &totalPackSize2; totalPackSize2 += totalPackSize; } if (totalUnPackSizePointer != 0) { totalUnPackSizePointer2 = &totalUnPackSize2; totalUnPackSize2 += totalUnPackSize; } numFiles2 += numFiles; numDirs2 += numDirs; } if (enableHeaders && !techMode && numArcs > 1) { g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2); g_StdOut << endl; g_StdOut << "Archives: " << numArcs << endl; } return S_OK; }
int Main2(int argc,TCHAR **argv) { UStringVector commandStrings; #ifdef _WIN32 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); #else extern void mySplitCommandLineW(int numArguments,TCHAR **arguments,UStringVector &parts); mySplitCommandLineW(argc,argv,commandStrings); #endif #ifndef UNDER_CE if (commandStrings.Size() > 0) commandStrings.Delete(0); #endif if (commandStrings.Size() == 0) { MessageBoxW(0, L"Specify command", L"7-Zip", 0); return 0; } /* { CSysString resultPath; NWindows::NFile::NDirectory::MyGetCurrentDirectory(resultPath); ::MessageBoxW(0, resultPath, L"7-Zip - curDir", 0); } */ CArchiveCommandLineOptions options; CArchiveCommandLineParser parser; parser.Parse1(commandStrings, options); parser.Parse2(options); #if defined(_WIN32) && defined(_7ZIP_LARGE_PAGES) if (options.LargePages) NSecurity::EnableLockMemoryPrivilege(); #endif CCodecs *codecs = new CCodecs; CMyComPtr<IUnknown> compressCodecsInfo = codecs; HRESULT result = codecs->Load(); if (result != S_OK) throw CSystemException(result); bool isExtractGroupCommand = options.Command.IsFromExtractGroup(); if (codecs->Formats.Size() == 0 && (isExtractGroupCommand || options.Command.IsFromUpdateGroup())) throw kNoFormats; CIntVector formatIndices; if (!codecs->FindFormatForArchiveType(options.ArcType, formatIndices)) { ErrorLangMessage(IDS_UNSUPPORTED_ARCHIVE_TYPE, 0x0200060D); return NExitCode::kFatalError; } if (options.Command.CommandType == NCommandType::kBenchmark) { HRESULT res; #ifdef EXTERNAL_CODECS CObjectVector<CCodecInfoEx> externalCodecs; res = LoadExternalCodecs(codecs, externalCodecs); if (res != S_OK) throw CSystemException(res); #endif res = Benchmark( #ifdef EXTERNAL_CODECS codecs, &externalCodecs, #endif options.NumThreads, options.DictionarySize); if (res != S_OK) throw CSystemException(res); } else if (isExtractGroupCommand) { CExtractCallbackImp *ecs = new CExtractCallbackImp; CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; #ifndef _NO_CRYPTO ecs->PasswordIsDefined = options.PasswordEnabled; ecs->Password = options.Password; #endif ecs->Init(); CExtractOptions eo; eo.StdOutMode = options.StdOutMode; eo.OutputDir = options.OutputDir; eo.YesToAll = options.YesToAll; eo.OverwriteMode = options.OverwriteMode; eo.PathMode = options.Command.GetPathMode(); eo.TestMode = options.Command.IsTestMode(); eo.CalcCrc = options.CalcCrc; #if !defined(_7ZIP_ST) && !defined(_SFX) eo.Properties = options.ExtractProperties; #endif bool messageWasDisplayed = false; HRESULT result = ExtractGUI(codecs, formatIndices, options.ArchivePathsSorted, options.ArchivePathsFullSorted, options.WildcardCensor.Pairs.Front().Head, eo, options.ShowDialog, messageWasDisplayed, ecs); if (result != S_OK) { if (result != E_ABORT && messageWasDisplayed) return NExitCode::kFatalError; throw CSystemException(result); } if (!ecs->IsOK()) return NExitCode::kFatalError; } else if (options.Command.IsFromUpdateGroup()) { #ifndef _NO_CRYPTO bool passwordIsDefined = options.PasswordEnabled && !options.Password.IsEmpty(); #endif CUpdateCallbackGUI callback; // callback.EnablePercents = options.EnablePercents; #ifndef _NO_CRYPTO callback.PasswordIsDefined = passwordIsDefined; callback.AskPassword = options.PasswordEnabled && options.Password.IsEmpty(); callback.Password = options.Password; #endif // callback.StdOutMode = options.UpdateOptions.StdOutMode; callback.Init(); if (!options.UpdateOptions.Init(codecs, formatIndices, options.ArchiveName)) { ErrorLangMessage(IDS_UPDATE_NOT_SUPPORTED, 0x02000601); return NExitCode::kFatalError; } bool messageWasDisplayed = false; HRESULT result = UpdateGUI( codecs, options.WildcardCensor, options.UpdateOptions, options.ShowDialog, messageWasDisplayed, &callback); if (result != S_OK) { if (result != E_ABORT && messageWasDisplayed) return NExitCode::kFatalError; throw CSystemException(result); } if (callback.FailedFiles.Size() > 0) { if (!messageWasDisplayed) throw CSystemException(E_FAIL); return NExitCode::kWarning; } } else { throw "Unsupported command"; } return 0; }
int Main2( #ifndef _WIN32 int numArgs, char *args[] #endif ) { #if defined(_WIN32) && !defined(UNDER_CE) SetFileApisToOEM(); #endif g_StdOut << kCopyrightString; UStringVector commandStrings; #ifdef _WIN32 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); #else // GetArguments(numArgs, args, commandStrings); mySplitCommandLine(numArgs,args,commandStrings); #endif #ifdef _WIN32 FString arcPath; { FString path; NDLL::MyGetModuleFileName(path); if (!MyGetFullPathName(path, arcPath)) { g_StdOut << "GetFullPathName Error"; return NExitCode::kFatalError; } } #else // After mySplitCommandLine showP7zipInfo(&g_StdOut); UString arcPath = commandStrings.Front(); #endif commandStrings.Delete(0); NCommandLineParser::CParser parser(kNumSwitches); try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { PrintHelpAndExit(); } if (parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) { PrintHelp(); return 0; } const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int numNonSwitchStrings = nonSwitchStrings.Size(); CArchiveCommand command; if (numNonSwitchStrings == 0) command.CommandType = NCommandType::kFullExtract; else { if (numNonSwitchStrings > 1) PrintHelpAndExit(); if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], command)) PrintHelpAndExit(); } NRecursedType::EEnum recursedType; recursedType = command.DefaultRecursedType(); NWildcard::CCensor wildcardCensor; bool thereAreSwitchIncludeWildcards; thereAreSwitchIncludeWildcards = false; AddToCensorFromNonSwitchesStrings(wildcardCensor, nonSwitchStrings, recursedType, thereAreSwitchIncludeWildcards); bool yesToAll = parser[NKey::kYes].ThereIs; // NExtractMode::EEnum extractMode; // bool isExtractGroupCommand = command.IsFromExtractGroup(extractMode); bool passwordEnabled = parser[NKey::kPassword].ThereIs; UString password; if (passwordEnabled) password = parser[NKey::kPassword].PostStrings[0]; if (!NFind::DoesFileExist(arcPath)) throw kCantFindSFX; FString outputDir; if (parser[NKey::kOutputDir].ThereIs) { outputDir = us2fs(parser[NKey::kOutputDir].PostStrings[0]); NName::NormalizeDirPathPrefix(outputDir); } wildcardCensor.AddPathsToCensor(NWildcard::k_RelatPath); { UStringVector v1, v2; v1.Add(fs2us(arcPath)); v2.Add(fs2us(arcPath)); const NWildcard::CCensorNode &wildcardCensorHead = wildcardCensor.Pairs.Front().Head; CCodecs *codecs = new CCodecs; CMyComPtr< #ifdef EXTERNAL_CODECS ICompressCodecsInfo #else IUnknown #endif > compressCodecsInfo = codecs; { HRESULT result = codecs->Load(); if (result != S_OK) throw CSystemException(result); } if (command.CommandType != NCommandType::kList) { CExtractCallbackConsole *ecs = new CExtractCallbackConsole; CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; ecs->Init(g_StdStream, &g_StdErr, g_StdStream); #ifndef _NO_CRYPTO ecs->PasswordIsDefined = passwordEnabled; ecs->Password = password; #endif /* COpenCallbackConsole openCallback; openCallback.Init(g_StdStream, g_StdStream); #ifndef _NO_CRYPTO openCallback.PasswordIsDefined = passwordEnabled; openCallback.Password = password; #endif */ CExtractOptions eo; eo.StdOutMode = false; eo.YesToAll = yesToAll; eo.TestMode = command.CommandType == NCommandType::kTest; eo.PathMode = NExtract::NPathMode::kFullPaths; eo.OverwriteMode = yesToAll ? NExtract::NOverwriteMode::kOverwrite : NExtract::NOverwriteMode::kAsk; eo.OutputDir = outputDir; UString errorMessage; CDecompressStat stat; HRESULT result = Extract( codecs, CObjectVector<COpenType>(), CIntVector(), v1, v2, wildcardCensorHead, eo, ecs, ecs, // NULL, // hash errorMessage, stat); if (!errorMessage.IsEmpty()) { (*g_StdStream) << endl << "Error: " << errorMessage;; if (result == S_OK) result = E_FAIL; } if (ecs->NumArcsWithError != 0 || ecs->NumFileErrors != 0) { if (ecs->NumArcsWithError != 0) (*g_StdStream) << endl << "Archive Errors" << endl; if (ecs->NumFileErrors != 0) (*g_StdStream) << endl << "Sub items Errors: " << ecs->NumFileErrors << endl; return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); } else { throw CSystemException(E_NOTIMPL); /* UInt64 numErrors = 0; UInt64 numWarnings = 0; HRESULT result = ListArchives( codecs, CObjectVector<COpenType>(), CIntVector(), false, // stdInMode v1, v2, true, // processAltStreams false, // showAltStreams wildcardCensorHead, true, // enableHeaders false, // techMode #ifndef _NO_CRYPTO passwordEnabled, password, #endif numErrors, numWarnings); if (numErrors > 0) { g_StdOut << endl << "Errors: " << numErrors; return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); */ } } return 0; }
int APIENTRY WinMain2() { UString password; bool assumeYes = false; bool outputFolderDefined = false; UString outputFolder; UStringVector commandStrings; NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); #ifndef UNDER_CE if (commandStrings.Size() > 0) commandStrings.Delete(0); #endif for (int i = 0; i < commandStrings.Size(); i++) { const UString &s = commandStrings[i]; if (s.CompareNoCase(L"-y") == 0) assumeYes = true; else if (s.Left(2).CompareNoCase(L"-o") == 0) { outputFolder = s.Mid(2); NWindows::NFile::NName::NormalizeDirPathPrefix(outputFolder); outputFolderDefined = !outputFolder.IsEmpty(); } else if (s.Left(2).CompareNoCase(L"-p") == 0) { password = s.Mid(2); } } UString path; NWindows::NDLL::MyGetModuleFileName(g_hInstance, path); UString fullPath; int fileNamePartStartIndex; if (!NWindows::NFile::NDirectory::MyGetFullPathName(path, fullPath, fileNamePartStartIndex)) { ShowErrorMessage(L"Error 1329484"); return 1; } CCodecs *codecs = new CCodecs; CMyComPtr<IUnknown> compressCodecsInfo = codecs; HRESULT result = codecs->Load(); if (result != S_OK) { ErrorMessageForHRESULT(result); return 1; } // COpenCallbackGUI openCallback; // openCallback.PasswordIsDefined = !password.IsEmpty(); // openCallback.Password = password; CExtractCallbackImp *ecs = new CExtractCallbackImp; CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; ecs->Init(); #ifndef _NO_CRYPTO ecs->PasswordIsDefined = !password.IsEmpty(); ecs->Password = password; #endif CExtractOptions eo; eo.OutputDir = outputFolderDefined ? outputFolder : fullPath.Left(fileNamePartStartIndex); eo.YesToAll = assumeYes; eo.OverwriteMode = assumeYes ? NExtract::NOverwriteMode::kWithoutPrompt : NExtract::NOverwriteMode::kAskBefore; eo.PathMode = NExtract::NPathMode::kFullPathnames; eo.TestMode = false; UStringVector v1, v2; v1.Add(fullPath); v2.Add(fullPath); NWildcard::CCensorNode wildcardCensor; wildcardCensor.AddItem(true, L"*", true, true, true); bool messageWasDisplayed = false; result = ExtractGUI(codecs, CIntVector(), v1, v2, wildcardCensor, eo, (assumeYes ? false: true), messageWasDisplayed, ecs); if (result == S_OK) { if (!ecs->IsOK()) return NExitCode::kFatalError; return 0; } if (result == E_ABORT) return NExitCode::kUserBreak; if (!messageWasDisplayed) { if (result == S_FALSE) ShowErrorMessage(L"Error in archive"); else ErrorMessageForHRESULT(result); } if (result == E_OUTOFMEMORY) return NExitCode::kMemoryError; return NExitCode::kFatalError; }
int APIENTRY WinMain2() { // OleInitialize is required for ProgressBar in TaskBar. #ifndef UNDER_CE OleInitialize(NULL); #endif #ifndef UNDER_CE g_ComCtl32Version = ::GetDllVersion(TEXT("comctl32.dll")); g_LVN_ITEMACTIVATE_Support = (g_ComCtl32Version >= MAKELONG(71, 4)); #endif UString password; bool assumeYes = false; bool outputFolderDefined = false; FString outputFolder; UStringVector commandStrings; NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); #ifndef UNDER_CE if (commandStrings.Size() > 0) commandStrings.Delete(0); #endif FOR_VECTOR (i, commandStrings) { const UString &s = commandStrings[i]; if (s.Len() > 1 && s[0] == '-') { wchar_t c = MyCharLower_Ascii(s[1]); if (c == 'y') { assumeYes = true; if (s.Len() != 2) { ShowErrorMessage(L"Bad command"); return 1; } } else if (c == 'o') { outputFolder = us2fs(s.Ptr(2)); NName::NormalizeDirPathPrefix(outputFolder); outputFolderDefined = !outputFolder.IsEmpty(); } else if (c == 'p') { password = s.Ptr(2); } } } FString path; NDLL::MyGetModuleFileName(path); FString fullPath; if (!MyGetFullPathName(path, fullPath)) { ShowErrorMessage(L"Error 1329484"); return 1; } CCodecs *codecs = new CCodecs; CMyComPtr<IUnknown> compressCodecsInfo = codecs; HRESULT result = codecs->Load(); if (result != S_OK) { ErrorMessageForHRESULT(result); return 1; } // COpenCallbackGUI openCallback; // openCallback.PasswordIsDefined = !password.IsEmpty(); // openCallback.Password = password; CExtractCallbackImp *ecs = new CExtractCallbackImp; CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; ecs->Init(); #ifndef _NO_CRYPTO ecs->PasswordIsDefined = !password.IsEmpty(); ecs->Password = password; #endif CExtractOptions eo; FString dirPrefix; if (!GetOnlyDirPrefix(path, dirPrefix)) { ShowErrorMessage(L"Error 1329485"); return 1; } eo.OutputDir = outputFolderDefined ? outputFolder : dirPrefix; eo.YesToAll = assumeYes; eo.OverwriteMode = assumeYes ? NExtract::NOverwriteMode::kOverwrite : NExtract::NOverwriteMode::kAsk; eo.PathMode = NExtract::NPathMode::kFullPaths; eo.TestMode = false; UStringVector v1, v2; v1.Add(fs2us(fullPath)); v2.Add(fs2us(fullPath)); NWildcard::CCensorNode wildcardCensor; wildcardCensor.AddItem(true, L"*", true, true, true, true); bool messageWasDisplayed = false; result = ExtractGUI(codecs, CObjectVector<COpenType>(), CIntVector(), v1, v2, wildcardCensor, eo, (assumeYes ? false: true), messageWasDisplayed, ecs); if (result == S_OK) { if (!ecs->IsOK()) return NExitCode::kFatalError; return 0; } if (result == E_ABORT) return NExitCode::kUserBreak; if (!messageWasDisplayed) { if (result == S_FALSE) ShowErrorMessage(L"Error in archive"); else ErrorMessageForHRESULT(result); } if (result == E_OUTOFMEMORY) return NExitCode::kMemoryError; return NExitCode::kFatalError; }
HRESULT ListArchives( CCodecs *codecs, UStringVector &archivePaths, UStringVector &archivePathsFull, const NWildcard::CCensorNode &wildcardCensor, bool enableHeaders, bool techMode, bool &passwordEnabled, UString &password, UInt64 &numErrors) { numErrors = 0; CFieldPrinter fieldPrinter; if (!techMode) fieldPrinter.Init(kStandardFieldTable, sizeof(kStandardFieldTable) / sizeof(kStandardFieldTable[0])); UInt64 numFiles2 = 0, numDirs2 = 0, totalPackSize2 = 0, totalUnPackSize2 = 0; UInt64 *totalPackSizePointer2 = 0, *totalUnPackSizePointer2 = 0; for (int i = 0; i < archivePaths.Size(); i++) { const UString &archiveName = archivePaths[i]; NFile::NFind::CFileInfoW archiveFileInfo; if (!NFile::NFind::FindFile(archiveName, archiveFileInfo) || archiveFileInfo.IsDirectory()) { g_StdOut << endl << "Error: " << archiveName << " is not archive" << endl; numErrors++; continue; } if (archiveFileInfo.IsDirectory()) { g_StdOut << endl << "Error: " << archiveName << " is not file" << endl; numErrors++; continue; } CArchiveLink archiveLink; COpenCallbackConsole openCallback; openCallback.OutStream = &g_StdOut; openCallback.PasswordIsDefined = passwordEnabled; openCallback.Password = password; HRESULT result = MyOpenArchive(codecs, archiveName, archiveLink, &openCallback); if (result != S_OK) { g_StdOut << endl << "Error: " << archiveName << " is not supported archive" << endl; numErrors++; continue; } for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = archivePathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { archivePaths.Delete(index); archivePathsFull.Delete(index); } } IInArchive *archive = archiveLink.GetArchive(); const UString defaultItemName = archiveLink.GetDefaultItemName(); if (enableHeaders) { g_StdOut << endl << kListing << archiveName << endl << endl; UInt32 numProps; if (archive->GetNumberOfArchiveProperties(&numProps) == S_OK) { for (UInt32 i = 0; i < numProps; i++) { CMyComBSTR name; PROPID propID; VARTYPE vt; if (archive->GetArchivePropertyInfo(i, &name, &propID, &vt) != S_OK) continue; NCOM::CPropVariant prop; if (archive->GetArchiveProperty(propID, &prop) != S_OK) continue; UString s = ConvertPropertyToString(prop, propID); if (!s.IsEmpty()) g_StdOut << GetPropName(propID, name) << " = " << s << endl; } } if (techMode) g_StdOut << "----------\n"; if (numProps > 0) g_StdOut << endl; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitle(); g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; } if (techMode) { RINOK(fieldPrinter.Init(archive)); } UInt64 numFiles = 0, numDirs = 0, totalPackSize = 0, totalUnPackSize = 0; UInt64 *totalPackSizePointer = 0, *totalUnPackSizePointer = 0; UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)); for(UInt32 i = 0; i < numItems; i++) { if (NConsoleClose::TestBreakSignal()) return E_ABORT; UString filePath; RINOK(GetArchiveItemPath(archive, i, defaultItemName, filePath)); bool isFolder; RINOK(IsArchiveItemFolder(archive, i, isFolder)); if (!wildcardCensor.CheckPath(filePath, !isFolder)) continue; fieldPrinter.PrintItemInfo(archive, defaultItemName, archiveFileInfo, i, techMode); UInt64 packSize, unpackSize; if (!GetUInt64Value(archive, i, kpidSize, unpackSize)) unpackSize = 0; else totalUnPackSizePointer = &totalUnPackSize; if (!GetUInt64Value(archive, i, kpidPackedSize, packSize)) packSize = 0; else totalPackSizePointer = &totalPackSize; g_StdOut << endl; if (isFolder) numDirs++; else numFiles++; totalPackSize += packSize; totalUnPackSize += unpackSize; } if (enableHeaders && !techMode) { fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles, numDirs, totalUnPackSizePointer, totalPackSizePointer); g_StdOut << endl; } if (totalPackSizePointer != 0) { totalPackSizePointer2 = &totalPackSize2; totalPackSize2 += totalPackSize; } if (totalUnPackSizePointer != 0) { totalUnPackSizePointer2 = &totalUnPackSize2; totalUnPackSize2 += totalUnPackSize; } numFiles2 += numFiles; numDirs2 += numDirs; } if (enableHeaders && !techMode && archivePaths.Size() > 1) { g_StdOut << endl; fieldPrinter.PrintTitleLines(); g_StdOut << endl; fieldPrinter.PrintSummaryInfo(numFiles2, numDirs2, totalUnPackSizePointer2, totalPackSizePointer2); g_StdOut << endl; g_StdOut << "Archives: " << archivePaths.Size() << endl; } return S_OK; }
// Create a new 7z archive for each folder contained in the archive to be // exploded. HRESULT ExplodeArchives(CCodecs *codecs, const CIntVector &formatIndices, bool stdInMode, UStringVector &arcPaths, UStringVector &arcPathsFull, UString& outputPath, UInt64 maxDepth, UInt64 &numErrors) { int numArcs = arcPaths.Size(); for (int i = 0; i < numArcs; i++) { UString archivePath = arcPaths[i]; /*UString outputPath = arcPaths[i]; outputPath.Replace(L'\\', L'/'); // linux and windows consistent const UString archiveName = StripFile(outputPath); outputPath.Empty();*/ archivePath.Replace(L'\\', L'/'); // linux, windows and archive consistent outputPath.Replace(L'\\', L'/'); FixPathFormat(outputPath); const UString archiveName = GetFileFromPath(archivePath); g_StdOut << "Outputting into : " << outputPath << endl; UInt64 arcPackSize = 0; if (!stdInMode) { NFile::NFind::CFileInfoW fi; if (!fi.Find(archivePath) || fi.IsDir()) { SHOW_ERROR("is not a file."); continue; } arcPackSize = fi.Size; } g_StdOut << endl << "Exploding : " << archivePath << endl << endl; CArchiveLink archiveLink; COpenCallbackConsole openCallback; openCallback.OutStream = &g_StdOut; #ifndef _NO_CRYPTO openCallback.PasswordIsDefined = false; #endif HRESULT result = archiveLink.Open2(codecs, formatIndices, stdInMode, NULL, archivePath, &openCallback); if (result != S_OK) { if (result == E_ABORT) return result; g_StdOut << endl << "Error: " << archivePath << ": "; if (result == S_FALSE) g_StdOut << "Can not open file as archive"; else if (result == E_OUTOFMEMORY) g_StdOut << "Can't allocate required memory"; else g_StdOut << NError::MyFormatMessage(result); g_StdOut << endl; numErrors++; continue; } // remove other files names if multi-volume if (!stdInMode) { for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { arcPaths.Delete(index); arcPathsFull.Delete(index); numArcs = arcPaths.Size(); } } } // don't support multi volume because i have to reopen the stream if (archiveLink.VolumePaths.Size() != 1) { SHOW_ERROR("Exploding multi-volume archives isn't supported."); continue; } bool szArchive = true; for (int x = 0; x < archiveLink.Arcs.Size(); x++) { const UString szName = L"7z"; const CArc &arc = archiveLink.Arcs[x]; if (codecs->Formats[arc.FormatIndex].Name != szName) { szArchive = false; break; } } if (!szArchive) { SHOW_ERROR("Only 7z archives can be exploded."); continue; } // Only 7z is supported, and it's been checked using namespace NArchive::N7z; IInArchive* inArc = archiveLink.GetArchive(); CHandler* szHandler = (CHandler*)inArc; // not a fan of having to reopen the file.. CInFileStream* _inStream = new CInFileStream; CMyComPtr<CInFileStream> inStream(_inStream); if (!inStream->Open(archivePath)) { SHOW_ERROR("Cannot be opened for reading."); continue; } // Explode the archive into each folder CObjectVector<szExplodeData> exploded; szHandler->Explode(exploded, maxDepth); if (exploded.Size() == 0) { SHOW_ERROR("Empty archive!"); continue; } // should make a struct that gets passed to Explode.. // something like /* * struct a { * CArchiveDatabase newDatabase; * CRecordVector<UInt64> folderSizes, folderPositions * }; * CObjectVector<a> exploded; * szHandler->Explode(exploded); */ // Save each folder as a new 7z archive for (int x = 0; x < exploded.Size(); x++) { UString relativeFilePath; // relative to archive UString fileName; CArchiveDatabase& newDatabase = exploded[x].newDatabase; szExplodeData& explodeData = exploded[x]; // each exploded archive will only have a single folder. // no longer true. need to make sure the selected file // is the highest in the dir tree. could make 7zhandler // give us this info i guess. if (newDatabase.Files.Size() > 0) { relativeFilePath = newDatabase.Files[0].Name; if (!newDatabase.Files[0].IsDir) { fileName = GetFileFromPath(relativeFilePath); StripFile(relativeFilePath); } } //g_StdOut << "Relative path " << relativeFilePath << endl; //g_StdOut << "Archive " << archivePath << endl; UString folderOutPath = outputPath + relativeFilePath; if (relativeFilePath.Length() != 0) { bool b = NWindows::NFile::NDirectory::CreateComplexDirectory(folderOutPath); if (!b) g_StdOut << "Couldn't create directory " << folderOutPath << endl; //relativeFilePath.Insert(folderOutPath.Length(), L'/'); } std::wstringstream sstream; sstream << folderOutPath.GetBuffer(); if (newDatabase.Files.Size() == 1) // can use file names sstream << fileName.GetBuffer(); else // use folder as name sstream << archiveName.GetBuffer() << L"_folder_" << x; sstream << ".7z"; g_StdOut << "Saving as '" << sstream.str().c_str() << "'" << endl; COutFileStream* _outstream = new COutFileStream; CMyComPtr<COutFileStream> outstream(_outstream); outstream->Create(sstream.str().c_str(), true); COutArchive out; out.Create(outstream, false); out.SkipPrefixArchiveHeader(); for (int folderIndex = 0; folderIndex < newDatabase.Folders.Size(); folderIndex++) { UInt64 folderLen = explodeData.folderSizes[folderIndex]; UInt64 folderStartPackPos = explodeData.folderPositions[folderIndex]; // write actual data RINOK(WriteRange(inStream, out.SeqStream, folderStartPackPos, folderLen, NULL)); } CCompressionMethodMode method, headerMethod; szHandler->SetCompressionMethod(method, headerMethod); CHeaderOptions headerOptions; headerOptions.CompressMainHeader = true; out.WriteDatabase(newDatabase, &headerMethod, headerOptions); out.Close(); /*#ifdef ENV_UNIX // Create a symlink for each file in the folder. // This makes it seem as though each file is individually accessible. for (int fileIndex = 0; fileIndex < newDatabase.Files.Size(); fileIndex++) { AString oldfile, newfile; UString woldfile = sstream.str().c_str(); UString wnewfile = outputPath + relativeFilePath + newDatabase.Files[fileIndex].Name + L".7z"; ConvertUnicodeToUTF8(woldfile, oldfile); ConvertUnicodeToUTF8(wnewfile, newfile); const char* link_to = oldfile.GetBuffer(); const char* link_name = newfile.GetBuffer(); unlink(link_name);// should ask user //g_StdOut << "Creating symlink to '" << link_to << "' called '" << link_name << "'" << endl; int status = symlink(link_to, link_name); if (status == -1) { AString error = "Couldn't create symlink for '"; error += newfile; error += "'"; SHOW_ERROR(error); g_StdOut << "Error: " << errno << endl; } } #endif*/ } archiveLink.Close(); // not needed but oh well } return S_OK; }
void Correct_FsPath(bool absIsAllowed, UStringVector &parts, bool isDir) { unsigned i = 0; if (absIsAllowed) { #if defined(_WIN32) && !defined(UNDER_CE) bool isDrive = false; #endif if (parts[0].IsEmpty()) { i = 1; #if defined(_WIN32) && !defined(UNDER_CE) if (parts.Size() > 1 && parts[1].IsEmpty()) { i = 2; if (parts.Size() > 2 && parts[2] == L"?") { i = 3; if (parts.Size() > 3 && NWindows::NFile::NName::IsDrivePath2(parts[3])) { isDrive = true; i = 4; } } } #endif } #if defined(_WIN32) && !defined(UNDER_CE) else if (NWindows::NFile::NName::IsDrivePath2(parts[0])) { isDrive = true; i = 1; } if (isDrive) { // we convert "c:name" to "c:\name", if absIsAllowed path. UString &ds = parts[i - 1]; if (ds.Len() > 2) { parts.Insert(i, ds.Ptr(2)); ds.DeleteFrom(2); } } #endif } for (; i < parts.Size();) { UString &s = parts[i]; Correct_PathPart(s); if (s.IsEmpty()) { if (isDir || i != parts.Size() - 1) { parts.Delete(i); continue; } s = k_EmptyReplaceName; } else { #ifdef _WIN32 CorrectUnsupportedName(s); #endif } i++; } if (!isDir) { if (parts.IsEmpty()) parts.Add((UString)k_EmptyReplaceName); else { UString &s = parts.Back(); if (s.IsEmpty()) s = k_EmptyReplaceName; } } }
int Main2( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ) { #ifdef _WIN32 SetFileApisToOEM(); #endif g_StdOut << kCopyrightString; UStringVector commandStrings; #ifdef _WIN32 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); #else GetArguments(numArguments, arguments, commandStrings); #endif UString archiveName = commandStrings.Front(); commandStrings.Delete(0); NCommandLineParser::CParser parser(kNumSwitches); try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { PrintHelpAndExit(); } if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) { PrintHelp(); return 0; } const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int numNonSwitchStrings = nonSwitchStrings.Size(); CArchiveCommand command; if (numNonSwitchStrings == 0) command.CommandType = NCommandType::kFullExtract; else { if (numNonSwitchStrings > 1) PrintHelpAndExit(); if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], command)) PrintHelpAndExit(); } NRecursedType::EEnum recursedType; recursedType = command.DefaultRecursedType(); NWildcard::CCensor wildcardCensor; bool thereAreSwitchIncludeWildCards; thereAreSwitchIncludeWildCards = false; AddToCensorFromNonSwitchesStrings(wildcardCensor, nonSwitchStrings, recursedType, thereAreSwitchIncludeWildCards); bool yesToAll = parser[NKey::kYes].ThereIs; #ifdef _WIN32 if (archiveName.Right(kDefaultExtLength).CompareNoCase(kDefaultExt) != 0) archiveName += kDefaultExt; #endif // NExtractMode::EEnum extractMode; // bool isExtractGroupCommand = command.IsFromExtractGroup(extractMode); bool passwordEnabled = parser[NKey::kPassword].ThereIs; UString password; if(passwordEnabled) password = parser[NKey::kPassword].PostStrings[0]; NFind::CFileInfoW archiveFileInfo; if (!NFind::FindFile(archiveName, archiveFileInfo)) throw kCantFindSFX; if (archiveFileInfo.IsDir()) throw kCantFindSFX; UString outputDir; if(parser[NKey::kOutputDir].ThereIs) { outputDir = parser[NKey::kOutputDir].PostStrings[0]; NName::NormalizeDirPathPrefix(outputDir); } { UStringVector v1, v2; v1.Add(archiveName); v2.Add(archiveName); const NWildcard::CCensorNode &wildcardCensorHead = wildcardCensor.Pairs.Front().Head; CCodecs *codecs = new CCodecs; CMyComPtr< #ifdef EXTERNAL_CODECS ICompressCodecsInfo #else IUnknown #endif > compressCodecsInfo = codecs; HRESULT result = codecs->Load(); if (result != S_OK) throw CSystemException(result); if(command.CommandType != NCommandType::kList) { CExtractCallbackConsole *ecs = new CExtractCallbackConsole; CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; ecs->OutStream = g_StdStream; ecs->PasswordIsDefined = passwordEnabled; ecs->Password = password; ecs->Init(); COpenCallbackConsole openCallback; openCallback.OutStream = g_StdStream; openCallback.PasswordIsDefined = passwordEnabled; openCallback.Password = password; CExtractOptions eo; eo.StdOutMode = false; eo.PathMode = NExtract::NPathMode::kFullPathnames; eo.TestMode = command.CommandType == NCommandType::kTest; eo.OverwriteMode = yesToAll ? NExtract::NOverwriteMode::kWithoutPrompt : NExtract::NOverwriteMode::kAskBefore; eo.OutputDir = outputDir; eo.YesToAll = yesToAll; UString errorMessage; CDecompressStat stat; HRESULT result = DecompressArchives( codecs, CIntVector(), v1, v2, wildcardCensorHead, eo, &openCallback, ecs, errorMessage, stat); if (!errorMessage.IsEmpty()) { (*g_StdStream) << endl << "Error: " << errorMessage;; if (result == S_OK) result = E_FAIL; } if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0) { if (ecs->NumArchiveErrors != 0) (*g_StdStream) << endl << "Archive Errors: " << ecs->NumArchiveErrors << endl; if (ecs->NumFileErrors != 0) (*g_StdStream) << endl << "Sub items Errors: " << ecs->NumFileErrors << endl; return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); } else { UInt64 numErrors = 0; HRESULT result = ListArchives( codecs, CIntVector(), v1, v2, wildcardCensorHead, true, false, passwordEnabled, password, numErrors); if (numErrors > 0) { g_StdOut << endl << "Errors: " << numErrors; return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); } } return 0; }
int Main2( #ifndef _WIN32 int numArguments, const char *arguments[] #endif ) { #ifdef _WIN32 SetFileApisToOEM(); #endif UStringVector commandStrings; #ifdef _WIN32 NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); #else extern void mySplitCommandLine(int numArguments,const char *arguments[],UStringVector &parts); mySplitCommandLine(numArguments,arguments,commandStrings); #endif // After mySplitCommandLine g_StdOut << kCopyrightString << " (locale=" << my_getlocale() <<",Utf16="; if (global_use_utf16_conversion) g_StdOut << "on"; else g_StdOut << "off"; g_StdOut << ",HugeFiles="; if (sizeof(off_t) >= 8) g_StdOut << "on,"; else g_StdOut << "off,"; int nbcpu = NWindows::NSystem::GetNumberOfProcessors(); if (nbcpu > 1) g_StdOut << nbcpu << " CPUs)\n"; else g_StdOut << nbcpu << " CPU)\n"; UString arcPath = commandStrings.Front(); commandStrings.Delete(0); NCommandLineParser::CParser parser(kNumSwitches); try { parser.ParseStrings(kSwitchForms, commandStrings); } catch(...) { PrintHelpAndExit(); } if(parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs) { PrintHelp(); return 0; } const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; int numNonSwitchStrings = nonSwitchStrings.Size(); CArchiveCommand command; if (numNonSwitchStrings == 0) command.CommandType = NCommandType::kFullExtract; else { if (numNonSwitchStrings > 1) PrintHelpAndExit(); if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], command)) PrintHelpAndExit(); } NRecursedType::EEnum recursedType; recursedType = command.DefaultRecursedType(); NWildcard::CCensor wildcardCensor; bool thereAreSwitchIncludeWildCards; thereAreSwitchIncludeWildCards = false; AddToCensorFromNonSwitchesStrings(wildcardCensor, nonSwitchStrings, recursedType, thereAreSwitchIncludeWildCards); bool yesToAll = parser[NKey::kYes].ThereIs; // NExtractMode::EEnum extractMode; // bool isExtractGroupCommand = command.IsFromExtractGroup(extractMode); bool passwordEnabled = parser[NKey::kPassword].ThereIs; UString password; if(passwordEnabled) password = parser[NKey::kPassword].PostStrings[0]; if (!NFind::DoesFileExist(arcPath)) throw kCantFindSFX; UString outputDir; if (parser[NKey::kOutputDir].ThereIs) { outputDir = parser[NKey::kOutputDir].PostStrings[0]; NName::NormalizeDirPathPrefix(outputDir); } { UStringVector v1, v2; v1.Add(arcPath); v2.Add(arcPath); const NWildcard::CCensorNode &wildcardCensorHead = wildcardCensor.Pairs.Front().Head; CCodecs *codecs = new CCodecs; CMyComPtr< #ifdef EXTERNAL_CODECS ICompressCodecsInfo #else IUnknown #endif > compressCodecsInfo = codecs; HRESULT result = codecs->Load(); if (result != S_OK) throw CSystemException(result); if(command.CommandType != NCommandType::kList) { CExtractCallbackConsole *ecs = new CExtractCallbackConsole; CMyComPtr<IFolderArchiveExtractCallback> extractCallback = ecs; ecs->OutStream = g_StdStream; #ifndef _NO_CRYPTO ecs->PasswordIsDefined = passwordEnabled; ecs->Password = password; #endif ecs->Init(); COpenCallbackConsole openCallback; openCallback.OutStream = g_StdStream; #ifndef _NO_CRYPTO openCallback.PasswordIsDefined = passwordEnabled; openCallback.Password = password; #endif CExtractOptions eo; eo.StdOutMode = false; eo.PathMode = NExtract::NPathMode::kFullPathnames; eo.TestMode = command.CommandType == NCommandType::kTest; eo.OverwriteMode = yesToAll ? NExtract::NOverwriteMode::kWithoutPrompt : NExtract::NOverwriteMode::kAskBefore; eo.OutputDir = outputDir; eo.YesToAll = yesToAll; UString errorMessage; CDecompressStat stat; HRESULT result = DecompressArchives( codecs, CIntVector(), v1, v2, wildcardCensorHead, eo, &openCallback, ecs, errorMessage, stat); if (!errorMessage.IsEmpty()) { (*g_StdStream) << endl << "Error: " << errorMessage;; if (result == S_OK) result = E_FAIL; } if (ecs->NumArchiveErrors != 0 || ecs->NumFileErrors != 0) { if (ecs->NumArchiveErrors != 0) (*g_StdStream) << endl << "Archive Errors: " << ecs->NumArchiveErrors << endl; if (ecs->NumFileErrors != 0) (*g_StdStream) << endl << "Sub items Errors: " << ecs->NumFileErrors << endl; return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); } else { UInt64 numErrors = 0; HRESULT result = ListArchives( codecs, CIntVector(), false, v1, v2, wildcardCensorHead, true, false, #ifndef _NO_CRYPTO passwordEnabled, password, #endif numErrors); if (numErrors > 0) { g_StdOut << endl << "Errors: " << numErrors; return NExitCode::kFatalError; } if (result != S_OK) throw CSystemException(result); } } return 0; }
HRESULT DecompressArchives( CCodecs *codecs, const CIntVector &formatIndices, UStringVector &arcPaths, UStringVector &arcPathsFull, const NWildcard::CCensorNode &wildcardCensor, const CExtractOptions &options, IOpenCallbackUI *openCallback, IExtractCallbackUI *extractCallback, UString &errorMessage, CDecompressStat &stat) { stat.Clear(); int i; UInt64 totalPackSize = 0; CRecordVector<UInt64> archiveSizes; int numArcs = options.StdInMode ? 1 : arcPaths.Size(); for (i = 0; i < numArcs; i++) { NFile::NFind::CFileInfoW fi; fi.Size = 0; if (!options.StdInMode) { const UString &arcPath = arcPaths[i]; if (!fi.Find(arcPath)) throw "there is no such archive"; if (fi.IsDir()) throw "can't decompress folder"; } archiveSizes.Add(fi.Size); totalPackSize += fi.Size; } CArchiveExtractCallback *extractCallbackSpec = new CArchiveExtractCallback; CMyComPtr<IArchiveExtractCallback> ec(extractCallbackSpec); bool multi = (numArcs > 1); extractCallbackSpec->InitForMulti(multi, options.PathMode, options.OverwriteMode); if (multi) { RINOK(extractCallback->SetTotal(totalPackSize)); } for (i = 0; i < numArcs; i++) { const UString &arcPath = arcPaths[i]; NFile::NFind::CFileInfoW fi; if (options.StdInMode) { fi.Size = 0; fi.Attrib = 0; } else { if (!fi.Find(arcPath) || fi.IsDir()) throw "there is no such archive"; } #ifndef _NO_CRYPTO openCallback->Open_ClearPasswordWasAskedFlag(); #endif RINOK(extractCallback->BeforeOpen(arcPath)); CArchiveLink archiveLink; CIntVector formatIndices2 = formatIndices; #ifndef _SFX if (formatIndices.IsEmpty()) { int pos = arcPath.ReverseFind(L'.'); if (pos >= 0) { UString s = arcPath.Mid(pos + 1); int index = codecs->FindFormatForExtension(s); if (index >= 0 && s == L"001") { s = arcPath.Left(pos); pos = s.ReverseFind(L'.'); if (pos >= 0) { int index2 = codecs->FindFormatForExtension(s.Mid(pos + 1)); if (index2 >= 0 && s.CompareNoCase(L"rar") != 0) { formatIndices2.Add(index2); formatIndices2.Add(index); } } } } } #endif HRESULT result = archiveLink.Open2(codecs, formatIndices2, options.StdInMode, NULL, arcPath, openCallback); if (result == E_ABORT) return result; bool crypted = false; #ifndef _NO_CRYPTO crypted = openCallback->Open_WasPasswordAsked(); /* if(!crypted) { fprintf(stderr, "%s is not encrypted!\n", "123"); exit(0); } */ #endif RINOK(extractCallback->OpenResult(arcPath, result, crypted)); if (result != S_OK) continue; if (!options.StdInMode) for (int v = 0; v < archiveLink.VolumePaths.Size(); v++) { int index = arcPathsFull.FindInSorted(archiveLink.VolumePaths[v]); if (index >= 0 && index > i) { arcPaths.Delete(index); arcPathsFull.Delete(index); totalPackSize -= archiveSizes[index]; archiveSizes.Delete(index); numArcs = arcPaths.Size(); } } if (archiveLink.VolumePaths.Size() != 0) { totalPackSize += archiveLink.VolumesSize; RINOK(extractCallback->SetTotal(totalPackSize)); } #ifndef _NO_CRYPTO UString password; RINOK(openCallback->Open_GetPasswordIfAny(password)); if (!password.IsEmpty()) { RINOK(extractCallback->SetPassword(password)); } #endif for (int v = 0; v < archiveLink.Arcs.Size(); v++) { const UString &s = archiveLink.Arcs[v].ErrorMessage; if (!s.IsEmpty()) { RINOK(extractCallback->MessageError(s)); } } CArc &arc = archiveLink.Arcs.Back(); arc.MTimeDefined = (!options.StdInMode && !fi.IsDevice); arc.MTime = fi.MTime; UInt64 packProcessed; RINOK(DecompressArchive(arc, fi.Size + archiveLink.VolumesSize, wildcardCensor, options, extractCallback, extractCallbackSpec, errorMessage, packProcessed)); if (!options.StdInMode) packProcessed = fi.Size + archiveLink.VolumesSize; extractCallbackSpec->LocalProgressSpec->InSize += packProcessed; extractCallbackSpec->LocalProgressSpec->OutSize = extractCallbackSpec->UnpackSize; if (!errorMessage.IsEmpty()) return E_FAIL; } stat.NumFolders = extractCallbackSpec->NumFolders; stat.NumFiles = extractCallbackSpec->NumFiles; stat.UnpackSize = extractCallbackSpec->UnpackSize; stat.CrcSum = extractCallbackSpec->CrcSum; stat.NumArchives = arcPaths.Size(); stat.PackSize = extractCallbackSpec->LocalProgressSpec->InSize; return S_OK; }