diff --git a/.github/workflows/publish-7z.yml b/.github/workflows/publish-7z.yml index c3f46ca..06f2e5e 100644 --- a/.github/workflows/publish-7z.yml +++ b/.github/workflows/publish-7z.yml @@ -16,7 +16,7 @@ jobs: DOWNLOAD_ARTIFACTS_DIR: ${{ github.workspace }}\build\downloaded-artifacts UPLOAD_ARTIFACTS_DIR: ${{ github.workspace }}\build\upload-artifacts ARTIFACTS_NAME: 7zip-x64-Release - GDRIVE_ARTIFACTS_RELEASES_DIR: ${{ secrets.ARTIFACTS_STORAGE_ROOT_PATH }}/7z/releases + GDRIVE_ARTIFACTS_RELEASES_DIR: ${{ secrets.ARTIFACTS_SDK_STORAGE_ROOT_PATH }}/7zSDK/releases steps: - uses: actions/checkout@v4 diff --git a/CPP/7zip/UI/Common/Extract.cpp b/CPP/7zip/UI/Common/Extract.cpp index 3c7fe0f..53894b8 100644 --- a/CPP/7zip/UI/Common/Extract.cpp +++ b/CPP/7zip/UI/Common/Extract.cpp @@ -45,7 +45,8 @@ static HRESULT DecompressArchive( CArchiveExtractCallback *ecs, UString &errorMessage, UInt64& stdInProcessed, - ScanFileState* pScanFileState) + ScanFileState* pScanFileState, + ArchiveOptions pArchiveOption) { const CArc &arc = arcLink.Arcs.Back(); stdInProcessed = 0; @@ -95,13 +96,68 @@ static HRESULT DecompressArchive( { UInt32 numItems; RINOK(archive->GetNumberOfItems(&numItems)) + UInt32 fileCountWithinArchive = 0; + UInt64 totalUncompressedSize = 0; + UInt64 totalCompressedSize = 0; + for (UInt32 i = 0; i < numItems; ++i) + { + NCOM::CPropVariant prop; + archive->GetProperty(i, kpidIsDir, &prop); + if (prop.vt == VT_BOOL && !prop.boolVal) + { + fileCountWithinArchive++; + + // Get uncompressed size + NCOM::CPropVariant sizeProp; + if (SUCCEEDED(archive->GetProperty(i, kpidSize, &sizeProp)) && sizeProp.vt == VT_UI8) + { + totalUncompressedSize += sizeProp.uhVal.QuadPart; + } + // Get compressed size + NCOM::CPropVariant packSizeProp; + if (SUCCEEDED(archive->GetProperty(i, kpidPackSize, &packSizeProp)) && packSizeProp.vt == VT_UI8) + { + totalCompressedSize += packSizeProp.uhVal.QuadPart; + } + } + } + + if (totalUncompressedSize > 0) + { + double compressionRatio = (totalCompressedSize * 100.0) / totalUncompressedSize; + if (compressionRatio > pArchiveOption.ArchiveMaxRatio) + { + return S_OK; + } + } + + if (pArchiveOption.ArchiveMaxCount != 0 && fileCountWithinArchive > pArchiveOption.ArchiveMaxCount) + { + return S_OK; + } CReadArcItem item; UString result; CScannerCommonFunctions objScannerCommonFunctions; + UInt64 totalFileSize = 0; for (UInt32 i = 0; i < numItems; i++) { + if (pArchiveOption.ArchiveTotalMaxSize != 0 && fileCountWithinArchive > 0 && totalFileSize > pArchiveOption.ArchiveTotalMaxSize) + { + break; + } + NCOM::CPropVariant sizeProp; + HRESULT res = archive->GetProperty(i, kpidSize, &sizeProp); + if (SUCCEEDED(res) && sizeProp.vt == VT_UI8) + { + UInt64 fileSize = sizeProp.uhVal.QuadPart; + totalFileSize = totalFileSize + fileSize; + if (pArchiveOption.ArchiveMaxSize != 0 && fileSize > pArchiveOption.ArchiveMaxSize) + { + continue; + } + } if (objScannerCommonFunctions.CheckForScanAbortState(pScanFileState)) { realIndices.Clear(); @@ -299,7 +355,8 @@ HRESULT Extract( #endif UString &errorMessage, CDecompressStat &st, - ScanFileState* pScanFileState) + ScanFileState* pScanFileState, + ArchiveOptions pArchiveOption) { st.Clear(); UInt64 totalPackSize = 0; @@ -523,7 +580,7 @@ HRESULT Extract( options, calcCrc, extractCallback, faeCallback, ecs, - errorMessage, packProcessed, pScanFileState)) + errorMessage, packProcessed, pScanFileState, pArchiveOption)) if (!options.StdInMode) packProcessed = fi.Size + arcLink.VolumesSize; diff --git a/CPP/7zip/UI/Common/Extract.h b/CPP/7zip/UI/Common/Extract.h index f5a22fe..eb78c88 100644 --- a/CPP/7zip/UI/Common/Extract.h +++ b/CPP/7zip/UI/Common/Extract.h @@ -105,6 +105,7 @@ HRESULT Extract( #endif UString &errorMessage, CDecompressStat &st, - ScanFileState* pScanFileState); + ScanFileState* pScanFileState, + ArchiveOptions pArchiveOption); #endif diff --git a/CPP/7zip/UI/Common/ScannerCommonFunctions.h b/CPP/7zip/UI/Common/ScannerCommonFunctions.h index d8e29d2..8bc3416 100644 --- a/CPP/7zip/UI/Common/ScannerCommonFunctions.h +++ b/CPP/7zip/UI/Common/ScannerCommonFunctions.h @@ -1,11 +1,19 @@ #pragma once - +#include enum class ScanFileState { E_ScanFileState_None, //File scan state: running E_ScanFileState_Abort //File scan state: scan abort by service }; +struct ArchiveOptions +{ + uint64_t ArchiveMaxSize; + uint64_t ArchiveTotalMaxSize; + uint64_t ArchiveMaxRatio; + uint64_t ArchiveMaxCount; +}; + class CScannerCommonFunctions { public: diff --git a/CPP/7zip/UI/Console/Main.cpp b/CPP/7zip/UI/Console/Main.cpp index 941994e..9467818 100644 --- a/CPP/7zip/UI/Console/Main.cpp +++ b/CPP/7zip/UI/Console/Main.cpp @@ -813,7 +813,7 @@ int Main2( } int ExtractArchiveFile(const TCHAR* chAction, const TCHAR* chArchiveName, const TCHAR* chInOutputFolderName, - const TCHAR* chPassword, const TCHAR* chFileFilter, ScanFileState* pScanFileState) + const TCHAR* chPassword, const TCHAR* chFileFilter, ScanFileState* pScanFileState, ArchiveOptions pArchiveOption) { #if defined(MY_CPU_SIZEOF_POINTER) { unsigned k = sizeof(void *); if (k != MY_CPU_SIZEOF_POINTER) throw "incorrect MY_CPU_PTR_SIZE"; } @@ -1377,7 +1377,7 @@ int ExtractArchiveFile(const TCHAR* chAction, const TCHAR* chArchiveName, const ArchivePathsFullSorted, options.Censor.Pairs.Front().Head, eo, ecs, ecs, ecs, - hashCalc, errorMessage, stat, pScanFileState); + hashCalc, errorMessage, stat, pScanFileState, pArchiveOption); ecs->ClosePercents(); @@ -1639,10 +1639,10 @@ int ExtractArchiveFile(const TCHAR* chAction, const TCHAR* chArchiveName, const bool WINAPI __stdcall UnMax7zArchive(const TCHAR* chAction, const TCHAR* chArchiveName, const TCHAR* chOutputFolderName, const TCHAR* chPassword, const TCHAR* chFileFilter, - ScanFileState* pScanFileState) + ScanFileState* pScanFileState, ArchiveOptions pArchiveOption) { int iRet = ExtractArchiveFile(chAction, chArchiveName, chOutputFolderName, - chPassword, chFileFilter, pScanFileState); + chPassword, chFileFilter, pScanFileState, pArchiveOption); return iRet == 0; } @@ -1659,6 +1659,7 @@ Description : It is a exported function which calls "ExtractFile" for extractio bool WINAPI __stdcall Max7zArchive(const TCHAR* chAction, const TCHAR* chArchiveName, const TCHAR* chInputFileFolderName, const TCHAR* chPassword, const TCHAR* chFileFilter) { - int iRet = ExtractArchiveFile(chAction, chArchiveName, chInputFileFolderName, chPassword, chFileFilter, NULL); + ArchiveOptions pArchiveOption = { 0 }; + int iRet = ExtractArchiveFile(chAction, chArchiveName, chInputFileFolderName, chPassword, chFileFilter, NULL, pArchiveOption); return iRet == 0; } diff --git a/Test_7zip/test_7zip.cpp b/Test_7zip/test_7zip.cpp index fcedcbd..15b8e4b 100644 --- a/Test_7zip/test_7zip.cpp +++ b/Test_7zip/test_7zip.cpp @@ -11,7 +11,7 @@ namespace fs = std::filesystem; using UnpackFunc = bool (*)(const TCHAR* chAction, const TCHAR* chArchiveName, const TCHAR* chOutputFolderName, - const TCHAR* chPassword, const TCHAR* chFileFilter, ScanFileState* pScanFileState); + const TCHAR* chPassword, const TCHAR* chFileFilter, ScanFileState* pScanFileState, ArchiveOptions pArchiveOption); using PackFunc = bool (*)(const TCHAR* chAction, const TCHAR* chArchiveName, const TCHAR* chInputFileFolderName, const TCHAR* chPassword, const TCHAR* chFileFilter); @@ -75,8 +75,13 @@ TEST_CASE("Zipping/Unzipping the file", "[7zip]") { std::wstring unpackDirName = L"-o" + kTestDir.wstring(); ScanFileState fileState = ScanFileState::E_ScanFileState_None; + ArchiveOptions ArchiveConfig = { 0 }; + ArchiveConfig.ArchiveMaxCount = 12; + ArchiveConfig.ArchiveMaxRatio = 250; + ArchiveConfig.ArchiveMaxSize = 0; + ArchiveConfig.ArchiveTotalMaxSize = 0; bool result = g_UnpackFunc(L"x", kPackedFile.wstring().data(), - unpackDirName.data(), kPassword.data(), nullptr, &fileState); + unpackDirName.data(), kPassword.data(), nullptr, &fileState,ArchiveConfig); REQUIRE(result); REQUIRE(fs::exists(kUnpackedFile)); std::ifstream unpackedFile(kUnpackedFile);