diff --git a/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$Backend.class b/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$Backend.class index 41ca622..dd1c615 100644 Binary files a/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$Backend.class and b/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$Backend.class differ diff --git a/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$ConflictMode.class b/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$ConflictMode.class index 098d94e..d22e6db 100644 Binary files a/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$ConflictMode.class and b/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$ConflictMode.class differ diff --git a/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$ExtractionRequest.class b/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$ExtractionRequest.class index f2ccd33..b6f04dc 100644 Binary files a/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$ExtractionRequest.class and b/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$ExtractionRequest.class differ diff --git a/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$ProgressTracker.class b/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$ProgressTracker.class index 8c1da8f..cb5c698 100644 Binary files a/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$ProgressTracker.class and b/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$ProgressTracker.class differ diff --git a/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$SevenZipArchiveContext.class b/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$SevenZipArchiveContext.class index 603dad7..2ada884 100644 Binary files a/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$SevenZipArchiveContext.class and b/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$SevenZipArchiveContext.class differ diff --git a/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$SevenZipVolumeCallback.class b/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$SevenZipVolumeCallback.class index 10566c8..9aaa953 100644 Binary files a/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$SevenZipVolumeCallback.class and b/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$SevenZipVolumeCallback.class differ diff --git a/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$WrongPasswordException.class b/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$WrongPasswordException.class index 6826c5e..dd31ed6 100644 Binary files a/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$WrongPasswordException.class and b/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain$WrongPasswordException.class differ diff --git a/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain.class b/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain.class index ef9eef2..4b4c798 100644 Binary files a/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain.class and b/resources/extractor-jvm/classes/com/sucukdeluxe/extractor/JBindExtractorMain.class differ diff --git a/resources/extractor-jvm/src/com/sucukdeluxe/extractor/JBindExtractorMain.java b/resources/extractor-jvm/src/com/sucukdeluxe/extractor/JBindExtractorMain.java index 413b830..d01a45c 100644 --- a/resources/extractor-jvm/src/com/sucukdeluxe/extractor/JBindExtractorMain.java +++ b/resources/extractor-jvm/src/com/sucukdeluxe/extractor/JBindExtractorMain.java @@ -356,7 +356,10 @@ public final class JBindExtractorMain { if (!encrypted || result == null) { return false; } - return result == ExtractOperationResult.CRCERROR || result == ExtractOperationResult.DATAERROR; + // Only DATAERROR reliably indicates wrong password. CRCERROR can also mean + // a genuinely corrupt or incomplete archive, and 7z-JBinding sometimes + // falsely reports encrypted=true for non-encrypted RAR files. + return result == ExtractOperationResult.DATAERROR; } private static boolean looksLikeWrongPassword(Throwable error, boolean encrypted) { @@ -367,7 +370,9 @@ public final class JBindExtractorMain { if (text.contains("wrong password") || text.contains("falsches passwort")) { return true; } - return encrypted && (text.contains("crc") || text.contains("data error") || text.contains("checksum")); + // Only "data error" suggests wrong password. CRC errors can also mean + // corrupt/incomplete archives, so we don't treat them as password failures. + return encrypted && text.contains("data error"); } private static boolean shouldUseZip4j(File archiveFile) { diff --git a/src/main/download-manager.ts b/src/main/download-manager.ts index 9eed2af..62e2523 100644 --- a/src/main/download-manager.ts +++ b/src/main/download-manager.ts @@ -4988,11 +4988,26 @@ export class DownloadManager extends EventEmitter { } } + // Pre-compute: does the package still have any non-terminal items? + const packageHasPendingItems = pkg.itemIds.some((itemId) => { + const item = this.session.items[itemId]; + return item != null && item.status !== "completed" && item.status !== "failed" && item.status !== "cancelled"; + }); + for (const candidate of candidates) { const partsOnDisk = collectArchiveCleanupTargets(candidate, dirFiles); const allPartsCompleted = partsOnDisk.every((part) => completedPaths.has(pathKey(part))); if (allPartsCompleted) { const candidateBase = path.basename(candidate).toLowerCase(); + + // For multi-part archives (.part1.rar), require ALL package items to be terminal. + // partsOnDisk only contains parts found ON DISK — pending parts that haven't been + // downloaded yet (no targetPath, no fileName) would slip through the regular checks. + if (/\.part0*1\.rar$/i.test(candidateBase) && packageHasPendingItems) { + logger.info(`Hybrid-Extract: ${path.basename(candidate)} übersprungen – Paket hat noch ausstehende Items`); + continue; + } + const hasUnstartedParts = [...pendingPaths].some((pendingPath) => { const pendingName = path.basename(pendingPath).toLowerCase(); return this.looksLikeArchivePart(pendingName, candidateBase);