mirror of
https://github.com/Maschell/JNUSLib.git
synced 2024-11-22 16:09:18 +01:00
The FST and Ticket attribute of the NUSTitle are now optionals
This commit is contained in:
parent
73440af121
commit
7c9fe334a8
@ -18,10 +18,12 @@ package de.mas.wiiu.jnus;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@ -34,15 +36,24 @@ import de.mas.wiiu.jnus.entities.fst.FST;
|
||||
import de.mas.wiiu.jnus.entities.fst.FSTEntry;
|
||||
import de.mas.wiiu.jnus.interfaces.NUSDataProvider;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
|
||||
public class NUSTitle {
|
||||
@Getter @Setter private FST FST;
|
||||
@Getter @Setter private TMD TMD;
|
||||
@Getter @Setter private Ticket ticket;
|
||||
@Getter @Setter private Optional<FST> FST = Optional.empty();
|
||||
@Getter @Setter private Optional<Ticket> ticket;
|
||||
|
||||
@Getter private final TMD TMD;
|
||||
|
||||
@Getter @Setter private boolean skipExistingFiles = true;
|
||||
@Getter @Setter private NUSDataProvider dataProvider = null;
|
||||
@Getter private final NUSDataProvider dataProvider;
|
||||
|
||||
public NUSTitle(@NonNull NUSDataProvider dataProvider) throws ParseException, IOException {
|
||||
byte[] tmdData = dataProvider.getRawTMD().orElseThrow(() -> new ParseException("No TMD data found", 0));
|
||||
this.TMD = de.mas.wiiu.jnus.entities.TMD.parseTMD(tmdData);
|
||||
this.dataProvider = dataProvider;
|
||||
|
||||
}
|
||||
|
||||
public List<FSTEntry> getAllFSTEntriesFlatByContentID(short ID) {
|
||||
return getFSTEntriesFlatByContent(getTMD().getContentByID((int) ID));
|
||||
@ -65,7 +76,10 @@ public class NUSTitle {
|
||||
}
|
||||
|
||||
public Stream<FSTEntry> getAllFSTEntriesAsStream() {
|
||||
return getAllFSTEntryChildrenAsStream(FST.getRoot());
|
||||
if (!FST.isPresent()) {
|
||||
return Stream.empty();
|
||||
}
|
||||
return getAllFSTEntryChildrenAsStream(FST.get().getRoot());
|
||||
}
|
||||
|
||||
public Stream<FSTEntry> getAllFSTEntryChildrenAsStream(FSTEntry cur) {
|
||||
@ -84,7 +98,11 @@ public class NUSTitle {
|
||||
}
|
||||
|
||||
public List<FSTEntry> getFSTEntriesByRegEx(String regEx) {
|
||||
return getFSTEntriesByRegEx(regEx, FST.getRoot());
|
||||
if (!FST.isPresent()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
return getFSTEntriesByRegEx(regEx, FST.get().getRoot());
|
||||
}
|
||||
|
||||
public List<FSTEntry> getFSTEntriesByRegEx(String regEx, FSTEntry entry) {
|
||||
@ -92,7 +110,10 @@ public class NUSTitle {
|
||||
}
|
||||
|
||||
public List<FSTEntry> getFSTEntriesByRegEx(String regEx, boolean onlyInPackage) {
|
||||
return getFSTEntriesByRegEx(regEx, FST.getRoot(), onlyInPackage);
|
||||
if (!FST.isPresent()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return getFSTEntriesByRegEx(regEx, FST.get().getRoot(), onlyInPackage);
|
||||
}
|
||||
|
||||
public List<FSTEntry> getFSTEntriesByRegEx(String regEx, FSTEntry entry, boolean allowNotInPackage) {
|
||||
@ -116,15 +137,20 @@ public class NUSTitle {
|
||||
}
|
||||
|
||||
public void printFiles() {
|
||||
getFST().getRoot().printRecursive(0);
|
||||
if (FST.isPresent()) {
|
||||
FST.get().getRoot().printRecursive(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void printContentFSTInfos() {
|
||||
for (Entry<Integer, ContentFSTInfo> e : getFST().getContentFSTInfos().entrySet()) {
|
||||
if (FST.isPresent()) {
|
||||
for (Entry<Integer, ContentFSTInfo> e : FST.get().getContentFSTInfos().entrySet()) {
|
||||
System.out.println(String.format("%08X", e.getKey()) + ": " + e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void printContentInfos() {
|
||||
for (Entry<Integer, Content> e : getTMD().getAllContents().entrySet()) {
|
||||
|
||||
|
@ -40,15 +40,9 @@ public class NUSTitleLoader {
|
||||
}
|
||||
|
||||
public static NUSTitle loadNusTitle(NUSTitleConfig config, Supplier<NUSDataProvider> dataProviderFunction) throws IOException, ParseException {
|
||||
NUSTitle result = new NUSTitle();
|
||||
|
||||
NUSDataProvider dataProvider = dataProviderFunction.get();
|
||||
result.setDataProvider(dataProvider);
|
||||
|
||||
byte[] tmdData = dataProvider.getRawTMD().orElseThrow(() -> new ParseException("No TMD data found", 0));
|
||||
|
||||
TMD tmd = TMD.parseTMD(tmdData);
|
||||
result.setTMD(tmd);
|
||||
NUSTitle result = new NUSTitle(dataProvider);
|
||||
|
||||
if (config.isNoDecryption()) {
|
||||
return result;
|
||||
@ -64,19 +58,20 @@ public class NUSTitleLoader {
|
||||
if (ticket == null) {
|
||||
new ParseException("Failed to get ticket data", 0);
|
||||
}
|
||||
result.setTicket(ticket);
|
||||
result.setTicket(Optional.of(ticket));
|
||||
|
||||
// If we have just content, we don't have a FST.
|
||||
if (tmd.getAllContents().size() == 1) {
|
||||
if (result.getTMD().getAllContents().size() == 1) {
|
||||
// The only way to check if the key is right, is by trying to decrypt the whole thing.
|
||||
FSTDataProvider dp = new FSTDataProviderNUSTitle(result);
|
||||
for (FSTEntry children : dp.getRoot().getChildren()) {
|
||||
dp.readFile(children);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
// If we have more than one content, the index 0 is the FST.
|
||||
Content fstContent = tmd.getContentByIndex(0);
|
||||
Content fstContent = result.getTMD().getContentByIndex(0);
|
||||
|
||||
InputStream fstContentEncryptedStream = dataProvider.getInputStreamFromContent(fstContent, 0, Optional.of(fstContent.getEncryptedFileSize()));
|
||||
|
||||
@ -90,10 +85,10 @@ public class NUSTitleLoader {
|
||||
fstBytes = aesDecryption.decrypt(fstBytes);
|
||||
}
|
||||
|
||||
Map<Integer, Content> contents = tmd.getAllContents();
|
||||
Map<Integer, Content> contents = result.getTMD().getAllContents();
|
||||
|
||||
FST fst = FST.parseFST(fstBytes, contents);
|
||||
result.setFST(fst);
|
||||
result.setFST(Optional.of(fst));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import java.util.stream.Collectors;
|
||||
|
||||
import de.mas.wiiu.jnus.NUSTitle;
|
||||
import de.mas.wiiu.jnus.entities.content.Content;
|
||||
import de.mas.wiiu.jnus.entities.fst.FST;
|
||||
import de.mas.wiiu.jnus.entities.fst.FSTEntry;
|
||||
import de.mas.wiiu.jnus.interfaces.FSTDataProvider;
|
||||
import de.mas.wiiu.jnus.interfaces.HasNUSTitle;
|
||||
@ -47,9 +46,8 @@ public class FSTDataProviderNUSTitle implements FSTDataProvider, HasNUSTitle {
|
||||
this.title = title;
|
||||
this.name = String.format("%016X", title.getTMD().getTitleID());
|
||||
|
||||
FST fst = title.getFST();
|
||||
if (fst != null) {
|
||||
rootEntry = title.getFST().getRoot();
|
||||
if (title.getFST().isPresent()) {
|
||||
rootEntry = title.getFST().get().getRoot();
|
||||
} else if (title.getTMD().getContentCount() == 1) {
|
||||
// If the tmd has only one content file, it has not FST. We have to create our own FST.
|
||||
Content c = title.getTMD().getAllContents().values().stream().collect(Collectors.toList()).get(0);
|
||||
@ -99,7 +97,15 @@ 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) {
|
||||
if (entry.isNotInPackage() || entry.getContent() == null || !title.getTicket().isPresent()) {
|
||||
if (!title.getTicket().isPresent()) {
|
||||
log.info("Decryption not possible because no ticket was set.");
|
||||
}else if(entry.isNotInPackage()) {
|
||||
log.info("Decryption not possible because the FSTEntry is not in this package");
|
||||
}else if(entry.getContent() == null) {
|
||||
// TODO: convert it to an Optional
|
||||
log.info("Decryption not possible because the Content was null");
|
||||
}
|
||||
outputStream.close();
|
||||
return false;
|
||||
}
|
||||
@ -111,7 +117,7 @@ public class FSTDataProviderNUSTitle implements FSTDataProvider, HasNUSTitle {
|
||||
InputStream in = dataProvider.getInputStreamFromContent(c, fileOffsetBlock);
|
||||
|
||||
try {
|
||||
NUSDecryption nusdecryption = new NUSDecryption(title.getTicket());
|
||||
NUSDecryption nusdecryption = new NUSDecryption(title.getTicket().get());
|
||||
Optional<byte[]> h3HashedOpt = Optional.empty();
|
||||
if (c.isHashed()) {
|
||||
h3HashedOpt = dataProvider.getContentH3Hash(c);
|
||||
|
Loading…
Reference in New Issue
Block a user