diff --git a/README.md b/README.md index 5cf5119..77d8eca 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Sometimes I add new posts about this project [on my home page](https://developer * [usb4java](https://mvnrepository.com/artifact/org.usb4java/usb4java) * Few icons taken from: [materialdesignicons.com](http://materialdesignicons.com/) * Information, ideas and data from ['fusee-launcher'](https://github.com/reswitched/fusee-launcher) application +* [Apache Commons CLI](https://commons.apache.org/proper/commons-cli/) #### List of awesome contributors! @@ -203,4 +204,4 @@ Want to support development? Make a donation* (see below): Thanks -Appreciate assistance and support of both [Vitaliy](https://github.com/SebastianUA) and [Konstantin](https://github.com/konstantin-kelemen). Without you all this magic would not have happened. \ No newline at end of file +Appreciate assistance and support of both [Vitaliy](https://github.com/SebastianUA) and [Konstantin](https://github.com/konstantin-kelemen). Without you all this magic would not have happened. diff --git a/pom.xml b/pom.xml index f3d39b8..f7a8f1c 100644 --- a/pom.xml +++ b/pom.xml @@ -50,6 +50,13 @@ + + + commons-cli + commons-cli + 1.4 + compile + org.openjfx javafx-controls diff --git a/src/main/java/nsusbloader/COM/ICommunications.java b/src/main/java/nsusbloader/COM/ICommunications.java new file mode 100644 index 0000000..e0c6cb2 --- /dev/null +++ b/src/main/java/nsusbloader/COM/ICommunications.java @@ -0,0 +1,24 @@ +/* + Copyright 2019-2020 Dmitry Isaenko + + This file is part of NS-USBloader. + + NS-USBloader 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. + + NS-USBloader 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 NS-USBloader. If not, see . +*/ +package nsusbloader.COM; + +public interface ICommunications extends Runnable { + void cancel(); + boolean isCancelled(); +} diff --git a/src/main/java/nsusbloader/COM/NET/NETCommunications.java b/src/main/java/nsusbloader/COM/NET/NETCommunications.java index ccd21f5..e13a610 100644 --- a/src/main/java/nsusbloader/COM/NET/NETCommunications.java +++ b/src/main/java/nsusbloader/COM/NET/NETCommunications.java @@ -18,7 +18,7 @@ */ package nsusbloader.COM.NET; -import javafx.concurrent.Task; +import nsusbloader.COM.ICommunications; import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.NSLDataTypes.EFileStatus; import nsusbloader.ModelControllers.Log; @@ -32,7 +32,7 @@ import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.*; -public class NETCommunications extends Task { // todo: thows IOException? +public class NETCommunications implements ICommunications { // todo: rewrite private ILogPrinter logPrinter; @@ -52,10 +52,17 @@ public class NETCommunications extends Task { // todo: thows IOException? private OutputStream currSockOS; private PrintWriter currSockPW; + + private volatile boolean cancel; /** * Simple constructor that everybody uses * */ - public NETCommunications(List filesList, String switchIP, boolean doNotServeRequests, String hostIPaddr, String hostPortNum, String extras){ + public NETCommunications(List filesList, + String switchIP, + boolean doNotServeRequests, + String hostIPaddr, + String hostPortNum, + String extras) { this.doNotServeRequests = doNotServeRequests; if (doNotServeRequests) this.extras = extras; @@ -263,19 +270,21 @@ public class NETCommunications extends Task { // todo: thows IOException? logPrinter.print("Can't determine possible variants. Returned:\n\t"+socketException.getMessage(), EMsgType.FAIL); } } - /** - * Override cancel block to close connection by ourselves - * */ @Override - protected void cancelled() { - this.close(EFileStatus.UNKNOWN); - super.cancelled(); + public boolean isCancelled(){ + return cancel; } @Override - protected Void call() { + public void cancel() { + cancel = true; + } + + @Override + public void run() { + if (!isValid | isCancelled()) - return null; + return; logPrinter.print("\tStart chain", EMsgType.INFO); // Create string that we'll send to TF and which initiates chain StringBuilder myStrBuilder; @@ -307,13 +316,13 @@ public class NETCommunications extends Task { // todo: thows IOException? catch (IOException uhe){ logPrinter.print("NET: Unable to connect to NS and send files list. Returned:\n\t"+uhe.getMessage(), EMsgType.FAIL); close(EFileStatus.UNKNOWN); - return null; + return; } // Check if we should serve requests if (this.doNotServeRequests){ logPrinter.print("NET: List of files transferred. Replies won't be served.", EMsgType.PASS); close(EFileStatus.UNKNOWN); - return null; + return; } logPrinter.print("NET: Initiation files list has been sent to NS.", EMsgType.PASS); @@ -353,7 +362,7 @@ public class NETCommunications extends Task { // todo: thows IOException? } if ( ! isCancelled() ) close(EFileStatus.UNKNOWN); - return null; + return; } // 200 206 400 (inv range) 404 416 (Range Not Satisfiable ) diff --git a/src/main/java/nsusbloader/COM/USB/GoldLeaf.java b/src/main/java/nsusbloader/COM/USB/GoldLeaf.java index 66dba20..3c720c0 100644 --- a/src/main/java/nsusbloader/COM/USB/GoldLeaf.java +++ b/src/main/java/nsusbloader/COM/USB/GoldLeaf.java @@ -21,6 +21,7 @@ package nsusbloader.COM.USB; import javafx.application.Platform; import javafx.concurrent.Task; import javafx.stage.FileChooser; +import nsusbloader.COM.ICommunications; import nsusbloader.MediatorControl; import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.NSLDataTypes.EMsgType; @@ -69,7 +70,7 @@ class GoldLeaf extends TransferModule { // For using in CMD_SelectFile with SPEC:/ prefix private File selectedFile; - GoldLeaf(DeviceHandle handler, LinkedHashMap nspMap, Task task, ILogPrinter logPrinter, boolean nspFilter){ + GoldLeaf(DeviceHandle handler, LinkedHashMap nspMap, ICommunications task, ILogPrinter logPrinter, boolean nspFilter){ super(handler, nspMap, task, logPrinter); final byte CMD_GetDriveCount = 1; diff --git a/src/main/java/nsusbloader/COM/USB/GoldLeaf_05.java b/src/main/java/nsusbloader/COM/USB/GoldLeaf_05.java index 5e3a463..1c8e29e 100644 --- a/src/main/java/nsusbloader/COM/USB/GoldLeaf_05.java +++ b/src/main/java/nsusbloader/COM/USB/GoldLeaf_05.java @@ -19,6 +19,7 @@ package nsusbloader.COM.USB; import javafx.concurrent.Task; +import nsusbloader.COM.ICommunications; import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.NSLDataTypes.EFileStatus; import nsusbloader.NSLDataTypes.EMsgType; @@ -53,7 +54,7 @@ public class GoldLeaf_05 extends TransferModule { private RandomAccessFile raf; // NSP File private NSSplitReader nsr; // It'a also NSP File - GoldLeaf_05(DeviceHandle handler, LinkedHashMap nspMap, Task task, ILogPrinter logPrinter){ + GoldLeaf_05(DeviceHandle handler, LinkedHashMap nspMap, ICommunications task, ILogPrinter logPrinter){ super(handler, nspMap, task, logPrinter); status = EFileStatus.FAILED; diff --git a/src/main/java/nsusbloader/COM/USB/GoldLeaf_07.java b/src/main/java/nsusbloader/COM/USB/GoldLeaf_07.java index 8f59a79..e52ad9c 100644 --- a/src/main/java/nsusbloader/COM/USB/GoldLeaf_07.java +++ b/src/main/java/nsusbloader/COM/USB/GoldLeaf_07.java @@ -22,6 +22,7 @@ import javafx.application.Platform; import javafx.concurrent.Task; import javafx.stage.FileChooser; import nsusbloader.COM.Helpers.NSSplitReader; +import nsusbloader.COM.ICommunications; import nsusbloader.MediatorControl; import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.NSLDataTypes.EMsgType; @@ -69,7 +70,7 @@ class GoldLeaf_07 extends TransferModule { // For using in CMD_SelectFile with SPEC:/ prefix private File selectedFile; - GoldLeaf_07(DeviceHandle handler, LinkedHashMap nspMap, Task task, ILogPrinter logPrinter, boolean nspFilter){ + GoldLeaf_07(DeviceHandle handler, LinkedHashMap nspMap, ICommunications task, ILogPrinter logPrinter, boolean nspFilter){ super(handler, nspMap, task, logPrinter); final byte CMD_GetDriveCount = 0x00; diff --git a/src/main/java/nsusbloader/COM/USB/TinFoil.java b/src/main/java/nsusbloader/COM/USB/TinFoil.java index 86e9d08..ad47689 100644 --- a/src/main/java/nsusbloader/COM/USB/TinFoil.java +++ b/src/main/java/nsusbloader/COM/USB/TinFoil.java @@ -19,6 +19,7 @@ package nsusbloader.COM.USB; import javafx.concurrent.Task; +import nsusbloader.COM.ICommunications; import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.NSLDataTypes.EFileStatus; import nsusbloader.NSLDataTypes.EMsgType; @@ -48,7 +49,7 @@ class TinFoil extends TransferModule { /* byte[] magic = new byte[4]; ByteBuffer bb = StandardCharsets.UTF_8.encode("TUC0").rewind().get(magic); // Let's rephrase this 'string' */ - TinFoil(DeviceHandle handler, LinkedHashMap nspMap, Task task, ILogPrinter logPrinter){ + TinFoil(DeviceHandle handler, LinkedHashMap nspMap, ICommunications task, ILogPrinter logPrinter){ super(handler, nspMap, task, logPrinter); logPrinter.print("============= Tinfoil =============", EMsgType.INFO); diff --git a/src/main/java/nsusbloader/COM/USB/TransferModule.java b/src/main/java/nsusbloader/COM/USB/TransferModule.java index f59ed97..0dae6d1 100644 --- a/src/main/java/nsusbloader/COM/USB/TransferModule.java +++ b/src/main/java/nsusbloader/COM/USB/TransferModule.java @@ -19,6 +19,7 @@ package nsusbloader.COM.USB; import javafx.concurrent.Task; +import nsusbloader.COM.ICommunications; import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.NSLDataTypes.EFileStatus; import nsusbloader.NSLDataTypes.EMsgType; @@ -33,9 +34,9 @@ public abstract class TransferModule { LinkedHashMap nspMap; ILogPrinter logPrinter; DeviceHandle handlerNS; - Task task; + ICommunications task; - TransferModule(DeviceHandle handler, LinkedHashMap nspMap, Task task, ILogPrinter printer){ + TransferModule(DeviceHandle handler, LinkedHashMap nspMap, ICommunications task, ILogPrinter printer){ this.handlerNS = handler; this.nspMap = nspMap; this.task = task; diff --git a/src/main/java/nsusbloader/COM/USB/UsbCommunications.java b/src/main/java/nsusbloader/COM/USB/UsbCommunications.java index 345e029..1d2e95d 100644 --- a/src/main/java/nsusbloader/COM/USB/UsbCommunications.java +++ b/src/main/java/nsusbloader/COM/USB/UsbCommunications.java @@ -19,6 +19,7 @@ package nsusbloader.COM.USB; import javafx.concurrent.Task; +import nsusbloader.COM.ICommunications; import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.ModelControllers.Log; import nsusbloader.NSLDataTypes.EFileStatus; @@ -31,13 +32,15 @@ import java.io.*; import java.util.*; // TODO: add filter option to show only NSP files -public class UsbCommunications extends Task { +public class UsbCommunications implements ICommunications { private ILogPrinter logPrinter; private LinkedHashMap nspMap; private String protocol; private boolean nspFilterForGl; + private volatile boolean cancel; + public UsbCommunications(List nspList, String protocol, boolean filterNspFilesOnlyForGl){ this.protocol = protocol; this.nspFilterForGl = filterNspFilesOnlyForGl; @@ -48,14 +51,14 @@ public class UsbCommunications extends Task { } @Override - protected Void call() { + public void run() { logPrinter.print("\tStart", EMsgType.INFO); UsbConnect usbConnect = UsbConnect.connectHomebrewMode(logPrinter); if (! usbConnect.isConnected()){ close(EFileStatus.FAILED); - return null; + return; } DeviceHandle handler = usbConnect.getNsHandler(); @@ -81,7 +84,7 @@ public class UsbCommunications extends Task { close(module.getStatus()); - return null; + return; } /** @@ -93,4 +96,13 @@ public class UsbCommunications extends Task { logPrinter.close(); } + @Override + public boolean isCancelled() { + return cancel; + } + + @Override + public void cancel() { + cancel = true; + } } \ No newline at end of file diff --git a/src/main/java/nsusbloader/Controllers/FrontController.java b/src/main/java/nsusbloader/Controllers/FrontController.java index 5016ff5..82f10ac 100644 --- a/src/main/java/nsusbloader/Controllers/FrontController.java +++ b/src/main/java/nsusbloader/Controllers/FrontController.java @@ -31,6 +31,7 @@ import javafx.scene.layout.Region; import javafx.stage.DirectoryChooser; import javafx.stage.FileChooser; import nsusbloader.AppPreferences; +import nsusbloader.COM.ICommunications; import nsusbloader.COM.NET.NETCommunications; import nsusbloader.COM.USB.UsbCommunications; import nsusbloader.MediatorControl; @@ -63,19 +64,20 @@ public class FrontController implements Initializable { private String previouslyOpenedPath; private Region btnUpStopImage; private ResourceBundle resourceBundle; - private Task usbNetCommunications; + private ICommunications usbNetCommunications; private Thread workThread; - + @Override public void initialize(URL url, ResourceBundle resourceBundle) { this.resourceBundle = resourceBundle; ObservableList choiceProtocolList = FXCollections.observableArrayList("TinFoil", "GoldLeaf"); + choiceProtocol.setItems(choiceProtocolList); choiceProtocol.getSelectionModel().select(AppPreferences.getInstance().getProtocol()); choiceProtocol.setOnAction(e-> { - tableFilesListController.setNewProtocol(choiceProtocol.getSelectionModel().getSelectedItem()); - if (choiceProtocol.getSelectionModel().getSelectedItem().equals("GoldLeaf")) { + tableFilesListController.setNewProtocol(getSelectedProtocol()); + if (getSelectedProtocol().equals("GoldLeaf")) { choiceNetUsb.setDisable(true); choiceNetUsb.getSelectionModel().select("USB"); nsIpLbl.setVisible(false); @@ -83,7 +85,7 @@ public class FrontController implements Initializable { } else { choiceNetUsb.setDisable(false); - if (choiceNetUsb.getSelectionModel().getSelectedItem().equals("NET")) { + if (getSelectedNetUsb().equals("NET")) { nsIpLbl.setVisible(true); nsIpTextField.setVisible(true); } @@ -91,17 +93,17 @@ public class FrontController implements Initializable { // Really bad disable-enable upload button function disableUploadStopBtn(tableFilesListController.isFilesForUploadListEmpty()); }); // Add listener to notify tableView controller - tableFilesListController.setNewProtocol(choiceProtocol.getSelectionModel().getSelectedItem()); // Notify tableView controller + tableFilesListController.setNewProtocol(getSelectedProtocol()); // Notify tableView controller ObservableList choiceNetUsbList = FXCollections.observableArrayList("USB", "NET"); choiceNetUsb.setItems(choiceNetUsbList); choiceNetUsb.getSelectionModel().select(AppPreferences.getInstance().getNetUsb()); - if (choiceProtocol.getSelectionModel().getSelectedItem().equals("GoldLeaf")) { + if (getSelectedProtocol().equals("GoldLeaf")) { choiceNetUsb.setDisable(true); choiceNetUsb.getSelectionModel().select("USB"); } choiceNetUsb.setOnAction(e->{ - if (choiceNetUsb.getSelectionModel().getSelectedItem().equals("NET")){ + if (getSelectedNetUsb().equals("NET")){ nsIpLbl.setVisible(true); nsIpTextField.setVisible(true); } @@ -112,7 +114,7 @@ public class FrontController implements Initializable { }); // Set and configure NS IP field behavior nsIpTextField.setText(AppPreferences.getInstance().getNsIp()); - if (choiceProtocol.getSelectionModel().getSelectedItem().equals("TinFoil") && choiceNetUsb.getSelectionModel().getSelectedItem().equals("NET")){ + if (getSelectedProtocol().equals("TinFoil") && getSelectedNetUsb().equals("NET")){ nsIpLbl.setVisible(true); nsIpTextField.setVisible(true); } @@ -299,7 +301,7 @@ public class FrontController implements Initializable { * */ private void stopBtnAction(){ if (workThread != null && workThread.isAlive()){ - usbNetCommunications.cancel(false); + usbNetCommunications.cancel(); } } /** diff --git a/src/main/java/nsusbloader/Controllers/NxdtController.java b/src/main/java/nsusbloader/Controllers/NxdtController.java index 74ba291..a5367df 100644 --- a/src/main/java/nsusbloader/Controllers/NxdtController.java +++ b/src/main/java/nsusbloader/Controllers/NxdtController.java @@ -28,7 +28,7 @@ import javafx.stage.DirectoryChooser; import nsusbloader.AppPreferences; import nsusbloader.MediatorControl; import nsusbloader.NSLDataTypes.EModule; -import nsusbloader.Utilities.NxdtTask; +import nsusbloader.Utilities.nxdumptool.NxdtTask; import java.io.File; import java.net.URL; diff --git a/src/main/java/nsusbloader/ModelControllers/LogPrinterCli.java b/src/main/java/nsusbloader/ModelControllers/LogPrinterCli.java index affa66e..ab1e3cd 100644 --- a/src/main/java/nsusbloader/ModelControllers/LogPrinterCli.java +++ b/src/main/java/nsusbloader/ModelControllers/LogPrinterCli.java @@ -34,9 +34,7 @@ public class LogPrinterCli implements ILogPrinter{ @Override public void update(File file, EFileStatus status) { } @Override - public void updateOneLinerStatus(boolean status){ } + public void updateOneLinerStatus(boolean status){ } @Override - public void close() { - System.out.println("\n-\n"); - } + public void close() { } } diff --git a/src/main/java/nsusbloader/ModelControllers/LogPrinterGui.java b/src/main/java/nsusbloader/ModelControllers/LogPrinterGui.java index 4bcb11c..111ea34 100644 --- a/src/main/java/nsusbloader/ModelControllers/LogPrinterGui.java +++ b/src/main/java/nsusbloader/ModelControllers/LogPrinterGui.java @@ -33,7 +33,7 @@ public class LogPrinterGui implements ILogPrinter { private final BlockingQueue msgQueue; private final BlockingQueue progressQueue; private final HashMap statusMap; // BlockingQueue for literally one object. TODO: read more books ; replace to hashMap - private AtomicBoolean oneLinerStatus; + private final AtomicBoolean oneLinerStatus; public LogPrinterGui(EModule whoIsAsking){ this.msgQueue = new LinkedBlockingQueue<>(); diff --git a/src/main/java/nsusbloader/NSLMain.java b/src/main/java/nsusbloader/NSLMain.java index b72475e..cd24e2c 100644 --- a/src/main/java/nsusbloader/NSLMain.java +++ b/src/main/java/nsusbloader/NSLMain.java @@ -25,12 +25,10 @@ import javafx.scene.Scene; import javafx.scene.image.Image; import javafx.stage.Stage; import nsusbloader.Controllers.NSLMainController; -import nsusbloader.Utilities.Rcm; +import nsusbloader.cli.CommandLineInterface; -import java.io.File; import java.util.Locale; import java.util.ResourceBundle; -import java.util.prefs.Preferences; public class NSLMain extends Application { @@ -83,70 +81,12 @@ public class NSLMain extends Application { } public static void main(String[] args) { - if (handleCli(args)) - return; - launch(args); - } - - private static boolean handleCli(String[] args){ - if (args.length == 0) - return false; - - NSLMain.isCli = true; - - try { - switch (args[0]) { - case "-v": - case "--version": - System.out.println("NS-USBloader " + NSLMain.appVersion); - return true; - case "-c": - case "--clean": - if (Preferences.userRoot().nodeExists("NS-USBloader")) { - Preferences.userRoot().node("NS-USBloader").removeNode(); - System.out.println("Settings removed"); - } - else - System.out.println("Nothing to remove"); - return true; - case "--rcm": // TODO: rewrite - if (args.length < 2){ - System.out.println("No payload file specified. Expected:\n" - + "... file.jar --rcm payload.bin\n" + "or\n" - + "... file.jar --rcm /home/user/payload.bin\n"); - return true; - } - - boolean isWindows = false; - if (System.getProperty("os.name").toLowerCase().replace(" ", "").contains("windows")) - isWindows = true; - - if (isWindows) { - if (! args[1].matches("^.:\\\\.*$")) - args[1] = System.getProperty("user.dir") + File.separator + args[1]; - } - else { - if (! args[1].startsWith("/")) - args[1] = System.getProperty("user.dir") + File.separator + args[1]; - } - - Rcm rcm = new Rcm(args[1]); - Thread rcmThread = new Thread(rcm); - rcmThread.start(); - return true; - case "--help": - default: - System.out.println("CLI Usage:\n" - + "\t --rcm payload.bin\tSend payload\n" - + "\t-c, --clean\tRemove/reset settings and exit\n" - + "\t-v, --version \tShow application version\n" - + "\t-h, --help\t\tShow this message"); - return true; - } + if (args.length == 0) { + launch(args); } - catch (Exception e){ - e.printStackTrace(); - return true; + else { + NSLMain.isCli = true; + new CommandLineInterface(args); } } } diff --git a/src/main/java/nsusbloader/Utilities/NxdtTask.java b/src/main/java/nsusbloader/Utilities/nxdumptool/NxdtTask.java similarity index 97% rename from src/main/java/nsusbloader/Utilities/NxdtTask.java rename to src/main/java/nsusbloader/Utilities/nxdumptool/NxdtTask.java index bb90540..4e4dc40 100644 --- a/src/main/java/nsusbloader/Utilities/NxdtTask.java +++ b/src/main/java/nsusbloader/Utilities/nxdumptool/NxdtTask.java @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with NS-USBloader. If not, see . */ -package nsusbloader.Utilities; +package nsusbloader.Utilities.nxdumptool; import javafx.concurrent.Task; import nsusbloader.COM.USB.UsbConnect; diff --git a/src/main/java/nsusbloader/Utilities/NxdtUsbAbi1.java b/src/main/java/nsusbloader/Utilities/nxdumptool/NxdtUsbAbi1.java similarity index 99% rename from src/main/java/nsusbloader/Utilities/NxdtUsbAbi1.java rename to src/main/java/nsusbloader/Utilities/nxdumptool/NxdtUsbAbi1.java index f67e6a6..1a8d87d 100644 --- a/src/main/java/nsusbloader/Utilities/NxdtUsbAbi1.java +++ b/src/main/java/nsusbloader/Utilities/nxdumptool/NxdtUsbAbi1.java @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with NS-USBloader. If not, see . */ -package nsusbloader.Utilities; +package nsusbloader.Utilities.nxdumptool; import javafx.concurrent.Task; import nsusbloader.COM.USB.UsbErrorCodes; diff --git a/src/main/java/nsusbloader/cli/CommandLineInterface.java b/src/main/java/nsusbloader/cli/CommandLineInterface.java new file mode 100644 index 0000000..4ac568e --- /dev/null +++ b/src/main/java/nsusbloader/cli/CommandLineInterface.java @@ -0,0 +1,167 @@ +/* + Copyright 2019-2020 Dmitry Isaenko + + This file is part of NS-USBloader. + + NS-USBloader 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. + + NS-USBloader 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 NS-USBloader. If not, see . +*/ +package nsusbloader.cli; + +import nsusbloader.NSLMain; +import nsusbloader.Utilities.Rcm; +import org.apache.commons.cli.*; + +import java.io.File; + +import java.util.prefs.Preferences; + +public class CommandLineInterface { + + public CommandLineInterface(String[] args) { + if (noRealKeys(args)){ + System.out.println("Try 'ns-usbloader --help' for more information."); + return; + } + + final Options cliOptions = createCliOptions(); + + CommandLineParser cliParser = new DefaultParser(); + try{ + CommandLine cli = cliParser.parse(cliOptions, args); + if (cli.hasOption('v') || cli.hasOption("version")){ + handleVersion(); + return; + } + if (cli.hasOption('h') || cli.hasOption("help")){ + handleHelp(cliOptions); + return; + } + if (cli.hasOption('r') || cli.hasOption("rcm")){ + final String payloadArgument = cli.getOptionValue("rcm"); + handleRcm(payloadArgument); + return; + } + if (cli.hasOption("c") || cli.hasOption("clean")){ + handleSettingClean(); + return; + } + if (cli.hasOption("n") || cli.hasOption("tfn")){ + final String[] tfnArguments = cli.getOptionValues("tfn"); + new TinfoilNet(tfnArguments); + return; + } + } + catch (ParseException pe){ + System.out.println(pe.getLocalizedMessage() + + "\nTry 'ns-usbloader --help' for more information."); + } + catch (InterruptedException ignore){} + catch (Exception e){ + System.out.println("CLI error"); + e.printStackTrace(); + } + } + + private boolean noRealKeys(String[] args){ + return (args.length > 0 && ! args[0].startsWith("-")); + } + + private Options createCliOptions(){ + final Options options = new Options(); + + final Option rcmOption = Option.builder("r") + .longOpt("rcm") + .desc("Send payload") + .hasArg(true) + .argName("[PATH/]payload.bin") + .numberOfArgs(1) + .build(); + + final Option cleanSettingsOption = Option.builder("c") + .longOpt("clean") + .desc("Remove/reset settings and exit") + .hasArg(false) + .build(); + + final Option versionOption = Option.builder("v") + .longOpt("version") + .desc("Show application version") + .hasArg(false) + .build(); + + final Option helpOption = Option.builder("h") + .longOpt("help") + .desc("Show this help") + .hasArg(false) + .build(); + + /* Tinfoil network mode options */ + final Option tinfoilNetOption = Option.builder("n") + .longOpt("tfn") + .desc("Install via Tinfoil/Awoo Network mode. Check '-n help' for information.") + .hasArgs() + .argName("...") + .build(); + + + final OptionGroup group = new OptionGroup(); + group.addOption(rcmOption); + group.addOption(tinfoilNetOption); + group.addOption(cleanSettingsOption); + group.addOption(versionOption); + group.addOption(helpOption); + + options.addOptionGroup(group); + + return options; + } + + private void handleVersion(){ + System.out.println("NS-USBloader " + NSLMain.appVersion); + } + private void handleSettingClean() throws Exception { + if (Preferences.userRoot().nodeExists("NS-USBloader")) { + Preferences.userRoot().node("NS-USBloader").removeNode(); + System.out.println("Settings removed"); + } + else + System.out.println("There are no settings in system to remove"); + } + private void handleRcm(String payload) throws InterruptedException{ + boolean isWindows = System.getProperty("os.name").toLowerCase().replace(" ", "").contains("windows"); + + if (isWindows) { + if (! payload.matches("^.:\\\\.*$")) + payload = System.getProperty("user.dir") + File.separator + payload; + } + else { + if (! payload.startsWith("/")) + payload = System.getProperty("user.dir") + File.separator + payload; + } + + Rcm rcm = new Rcm(payload); + Thread rcmThread = new Thread(rcm); + rcmThread.start(); + rcmThread.join(); + } + private void handleHelp(Options cliOptions){ + new HelpFormatter().printHelp( + 120, + "NS-USBloader.jar [OPTION]... [FILE]...", + "options:", + cliOptions, + "\n"); + } + +} diff --git a/src/main/java/nsusbloader/cli/TinfoilNet.java b/src/main/java/nsusbloader/cli/TinfoilNet.java new file mode 100644 index 0000000..2a4c025 --- /dev/null +++ b/src/main/java/nsusbloader/cli/TinfoilNet.java @@ -0,0 +1,130 @@ +/* + Copyright 2019-2020 Dmitry Isaenko + + This file is part of NS-USBloader. + + NS-USBloader 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. + + NS-USBloader 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 NS-USBloader. If not, see . +*/ +package nsusbloader.cli; + +import nsusbloader.COM.NET.NETCommunications; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +// TODO: Add 'don't serve requests' option +// TODO: Refactor: remove duplicates; make logic flow more 'exception-driven' +public class TinfoilNet { + + private String nsIp; + + private String hostIp = ""; + private String hostPortNum = ""; + private String hostExtras = ""; + + private int parseFileSince = 1; + + TinfoilNet(String[] arguments) throws InterruptedException{ + + if (arguments == null) { + showIncorrectCommandMessage(); + return; + } + + if (arguments.length == 1){ + if (isHelp(arguments[0])) + showHelp(); + else + showIncorrectCommandMessage(); + return; + } + + if (arguments.length < 2){ + showIncorrectCommandMessage(); + return; + } + + if (parseNsIP(arguments[0])) + return; + parseHostIPAndExtras(arguments[1]); + if (checkArgumentsCount(arguments.length)) + return; + + List filesList = new ArrayList<>(); + for (; parseFileSince < arguments.length; parseFileSince++) + filesList.add(new File(arguments[parseFileSince])); + + NETCommunications netCommunications = new NETCommunications( + filesList, + nsIp, + false, + hostIp, + hostPortNum, + hostExtras); + Thread netCommThread = new Thread(netCommunications); + netCommThread.start(); + netCommThread.join(); + } + + private boolean isHelp(String argument){ + return argument.equals("help"); + } + private void showHelp(){ + System.out.println("Usage:\n" + + "\tns-usbloader -n nsip= [hostip=] FILE1 ...\n" + + "\tns-usbloader --tfn nsip= [hostip=] FILE1 ..." + + "\n\nOptions:" + + "\n\tnsip=\t\t\tDefine NS IP address (mandatory)" + + "\n\thostip=\tDefine this host IP address. Will be obtained automatically if not set."); + } + private void showIncorrectCommandMessage(){ + System.out.println("Try 'ns-usbloader -n help' for more information."); + } + + private boolean parseNsIP(String argument1){ + if (argument1.startsWith("nsip=")){ + nsIp = argument1.replaceAll("^nsip=", ""); + + if (nsIp.isEmpty()) { + showIncorrectCommandMessage(); + return true; + } + } + else{ + showIncorrectCommandMessage(); + return true; + } + return false; + } + private void parseHostIPAndExtras(String argument2){ + if (argument2.startsWith("hostip=")){ + parseFileSince = 2; + hostIp = argument2.replaceAll("(^hostip=)|(:.+?$)|(:$)", ""); + + if (argument2.contains(":")) + hostPortNum = argument2.replaceAll("(^.+:)|(/.+?$)|(/$)", ""); + + if (argument2.contains("/")) + hostExtras = argument2.replaceAll("^[^/]*/", ""); + } + } + private boolean checkArgumentsCount(int argumentsLength){ + if (argumentsLength == parseFileSince){ + showIncorrectCommandMessage(); + return true; + } + return false; + } +}