/**************************************************************************** * 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.Arrays; import java.util.List; import java.util.Map.Entry; import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; import de.mas.wiiu.jnus.entities.TMD; import de.mas.wiiu.jnus.entities.Ticket; import de.mas.wiiu.jnus.entities.content.Content; import de.mas.wiiu.jnus.entities.content.ContentFSTInfo; import de.mas.wiiu.jnus.entities.fst.FST; import de.mas.wiiu.jnus.entities.fst.FSTEntry; import de.mas.wiiu.jnus.implementations.NUSDataProvider; import lombok.Getter; import lombok.Setter; import lombok.val; public class NUSTitle { @Getter @Setter private FST FST; @Getter @Setter private TMD TMD; @Getter @Setter private Ticket ticket; @Getter @Setter private boolean skipExistingFiles = true; @Getter @Setter private NUSDataProvider dataProvider = null; public List getAllFSTEntriesFlatByContentID(short ID) { return getFSTEntriesFlatByContent(getTMD().getContentByID((int) ID)); } public List getFSTEntriesFlatByContentIndex(int index) { return getFSTEntriesFlatByContent(getTMD().getContentByIndex(index)); } public List getFSTEntriesFlatByContent(Content content) { return getFSTEntriesFlatByContents(new ArrayList(Arrays.asList(content))); } public List getFSTEntriesFlatByContents(List list) { return list.stream().flatMap(c -> c.getEntries().stream()).collect(Collectors.toList()); } public List getAllFSTEntriesFlat() { return getFSTEntriesFlatByContents(new ArrayList(getTMD().getAllContents().values())); } public Stream getAllFSTEntriesAsStream() { return getAllFSTEntryChildrenAsStream(FST.getRoot()); } public Stream getAllFSTEntryChildrenAsStream(FSTEntry cur) { return getAllFSTEntryChildrenAsStream(cur, false); } public Stream getAllFSTEntryChildrenAsStream(FSTEntry cur, boolean allowNotInPackage) { return cur.getChildren().stream() // .filter(e -> allowNotInPackage || !e.isNotInPackage()) // .flatMap(e -> { if (!e.isDir()) { return Stream.of(e); } return getAllFSTEntryChildrenAsStream(e, allowNotInPackage); }); } public Optional getFSTEntryByFullPath(String givenFullPath) { String fullPath = givenFullPath.replace("/", File.separator); if (!fullPath.startsWith(File.separator)) { fullPath = File.separator + fullPath; } String[] dirs = fullPath.split(Pattern.quote(File.separator)); if (dirs.length <= 1) { return Optional.of(FST.getRoot()); } String dirPath = fullPath.substring(0, fullPath.length() - dirs[dirs.length - 1].length() - 1); String path = fullPath; return getFileEntryDir(dirPath).flatMap(e -> getAllFSTEntryChildrenAsStream(e).filter(en -> path.equals(en.getFullPath())).findAny()); } public List getFSTEntriesByRegEx(String regEx) { return getFSTEntriesByRegEx(regEx, FST.getRoot()); } public List getFSTEntriesByRegEx(String regEx, FSTEntry entry) { return getFSTEntriesByRegEx(regEx, entry, true); } public List getFSTEntriesByRegEx(String regEx, boolean onlyInPackage) { return getFSTEntriesByRegEx(regEx, FST.getRoot(), onlyInPackage); } public List getFSTEntriesByRegEx(String regEx, FSTEntry entry, boolean allowNotInPackage) { Pattern p = Pattern.compile(regEx); return getFSTEntriesByRegExStream(p, entry, allowNotInPackage).collect(Collectors.toList()); } private Stream getFSTEntriesByRegExStream(Pattern p, FSTEntry entry, boolean allowNotInPackage) { return entry.getChildren().stream()// .filter(e -> allowNotInPackage || !e.isNotInPackage()) // .flatMap(e -> { if (!e.isDir()) { if (p.matcher(e.getFullPath().replace("/", File.separator)).matches()) { return Stream.of(e); } else { return Stream.empty(); } } return getFSTEntriesByRegExStream(p, e, allowNotInPackage); }); } public Optional getFileEntryDir(String string) { return getFileEntryDir(string.replace("/", File.separator), FST.getRoot()); } public Optional getFileEntryDir(String string, FSTEntry curEntry) { for (val curChild : curEntry.getDirChildren()) { if (string.startsWith(curChild.getFullPath())) { if (string.equals(curChild.getFullPath())) { return Optional.of(curChild); } return getFileEntryDir(string, curChild); } } return Optional.empty(); } public void printFiles() { getFST().getRoot().printRecursive(0); } public void printContentFSTInfos() { for (Entry e : getFST().getContentFSTInfos().entrySet()) { System.out.println(String.format("%08X", e.getKey()) + ": " + e.getValue()); } } public void printContentInfos() { for (Entry e : getTMD().getAllContents().entrySet()) { System.out.println(String.format("%08X", e.getKey()) + ": " + e.getValue()); System.out.println(e.getValue().getContentFSTInfo()); for (FSTEntry entry : e.getValue().getEntries()) { System.out.println(entry.getFullPath() + String.format(" size: %016X", entry.getFileSize()) + String.format(" offset: %016X", entry.getFileOffset()) + String.format(" flags: %04X", entry.getFlags())); } System.out.println("-"); } } public void cleanup() throws IOException { if (getDataProvider() != null) { getDataProvider().cleanup(); } } public void printDetailedData() { printFiles(); printContentFSTInfos(); printContentInfos(); System.out.println(); } @Override public String toString() { return "NUSTitle [dataProvider=" + dataProvider + "]"; } }