Compare commits

..

No commits in common. "cd5c0c5e7b62baa6ad2c88a48bec1e611aba81a3" and "94126943d5f0d9abf556bea5bcca385ba335f1c1" have entirely different histories.

3 changed files with 9 additions and 96 deletions

View File

@ -1,6 +1,6 @@
{
"name": "real-debrid-downloader",
"version": "1.7.39",
"version": "1.7.38",
"description": "Desktop downloader",
"main": "build/main/main/main.js",
"author": "Sucukdeluxe",

View File

@ -4225,11 +4225,7 @@ export class DownloadManager extends EventEmitter {
failure: ExtractArchiveFailureInfo,
scope: "hybrid" | "full"
): number {
// Allow auto-recovery for both crc_error and wrong_password when suggestRedownload is set.
// Encrypted RAR5 archives with corrupt content produce "Checksum error in the encrypted
// file" which is indistinguishable from a wrong-password error. When the JVM extractor
// also failed (suggestRedownload=true), re-downloading is warranted for both categories.
if (!failure.suggestRedownload || (failure.category !== "crc_error" && failure.category !== "wrong_password")) {
if (!failure.suggestRedownload || failure.category !== "crc_error") {
return 0;
}
@ -4273,24 +4269,8 @@ export class DownloadManager extends EventEmitter {
}
if (hasValidSignature) {
// Check if other archives in this package were successfully extracted.
// If a known password worked for siblings but NOT for this archive,
// the file is very likely corrupt despite having a valid header.
const otherItemsExtracted = items.some((item) =>
item.status === "completed" && isExtractedLabel(item.fullStatus)
&& !archiveItems.includes(item)
);
if (otherItemsExtracted) {
logger.warn(
`Auto-Recovery (${scope}): ${failure.archiveName} - Signatur gueltig aber ` +
`andere Archive im Paket bereits entpackt (bekanntes Passwort existiert). ` +
`Erzwinge Re-Download aller ${archiveItems.length} Parts (wahrscheinliche Korruption)`
);
corruptArchiveItems.push(...inspectedArchiveItems);
} else {
logger.warn(`Auto-Recovery (${scope}): ${failure.archiveName} uebersprungen - Dateien korrekte Groesse, Archiv-Signatur gueltig (vermutlich falsches Passwort)`);
return 0;
}
logger.warn(`Auto-Recovery (${scope}): ${failure.archiveName} uebersprungen - Dateien korrekte Groesse, Archiv-Signatur gueltig (vermutlich falsches Passwort)`);
return 0;
}
logger.warn(
@ -6884,20 +6864,6 @@ export class DownloadManager extends EventEmitter {
if (!stream.destroyed) {
stream.destroy();
}
// fsync for pre-allocated files: force OS to flush all pending writes to
// disk so extraction processes opening the file immediately after download
// see the complete data (prevents "Checksum error" on Windows when file
// handles haven't been fully released yet).
if (!bodyError && preAllocated) {
try {
const syncFd = await fs.promises.open(effectiveTargetPath, "r");
try {
await syncFd.datasync();
} finally {
await syncFd.close();
}
} catch { /* best-effort; extraction retry will catch any remaining issues */ }
}
// If the body read succeeded but the final flush or stream close failed,
// propagate the error so the download is retried instead of marked complete.
if (bodyError) {

View File

@ -1970,61 +1970,11 @@ async function runExternalExtract(
}
} catch (legacyError) {
const legacyText = String((legacyError as Error)?.message || legacyError || "");
const legacyCategory = classifyExtractionError(legacyText);
const isCrcOrWrongPw = legacyCategory === "crc_error" || legacyCategory === "wrong_password";
// ── Retry once after 2s delay ──
// On Windows, freshly completed downloads may still have file handles not
// fully released by the OS. Encrypted RAR5 headers are especially sensitive:
// even a single unreadable byte causes "Checksum error in the encrypted file"
// at bestPercent=0, indistinguishable from a wrong password.
// A short delay allows the OS to finalise all handles and flush caches.
if (isCrcOrWrongPw && !signal?.aborted) {
const retryDelayMs = 2500;
logger.warn(
`Legacy-Extraktion fehlgeschlagen (${legacyCategory}), Retry nach ${retryDelayMs}ms Delay: ${archiveName}`
);
await extractRetryDelay(retryDelayMs);
if (!signal?.aborted) {
try {
const retryCmd = usedCommand;
const retryPassword = await runExternalExtractInner(
retryCmd,
archivePath,
effectiveTargetDir,
conflictMode,
passwordCandidates,
onArchiveProgress,
signal,
timeoutMs,
hybridMode,
onPasswordAttempt,
forceFlatMode,
flatModeResult
);
logger.info(`Legacy-Retry erfolgreich: ${archiveName}`);
password = retryPassword;
usedCommand = retryCmd;
} catch (retryError) {
const retryText = String((retryError as Error)?.message || retryError || "");
const retryCategory = classifyExtractionError(retryText);
logger.warn(`Legacy-Retry ebenfalls fehlgeschlagen (${retryCategory}): ${archiveName}`);
const suggestRedownload = jvmCodecError && (retryCategory === "crc_error" || retryCategory === "wrong_password");
throw withExtractionErrorHints(retryError, {
suggestRedownload,
jvmFailureReason: jvmFailureReason || undefined
});
}
} else {
throw legacyError;
}
} else {
const suggestRedownload = jvmCodecError && isCrcOrWrongPw;
throw withExtractionErrorHints(legacyError, {
suggestRedownload,
jvmFailureReason: jvmFailureReason || undefined
});
}
const suggestRedownload = jvmCodecError && classifyExtractionError(legacyText) === "crc_error";
throw withExtractionErrorHints(legacyError, {
suggestRedownload,
jvmFailureReason: jvmFailureReason || undefined
});
}
const legacyMs = Date.now() - legacyStartedAt;
const extractorName = path.basename(usedCommand).replace(/\.exe$/i, "");
@ -2195,9 +2145,6 @@ async function runExternalExtractInner(
throw new Error(lastError || "Entpacken fehlgeschlagen");
}
// Delay helper for extraction retries (allows file handles to be released on Windows)
const extractRetryDelay = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));
function isZipSafetyGuardError(error: unknown): boolean {
const text = String(error || "").toLowerCase();
return text.includes("path traversal")