diff --git a/src/de/mas/wiiu/jnus/DecryptionService.java b/src/de/mas/wiiu/jnus/DecryptionService.java index 46144c9..7c7cbda 100644 --- a/src/de/mas/wiiu/jnus/DecryptionService.java +++ b/src/de/mas/wiiu/jnus/DecryptionService.java @@ -66,7 +66,7 @@ public final class DecryptionService { public CompletableFuture decryptFSTEntryToAsync(boolean useFullPath, FSTEntry entry, String outputPath, boolean skipExistingFile) { return CompletableFuture.runAsync(() -> { try { - if (entry.isNotInPackage() || entry.getContent() == null) { + if (entry.isNotInPackage() || !entry.getContent().isPresent()) { return; } @@ -99,7 +99,7 @@ public final class DecryptionService { return; } if (targetFile.length() == entry.getFileSize()) { - Content c = entry.getContent(); + Content c = entry.getContent().get(); if (c.isHashed()) { log.info("File already exists: " + entry.getFilename()); return; diff --git a/src/de/mas/wiiu/jnus/entities/fst/FSTEntry.java b/src/de/mas/wiiu/jnus/entities/fst/FSTEntry.java index c5b84a6..baf2add 100644 --- a/src/de/mas/wiiu/jnus/entities/fst/FSTEntry.java +++ b/src/de/mas/wiiu/jnus/entities/fst/FSTEntry.java @@ -20,14 +20,14 @@ import java.io.File; import java.io.PrintStream; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.function.Supplier; import de.mas.wiiu.jnus.entities.content.Content; import lombok.Data; import lombok.Getter; -import lombok.extern.java.Log; +import lombok.NonNull; -@Log /** * Represents one FST Entry * @@ -41,7 +41,7 @@ public class FSTEntry { private String filename = null; private final Supplier filenameSupplier; - @Getter private final FSTEntry parent; + @Getter private final Optional parent; @Getter private final List children = new ArrayList<>(); @@ -50,7 +50,7 @@ public class FSTEntry { @Getter private final long fileSize; @Getter private final long fileOffset; - @Getter private final Content content; + @Getter private final Optional content; @Getter private final boolean isDir; @Getter private final boolean isRoot; @@ -62,14 +62,14 @@ public class FSTEntry { this.filenameSupplier = fstParam.getFileNameSupplier(); this.flags = fstParam.getFlags(); this.parent = fstParam.getParent(); - if (parent != null) { - parent.children.add(this); + if (parent.isPresent()) { + parent.get().children.add(this); } this.fileSize = fstParam.getFileSize(); this.fileOffset = fstParam.getFileOffset(); this.content = fstParam.getContent(); - if (content != null) { - content.addEntry(this); + if (content.isPresent()) { + content.get().addEntry(this); } this.isDir = fstParam.isDir(); this.isRoot = fstParam.isRoot(); @@ -88,14 +88,14 @@ public class FSTEntry { param.setDir(true); return new FSTEntry(param); } - - public static FSTEntry createFSTEntry(FSTEntry parent, String filename, Content content) { + + public static FSTEntry createFSTEntry(@NonNull FSTEntry parent, @NonNull String filename, @NonNull Content content) { FSTEntryParam param = new FSTEntryParam(); param.setFileNameSupplier(() -> filename); param.setFileSize(content.getDecryptedFileSize()); - param.setContent(content); + param.setContent(Optional.of(content)); param.setDir(false); - param.setParent(parent); + param.setParent(Optional.of(parent)); return new FSTEntry(param); } @@ -111,8 +111,9 @@ public class FSTEntry { } private StringBuilder getPathInternal() { - if (parent != null) { - return parent.getPathInternal().append(parent.getFilename()).append(File.separator); + if (parent.isPresent()) { + FSTEntry par = parent.get(); + return par.getPathInternal().append(par.getFilename()).append(File.separator); } return new StringBuilder(); } @@ -159,14 +160,10 @@ public class FSTEntry { public List getFSTEntriesByContent(Content content) { List entries = new ArrayList<>(); - if (this.content == null) { - log.warning("Error in getFSTEntriesByContent, content null"); - System.exit(0); - } else { - if (this.content.equals(content)) { - entries.add(this); - } + if (this.content.isPresent() && this.content.get().equals(content)) { + entries.add(this); } + for (FSTEntry child : getChildren()) { entries.addAll(child.getFSTEntriesByContent(content)); } @@ -174,7 +171,7 @@ public class FSTEntry { } public long getFileOffsetBlock() { - if (getContent().isHashed()) { + if (getContent().isPresent() && getContent().get().isHashed()) { return (getFileOffset() / 0xFC00) * 0x10000; } else { return getFileOffset(); @@ -211,14 +208,14 @@ public class FSTEntry { @Data protected static class FSTEntryParam { private Supplier fileNameSupplier = () -> ""; - private FSTEntry parent = null; + private Optional parent = Optional.empty(); private short flags; private long fileSize = 0; private long fileOffset = 0; - private Content content = null; + private Optional content = Optional.empty(); private boolean isDir = false; private boolean isRoot = false; diff --git a/src/de/mas/wiiu/jnus/entities/fst/FSTService.java b/src/de/mas/wiiu/jnus/entities/fst/FSTService.java index d969b76..19449b8 100644 --- a/src/de/mas/wiiu/jnus/entities/fst/FSTService.java +++ b/src/de/mas/wiiu/jnus/entities/fst/FSTService.java @@ -20,6 +20,7 @@ import java.text.ParseException; import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import de.mas.wiiu.jnus.entities.content.Content; import de.mas.wiiu.jnus.entities.content.ContentFSTInfo; @@ -109,7 +110,7 @@ public final class FSTService { } } else { // TODO: make content attribute in a fstentry optional - entryParam.setContent(content); + entryParam.setContent(Optional.of(content)); ContentFSTInfo contentFSTInfo = contentsFSTByIndex.get((int) contentIndex); if (contentFSTInfo == null) { log.warning("ContentFSTInfo for FST Entry not found"); @@ -121,7 +122,7 @@ public final class FSTService { } entryParam.setContentFSTID(contentIndex); - entryParam.setParent(parent); + entryParam.setParent(Optional.of(parent)); FSTEntry entry = new FSTEntry(entryParam); fstEntryToOffsetMap.put(entryOffset, entry); diff --git a/src/de/mas/wiiu/jnus/implementations/FSTDataProviderNUSTitle.java b/src/de/mas/wiiu/jnus/implementations/FSTDataProviderNUSTitle.java index ed34724..c4625dd 100644 --- a/src/de/mas/wiiu/jnus/implementations/FSTDataProviderNUSTitle.java +++ b/src/de/mas/wiiu/jnus/implementations/FSTDataProviderNUSTitle.java @@ -75,11 +75,16 @@ public class FSTDataProviderNUSTitle implements FSTDataProvider, HasNUSTitle { @Override public void readFileToStream(OutputStream out, FSTEntry entry, long offset, Optional size) throws IOException { + if (!entry.getContent().isPresent()) { + out.close(); + throw new IOException("Content for the FSTEntry not found: " + entry); + } long fileOffset = entry.getFileOffset() + offset; long fileOffsetBlock = fileOffset; long usedSize = size.orElse(entry.getFileSize()); + Content c = entry.getContent().get(); - if (entry.getContent().isHashed()) { + if (c.isHashed()) { fileOffsetBlock = (fileOffset / 0xFC00) * 0x10000; } else { fileOffsetBlock = (fileOffset / 0x8000) * 0x8000; @@ -97,12 +102,12 @@ public class FSTDataProviderNUSTitle implements FSTDataProvider, HasNUSTitle { private boolean decryptFSTEntryToStream(FSTEntry entry, OutputStream outputStream, long fileOffsetBlock, long fileOffset, long fileSize) throws IOException, CheckSumWrongException { - if (entry.isNotInPackage() || entry.getContent() == null || !title.getTicket().isPresent()) { + if (entry.isNotInPackage() || !entry.getContent().isPresent() || !title.getTicket().isPresent()) { if (!title.getTicket().isPresent()) { log.info("Decryption not possible because no ticket was set."); - }else if(entry.isNotInPackage()) { + } else if (entry.isNotInPackage()) { log.info("Decryption not possible because the FSTEntry is not in this package"); - }else if(entry.getContent() == null) { + } else if (entry.getContent() == null) { // TODO: convert it to an Optional log.info("Decryption not possible because the Content was null"); } @@ -110,7 +115,7 @@ public class FSTDataProviderNUSTitle implements FSTDataProvider, HasNUSTitle { return false; } - Content c = entry.getContent(); + Content c = entry.getContent().get(); NUSDataProvider dataProvider = title.getDataProvider(); @@ -124,7 +129,7 @@ public class FSTDataProviderNUSTitle implements FSTDataProvider, HasNUSTitle { } return nusdecryption.decryptStreams(in, outputStream, fileSize, fileOffset, c, h3HashedOpt); } catch (CheckSumWrongException e) { - if (entry.getContent().isUNKNWNFlag1Set()) { + if (c.isUNKNWNFlag1Set()) { log.info("Hash doesn't match. But file is optional. Don't worry."); } else { StringBuilder sb = new StringBuilder();