Refactoring:

* Replace UI-friendly Tasks to Runnable in all TF/GL NET/USB processes; implement similar interface for this.
* Add Apache Commons CLI to handle CLI.
* Extend/update CLI commands keys/functions, descriptions etc.
* Add draft CLI command for Tinfoil/Awoo Net-install mode.
This commit is contained in:
Dmitry Isaenko 2020-07-06 04:08:51 +03:00
parent 6b65c74c9d
commit 3c89df9dcd
19 changed files with 404 additions and 109 deletions

View file

@ -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) * [usb4java](https://mvnrepository.com/artifact/org.usb4java/usb4java)
* Few icons taken from: [materialdesignicons.com](http://materialdesignicons.com/) * Few icons taken from: [materialdesignicons.com](http://materialdesignicons.com/)
* Information, ideas and data from ['fusee-launcher'](https://github.com/reswitched/fusee-launcher) application * 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! #### List of awesome contributors!

View file

@ -50,6 +50,13 @@
</issueManagement> </issueManagement>
<!-- openJFX Linux --> <!-- openJFX Linux -->
<dependencies> <dependencies>
<!-- https://mvnrepository.com/artifact/commons-cli/commons-cli -->
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.4</version>
<scope>compile</scope>
</dependency>
<dependency> <dependency>
<groupId>org.openjfx</groupId> <groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId> <artifactId>javafx-controls</artifactId>

View file

@ -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 <https://www.gnu.org/licenses/>.
*/
package nsusbloader.COM;
public interface ICommunications extends Runnable {
void cancel();
boolean isCancelled();
}

View file

@ -18,7 +18,7 @@
*/ */
package nsusbloader.COM.NET; package nsusbloader.COM.NET;
import javafx.concurrent.Task; import nsusbloader.COM.ICommunications;
import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.ModelControllers.ILogPrinter;
import nsusbloader.NSLDataTypes.EFileStatus; import nsusbloader.NSLDataTypes.EFileStatus;
import nsusbloader.ModelControllers.Log; import nsusbloader.ModelControllers.Log;
@ -32,7 +32,7 @@ import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.*; import java.util.*;
public class NETCommunications extends Task<Void> { // todo: thows IOException? public class NETCommunications implements ICommunications { // todo: rewrite
private ILogPrinter logPrinter; private ILogPrinter logPrinter;
@ -52,10 +52,17 @@ public class NETCommunications extends Task<Void> { // todo: thows IOException?
private OutputStream currSockOS; private OutputStream currSockOS;
private PrintWriter currSockPW; private PrintWriter currSockPW;
private volatile boolean cancel;
/** /**
* Simple constructor that everybody uses * Simple constructor that everybody uses
* */ * */
public NETCommunications(List<File> filesList, String switchIP, boolean doNotServeRequests, String hostIPaddr, String hostPortNum, String extras){ public NETCommunications(List<File> filesList,
String switchIP,
boolean doNotServeRequests,
String hostIPaddr,
String hostPortNum,
String extras) {
this.doNotServeRequests = doNotServeRequests; this.doNotServeRequests = doNotServeRequests;
if (doNotServeRequests) if (doNotServeRequests)
this.extras = extras; this.extras = extras;
@ -263,19 +270,21 @@ public class NETCommunications extends Task<Void> { // todo: thows IOException?
logPrinter.print("Can't determine possible variants. Returned:\n\t"+socketException.getMessage(), EMsgType.FAIL); logPrinter.print("Can't determine possible variants. Returned:\n\t"+socketException.getMessage(), EMsgType.FAIL);
} }
} }
/**
* Override cancel block to close connection by ourselves
* */
@Override @Override
protected void cancelled() { public boolean isCancelled(){
this.close(EFileStatus.UNKNOWN); return cancel;
super.cancelled();
} }
@Override @Override
protected Void call() { public void cancel() {
cancel = true;
}
@Override
public void run() {
if (!isValid | isCancelled()) if (!isValid | isCancelled())
return null; return;
logPrinter.print("\tStart chain", EMsgType.INFO); logPrinter.print("\tStart chain", EMsgType.INFO);
// Create string that we'll send to TF and which initiates chain // Create string that we'll send to TF and which initiates chain
StringBuilder myStrBuilder; StringBuilder myStrBuilder;
@ -307,13 +316,13 @@ public class NETCommunications extends Task<Void> { // todo: thows IOException?
catch (IOException uhe){ catch (IOException uhe){
logPrinter.print("NET: Unable to connect to NS and send files list. Returned:\n\t"+uhe.getMessage(), EMsgType.FAIL); logPrinter.print("NET: Unable to connect to NS and send files list. Returned:\n\t"+uhe.getMessage(), EMsgType.FAIL);
close(EFileStatus.UNKNOWN); close(EFileStatus.UNKNOWN);
return null; return;
} }
// Check if we should serve requests // Check if we should serve requests
if (this.doNotServeRequests){ if (this.doNotServeRequests){
logPrinter.print("NET: List of files transferred. Replies won't be served.", EMsgType.PASS); logPrinter.print("NET: List of files transferred. Replies won't be served.", EMsgType.PASS);
close(EFileStatus.UNKNOWN); close(EFileStatus.UNKNOWN);
return null; return;
} }
logPrinter.print("NET: Initiation files list has been sent to NS.", EMsgType.PASS); logPrinter.print("NET: Initiation files list has been sent to NS.", EMsgType.PASS);
@ -353,7 +362,7 @@ public class NETCommunications extends Task<Void> { // todo: thows IOException?
} }
if ( ! isCancelled() ) if ( ! isCancelled() )
close(EFileStatus.UNKNOWN); close(EFileStatus.UNKNOWN);
return null; return;
} }
// 200 206 400 (inv range) 404 416 (Range Not Satisfiable ) // 200 206 400 (inv range) 404 416 (Range Not Satisfiable )

View file

@ -21,6 +21,7 @@ package nsusbloader.COM.USB;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import nsusbloader.COM.ICommunications;
import nsusbloader.MediatorControl; import nsusbloader.MediatorControl;
import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.ModelControllers.ILogPrinter;
import nsusbloader.NSLDataTypes.EMsgType; import nsusbloader.NSLDataTypes.EMsgType;
@ -69,7 +70,7 @@ class GoldLeaf extends TransferModule {
// For using in CMD_SelectFile with SPEC:/ prefix // For using in CMD_SelectFile with SPEC:/ prefix
private File selectedFile; private File selectedFile;
GoldLeaf(DeviceHandle handler, LinkedHashMap<String, File> nspMap, Task<Void> task, ILogPrinter logPrinter, boolean nspFilter){ GoldLeaf(DeviceHandle handler, LinkedHashMap<String, File> nspMap, ICommunications task, ILogPrinter logPrinter, boolean nspFilter){
super(handler, nspMap, task, logPrinter); super(handler, nspMap, task, logPrinter);
final byte CMD_GetDriveCount = 1; final byte CMD_GetDriveCount = 1;

View file

@ -19,6 +19,7 @@
package nsusbloader.COM.USB; package nsusbloader.COM.USB;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import nsusbloader.COM.ICommunications;
import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.ModelControllers.ILogPrinter;
import nsusbloader.NSLDataTypes.EFileStatus; import nsusbloader.NSLDataTypes.EFileStatus;
import nsusbloader.NSLDataTypes.EMsgType; import nsusbloader.NSLDataTypes.EMsgType;
@ -53,7 +54,7 @@ public class GoldLeaf_05 extends TransferModule {
private RandomAccessFile raf; // NSP File private RandomAccessFile raf; // NSP File
private NSSplitReader nsr; // It'a also NSP File private NSSplitReader nsr; // It'a also NSP File
GoldLeaf_05(DeviceHandle handler, LinkedHashMap<String, File> nspMap, Task<Void> task, ILogPrinter logPrinter){ GoldLeaf_05(DeviceHandle handler, LinkedHashMap<String, File> nspMap, ICommunications task, ILogPrinter logPrinter){
super(handler, nspMap, task, logPrinter); super(handler, nspMap, task, logPrinter);
status = EFileStatus.FAILED; status = EFileStatus.FAILED;

View file

@ -22,6 +22,7 @@ import javafx.application.Platform;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import nsusbloader.COM.Helpers.NSSplitReader; import nsusbloader.COM.Helpers.NSSplitReader;
import nsusbloader.COM.ICommunications;
import nsusbloader.MediatorControl; import nsusbloader.MediatorControl;
import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.ModelControllers.ILogPrinter;
import nsusbloader.NSLDataTypes.EMsgType; import nsusbloader.NSLDataTypes.EMsgType;
@ -69,7 +70,7 @@ class GoldLeaf_07 extends TransferModule {
// For using in CMD_SelectFile with SPEC:/ prefix // For using in CMD_SelectFile with SPEC:/ prefix
private File selectedFile; private File selectedFile;
GoldLeaf_07(DeviceHandle handler, LinkedHashMap<String, File> nspMap, Task<Void> task, ILogPrinter logPrinter, boolean nspFilter){ GoldLeaf_07(DeviceHandle handler, LinkedHashMap<String, File> nspMap, ICommunications task, ILogPrinter logPrinter, boolean nspFilter){
super(handler, nspMap, task, logPrinter); super(handler, nspMap, task, logPrinter);
final byte CMD_GetDriveCount = 0x00; final byte CMD_GetDriveCount = 0x00;

View file

@ -19,6 +19,7 @@
package nsusbloader.COM.USB; package nsusbloader.COM.USB;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import nsusbloader.COM.ICommunications;
import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.ModelControllers.ILogPrinter;
import nsusbloader.NSLDataTypes.EFileStatus; import nsusbloader.NSLDataTypes.EFileStatus;
import nsusbloader.NSLDataTypes.EMsgType; import nsusbloader.NSLDataTypes.EMsgType;
@ -48,7 +49,7 @@ class TinFoil extends TransferModule {
/* byte[] magic = new byte[4]; /* byte[] magic = new byte[4];
ByteBuffer bb = StandardCharsets.UTF_8.encode("TUC0").rewind().get(magic); // Let's rephrase this 'string' */ ByteBuffer bb = StandardCharsets.UTF_8.encode("TUC0").rewind().get(magic); // Let's rephrase this 'string' */
TinFoil(DeviceHandle handler, LinkedHashMap<String, File> nspMap, Task<Void> task, ILogPrinter logPrinter){ TinFoil(DeviceHandle handler, LinkedHashMap<String, File> nspMap, ICommunications task, ILogPrinter logPrinter){
super(handler, nspMap, task, logPrinter); super(handler, nspMap, task, logPrinter);
logPrinter.print("============= Tinfoil =============", EMsgType.INFO); logPrinter.print("============= Tinfoil =============", EMsgType.INFO);

View file

@ -19,6 +19,7 @@
package nsusbloader.COM.USB; package nsusbloader.COM.USB;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import nsusbloader.COM.ICommunications;
import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.ModelControllers.ILogPrinter;
import nsusbloader.NSLDataTypes.EFileStatus; import nsusbloader.NSLDataTypes.EFileStatus;
import nsusbloader.NSLDataTypes.EMsgType; import nsusbloader.NSLDataTypes.EMsgType;
@ -33,9 +34,9 @@ public abstract class TransferModule {
LinkedHashMap<String, File> nspMap; LinkedHashMap<String, File> nspMap;
ILogPrinter logPrinter; ILogPrinter logPrinter;
DeviceHandle handlerNS; DeviceHandle handlerNS;
Task<Void> task; ICommunications task;
TransferModule(DeviceHandle handler, LinkedHashMap<String, File> nspMap, Task<Void> task, ILogPrinter printer){ TransferModule(DeviceHandle handler, LinkedHashMap<String, File> nspMap, ICommunications task, ILogPrinter printer){
this.handlerNS = handler; this.handlerNS = handler;
this.nspMap = nspMap; this.nspMap = nspMap;
this.task = task; this.task = task;

View file

@ -19,6 +19,7 @@
package nsusbloader.COM.USB; package nsusbloader.COM.USB;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import nsusbloader.COM.ICommunications;
import nsusbloader.ModelControllers.ILogPrinter; import nsusbloader.ModelControllers.ILogPrinter;
import nsusbloader.ModelControllers.Log; import nsusbloader.ModelControllers.Log;
import nsusbloader.NSLDataTypes.EFileStatus; import nsusbloader.NSLDataTypes.EFileStatus;
@ -31,13 +32,15 @@ import java.io.*;
import java.util.*; import java.util.*;
// TODO: add filter option to show only NSP files // TODO: add filter option to show only NSP files
public class UsbCommunications extends Task<Void> { public class UsbCommunications implements ICommunications {
private ILogPrinter logPrinter; private ILogPrinter logPrinter;
private LinkedHashMap<String, File> nspMap; private LinkedHashMap<String, File> nspMap;
private String protocol; private String protocol;
private boolean nspFilterForGl; private boolean nspFilterForGl;
private volatile boolean cancel;
public UsbCommunications(List<File> nspList, String protocol, boolean filterNspFilesOnlyForGl){ public UsbCommunications(List<File> nspList, String protocol, boolean filterNspFilesOnlyForGl){
this.protocol = protocol; this.protocol = protocol;
this.nspFilterForGl = filterNspFilesOnlyForGl; this.nspFilterForGl = filterNspFilesOnlyForGl;
@ -48,14 +51,14 @@ public class UsbCommunications extends Task<Void> {
} }
@Override @Override
protected Void call() { public void run() {
logPrinter.print("\tStart", EMsgType.INFO); logPrinter.print("\tStart", EMsgType.INFO);
UsbConnect usbConnect = UsbConnect.connectHomebrewMode(logPrinter); UsbConnect usbConnect = UsbConnect.connectHomebrewMode(logPrinter);
if (! usbConnect.isConnected()){ if (! usbConnect.isConnected()){
close(EFileStatus.FAILED); close(EFileStatus.FAILED);
return null; return;
} }
DeviceHandle handler = usbConnect.getNsHandler(); DeviceHandle handler = usbConnect.getNsHandler();
@ -81,7 +84,7 @@ public class UsbCommunications extends Task<Void> {
close(module.getStatus()); close(module.getStatus());
return null; return;
} }
/** /**
@ -93,4 +96,13 @@ public class UsbCommunications extends Task<Void> {
logPrinter.close(); logPrinter.close();
} }
@Override
public boolean isCancelled() {
return cancel;
}
@Override
public void cancel() {
cancel = true;
}
} }

View file

@ -31,6 +31,7 @@ import javafx.scene.layout.Region;
import javafx.stage.DirectoryChooser; import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import nsusbloader.AppPreferences; import nsusbloader.AppPreferences;
import nsusbloader.COM.ICommunications;
import nsusbloader.COM.NET.NETCommunications; import nsusbloader.COM.NET.NETCommunications;
import nsusbloader.COM.USB.UsbCommunications; import nsusbloader.COM.USB.UsbCommunications;
import nsusbloader.MediatorControl; import nsusbloader.MediatorControl;
@ -63,7 +64,7 @@ public class FrontController implements Initializable {
private String previouslyOpenedPath; private String previouslyOpenedPath;
private Region btnUpStopImage; private Region btnUpStopImage;
private ResourceBundle resourceBundle; private ResourceBundle resourceBundle;
private Task<Void> usbNetCommunications; private ICommunications usbNetCommunications;
private Thread workThread; private Thread workThread;
@Override @Override
@ -71,11 +72,12 @@ public class FrontController implements Initializable {
this.resourceBundle = resourceBundle; this.resourceBundle = resourceBundle;
ObservableList<String> choiceProtocolList = FXCollections.observableArrayList("TinFoil", "GoldLeaf"); ObservableList<String> choiceProtocolList = FXCollections.observableArrayList("TinFoil", "GoldLeaf");
choiceProtocol.setItems(choiceProtocolList); choiceProtocol.setItems(choiceProtocolList);
choiceProtocol.getSelectionModel().select(AppPreferences.getInstance().getProtocol()); choiceProtocol.getSelectionModel().select(AppPreferences.getInstance().getProtocol());
choiceProtocol.setOnAction(e-> { choiceProtocol.setOnAction(e-> {
tableFilesListController.setNewProtocol(choiceProtocol.getSelectionModel().getSelectedItem()); tableFilesListController.setNewProtocol(getSelectedProtocol());
if (choiceProtocol.getSelectionModel().getSelectedItem().equals("GoldLeaf")) { if (getSelectedProtocol().equals("GoldLeaf")) {
choiceNetUsb.setDisable(true); choiceNetUsb.setDisable(true);
choiceNetUsb.getSelectionModel().select("USB"); choiceNetUsb.getSelectionModel().select("USB");
nsIpLbl.setVisible(false); nsIpLbl.setVisible(false);
@ -83,7 +85,7 @@ public class FrontController implements Initializable {
} }
else { else {
choiceNetUsb.setDisable(false); choiceNetUsb.setDisable(false);
if (choiceNetUsb.getSelectionModel().getSelectedItem().equals("NET")) { if (getSelectedNetUsb().equals("NET")) {
nsIpLbl.setVisible(true); nsIpLbl.setVisible(true);
nsIpTextField.setVisible(true); nsIpTextField.setVisible(true);
} }
@ -91,17 +93,17 @@ public class FrontController implements Initializable {
// Really bad disable-enable upload button function // Really bad disable-enable upload button function
disableUploadStopBtn(tableFilesListController.isFilesForUploadListEmpty()); disableUploadStopBtn(tableFilesListController.isFilesForUploadListEmpty());
}); // Add listener to notify tableView controller }); // Add listener to notify tableView controller
tableFilesListController.setNewProtocol(choiceProtocol.getSelectionModel().getSelectedItem()); // Notify tableView controller tableFilesListController.setNewProtocol(getSelectedProtocol()); // Notify tableView controller
ObservableList<String> choiceNetUsbList = FXCollections.observableArrayList("USB", "NET"); ObservableList<String> choiceNetUsbList = FXCollections.observableArrayList("USB", "NET");
choiceNetUsb.setItems(choiceNetUsbList); choiceNetUsb.setItems(choiceNetUsbList);
choiceNetUsb.getSelectionModel().select(AppPreferences.getInstance().getNetUsb()); choiceNetUsb.getSelectionModel().select(AppPreferences.getInstance().getNetUsb());
if (choiceProtocol.getSelectionModel().getSelectedItem().equals("GoldLeaf")) { if (getSelectedProtocol().equals("GoldLeaf")) {
choiceNetUsb.setDisable(true); choiceNetUsb.setDisable(true);
choiceNetUsb.getSelectionModel().select("USB"); choiceNetUsb.getSelectionModel().select("USB");
} }
choiceNetUsb.setOnAction(e->{ choiceNetUsb.setOnAction(e->{
if (choiceNetUsb.getSelectionModel().getSelectedItem().equals("NET")){ if (getSelectedNetUsb().equals("NET")){
nsIpLbl.setVisible(true); nsIpLbl.setVisible(true);
nsIpTextField.setVisible(true); nsIpTextField.setVisible(true);
} }
@ -112,7 +114,7 @@ public class FrontController implements Initializable {
}); });
// Set and configure NS IP field behavior // Set and configure NS IP field behavior
nsIpTextField.setText(AppPreferences.getInstance().getNsIp()); 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); nsIpLbl.setVisible(true);
nsIpTextField.setVisible(true); nsIpTextField.setVisible(true);
} }
@ -299,7 +301,7 @@ public class FrontController implements Initializable {
* */ * */
private void stopBtnAction(){ private void stopBtnAction(){
if (workThread != null && workThread.isAlive()){ if (workThread != null && workThread.isAlive()){
usbNetCommunications.cancel(false); usbNetCommunications.cancel();
} }
} }
/** /**

View file

@ -28,7 +28,7 @@ import javafx.stage.DirectoryChooser;
import nsusbloader.AppPreferences; import nsusbloader.AppPreferences;
import nsusbloader.MediatorControl; import nsusbloader.MediatorControl;
import nsusbloader.NSLDataTypes.EModule; import nsusbloader.NSLDataTypes.EModule;
import nsusbloader.Utilities.NxdtTask; import nsusbloader.Utilities.nxdumptool.NxdtTask;
import java.io.File; import java.io.File;
import java.net.URL; import java.net.URL;

View file

@ -36,7 +36,5 @@ public class LogPrinterCli implements ILogPrinter{
@Override @Override
public void updateOneLinerStatus(boolean status){ } public void updateOneLinerStatus(boolean status){ }
@Override @Override
public void close() { public void close() { }
System.out.println("\n-\n");
}
} }

View file

@ -33,7 +33,7 @@ public class LogPrinterGui implements ILogPrinter {
private final BlockingQueue<String> msgQueue; private final BlockingQueue<String> msgQueue;
private final BlockingQueue<Double> progressQueue; private final BlockingQueue<Double> progressQueue;
private final HashMap<String, EFileStatus> statusMap; // BlockingQueue for literally one object. TODO: read more books ; replace to hashMap private final HashMap<String, EFileStatus> statusMap; // BlockingQueue for literally one object. TODO: read more books ; replace to hashMap
private AtomicBoolean oneLinerStatus; private final AtomicBoolean oneLinerStatus;
public LogPrinterGui(EModule whoIsAsking){ public LogPrinterGui(EModule whoIsAsking){
this.msgQueue = new LinkedBlockingQueue<>(); this.msgQueue = new LinkedBlockingQueue<>();

View file

@ -25,12 +25,10 @@ import javafx.scene.Scene;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.stage.Stage; import javafx.stage.Stage;
import nsusbloader.Controllers.NSLMainController; import nsusbloader.Controllers.NSLMainController;
import nsusbloader.Utilities.Rcm; import nsusbloader.cli.CommandLineInterface;
import java.io.File;
import java.util.Locale; import java.util.Locale;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.prefs.Preferences;
public class NSLMain extends Application { public class NSLMain extends Application {
@ -83,70 +81,12 @@ public class NSLMain extends Application {
} }
public static void main(String[] args) { public static void main(String[] args) {
if (handleCli(args)) if (args.length == 0) {
return;
launch(args); 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 { else {
if (! args[1].startsWith("/")) NSLMain.isCli = true;
args[1] = System.getProperty("user.dir") + File.separator + args[1]; new CommandLineInterface(args);
}
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;
}
}
catch (Exception e){
e.printStackTrace();
return true;
} }
} }
} }

View file

@ -16,7 +16,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>. along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
*/ */
package nsusbloader.Utilities; package nsusbloader.Utilities.nxdumptool;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import nsusbloader.COM.USB.UsbConnect; import nsusbloader.COM.USB.UsbConnect;

View file

@ -16,7 +16,7 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>. along with NS-USBloader. If not, see <https://www.gnu.org/licenses/>.
*/ */
package nsusbloader.Utilities; package nsusbloader.Utilities.nxdumptool;
import javafx.concurrent.Task; import javafx.concurrent.Task;
import nsusbloader.COM.USB.UsbErrorCodes; import nsusbloader.COM.USB.UsbErrorCodes;

View file

@ -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 <https://www.gnu.org/licenses/>.
*/
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");
}
}

View file

@ -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 <https://www.gnu.org/licenses/>.
*/
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<File> 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=<arg1> [hostip=<arg2>] FILE1 ...\n"
+ "\tns-usbloader --tfn nsip=<arg1> [hostip=<arg2>] FILE1 ..."
+ "\n\nOptions:"
+ "\n\tnsip=<ip>\t\t\tDefine NS IP address (mandatory)"
+ "\n\thostip=<ip[:port][/extra]>\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;
}
}