package de.mas.jnustool; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.Arrays; import java.util.List; import de.mas.jnustool.util.Decryption; import de.mas.jnustool.util.Downloader; import de.mas.jnustool.util.HashUtil; import de.mas.jnustool.util.Settings; import de.mas.jnustool.util.Util; public class FEntry implements IHasName{ private FST fst; public static int DIR_FLAG = 1; public static int NOT_IN_NUSTITLE_FLAG = 0x80; public static int EXTRACT_WITH_HASH_FLAG = 0x440; public static int CHANGE_OFFSET_FLAG = 0x04; private boolean dir = false; private boolean in_nus_title = false; private boolean extract_withHash = false; private String fileName = ""; private String path = ""; private long fileOffset = 0L; private long fileLength = 0; private byte[] hash; private int contentID = 0; private int NUScontentID = 0; private List pathList; private Content content = null; private short flags = 0; public short getFlags() { return flags; } public void setFlags(short flags) { this.flags = flags; } public FEntry(String path, String filename, int contentID,int NUScontentID, long fileOffset, long fileLength, boolean dir, boolean in_nus_title, boolean extract_withHash, List pathList,FST fst,byte[] hash,Content content,short flags) { setPath(path); setFileName(filename); setContentID(contentID); setFileOffset(fileOffset); setFileLength(fileLength); setDir(dir); setInNusTitle(in_nus_title); setExtractWithHash(extract_withHash); setNUScontentID(NUScontentID); setPathList(pathList); setHash(hash); setFlags(flags); setContent(content); this.fst = fst; } public boolean isDir() { return dir; } private void setDir(boolean dir) { this.dir = dir; } public boolean isInNUSTitle() { return in_nus_title; } private void setInNusTitle(boolean in_nus_title) { this.in_nus_title = in_nus_title; } public boolean isExtractWithHash() { return extract_withHash; } private void setExtractWithHash(boolean extract_withHash) { this.extract_withHash = extract_withHash; } public String getFileName() { return fileName; } private void setFileName(String filename) { this.fileName = filename; } public String getPath() { return path; } public String getFullPath() { return path + fileName; } private void setPath(String path) { this.path = path; } public long getFileOffset() { return fileOffset; } private void setFileOffset(long fileOffset) { this.fileOffset = fileOffset; } public int getContentID() { return contentID; } private void setContentID(int contentID) { this.contentID = contentID; } public long getFileLength() { return fileLength; } private void setFileLength(long fileLength) { this.fileLength = fileLength; } @Override public String toString() { return getFullPath() + " Content ID:" + contentID + " Size: " + fileLength/1024.0/1024.0 +"MB Offset: " + fileOffset; } public int getNUScontentID() { return NUScontentID; } private void setNUScontentID(int nUScontentID) { NUScontentID = nUScontentID; } public String getDownloadPath(){ String [] path = getFullPath().split("/"); String folder = getTargetPath() +"/"; for(int i = 0;i getPathList() { return pathList; } public void setPathList(List pathList) { this.pathList = pathList; } public String getContentPath() { return fst.getTmd().getContentPath() + "/" + String.format("%08X", getNUScontentID()) + ".app"; } public String getH3Path() { return fst.getTmd().getContentPath() + "/" + String.format("%08X", getNUScontentID()) + ".h3"; } public long getTitleID() { return fst.getTmd().titleID; } public TIK getTicket() { return fst.getTmd().getNUSTitle().getTicket(); } public String getTargetPath(){ return fst.getTmd().getNUSTitle().getTargetPath(); } public byte[] downloadAsByteArray() throws IOException { return Downloader.getInstance().downloadAndDecrypt(this,null,true); } @Override public String getName() { return getFileName(); } public byte[] getHash() { return Arrays.copyOfRange(hash,0,20); } public void setHash(byte[] hash) { this.hash = hash; } public Content getContent() { return content; } public void setContent(Content content) { this.content = content; } public FST getFst() { return fst; } public byte[] getAsByteArray() throws IOException { boolean localCopyValid = localValidEncryptedFileFound(); if(localCopyValid){ Logger.log("Decrypting meta.xml"); Decryption decrypt = new Decryption(fst.getTmd().getNUSTitle().getTicket()); return decrypt.decryptAsByte(this,getDownloadPath()); }else{ Logger.log("Downloading meta.xml"); return downloadAsByteArray(); } } public byte[] getH3() throws IOException { byte[] h3 = new byte[0x14]; File h3_file = new File(getH3Path()); if(h3_file.exists()){ h3 = Files.readAllBytes(h3_file.toPath()); }else{ h3 = Downloader.getInstance().downloadContentH3AsByte(getFst().getTmd().getNUSTitle().getTitleID(), getNUScontentID()); } if(!Arrays.equals(HashUtil.hashSHA1(h3),getHash())){ System.out.println(".h3 file checksum failed"); System.out.println("real hash :" + Util.ByteArrayToString(HashUtil.hashSHA1(h3))); System.out.println("expected hash:" + Util.ByteArrayToString(getHash())); System.exit(-2); } return h3; } }