From 012b1df5d89e017385c5f5ddbae7d15b03d6573a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=97=B1=20PixelyIon?= Date: Thu, 4 Jul 2019 01:25:06 +0530 Subject: [PATCH] NRO Validation The NRO files are now validated before they're added to the game list. --- .../gq/cyuubi/lightswitch/FileAdapter.java | 2 +- .../gq/cyuubi/lightswitch/MainActivity.java | 4 ++- .../java/gq/cyuubi/lightswitch/NroMeta.java | 33 +++++++++++++++++-- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/gq/cyuubi/lightswitch/FileAdapter.java b/app/src/main/java/gq/cyuubi/lightswitch/FileAdapter.java index ffc88990..cdda9333 100644 --- a/app/src/main/java/gq/cyuubi/lightswitch/FileAdapter.java +++ b/app/src/main/java/gq/cyuubi/lightswitch/FileAdapter.java @@ -28,7 +28,7 @@ class GameItem { public GameItem(File file) { this.file = file; index = file.getName().lastIndexOf("."); - meta = NroMeta.GetNroTitle(getPath()); + meta = NroMeta.getTitleEntry(getPath()); } public Bitmap getIcon() { diff --git a/app/src/main/java/gq/cyuubi/lightswitch/MainActivity.java b/app/src/main/java/gq/cyuubi/lightswitch/MainActivity.java index 617f137e..92497057 100644 --- a/app/src/main/java/gq/cyuubi/lightswitch/MainActivity.java +++ b/app/src/main/java/gq/cyuubi/lightswitch/MainActivity.java @@ -51,7 +51,9 @@ public class MainActivity extends AppCompatActivity { try { String file_str = file_i.getName(); if (ext.equalsIgnoreCase(file_str.substring(file_str.lastIndexOf(".") + 1))) { - files.add(file_i); + if(NroMeta.verifyFile(file_i.getAbsolutePath())) { + files.add(file_i); + } } } catch (StringIndexOutOfBoundsException e) { } diff --git a/app/src/main/java/gq/cyuubi/lightswitch/NroMeta.java b/app/src/main/java/gq/cyuubi/lightswitch/NroMeta.java index b21aecfc..356246cb 100644 --- a/app/src/main/java/gq/cyuubi/lightswitch/NroMeta.java +++ b/app/src/main/java/gq/cyuubi/lightswitch/NroMeta.java @@ -32,7 +32,7 @@ final class TitleEntry { } public class NroMeta { - public static TitleEntry GetNroTitle(String file) { + public static TitleEntry getTitleEntry(String file) { try { RandomAccessFile f = new RandomAccessFile(file, "r"); f.seek(0x18); // Skip to NroHeader.size @@ -41,7 +41,7 @@ public class NroMeta { byte[] buffer = new byte[4]; f.read(buffer); if (!(new String(buffer).equals("ASET"))) - return null; + throw new IOException(); f.skipBytes(0x4); long iconOffset = Long.reverseBytes(f.readLong()); @@ -57,7 +57,7 @@ public class NroMeta { long nacpOffset = Long.reverseBytes(f.readLong()); long nacpSize = Long.reverseBytes(f.readLong()); if (nacpOffset == 0 || nacpSize == 0) - return null; + throw new IOException(); f.seek(asetOffset + nacpOffset); byte[] name = new byte[0x200]; f.read(name); @@ -70,4 +70,31 @@ public class NroMeta { return null; } } + public static boolean verifyFile(String file) { + try { + RandomAccessFile f = new RandomAccessFile(file, "r"); + f.seek(0x18); // Skip to NroHeader.size + int asetOffset = Integer.reverseBytes(f.readInt()); + f.seek(asetOffset); // Skip to the offset specified by NroHeader.size + byte[] buffer = new byte[4]; + f.read(buffer); + if (!(new String(buffer).equals("ASET"))) + return false; + + f.skipBytes(0x4); + long iconOffset = Long.reverseBytes(f.readLong()); + int iconSize = Integer.reverseBytes(f.readInt()); + if (iconOffset == 0 || iconSize == 0) + return false; + + f.seek(asetOffset + 0x18); + long nacpOffset = Long.reverseBytes(f.readLong()); + long nacpSize = Long.reverseBytes(f.readLong()); + if (nacpOffset == 0 || nacpSize == 0) + return false; + } catch (IOException e) { + return false; + } + return true; + } }