diff --git a/src/de/mas/wiiu/jnus/WUDService.java b/src/de/mas/wiiu/jnus/WUDService.java index 88e817c..6ecd8fe 100644 --- a/src/de/mas/wiiu/jnus/WUDService.java +++ b/src/de/mas/wiiu/jnus/WUDService.java @@ -110,7 +110,7 @@ public final class WUDService { Map sectorHashes = new HashMap<>(); Map 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; diff --git a/src/de/mas/wiiu/jnus/implementations/FSTDataProviderNUSTitle.java b/src/de/mas/wiiu/jnus/implementations/FSTDataProviderNUSTitle.java index 58db709..bfa104f 100644 --- a/src/de/mas/wiiu/jnus/implementations/FSTDataProviderNUSTitle.java +++ b/src/de/mas/wiiu/jnus/implementations/FSTDataProviderNUSTitle.java @@ -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 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 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; } - } diff --git a/src/de/mas/wiiu/jnus/implementations/FSTDataProviderWUDDataPartition.java b/src/de/mas/wiiu/jnus/implementations/FSTDataProviderWUDDataPartition.java index 34d13bf..f0db96e 100644 --- a/src/de/mas/wiiu/jnus/implementations/FSTDataProviderWUDDataPartition.java +++ b/src/de/mas/wiiu/jnus/implementations/FSTDataProviderWUDDataPartition.java @@ -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 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 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 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); + + } + } diff --git a/src/de/mas/wiiu/jnus/implementations/NUSDataProviderWUD.java b/src/de/mas/wiiu/jnus/implementations/NUSDataProviderWUD.java index 22d14e5..e8a74fa 100644 --- a/src/de/mas/wiiu/jnus/implementations/NUSDataProviderWUD.java +++ b/src/de/mas/wiiu/jnus/implementations/NUSDataProviderWUD.java @@ -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 diff --git a/src/de/mas/wiiu/jnus/implementations/wud/reader/WUDDiscReader.java b/src/de/mas/wiiu/jnus/implementations/wud/reader/WUDDiscReader.java index 53d79c9..2fbb6f1 100644 --- a/src/de/mas/wiiu/jnus/implementations/wud/reader/WUDDiscReader.java +++ b/src/de/mas/wiiu/jnus/implementations/wud/reader/WUDDiscReader.java @@ -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; + } /** * diff --git a/src/de/mas/wiiu/jnus/implementations/wud/reader/WUDDiscReaderCompressed.java b/src/de/mas/wiiu/jnus/implementations/wud/reader/WUDDiscReaderCompressed.java index 2e985b7..86ccae5 100644 --- a/src/de/mas/wiiu/jnus/implementations/wud/reader/WUDDiscReaderCompressed.java +++ b/src/de/mas/wiiu/jnus/implementations/wud/reader/WUDDiscReaderCompressed.java @@ -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(); diff --git a/src/de/mas/wiiu/jnus/implementations/wud/reader/WUDDiscReaderSplitted.java b/src/de/mas/wiiu/jnus/implementations/wud/reader/WUDDiscReaderSplitted.java index 6c8156f..42aa896 100644 --- a/src/de/mas/wiiu/jnus/implementations/wud/reader/WUDDiscReaderSplitted.java +++ b/src/de/mas/wiiu/jnus/implementations/wud/reader/WUDDiscReaderSplitted.java @@ -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; diff --git a/src/de/mas/wiiu/jnus/implementations/wud/reader/WUDDiscReaderUncompressed.java b/src/de/mas/wiiu/jnus/implementations/wud/reader/WUDDiscReaderUncompressed.java index 4c3e876..a8118e9 100644 --- a/src/de/mas/wiiu/jnus/implementations/wud/reader/WUDDiscReaderUncompressed.java +++ b/src/de/mas/wiiu/jnus/implementations/wud/reader/WUDDiscReaderUncompressed.java @@ -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; + } + } diff --git a/src/de/mas/wiiu/jnus/interfaces/FSTDataProvider.java b/src/de/mas/wiiu/jnus/interfaces/FSTDataProvider.java index eed5f05..f931868 100644 --- a/src/de/mas/wiiu/jnus/interfaces/FSTDataProvider.java +++ b/src/de/mas/wiiu/jnus/interfaces/FSTDataProvider.java @@ -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 size) throws IOException; + default public InputStream readFileAsStream(FSTEntry entry, long offset, Optional 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 size) throws IOException; }