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; }
HRESULT CCodecs::LoadDllsFromFolder(const CSysString &folderPrefix) { #ifdef _UNICODE NFile::NFind::CEnumeratorW enumerator(folderPrefix + CSysString(TEXT("*"))); NFile::NFind::CFileInfoW fi; #else NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*"))); NFile::NFind::CFileInfo fi; #endif while (enumerator.Next(fi)) { if (fi.IsDir()) continue; RINOK(LoadDll(folderPrefix + fi.Name)); } return S_OK; }
STDMETHODIMP COpenArchiveCallback::GetStream(const wchar_t *name, IInStream **inStream) { *inStream = NULL; if (_subArchiveMode) return S_FALSE; NFile::NFind::CFileInfoW fileInfo; UString fullPath = _folderPrefix + name; if (!fileInfo.Find(fullPath)) return S_FALSE; _fileInfo = fileInfo; if (_fileInfo.IsDir()) return S_FALSE; CInFileStream *inFile = new CInFileStream; CMyComPtr<IInStream> inStreamTemp = inFile; if (!inFile->Open(fullPath)) return ::GetLastError(); *inStream = inStreamTemp.Detach(); return S_OK; }
UString CreateArchiveName(const UString &srcName, bool fromPrev, bool keepName) { UString resultName = L"Archive"; if (fromPrev) { UString dirPrefix; if (NFile::NDirectory::GetOnlyDirPrefix(srcName, dirPrefix)) { if (dirPrefix.Length() > 0) if (dirPrefix[dirPrefix.Length() - 1] == WCHAR_PATH_SEPARATOR) { dirPrefix.Delete(dirPrefix.Length() - 1); NFile::NFind::CFileInfoW fileInfo; if (NFile::NFind::FindFile(dirPrefix, fileInfo)) resultName = fileInfo.Name; } } } else { NFile::NFind::CFileInfoW fileInfo; if (!NFile::NFind::FindFile(srcName, fileInfo)) return resultName; resultName = fileInfo.Name; if (!fileInfo.IsDir() && !keepName) { int dotPos = resultName.ReverseFind('.'); if (dotPos > 0) { UString archiveName2 = resultName.Left(dotPos); if (archiveName2.ReverseFind('.') < 0) resultName = archiveName2; } } } return resultName; }
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; }
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); if ((HWND) lParam != NULL && wmEvent != 0) break; if (wmId >= kToolbarStartID) { ExecuteCommand(wmId); return 0; } if (OnMenuCommand(hWnd, wmId)) return 0; break; case WM_INITMENUPOPUP: OnMenuActivating(hWnd, HMENU(wParam), LOWORD(lParam)); break; /* It doesn't help case WM_EXITMENULOOP: { OnMenuUnActivating(hWnd); break; } case WM_UNINITMENUPOPUP: OnMenuUnActivating(hWnd, HMENU(wParam), lParam); break; */ case WM_CREATE: { /* INITCOMMONCONTROLSEX icex; icex.dwSize = sizeof(INITCOMMONCONTROLSEX); icex.dwICC = ICC_BAR_CLASSES; InitCommonControlsEx(&icex); // Toolbar buttons used to create the first 4 buttons. TBBUTTON tbb [ ] = { // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0}, // {VIEW_PARENTFOLDER, kParentFolderID, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0}, // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0}, {VIEW_NEWFOLDER, ID_FILE_CREATEFOLDER, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0}, }; int baseID = 100; NWindows::NControl::CToolBar aToolBar; aToolBar.Attach(::CreateToolbarEx (hWnd, WS_CHILD | WS_BORDER | WS_VISIBLE | TBSTYLE_TOOLTIPS, // | TBSTYLE_FLAT baseID + 2, 11, (HINSTANCE)HINST_COMMCTRL, IDB_VIEW_SMALL_COLOR, (LPCTBBUTTON)&tbb, sizeof(tbb) / sizeof(tbb[0]), 0, 0, 100, 30, sizeof (TBBUTTON))); */ // HCURSOR cursor = ::LoadCursor(0, IDC_SIZEWE); // ::SetCursor(cursor); if (g_PanelsInfoDefined) g_Splitter.SetPos(hWnd, g_SplitterPos); else { g_Splitter.SetRatio(hWnd, kSplitterRateMax / 2); g_SplitterPos = g_Splitter.GetPos(); } RECT rect; ::GetClientRect(hWnd, &rect); int xSize = rect.right; int xSizes[2]; xSizes[0] = g_Splitter.GetPos(); xSizes[1] = xSize - kSplitterWidth - xSizes[0]; if (xSizes[1] < 0) xSizes[1] = 0; g_App.CreateDragTarget(); bool archiveIsOpened; bool encrypted; bool needOpenFile = false; if (!g_MainPath.IsEmpty() /* && g_OpenArchive */) { NFile::NFind::CFileInfoW fileInfo; if (NFile::NFind::FindFile(g_MainPath, fileInfo)) if (!fileInfo.IsDir()) needOpenFile = true; } HRESULT res = g_App.Create(hWnd, g_MainPath, xSizes, archiveIsOpened, encrypted); if (res == E_ABORT) { return -1; } if (needOpenFile && !archiveIsOpened || res != S_OK) { UString message = L"Error"; if (res == S_FALSE || res == S_OK) { if (encrypted) message = MyFormatNew(IDS_CANT_OPEN_ENCRYPTED_ARCHIVE, 0x0200060A, g_MainPath); else message = MyFormatNew(IDS_CANT_OPEN_ARCHIVE, 0x02000609, g_MainPath); } else { if (res != S_OK) { if (res == E_OUTOFMEMORY) message = LangString(IDS_MEM_ERROR, 0x0200060B); else if (!NError::MyFormatMessage(res, message)) message = L"Error"; } } MessageBoxW(0, message, L"7-zip", MB_ICONERROR); return -1; } // g_SplitterPos = 0; // ::DragAcceptFiles(hWnd, TRUE); RegisterDragDrop(hWnd, g_App._dropTarget); break; } case WM_DESTROY: { // ::DragAcceptFiles(hWnd, FALSE); RevokeDragDrop(hWnd); g_App._dropTarget.Release(); g_App.Save(); g_App.Release(); SaveWindowInfo(hWnd); PostQuitMessage(0); break; } /* case WM_MOVE: { break; } */ case WM_LBUTTONDOWN: g_StartCaptureMousePos = LOWORD(lParam); g_StartCaptureSplitterPos = g_Splitter.GetPos(); ::SetCapture(hWnd); break; case WM_LBUTTONUP: { ::ReleaseCapture(); break; } case WM_MOUSEMOVE: { if ((wParam & MK_LBUTTON) != 0 && ::GetCapture() == hWnd) { g_Splitter.SetPos(hWnd, g_StartCaptureSplitterPos + (short)LOWORD(lParam) - g_StartCaptureMousePos); MoveSubWindows(hWnd); } break; } case WM_SIZE: { if (g_CanChangeSplitter) g_Splitter.SetPosFromRatio(hWnd); else { g_Splitter.SetPos(hWnd, g_SplitterPos ); g_CanChangeSplitter = true; } OnSize(hWnd); /* int xSize = LOWORD(lParam); int ySize = HIWORD(lParam); // int xSplitter = 2; int xWidth = g_SplitPos; // int xSplitPos = xWidth; g_Panel[0]._listView.MoveWindow(0, 0, xWidth, ySize); g_Panel[1]._listView.MoveWindow(xSize - xWidth, 0, xWidth, ySize); */ return 0; break; } case WM_SETFOCUS: // g_App.SetFocus(g_App.LastFocusedPanel); g_App.SetFocusToLastItem(); break; /* case WM_ACTIVATE: { int fActive = LOWORD(wParam); switch (fActive) { case WA_INACTIVE: { // g_FocusIndex = g_App.LastFocusedPanel; // g_App.LastFocusedPanel = g_App.GetFocusedPanelIndex(); // return 0; } } break; } */ /* case kLangWasChangedMessage: MyLoadMenu(g_HWND); return 0; */ /* case WM_SETTINGCHANGE: break; */ case WM_NOTIFY: { g_App.OnNotify((int)wParam, (LPNMHDR)lParam); break; } /* case WM_DROPFILES: { g_App.GetFocusedPanel().CompressDropFiles((HDROP)wParam); return 0 ; } */ } #ifndef _UNICODE if (g_IsNT) return DefWindowProcW(hWnd, message, wParam, lParam); else #endif return DefWindowProc(hWnd, message, wParam, lParam); }
STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT commandIDFirst, UINT commandIDLast, UINT flags) { LoadLangOneTime(); if (_fileNames.Size() == 0) return E_FAIL; UINT currentCommandID = commandIDFirst; if ((flags & 0x000F) != CMF_NORMAL && (flags & CMF_VERBSONLY) == 0 && (flags & CMF_EXPLORE) == 0) return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID); _commandMap.Clear(); CMenu popupMenu; CMenuDestroyer menuDestroyer; CContextMenuInfo ci; ci.Load(); MENUITEMINFO menuItem; UINT subIndex = indexMenu; if (ci.Cascaded) { CCommandMapItem commandMapItem; if (!popupMenu.CreatePopup()) return E_FAIL; menuDestroyer.Attach(popupMenu); commandMapItem.CommandInternalID = kCommandNULL; commandMapItem.Verb = kMainVerb; commandMapItem.HelpString = LangString(IDS_CONTEXT_CAPTION_HELP, 0x02000102); _commandMap.Add(commandMapItem); menuItem.wID = currentCommandID++; subIndex = 0; } else { popupMenu.Attach(hMenu); } UInt32 contextMenuFlags = ci.Flags; UString mainString; if (_fileNames.Size() == 1 && currentCommandID + 6 <= commandIDLast) { const UString &fileName = _fileNames.Front(); UString folderPrefix; NFile::NDirectory::GetOnlyDirPrefix(fileName, folderPrefix); NFile::NFind::CFileInfoW fileInfo; if (!fileInfo.Find(fileName)) return E_FAIL; if (!fileInfo.IsDir() && DoNeedExtract(fileInfo.Name)) { // Open bool thereIsMainOpenItem = ((contextMenuFlags & NContextMenuFlags::kOpen) != 0); if (thereIsMainOpenItem) { CCommandMapItem commandMapItem; FillCommand(kOpen, mainString, commandMapItem); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString); _commandMap.Add(commandMapItem); } if ((contextMenuFlags & NContextMenuFlags::kOpenAs) != 0 && (!thereIsMainOpenItem || !FindExt(kNoOpenAsExtensions, fileInfo.Name))) { CMenu subMenu; if (subMenu.CreatePopup()) { CCommandMapItem commandMapItem; CMenuItem menuItem; menuItem.fType = MFT_STRING; menuItem.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID; menuItem.wID = currentCommandID++; menuItem.hSubMenu = subMenu; menuItem.StringValue = LangString(IDS_CONTEXT_OPEN, 0x02000103); popupMenu.InsertItem(subIndex++, true, menuItem); commandMapItem.CommandInternalID = kCommandNULL; commandMapItem.Verb = kMainVerb; commandMapItem.HelpString = LangString(IDS_CONTEXT_OPEN_HELP, 0x02000104); _commandMap.Add(commandMapItem); UINT subIndex2 = 0; const wchar_t *exts[] = { L"", L"*", L"7z", L"zip", L"cab", L"rar" }; for (int i = (thereIsMainOpenItem ? 1 : 0); i < sizeof(exts) / sizeof(exts[0]); i++) { CCommandMapItem commandMapItem; if (i == 0) FillCommand(kOpen, mainString, commandMapItem); else { mainString = exts[i]; commandMapItem.CommandInternalID = kOpen; commandMapItem.Verb = (UString)kMainVerb + L".Open." + mainString; commandMapItem.HelpString = mainString; commandMapItem.ArcType = mainString; } MyInsertMenu(subMenu, subIndex2++, currentCommandID++, mainString); _commandMap.Add(commandMapItem); } subMenu.Detach(); } } } } if (_fileNames.Size() > 0 && currentCommandID + 10 <= commandIDLast) { bool needExtract = false; for(int i = 0; i < _fileNames.Size(); i++) { NFile::NFind::CFileInfoW fileInfo; if (!fileInfo.Find(_fileNames[i])) return E_FAIL; if (!fileInfo.IsDir() && DoNeedExtract(fileInfo.Name)) needExtract = true; } const UString &fileName = _fileNames.Front(); if (needExtract) { UString folderPrefix; NFile::NDirectory::GetOnlyDirPrefix(fileName, folderPrefix); NFile::NFind::CFileInfoW fileInfo; if (!fileInfo.Find(fileName)) return E_FAIL; // Extract if ((contextMenuFlags & NContextMenuFlags::kExtract) != 0) { CCommandMapItem commandMapItem; FillCommand(kExtract, mainString, commandMapItem); if (_dropMode) commandMapItem.Folder = _dropPath; else commandMapItem.Folder = folderPrefix; commandMapItem.Folder += GetSubFolderNameForExtract(fileInfo.Name) + UString(WCHAR_PATH_SEPARATOR); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString); _commandMap.Add(commandMapItem); } // Extract Here if ((contextMenuFlags & NContextMenuFlags::kExtractHere) != 0) { CCommandMapItem commandMapItem; FillCommand(kExtractHere, mainString, commandMapItem); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString); if (_dropMode) commandMapItem.Folder = _dropPath; else commandMapItem.Folder = folderPrefix; _commandMap.Add(commandMapItem); } // Extract To if ((contextMenuFlags & NContextMenuFlags::kExtractTo) != 0) { CCommandMapItem commandMapItem; UString s; FillCommand(kExtractTo, s, commandMapItem); UString folder; if (_fileNames.Size() == 1) folder = GetSubFolderNameForExtract(fileInfo.Name); else folder = L'*'; if (_dropMode) commandMapItem.Folder = _dropPath; else commandMapItem.Folder = folderPrefix; commandMapItem.Folder += folder; s = MyFormatNew(s, GetQuotedReducedString(folder + UString(WCHAR_PATH_SEPARATOR))); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s); _commandMap.Add(commandMapItem); } // Test if ((contextMenuFlags & NContextMenuFlags::kTest) != 0) { CCommandMapItem commandMapItem; FillCommand(kTest, mainString, commandMapItem); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString); _commandMap.Add(commandMapItem); } } UString archiveName = CreateArchiveName(fileName, _fileNames.Size() > 1, false); UString archiveName7z = archiveName + L".7z"; UString archiveNameZip = archiveName + L".zip"; UString archivePathPrefix; NFile::NDirectory::GetOnlyDirPrefix(fileName, archivePathPrefix); // Compress if ((contextMenuFlags & NContextMenuFlags::kCompress) != 0) { CCommandMapItem commandMapItem; if (_dropMode) commandMapItem.Folder = _dropPath; else commandMapItem.Folder = archivePathPrefix; commandMapItem.ArcName = archiveName; FillCommand(kCompress, mainString, commandMapItem); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString); _commandMap.Add(commandMapItem); } #ifdef EMAIL_SUPPORT // CompressEmail if ((contextMenuFlags & NContextMenuFlags::kCompressEmail) != 0 && !_dropMode) { CCommandMapItem commandMapItem; commandMapItem.ArcName = archiveName; FillCommand(kCompressEmail, mainString, commandMapItem); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString); _commandMap.Add(commandMapItem); } #endif // CompressTo7z if (contextMenuFlags & NContextMenuFlags::kCompressTo7z) { CCommandMapItem commandMapItem; UString s; FillCommand(kCompressTo7z, s, commandMapItem); if (_dropMode) commandMapItem.Folder = _dropPath; else commandMapItem.Folder = archivePathPrefix; commandMapItem.ArcName = archiveName7z; commandMapItem.ArcType = L"7z"; s = MyFormatNew(s, GetQuotedReducedString(archiveName7z)); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s); _commandMap.Add(commandMapItem); } #ifdef EMAIL_SUPPORT // CompressTo7zEmail if ((contextMenuFlags & NContextMenuFlags::kCompressTo7zEmail) != 0 && !_dropMode) { CCommandMapItem commandMapItem; UString s; FillCommand(kCompressTo7zEmail, s, commandMapItem); commandMapItem.ArcName = archiveName7z; commandMapItem.ArcType = L"7z"; s = MyFormatNew(s, GetQuotedReducedString(archiveName7z)); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s); _commandMap.Add(commandMapItem); } #endif // CompressToZip if (contextMenuFlags & NContextMenuFlags::kCompressToZip) { CCommandMapItem commandMapItem; UString s; FillCommand(kCompressToZip, s, commandMapItem); if (_dropMode) commandMapItem.Folder = _dropPath; else commandMapItem.Folder = archivePathPrefix; commandMapItem.ArcName = archiveNameZip; commandMapItem.ArcType = L"zip"; s = MyFormatNew(s, GetQuotedReducedString(archiveNameZip)); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s); _commandMap.Add(commandMapItem); } #ifdef EMAIL_SUPPORT // CompressToZipEmail if ((contextMenuFlags & NContextMenuFlags::kCompressToZipEmail) != 0 && !_dropMode) { CCommandMapItem commandMapItem; UString s; FillCommand(kCompressToZipEmail, s, commandMapItem); commandMapItem.ArcName = archiveNameZip; commandMapItem.ArcType = L"zip"; s = MyFormatNew(s, GetQuotedReducedString(archiveNameZip)); MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s); _commandMap.Add(commandMapItem); } #endif } // don't use InsertMenu: See MSDN: // PRB: Duplicate Menu Items In the File Menu For a Shell Context Menu Extension // ID: Q214477 if (ci.Cascaded) { CMenuItem menuItem; menuItem.fType = MFT_STRING; menuItem.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID; menuItem.wID = currentCommandID++; menuItem.hSubMenu = popupMenu.Detach(); menuDestroyer.Disable(); menuItem.StringValue = LangString(IDS_CONTEXT_POPUP_CAPTION, 0x02000101); CMenu menu; menu.Attach(hMenu); menu.InsertItem(indexMenu++, true, menuItem); } return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID - commandIDFirst); }
void CApp::Combine() { int srcPanelIndex = GetFocusedPanelIndex(); CPanel &srcPanel = Panels[srcPanelIndex]; if (!srcPanel.IsFSFolder()) { srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); return; } CRecordVector<UInt32> indices; srcPanel.GetOperatedItemIndices(indices); if (indices.IsEmpty()) return; int index = indices[0]; if (indices.Size() != 1 || srcPanel.IsItemFolder(index)) { srcPanel.MessageBoxErrorLang(IDS_COMBINE_SELECT_ONE_FILE, 0x03020620); return; } const UString itemName = srcPanel.GetItemName(index); UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index); UString path = srcPath; int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); CPanel &destPanel = Panels[destPanelIndex]; if (NumPanels > 1) if (destPanel.IsFSFolder()) path = destPanel._currentFolderPrefix; CVolSeqName volSeqName; if (!volSeqName.ParseName(itemName)) { srcPanel.MessageBoxErrorLang(IDS_COMBINE_CANT_DETECT_SPLIT_FILE, 0x03020621); return; } { CThreadCombine combiner; UString nextName = itemName; combiner.TotalSize = 0; for (;;) { NFile::NFind::CFileInfoW fileInfo; if (!fileInfo.Find(srcPath + nextName) || fileInfo.IsDir()) break; combiner.Names.Add(nextName); combiner.TotalSize += fileInfo.Size; nextName = volSeqName.GetNextName(); } if (combiner.Names.Size() == 1) { srcPanel.MessageBoxErrorLang(IDS_COMBINE_CANT_FIND_MORE_THAN_ONE_PART, 0x03020622); return; } if (combiner.TotalSize == 0) { srcPanel.MessageBoxMyError(L"No data"); return; } UString info; AddValuePair2(IDS_FILES_COLON, 0x02000320, combiner.Names.Size(), combiner.TotalSize, info); info += L"\n"; info += srcPath; int i; for (i = 0; i < combiner.Names.Size() && i < 2; i++) AddInfoFileName(combiner.Names[i], info); if (i != combiner.Names.Size()) { if (i + 1 != combiner.Names.Size()) AddInfoFileName(L"...", info); AddInfoFileName(combiner.Names.Back(), info); } { CCopyDialog copyDialog; copyDialog.Value = path; copyDialog.Title = LangString(IDS_COMBINE, 0x03020600); copyDialog.Title += ' '; copyDialog.Title += srcPanel.GetItemRelPath(index); copyDialog.Static = LangString(IDS_COMBINE_TO, 0x03020601); copyDialog.Info = info; if (copyDialog.Create(srcPanel.GetParent()) == IDCANCEL) return; path = copyDialog.Value; } NFile::NName::NormalizeDirPathPrefix(path); if (!NFile::NDirectory::CreateComplexDirectory(path)) { srcPanel.MessageBoxMyError(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, 0x02000603, path)); return; } UString outName = volSeqName.UnchangedPart; while (!outName.IsEmpty()) { int lastIndex = outName.Length() - 1; if (outName[lastIndex] != L'.') break; outName.Delete(lastIndex); } if (outName.IsEmpty()) outName = L"file"; NFile::NFind::CFileInfoW fileInfo; UString destFilePath = path + outName; combiner.OutputPath = destFilePath; if (fileInfo.Find(destFilePath)) { srcPanel.MessageBoxMyError(MyFormatNew(IDS_FILE_EXIST, 0x03020A04, destFilePath)); return; } CProgressDialog &progressDialog = combiner.ProgressDialog; progressDialog.ShowCompressionInfo = false; UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000); UString title = LangString(IDS_COMBINING, 0x03020610); progressDialog.MainWindow = _window; progressDialog.MainTitle = progressWindowTitle; progressDialog.MainAddTitle = title + UString(L" "); combiner.InputDirPrefix = srcPath; // CPanel::CDisableTimerProcessing disableTimerProcessing1(srcPanel); // CPanel::CDisableTimerProcessing disableTimerProcessing2(destPanel); if (combiner.Create(title, _window) != 0) return; } RefreshTitleAlways(); // disableTimerProcessing1.Restore(); // disableTimerProcessing2.Restore(); // srcPanel.SetFocusToList(); // srcPanel.RefreshListCtrlSaveFocused(); }
void CApp::Split() { int srcPanelIndex = GetFocusedPanelIndex(); CPanel &srcPanel = Panels[srcPanelIndex]; if (!srcPanel.IsFSFolder()) { srcPanel.MessageBoxErrorLang(IDS_OPERATION_IS_NOT_SUPPORTED, 0x03020208); return; } CRecordVector<UInt32> indices; srcPanel.GetOperatedItemIndices(indices); if (indices.IsEmpty()) return; if (indices.Size() != 1) { srcPanel.MessageBoxErrorLang(IDS_SELECT_ONE_FILE, 0x03020A02); return; } int index = indices[0]; if (srcPanel.IsItemFolder(index)) { srcPanel.MessageBoxErrorLang(IDS_SELECT_ONE_FILE, 0x03020A02); return; } const UString itemName = srcPanel.GetItemName(index); UString srcPath = srcPanel._currentFolderPrefix + srcPanel.GetItemPrefix(index); UString path = srcPath; int destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex); CPanel &destPanel = Panels[destPanelIndex]; if (NumPanels > 1) if (destPanel.IsFSFolder()) path = destPanel._currentFolderPrefix; CSplitDialog splitDialog; splitDialog.FilePath = srcPanel.GetItemRelPath(index); splitDialog.Path = path; if (splitDialog.Create(srcPanel.GetParent()) == IDCANCEL) return; NFile::NFind::CFileInfoW fileInfo; if (!fileInfo.Find(srcPath + itemName)) { srcPanel.MessageBoxMyError(L"Can not find file"); return; } if (fileInfo.Size <= splitDialog.VolumeSizes.Front()) { srcPanel.MessageBoxErrorLang(IDS_SPLIT_VOL_MUST_BE_SMALLER, 0x03020522); return; } const UInt64 numVolumes = GetNumberOfVolumes(fileInfo.Size, splitDialog.VolumeSizes); if (numVolumes >= 100) { wchar_t s[32]; ConvertUInt64ToString(numVolumes, s); if (::MessageBoxW(srcPanel, MyFormatNew(IDS_SPLIT_CONFIRM_MESSAGE, 0x03020521, s), LangString(IDS_SPLIT_CONFIRM_TITLE, 0x03020520), MB_YESNOCANCEL | MB_ICONQUESTION) != IDYES) return; } path = splitDialog.Path; NFile::NName::NormalizeDirPathPrefix(path); if (!NFile::NDirectory::CreateComplexDirectory(path)) { srcPanel.MessageBoxMyError(MyFormatNew(IDS_CANNOT_CREATE_FOLDER, 0x02000603, path)); return; } { CThreadSplit spliter; spliter.NumVolumes = numVolumes; CProgressDialog &progressDialog = spliter.ProgressDialog; UString progressWindowTitle = LangString(IDS_APP_TITLE, 0x03000000); UString title = LangString(IDS_SPLITTING, 0x03020510); progressDialog.ShowCompressionInfo = false; progressDialog.MainWindow = _window; progressDialog.MainTitle = progressWindowTitle; progressDialog.MainAddTitle = title + UString(L" "); progressDialog.Sync.SetTitleFileName(itemName); spliter.FilePath = srcPath + itemName; spliter.VolBasePath = path + itemName; spliter.VolumeSizes = splitDialog.VolumeSizes; // if (splitDialog.VolumeSizes.Size() == 0) return; // CPanel::CDisableTimerProcessing disableTimerProcessing1(srcPanel); // CPanel::CDisableTimerProcessing disableTimerProcessing2(destPanel); if (spliter.Create(title, _window) != 0) return; } RefreshTitleAlways(); // disableTimerProcessing1.Restore(); // disableTimerProcessing2.Restore(); // srcPanel.SetFocusToList(); // srcPanel.RefreshListCtrlSaveFocused(); }
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 Process2() { // NCOM::CComInitializer comInitializer; ProgressDialog->WaitCreating(); CVolSeqName volSeqName; if (!volSeqName.ParseName(FirstVolumeName)) throw L"Can not detect file as splitted file"; UString nextName = InputDirPrefix + FirstVolumeName; UInt64 totalSize = 0; for (;;) { NFile::NFind::CFileInfoW fileInfo; if (!NFile::NFind::FindFile(nextName, fileInfo)) break; if (fileInfo.IsDirectory()) break; totalSize += fileInfo.Size; nextName = InputDirPrefix + volSeqName.GetNextName(); } if (totalSize == 0) throw L"no data"; ProgressDialog->ProgressSynch.SetProgress(totalSize, 0); if (!volSeqName.ParseName(FirstVolumeName)) throw L"Can not detect file as splitted file"; UString outName = volSeqName.UnchangedPart; while(!outName.IsEmpty()) { int lastIndex = outName.Length() - 1; if (outName[lastIndex] != L'.') break; outName.Delete(lastIndex); } if (outName.IsEmpty()) outName = L"file"; NFile::NIO::COutFile outFile; if (!outFile.Create(OutputDirPrefix + outName, false)) throw L"Can create open output file"; NFile::NIO::CInFile inFile; CMyBuffer bufferObject; if (!bufferObject.Allocate(kBufSize)) throw L"Can not allocate buffer"; Byte *buffer = (Byte *)(void *)bufferObject; UInt64 pos = 0; nextName = InputDirPrefix + FirstVolumeName; bool needOpen = true; for (;;) { if (needOpen) { NFile::NFind::CFileInfoW fileInfo; if (!NFile::NFind::FindFile(nextName, fileInfo)) break; if (fileInfo.IsDirectory()) break; if (!inFile.Open(nextName)) throw L"Can not open file"; ProgressDialog->ProgressSynch.SetCurrentFileName(fileInfo.Name); nextName = InputDirPrefix + volSeqName.GetNextName(); needOpen = false; } UInt32 processedSize; if (!inFile.Read(buffer, kBufSize, processedSize)) throw L"Can not read input file"; if (processedSize == 0) { needOpen = true; continue; } UInt32 needSize = processedSize; if (!outFile.Write(buffer, needSize, processedSize)) throw L"Can not write output file"; if (needSize != processedSize) throw L"Can not write output file"; pos += processedSize; HRESULT res = ProgressDialog->ProgressSynch.SetPosAndCheckPaused(pos); if (res != S_OK) return; } }
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; }
STDMETHODIMP P7ZipArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) { *outStream = 0; _outFileStream.Release(); { // Get Name NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop)); UString fullPath; if (prop.vt == VT_EMPTY) fullPath = kEmptyFileAlias; else { if (prop.vt != VT_BSTR) return E_FAIL; fullPath = prop.bstrVal; } _filePath = fullPath; } if (askExtractMode != NArchive::NExtract::NAskMode::kExtract) return S_OK; { // Get Attrib NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop)); if (prop.vt == VT_EMPTY) { _processedFileInfo.Attrib = 0; _processedFileInfo.AttribDefined = false; } else { if (prop.vt != VT_UI4) return E_FAIL; _processedFileInfo.Attrib = prop.ulVal; _processedFileInfo.AttribDefined = true; } } RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.isDir)); { // Get Modified Time NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop)); _processedFileInfo.MTimeDefined = false; switch(prop.vt) { case VT_EMPTY: // _processedFileInfo.MTime = _utcMTimeDefault; break; case VT_FILETIME: _processedFileInfo.MTime = prop.filetime; _processedFileInfo.MTimeDefined = true; break; default: return E_FAIL; } } { // Get Size NCOM::CPropVariant prop; RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop)); bool newFileSizeDefined = (prop.vt != VT_EMPTY); UInt64 newFileSize; if (newFileSizeDefined) newFileSize = ConvertPropVariantToUInt64(prop); } { // Create folders for file int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR); if (slashPos >= 0) NFile::NDirectory::CreateComplexDirectory(_directoryPath + _filePath.Left(slashPos)); } UString fullProcessedPath = _directoryPath + _filePath; _diskFilePath = fullProcessedPath; if (_processedFileInfo.isDir) { NFile::NDirectory::CreateComplexDirectory(fullProcessedPath); } else { NFile::NFind::CFileInfoW fi; if (fi.Find(fullProcessedPath)) { if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath)) { PrintString(UString(kCantDeleteOutputFile) + fullProcessedPath); return E_ABORT; } } _outFileStreamSpec = new COutFileStream; CMyComPtr<ISequentialOutStream> outStreamLoc(_outFileStreamSpec); if (!_outFileStreamSpec->Open(fullProcessedPath, CREATE_ALWAYS)) { PrintString((UString)L"can not open output file " + fullProcessedPath); return E_ABORT; } _outFileStream = outStreamLoc; *outStream = outStreamLoc.Detach(); } return S_OK; }