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:
parent
6b65c74c9d
commit
3c89df9dcd
19 changed files with 404 additions and 109 deletions
|
@ -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!
|
||||
|
||||
|
|
7
pom.xml
7
pom.xml
|
@ -50,6 +50,13 @@
|
|||
</issueManagement>
|
||||
<!-- openJFX Linux -->
|
||||
<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>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-controls</artifactId>
|
||||
|
|
24
src/main/java/nsusbloader/COM/ICommunications.java
Normal file
24
src/main/java/nsusbloader/COM/ICommunications.java
Normal 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();
|
||||
}
|
|
@ -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<Void> { // todo: thows IOException?
|
||||
public class NETCommunications implements ICommunications { // todo: rewrite
|
||||
|
||||
private ILogPrinter logPrinter;
|
||||
|
||||
|
@ -52,10 +52,17 @@ public class NETCommunications extends Task<Void> { // todo: thows IOException?
|
|||
|
||||
private OutputStream currSockOS;
|
||||
private PrintWriter currSockPW;
|
||||
|
||||
private volatile boolean cancel;
|
||||
/**
|
||||
* 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;
|
||||
if (doNotServeRequests)
|
||||
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);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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<Void> { // 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<Void> { // todo: thows IOException?
|
|||
}
|
||||
if ( ! isCancelled() )
|
||||
close(EFileStatus.UNKNOWN);
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
// 200 206 400 (inv range) 404 416 (Range Not Satisfiable )
|
||||
|
|
|
@ -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<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);
|
||||
|
||||
final byte CMD_GetDriveCount = 1;
|
||||
|
|
|
@ -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<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);
|
||||
status = EFileStatus.FAILED;
|
||||
|
||||
|
|
|
@ -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<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);
|
||||
|
||||
final byte CMD_GetDriveCount = 0x00;
|
||||
|
|
|
@ -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<String, File> nspMap, Task<Void> task, ILogPrinter logPrinter){
|
||||
TinFoil(DeviceHandle handler, LinkedHashMap<String, File> nspMap, ICommunications task, ILogPrinter logPrinter){
|
||||
super(handler, nspMap, task, logPrinter);
|
||||
logPrinter.print("============= Tinfoil =============", EMsgType.INFO);
|
||||
|
||||
|
|
|
@ -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<String, File> nspMap;
|
||||
ILogPrinter logPrinter;
|
||||
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.nspMap = nspMap;
|
||||
this.task = task;
|
||||
|
|
|
@ -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<Void> {
|
||||
public class UsbCommunications implements ICommunications {
|
||||
|
||||
private ILogPrinter logPrinter;
|
||||
private LinkedHashMap<String, File> nspMap;
|
||||
private String protocol;
|
||||
private boolean nspFilterForGl;
|
||||
|
||||
private volatile boolean cancel;
|
||||
|
||||
public UsbCommunications(List<File> nspList, String protocol, boolean filterNspFilesOnlyForGl){
|
||||
this.protocol = protocol;
|
||||
this.nspFilterForGl = filterNspFilesOnlyForGl;
|
||||
|
@ -48,14 +51,14 @@ public class UsbCommunications extends Task<Void> {
|
|||
}
|
||||
|
||||
@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<Void> {
|
|||
|
||||
close(module.getStatus());
|
||||
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -93,4 +96,13 @@ public class UsbCommunications extends Task<Void> {
|
|||
logPrinter.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
cancel = true;
|
||||
}
|
||||
}
|
|
@ -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,7 +64,7 @@ public class FrontController implements Initializable {
|
|||
private String previouslyOpenedPath;
|
||||
private Region btnUpStopImage;
|
||||
private ResourceBundle resourceBundle;
|
||||
private Task<Void> usbNetCommunications;
|
||||
private ICommunications usbNetCommunications;
|
||||
private Thread workThread;
|
||||
|
||||
@Override
|
||||
|
@ -71,11 +72,12 @@ public class FrontController implements Initializable {
|
|||
this.resourceBundle = resourceBundle;
|
||||
|
||||
ObservableList<String> 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<String> 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();
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -36,7 +36,5 @@ public class LogPrinterCli implements ILogPrinter{
|
|||
@Override
|
||||
public void updateOneLinerStatus(boolean status){ }
|
||||
@Override
|
||||
public void close() {
|
||||
System.out.println("\n-\n");
|
||||
}
|
||||
public void close() { }
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ public class LogPrinterGui implements ILogPrinter {
|
|||
private final BlockingQueue<String> msgQueue;
|
||||
private final BlockingQueue<Double> progressQueue;
|
||||
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){
|
||||
this.msgQueue = new LinkedBlockingQueue<>();
|
||||
|
|
|
@ -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;
|
||||
if (args.length == 0) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
catch (Exception e){
|
||||
e.printStackTrace();
|
||||
return true;
|
||||
NSLMain.isCli = true;
|
||||
new CommandLineInterface(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
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.Utilities;
|
||||
package nsusbloader.Utilities.nxdumptool;
|
||||
|
||||
import javafx.concurrent.Task;
|
||||
import nsusbloader.COM.USB.UsbConnect;
|
|
@ -16,7 +16,7 @@
|
|||
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.Utilities;
|
||||
package nsusbloader.Utilities.nxdumptool;
|
||||
|
||||
import javafx.concurrent.Task;
|
||||
import nsusbloader.COM.USB.UsbErrorCodes;
|
167
src/main/java/nsusbloader/cli/CommandLineInterface.java
Normal file
167
src/main/java/nsusbloader/cli/CommandLineInterface.java
Normal 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");
|
||||
}
|
||||
|
||||
}
|
130
src/main/java/nsusbloader/cli/TinfoilNet.java
Normal file
130
src/main/java/nsusbloader/cli/TinfoilNet.java
Normal 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;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue