Fix multi-part RAR: use explicit ArchiveFormat instead of VolumedArchiveInStream
VolumedArchiveInStream only works for .7z.001 splits - it rejects RAR filenames. For multi-part RAR (.partN.rar), use RandomAccessFileInStream with explicit ArchiveFormat.RAR5/RAR format specification. Auto-detection with null format can fail for multi-volume RAR archives. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
462fc0397e
commit
35e84e652e
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -11,6 +11,7 @@ import net.sf.sevenzipjbinding.IInStream;
|
|||||||
import net.sf.sevenzipjbinding.ISequentialOutStream;
|
import net.sf.sevenzipjbinding.ISequentialOutStream;
|
||||||
import net.sf.sevenzipjbinding.ICryptoGetTextPassword;
|
import net.sf.sevenzipjbinding.ICryptoGetTextPassword;
|
||||||
import net.sf.sevenzipjbinding.PropID;
|
import net.sf.sevenzipjbinding.PropID;
|
||||||
|
import net.sf.sevenzipjbinding.ArchiveFormat;
|
||||||
import net.sf.sevenzipjbinding.SevenZip;
|
import net.sf.sevenzipjbinding.SevenZip;
|
||||||
import net.sf.sevenzipjbinding.SevenZipException;
|
import net.sf.sevenzipjbinding.SevenZipException;
|
||||||
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
|
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
|
||||||
@ -328,13 +329,9 @@ public final class JBindExtractorMain {
|
|||||||
String effectivePassword = password == null ? "" : password;
|
String effectivePassword = password == null ? "" : password;
|
||||||
SevenZipVolumeCallback callback = new SevenZipVolumeCallback(archiveFile, effectivePassword);
|
SevenZipVolumeCallback callback = new SevenZipVolumeCallback(archiveFile, effectivePassword);
|
||||||
|
|
||||||
// Multi-volume archives need VolumedArchiveInStream so 7z-JBinding can
|
// VolumedArchiveInStream is ONLY for .7z.001 split archives.
|
||||||
// request additional volumes via the IArchiveOpenVolumeCallback.
|
// It internally checks for the ".7z.001" suffix and rejects everything else.
|
||||||
boolean isMultiVolume = SEVEN_ZIP_SPLIT_RE.matcher(nameLower).matches()
|
if (SEVEN_ZIP_SPLIT_RE.matcher(nameLower).matches()) {
|
||||||
|| RAR_MULTIPART_RE.matcher(nameLower).matches()
|
|
||||||
|| hasOldStyleRarSplits(archiveFile);
|
|
||||||
|
|
||||||
if (isMultiVolume) {
|
|
||||||
VolumedArchiveInStream volumed = new VolumedArchiveInStream(archiveFile.getName(), callback);
|
VolumedArchiveInStream volumed = new VolumedArchiveInStream(archiveFile.getName(), callback);
|
||||||
IInArchive archive = SevenZip.openInArchive(null, volumed, callback);
|
IInArchive archive = SevenZip.openInArchive(null, volumed, callback);
|
||||||
return new SevenZipArchiveContext(archive, null, volumed, callback);
|
return new SevenZipArchiveContext(archive, null, volumed, callback);
|
||||||
@ -342,6 +339,35 @@ public final class JBindExtractorMain {
|
|||||||
|
|
||||||
RandomAccessFile raf = new RandomAccessFile(archiveFile, "r");
|
RandomAccessFile raf = new RandomAccessFile(archiveFile, "r");
|
||||||
RandomAccessFileInStream stream = new RandomAccessFileInStream(raf);
|
RandomAccessFileInStream stream = new RandomAccessFileInStream(raf);
|
||||||
|
|
||||||
|
// Multi-part RAR (.part1.rar, .part2.rar or old-style .rar/.r01/.r02):
|
||||||
|
// Auto-detection with null format can fail for multi-volume RAR because
|
||||||
|
// 7z-JBinding may not fully recognize the format from a single part.
|
||||||
|
// Specify the format explicitly (try RAR5 first, then RAR4).
|
||||||
|
if (RAR_MULTIPART_RE.matcher(nameLower).matches() || hasOldStyleRarSplits(archiveFile)) {
|
||||||
|
ArchiveFormat[] rarFormats = { ArchiveFormat.RAR5, ArchiveFormat.RAR };
|
||||||
|
Exception lastError = null;
|
||||||
|
for (ArchiveFormat fmt : rarFormats) {
|
||||||
|
try {
|
||||||
|
stream.seek(0L, 0);
|
||||||
|
IInArchive archive = SevenZip.openInArchive(fmt, stream, callback);
|
||||||
|
return new SevenZipArchiveContext(archive, stream, null, callback);
|
||||||
|
} catch (Exception e) {
|
||||||
|
lastError = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Final attempt with auto-detection
|
||||||
|
try {
|
||||||
|
stream.seek(0L, 0);
|
||||||
|
IInArchive archive = SevenZip.openInArchive(null, stream, callback);
|
||||||
|
return new SevenZipArchiveContext(archive, stream, null, callback);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Close the RAF since we're about to throw
|
||||||
|
try { raf.close(); } catch (Throwable ignored) {}
|
||||||
|
throw lastError != null ? lastError : e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IInArchive archive = SevenZip.openInArchive(null, stream, callback);
|
IInArchive archive = SevenZip.openInArchive(null, stream, callback);
|
||||||
return new SevenZipArchiveContext(archive, stream, null, callback);
|
return new SevenZipArchiveContext(archive, stream, null, callback);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user