mirror of
https://github.com/Maschell/JNUSLib.git
synced 2024-11-25 17:36:55 +01:00
- Replace the readFileAsStream (to InputStream) function with a default implementation in the FSTDataProvider interface. This way the implementations only need to provide a function to write into a outputstream.
- Optimize the readEncryptedToStream function on the DiscReader. The normal wud reader don't need to pipe the stream anymore.
This commit is contained in:
parent
89d5927acd
commit
fbceae0558
@ -110,7 +110,7 @@ public final class WUDService {
|
||||
Map<ByteArrayWrapper, Integer> sectorHashes = new HashMap<>();
|
||||
Map<Integer, Integer> sectorMapping = new TreeMap<>();
|
||||
|
||||
InputStream in = image.getWUDDiscReader().readEncryptedToInputStream(0, image.getWUDFileSize());
|
||||
InputStream in = image.getWUDDiscReader().readEncryptedToStream(0, image.getWUDFileSize());
|
||||
|
||||
int bufferSize = WUDImageCompressedInfo.SECTOR_SIZE;
|
||||
byte[] blockBuffer = new byte[bufferSize];
|
||||
@ -168,8 +168,8 @@ public final class WUDService {
|
||||
log.warning("Filesize is different");
|
||||
return false;
|
||||
}
|
||||
InputStream in1 = firstImage.getWUDDiscReader().readEncryptedToInputStream(0, WUDImage.WUD_FILESIZE);
|
||||
InputStream in2 = secondImage.getWUDDiscReader().readEncryptedToInputStream(0, WUDImage.WUD_FILESIZE);
|
||||
InputStream in1 = firstImage.getWUDDiscReader().readEncryptedToStream(0, WUDImage.WUD_FILESIZE);
|
||||
InputStream in2 = secondImage.getWUDDiscReader().readEncryptedToStream(0, WUDImage.WUD_FILESIZE);
|
||||
|
||||
boolean result = true;
|
||||
int bufferSize = 1024 * 1024 + 19;
|
||||
@ -249,7 +249,7 @@ public final class WUDService {
|
||||
}
|
||||
|
||||
log.info("Writing decompressed file to: " + outputFile.getAbsolutePath());
|
||||
InputStream in = image.getWUDDiscReader().readEncryptedToInputStream(0, WUDImage.WUD_FILESIZE);
|
||||
InputStream in = image.getWUDDiscReader().readEncryptedToStream(0, WUDImage.WUD_FILESIZE);
|
||||
OutputStream out = new FileOutputStream(outputFile);
|
||||
|
||||
int bufferSize = 1024 * 1024;
|
||||
@ -295,7 +295,7 @@ public final class WUDService {
|
||||
log.info("The input file is splitted. The calculated hash is the hash of the corresponding .wud file, not this splitted .wud");
|
||||
}
|
||||
|
||||
InputStream in = image.getWUDDiscReader().readEncryptedToInputStream(0, WUDImage.WUD_FILESIZE);
|
||||
InputStream in = image.getWUDDiscReader().readEncryptedToStream(0, WUDImage.WUD_FILESIZE);
|
||||
|
||||
int bufferSize = 1024 * 1024 * 10;
|
||||
long totalread = 0;
|
||||
|
@ -17,11 +17,9 @@
|
||||
package de.mas.wiiu.jnus.implementations;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PipedOutputStream;
|
||||
import java.util.Optional;
|
||||
|
||||
import de.mas.wiiu.jnus.NUSTitle;
|
||||
@ -31,8 +29,6 @@ import de.mas.wiiu.jnus.interfaces.FSTDataProvider;
|
||||
import de.mas.wiiu.jnus.interfaces.HasNUSTitle;
|
||||
import de.mas.wiiu.jnus.interfaces.NUSDataProvider;
|
||||
import de.mas.wiiu.jnus.utils.CheckSumWrongException;
|
||||
import de.mas.wiiu.jnus.utils.PipedInputStreamWithException;
|
||||
import de.mas.wiiu.jnus.utils.StreamUtils;
|
||||
import de.mas.wiiu.jnus.utils.Utils;
|
||||
import de.mas.wiiu.jnus.utils.cryptography.NUSDecryption;
|
||||
import lombok.Getter;
|
||||
@ -57,52 +53,17 @@ public class FSTDataProviderNUSTitle implements FSTDataProvider, HasNUSTitle {
|
||||
@Override
|
||||
public byte[] readFile(FSTEntry entry, long offset, long size) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
try {
|
||||
readFileToOutputStream(out, entry, offset, size);
|
||||
} catch (CheckSumWrongException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
|
||||
readFileToStream(out, entry, offset, Optional.of(size));
|
||||
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream readFileAsStream(FSTEntry entry, long offset, Optional<Long> size) throws IOException {
|
||||
long filesize = size.orElse(entry.getFileSize());
|
||||
try {
|
||||
return readFileAsInputStream(entry, offset, filesize);
|
||||
} catch (CheckSumWrongException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public PipedInputStreamWithException readFileAsInputStream(FSTEntry entry, long offset, long size) throws IOException, CheckSumWrongException {
|
||||
PipedInputStreamWithException in = new PipedInputStreamWithException();
|
||||
PipedOutputStream out = new PipedOutputStream(in);
|
||||
|
||||
new Thread(() -> {
|
||||
try {
|
||||
readFileToOutputStream(out, entry, offset, size);
|
||||
in.throwException(null);
|
||||
} catch (Exception e) {
|
||||
in.throwException(e);
|
||||
}
|
||||
}).start();
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFileToStream(OutputStream outputStream, FSTEntry entry) throws IOException {
|
||||
try {
|
||||
readFileToOutputStream(outputStream, entry, 0, entry.getFileSize());
|
||||
} catch (CheckSumWrongException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean readFileToOutputStream(OutputStream out, FSTEntry entry, long offset, long size) throws IOException, CheckSumWrongException {
|
||||
public void readFileToStream(OutputStream out, FSTEntry entry, long offset, Optional<Long> size) throws IOException {
|
||||
long fileOffset = entry.getFileOffset() + offset;
|
||||
long fileOffsetBlock = fileOffset;
|
||||
long usedSize = size.orElse(entry.getFileSize());
|
||||
|
||||
if (entry.getContent().isHashed()) {
|
||||
fileOffsetBlock = (fileOffset / 0xFC00) * 0x10000;
|
||||
@ -113,10 +74,14 @@ public class FSTDataProviderNUSTitle implements FSTDataProvider, HasNUSTitle {
|
||||
fileOffsetBlock -= 16;
|
||||
}
|
||||
}
|
||||
return decryptFSTEntryToStream(entry, out, size, fileOffset, fileOffsetBlock);
|
||||
try {
|
||||
decryptFSTEntryToStream(entry, out, fileOffsetBlock, fileOffset, usedSize);
|
||||
} catch (CheckSumWrongException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean decryptFSTEntryToStream(FSTEntry entry, OutputStream outputStream, long fileSize, long fileOffset, long fileOffsetBlock)
|
||||
private boolean decryptFSTEntryToStream(FSTEntry entry, OutputStream outputStream, long fileOffsetBlock, long fileOffset, long fileSize)
|
||||
throws IOException, CheckSumWrongException {
|
||||
if (entry.isNotInPackage() || entry.getContent() == null) {
|
||||
outputStream.close();
|
||||
@ -195,5 +160,4 @@ public class FSTDataProviderNUSTitle implements FSTDataProvider, HasNUSTitle {
|
||||
public NUSTitle getNUSTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -54,27 +54,6 @@ public class FSTDataProviderWUDDataPartition implements FSTDataProvider {
|
||||
return getChunkOfData(info.getOffset(), entry.getFileOffset() + offset, size, discReader, titleKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFileToStream(OutputStream out, FSTEntry entry) throws IOException {
|
||||
ContentFSTInfo info = partition.getFST().getContentFSTInfos().get((int) entry.getContentFSTID());
|
||||
if (titleKey == null) {
|
||||
discReader.readEncryptedToOutputStream(out, partition.getAbsolutePartitionOffset() + info.getOffset() + entry.getFileOffset(), entry.getFileSize());
|
||||
}
|
||||
discReader.readDecryptedToOutputStream(out, partition.getAbsolutePartitionOffset() + info.getOffset(), entry.getFileOffset(), entry.getFileSize(),
|
||||
titleKey, null, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream readFileAsStream(FSTEntry entry, long offset, Optional<Long> size) throws IOException {
|
||||
ContentFSTInfo info = partition.getFST().getContentFSTInfos().get((int) entry.getContentFSTID());
|
||||
long fileSize = size.orElse(entry.getFileSize());
|
||||
if (titleKey == null) {
|
||||
return discReader.readEncryptedToInputStream(partition.getAbsolutePartitionOffset() + info.getOffset() + entry.getFileOffset() + offset, fileSize);
|
||||
}
|
||||
return discReader.readDecryptedToInputStream(partition.getAbsolutePartitionOffset() + info.getOffset(), entry.getFileOffset() + offset, fileSize,
|
||||
titleKey, null, false);
|
||||
}
|
||||
|
||||
public byte[] getChunkOfData(long contentOffset, long fileoffset, long size, WUDDiscReader discReader, byte[] titleKey) throws IOException {
|
||||
if (titleKey == null) {
|
||||
return discReader.readEncryptedToByteArray(partition.getAbsolutePartitionOffset() + contentOffset, fileoffset, (int) size);
|
||||
@ -82,4 +61,27 @@ public class FSTDataProviderWUDDataPartition implements FSTDataProvider {
|
||||
return discReader.readDecryptedToByteArray(partition.getAbsolutePartitionOffset() + contentOffset, fileoffset, (int) size, titleKey, null, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFileToStream(OutputStream out, FSTEntry entry, long offset, Optional<Long> size) throws IOException {
|
||||
ContentFSTInfo info = partition.getFST().getContentFSTInfos().get((int) entry.getContentFSTID());
|
||||
long usedSize = size.orElse(entry.getFileSize());
|
||||
if (titleKey == null) {
|
||||
discReader.readEncryptedToStream(out, partition.getAbsolutePartitionOffset() + info.getOffset() + entry.getFileOffset() + offset, usedSize);
|
||||
}
|
||||
discReader.readDecryptedToOutputStream(out, partition.getAbsolutePartitionOffset() + info.getOffset(), entry.getFileOffset() + offset, usedSize,
|
||||
titleKey, null, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream readFileAsStream(FSTEntry entry, long offset, Optional<Long> size) throws IOException {
|
||||
if (titleKey == null) {
|
||||
ContentFSTInfo info = partition.getFST().getContentFSTInfos().get((int) entry.getContentFSTID());
|
||||
long usedSize = size.orElse(entry.getFileSize());
|
||||
return discReader.readEncryptedToStream(partition.getAbsolutePartitionOffset() + info.getOffset() + entry.getFileOffset() + offset, usedSize);
|
||||
}
|
||||
|
||||
return FSTDataProvider.super.readFileAsStream(entry, offset, size);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ public class NUSDataProviderWUD implements NUSDataProvider {
|
||||
if (size.isPresent()) {
|
||||
usedSize = size.get();
|
||||
}
|
||||
return discReader.readEncryptedToInputStream(offset, usedSize);
|
||||
return discReader.readEncryptedToStream(offset, usedSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -21,13 +21,13 @@ import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PipedInputStream;
|
||||
import java.io.PipedOutputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
|
||||
import de.mas.wiiu.jnus.implementations.wud.WUDImage;
|
||||
import de.mas.wiiu.jnus.utils.PipedInputStreamWithException;
|
||||
import de.mas.wiiu.jnus.utils.cryptography.AESDecryption;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.java.Log;
|
||||
@ -40,42 +40,12 @@ public abstract class WUDDiscReader {
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
public InputStream readEncryptedToInputStream(long offset, long size) throws IOException {
|
||||
PipedInputStream in = new PipedInputStream();
|
||||
PipedOutputStream out = new PipedOutputStream(in);
|
||||
|
||||
new Thread(() -> {
|
||||
try {
|
||||
readEncryptedToOutputStream(out, offset, size);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, "readEncryptedToInputStream@" + this.hashCode()).start();
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
public byte[] readEncryptedToByteArray(long offset, long fileoffset, long size) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
readEncryptedToOutputStream(out, offset + fileoffset, size);
|
||||
readEncryptedToStream(out, offset + fileoffset, size);
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
public InputStream readDecryptedToInputStream(long clusterOffset, long offset, long size, byte[] key, byte[] IV, boolean useFixedIV) throws IOException {
|
||||
PipedInputStream in = new PipedInputStream();
|
||||
PipedOutputStream out = new PipedOutputStream(in);
|
||||
|
||||
new Thread(() -> {
|
||||
try {
|
||||
readDecryptedToOutputStream(out, clusterOffset, offset, size, key, IV, useFixedIV);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, "readDecryptedToInputStream@" + this.hashCode()).start();
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
public byte[] readDecryptedToByteArray(long offset, long fileoffset, long size, byte[] key, byte[] IV, boolean useFixedIV) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
|
||||
@ -83,7 +53,23 @@ public abstract class WUDDiscReader {
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
public abstract void readEncryptedToOutputStream(OutputStream out, long offset, long size) throws IOException;
|
||||
public abstract void readEncryptedToStream(OutputStream out, long offset, long size) throws IOException;
|
||||
|
||||
public InputStream readEncryptedToStream(long offset, long size) throws IOException {
|
||||
PipedInputStreamWithException in = new PipedInputStreamWithException();
|
||||
PipedOutputStream out = new PipedOutputStream(in);
|
||||
|
||||
new Thread(() -> {
|
||||
try {
|
||||
readEncryptedToStream(out, offset, size);
|
||||
in.throwException(null);
|
||||
} catch (Exception e) {
|
||||
in.throwException(e);
|
||||
}
|
||||
}).start();
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -36,7 +36,7 @@ public class WUDDiscReaderCompressed extends WUDDiscReader {
|
||||
* Expects the .wux format by Exzap. You can more infos about it here. https://gbatemp.net/threads/wii-u-image-wud-compression-tool.397901/
|
||||
*/
|
||||
@Override
|
||||
public void readEncryptedToOutputStream(OutputStream out, long offset, long size) throws IOException {
|
||||
public void readEncryptedToStream(OutputStream out, long offset, long size) throws IOException {
|
||||
// make sure there is no out-of-bounds read
|
||||
WUDImageCompressedInfo info = getImage().getCompressedInfo();
|
||||
|
||||
|
@ -37,7 +37,7 @@ public class WUDDiscReaderSplitted extends WUDDiscReader {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readEncryptedToOutputStream(OutputStream outputStream, long offset, long size) throws IOException {
|
||||
public void readEncryptedToStream(OutputStream outputStream, long offset, long size) throws IOException {
|
||||
RandomAccessFile input = getFileByOffset(offset);
|
||||
|
||||
int bufferSize = 0x8000;
|
||||
|
@ -18,6 +18,7 @@ package de.mas.wiiu.jnus.implementations.wud.reader;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
|
||||
@ -30,7 +31,7 @@ public class WUDDiscReaderUncompressed extends WUDDiscReader {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readEncryptedToOutputStream(OutputStream outputStream, long offset, long size) throws IOException {
|
||||
public void readEncryptedToStream(OutputStream outputStream, long offset, long size) throws IOException {
|
||||
|
||||
FileInputStream input = new FileInputStream(getImage().getFileHandle());
|
||||
|
||||
@ -61,4 +62,11 @@ public class WUDDiscReaderUncompressed extends WUDDiscReader {
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream readEncryptedToStream(long offset, long size) throws IOException {
|
||||
FileInputStream input = new FileInputStream(getImage().getFileHandle());
|
||||
StreamUtils.skipExactly(input, offset);
|
||||
return input;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,9 +19,11 @@ package de.mas.wiiu.jnus.interfaces;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PipedOutputStream;
|
||||
import java.util.Optional;
|
||||
|
||||
import de.mas.wiiu.jnus.entities.fst.FSTEntry;
|
||||
import de.mas.wiiu.jnus.utils.PipedInputStreamWithException;
|
||||
|
||||
public interface FSTDataProvider {
|
||||
public String getName();
|
||||
@ -34,8 +36,26 @@ public interface FSTDataProvider {
|
||||
|
||||
public byte[] readFile(FSTEntry entry, long offset, long size) throws IOException;
|
||||
|
||||
public InputStream readFileAsStream(FSTEntry entry, long offset, Optional<Long> size) throws IOException;
|
||||
default public InputStream readFileAsStream(FSTEntry entry, long offset, Optional<Long> size) throws IOException {
|
||||
PipedInputStreamWithException in = new PipedInputStreamWithException();
|
||||
PipedOutputStream out = new PipedOutputStream(in);
|
||||
|
||||
public void readFileToStream(OutputStream out, FSTEntry entry) throws IOException;
|
||||
new Thread(() -> {
|
||||
try {
|
||||
readFileToStream(out, entry, offset, size);
|
||||
in.throwException(null);
|
||||
} catch (Exception e) {
|
||||
in.throwException(e);
|
||||
}
|
||||
}).start();
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
default public void readFileToStream(OutputStream out, FSTEntry entry, long offset) throws IOException {
|
||||
readFileToStream(out, entry, offset, Optional.empty());
|
||||
}
|
||||
|
||||
public void readFileToStream(OutputStream out, FSTEntry entry, long offset, Optional<Long> size) throws IOException;
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user