/****************************************************************************
* Copyright (C) 2016-2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
****************************************************************************/
package de.mas.wiiu.jnus;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
import de.mas.wiiu.jnus.entities.content.Content;
import de.mas.wiiu.jnus.implementations.NUSDataProvider;
import de.mas.wiiu.jnus.utils.FileUtils;
import de.mas.wiiu.jnus.utils.Parallelizable;
import de.mas.wiiu.jnus.utils.Utils;
import lombok.Getter;
import lombok.extern.java.Log;
@Log
public final class ExtractionService {
private static Map instances = new HashMap<>();
@Getter private final NUSTitle NUSTitle;
private boolean parallelizable = false;
public static ExtractionService getInstance(NUSTitle nustitle) {
if (!instances.containsKey(nustitle)) {
instances.put(nustitle, new ExtractionService(nustitle));
}
return instances.get(nustitle);
}
private ExtractionService(NUSTitle nustitle) {
if (nustitle.getDataProvider() instanceof Parallelizable) {
parallelizable = true;
}
this.NUSTitle = nustitle;
}
private NUSDataProvider getDataProvider() {
return getNUSTitle().getDataProvider();
}
public void extractAllEncrpytedContentFileHashes(String outputFolder) throws IOException {
extractEncryptedContentHashesTo(new ArrayList(getNUSTitle().getTMD().getAllContents().values()), outputFolder);
}
public void extractEncryptedContentHashesTo(List list, String outputFolder) throws IOException {
Utils.createDir(outputFolder);
NUSDataProvider dataProvider = getDataProvider();
for (Content c : list) {
dataProvider.saveContentH3Hash(c, outputFolder);
}
}
public void extractAllEncryptedContentFiles(String outputFolder) throws IOException {
extractAllEncryptedContentFilesWithHashesTo(outputFolder);
}
public void extractAllEncryptedContentFilesWithoutHashesTo(String outputFolder) throws IOException {
extractEncryptedContentFilesTo(new ArrayList(getNUSTitle().getTMD().getAllContents().values()), outputFolder, false);
}
public void extractAllEncryptedContentFilesWithHashesTo(String outputFolder) throws IOException {
extractEncryptedContentFilesTo(new ArrayList(getNUSTitle().getTMD().getAllContents().values()), outputFolder, true);
}
public void extractEncryptedContentTo(Content content, String outputFolder, boolean withHashes) throws IOException {
NUSDataProvider dataProvider = getDataProvider();
if (withHashes) {
dataProvider.saveEncryptedContentWithH3Hash(content, outputFolder);
} else {
dataProvider.saveEncryptedContent(content, outputFolder);
}
}
public void extractEncryptedContentFilesTo(List list, String outputFolder, boolean withHashes) throws IOException {
Utils.createDir(outputFolder);
if (parallelizable && Settings.ALLOW_PARALLELISATION) {
try {
CompletableFuture.allOf(list.stream().map((Content c) -> CompletableFuture.runAsync(() -> {
try {
extractEncryptedContentTo(c, outputFolder, withHashes);
} catch (IOException e) {
throw new CompletionException(e);
}
})).toArray(CompletableFuture[]::new)).get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
} else {
for (Content c : list) {
extractEncryptedContentTo(c, outputFolder, withHashes);
}
}
}
public void extractTMDTo(String output) throws IOException {
Utils.createDir(output);
byte[] rawTMD = getDataProvider().getRawTMD();
if (rawTMD == null || rawTMD.length == 0) {
log.info("Couldn't write TMD: No TMD loaded");
return;
}
String tmd_path = output + File.separator + Settings.TMD_FILENAME;
log.info("Extracting TMD to: " + tmd_path);
FileUtils.saveByteArrayToFile(tmd_path, rawTMD);
}
public boolean extractTicketTo(String output) throws IOException {
Utils.createDir(output);
byte[] rawTicket = getDataProvider().getRawTicket();
if (rawTicket == null || rawTicket.length == 0) {
log.info("Couldn't write Ticket: No Ticket loaded");
return false;
}
String ticket_path = output + File.separator + Settings.TICKET_FILENAME;
log.info("Extracting Ticket to: " + ticket_path);
return FileUtils.saveByteArrayToFile(ticket_path, rawTicket);
}
public void extractCertTo(String output) throws IOException {
Utils.createDir(output);
byte[] rawCert = getDataProvider().getRawCert();
if (rawCert == null || rawCert.length == 0) {
log.info("Couldn't write Cert: No Cert loaded");
return;
}
String cert_path = output + File.separator + Settings.CERT_FILENAME;
log.info("Extracting Cert to: " + cert_path);
FileUtils.saveByteArrayToFile(cert_path, rawCert);
}
public void extractAll(String outputFolder) throws IOException {
Utils.createDir(outputFolder);
extractAllEncryptedContentFilesWithHashesTo(outputFolder);
extractCertTo(outputFolder);
extractTMDTo(outputFolder);
extractTicketTo(outputFolder);
}
}