diff --git a/README.md b/README.md index 0004073..c6c7759 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # NS-USBloader -NS-USBloader is a PC-side TinFoil and GoldLeaf NSP USB uploader. Replacement for default *usb_install_pc.py* and *GoldTree*. +NS-USBloader is a PC-side TinFoil (USB and Network) and GoldLeaf NSP USB uploader. Replacement for default *usb_install_pc.py*, *remote_install_pc.py* and *GoldTree*. With GUI and cookies. @@ -81,12 +81,14 @@ Français by [Stephane Meden (JackFromNice)](https://github.com/JackFromNice) ## TODO: - [x] macOS QA v0.1 (Mojave) - [x] macOS QA v0.2.2 (Mojave) +- [ ] macOS QA v0.3 (Mojave) - [x] Windows support - [x] code refactoring - [x] GoldLeaf support - [ ] XCI support - [ ] File order sort (non-critical) - [ ] More deep file analyze before uploading. +- [] Network mode support for TinFoil ## Thanks Appreciate assistance and support of both Vitaliy and Konstantin. Without you all this magic would not have happened. diff --git a/src/main/java/nsusbloader/AppPreferences.java b/src/main/java/nsusbloader/AppPreferences.java index 62baa86..fc5344d 100644 --- a/src/main/java/nsusbloader/AppPreferences.java +++ b/src/main/java/nsusbloader/AppPreferences.java @@ -22,10 +22,24 @@ public class AppPreferences { protocol = "TinFoil"; return protocol; } + public String getNetUsb(){ + String netUsb = preferences.get("NETUSB", "USB"); // Don't let user to change settings manually + if (!netUsb.matches("(^USB$)|(^NET$)")) + netUsb = "USB"; + return netUsb; + } public void setTheme(String theme){ preferences.put("THEME", theme); } public void setProtocol(String protocol){ preferences.put("PROTOCOL", protocol); } + public void setNetUsb(String netUsb){ preferences.put("NETUSB", netUsb); } + public void setNsIp(String ip){preferences.put("NSIP", ip);} + public String getNsIp(){return preferences.get("NSIP", "192.168.1.42");} public String getRecent(){ return preferences.get("RECENT", System.getProperty("user.home")); } public void setRecent(String path){ preferences.put("RECENT", path); } + //------------ SETTINGS ------------------// + public boolean getNsIpValidationNeeded() {return preferences.getBoolean("NSIPVALIDATION", true);} + public void setNsIpValidationNeeded(boolean need){preferences.putBoolean("NSIPVALIDATION", need);} + public boolean getExpertMode(){return preferences.getBoolean("EXPERTMODE", false);} + public void setExpertMode(boolean mode){preferences.putBoolean("EXPERTMODE", mode);} } diff --git a/src/main/java/nsusbloader/Controllers/NSLMainController.java b/src/main/java/nsusbloader/Controllers/NSLMainController.java index f253207..5cba9af 100644 --- a/src/main/java/nsusbloader/Controllers/NSLMainController.java +++ b/src/main/java/nsusbloader/Controllers/NSLMainController.java @@ -12,7 +12,9 @@ import javafx.scene.layout.Region; import javafx.stage.FileChooser; import nsusbloader.AppPreferences; import nsusbloader.MediatorControl; +import nsusbloader.NET.NETCommunications; import nsusbloader.NSLMain; +import nsusbloader.ServiceWindow; import nsusbloader.USB.UsbCommunications; import java.io.File; @@ -35,7 +37,7 @@ public class NSLMainController implements Initializable { @FXML public ProgressBar progressBar; // Accessible from Mediator @FXML - private ChoiceBox choiceProtocol; + private ChoiceBox choiceProtocol, choiceNetUsb; @FXML private Button switchThemeBtn; @@ -44,6 +46,12 @@ public class NSLMainController implements Initializable { @FXML public NSTableViewController tableFilesListController; // Accessible from Mediator + @FXML + private NetTabController NetTabController; + @FXML + private TextField nsIpTextField; + @FXML + private Label nsIpLbl; private UsbCommunications usbCommunications; private Thread usbThread; @@ -78,10 +86,46 @@ public class NSLMainController implements Initializable { ObservableList choiceProtocolList = FXCollections.observableArrayList("TinFoil", "GoldLeaf"); choiceProtocol.setItems(choiceProtocolList); - choiceProtocol.getSelectionModel().select(AppPreferences.getInstance().getProtocol()); // TODO: shared settings - choiceProtocol.setOnAction(e->tableFilesListController.setNewProtocol(choiceProtocol.getSelectionModel().getSelectedItem())); // Add listener to notify tableView controller + choiceProtocol.getSelectionModel().select(AppPreferences.getInstance().getProtocol()); + choiceProtocol.setOnAction(e-> { + tableFilesListController.setNewProtocol(choiceProtocol.getSelectionModel().getSelectedItem()); + if (choiceProtocol.getSelectionModel().getSelectedItem().equals("GoldLeaf")) { + choiceNetUsb.setDisable(true); + nsIpLbl.setVisible(false); + nsIpTextField.setVisible(false); + } + else { + choiceNetUsb.setDisable(false); + if (choiceNetUsb.getSelectionModel().getSelectedItem().equals("NET")) { + nsIpLbl.setVisible(true); + nsIpTextField.setVisible(true); + } + } + }); // Add listener to notify tableView controller tableFilesListController.setNewProtocol(choiceProtocol.getSelectionModel().getSelectedItem()); // Notify tableView controller + ObservableList choiceNetUsbList = FXCollections.observableArrayList("USB", "NET"); + choiceNetUsb.setItems(choiceNetUsbList); + choiceNetUsb.getSelectionModel().select(AppPreferences.getInstance().getNetUsb()); + if (choiceProtocol.getSelectionModel().getSelectedItem().equals("GoldLeaf")) { + choiceNetUsb.setDisable(true); + } + choiceNetUsb.setOnAction(e->{ + if (choiceNetUsb.getSelectionModel().getSelectedItem().equals("NET")){ + nsIpLbl.setVisible(true); + nsIpTextField.setVisible(true); + } + else{ + nsIpLbl.setVisible(false); + nsIpTextField.setVisible(false); + } + }); + nsIpTextField.setText(AppPreferences.getInstance().getNsIp()); + if (choiceProtocol.getSelectionModel().getSelectedItem().equals("TinFoil") && choiceNetUsb.getSelectionModel().getSelectedItem().equals("NET")){ + nsIpLbl.setVisible(true); + nsIpTextField.setVisible(true); + } + this.previouslyOpenedPath = null; Region btnSwitchImage = new Region(); @@ -133,20 +177,42 @@ public class NSLMainController implements Initializable { * It's button listener when no transmission executes * */ private void uploadBtnAction(){ - if (usbThread == null || !usbThread.isAlive()){ - List nspToUpload; - if ((nspToUpload = tableFilesListController.getFilesForUpload()) == null) { - logArea.setText(resourceBundle.getString("logsNoFolderFileSelected")); - return; - }else { - logArea.setText(resourceBundle.getString("logsFilesToUploadTitle")+"\n"); - for (File item: nspToUpload) - logArea.appendText(" "+item.getAbsolutePath()+"\n"); + if ((usbThread == null || !usbThread.isAlive())){ + if (choiceProtocol.getSelectionModel().getSelectedItem().equals("GoldLeaf") || + ( + choiceProtocol.getSelectionModel().getSelectedItem().equals("TinFoil") + && choiceNetUsb.getSelectionModel().getSelectedItem().equals("USB") + ) + ){ + List nspToUpload; + if ((nspToUpload = tableFilesListController.getFilesForUpload()) == null) { + logArea.setText(resourceBundle.getString("logsNoFolderFileSelected")); + return; + }else { + logArea.setText(resourceBundle.getString("logsFilesToUploadTitle")+"\n"); + for (File item: nspToUpload) + logArea.appendText(" "+item.getAbsolutePath()+"\n"); + } + usbCommunications = new UsbCommunications(nspToUpload, choiceProtocol.getSelectionModel().getSelectedItem()); + usbThread = new Thread(usbCommunications); + usbThread.setDaemon(true); + usbThread.start(); + } + else { // NET INSTALL OVER TINFOIL + if (NetTabController.isNsIpValidate() && !nsIpTextField.getText().trim().matches("^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])$")) + if (!ServiceWindow.getConfirmationWindow(resourceBundle.getString("windowTitleBadIp"),resourceBundle.getString("windowBodyBadIp"))) + return; + String nsIP = nsIpTextField.getText().trim(); + if (!NetTabController.getExpertModeSelected()) { + NETCommunications netCommunications = new NETCommunications(nsIP); + usbThread = new Thread(netCommunications); + usbThread.setDaemon(true); + usbThread.start(); + } + else { + // TODO; pass to another constructor + } } - usbCommunications = new UsbCommunications(nspToUpload, choiceProtocol.getSelectionModel().getSelectedItem()); - usbThread = new Thread(usbCommunications); - usbThread.setDaemon(true); - usbThread.start(); } } /** @@ -235,5 +301,9 @@ public class NSLMainController implements Initializable { public void exit(){ AppPreferences.getInstance().setProtocol(choiceProtocol.getSelectionModel().getSelectedItem()); AppPreferences.getInstance().setRecent(previouslyOpenedPath); + AppPreferences.getInstance().setNetUsb(choiceNetUsb.getSelectionModel().getSelectedItem()); + AppPreferences.getInstance().setNsIp(nsIpTextField.getText().trim()); + AppPreferences.getInstance().setNsIpValidationNeeded(NetTabController.isNsIpValidate()); + AppPreferences.getInstance().setExpertMode(NetTabController.getExpertModeSelected()); } } diff --git a/src/main/java/nsusbloader/Controllers/NetTabController.java b/src/main/java/nsusbloader/Controllers/NetTabController.java new file mode 100644 index 0000000..272ef87 --- /dev/null +++ b/src/main/java/nsusbloader/Controllers/NetTabController.java @@ -0,0 +1,49 @@ +package nsusbloader.Controllers; + +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.CheckBox; +import javafx.scene.control.Label; +import javafx.scene.control.TextField; +import nsusbloader.AppPreferences; + + +import java.net.URL; +import java.util.ResourceBundle; + +public class NetTabController implements Initializable { + + @FXML + private CheckBox validateNSHostNameCb; + @FXML + private TextField pcIpTextField; + @FXML + private CheckBox expertModeCb; + @FXML + private Label hostIpLbl; + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + validateNSHostNameCb.setSelected(AppPreferences.getInstance().getNsIpValidationNeeded()); + if (AppPreferences.getInstance().getExpertMode()) { + expertModeCb.setSelected(true); + hostIpLbl.setVisible(true); + pcIpTextField.setVisible(true); + } + expertModeCb.setOnAction(e->{ + if (expertModeCb.isSelected()){ + hostIpLbl.setVisible(true); + pcIpTextField.setVisible(true); + } + else { + hostIpLbl.setVisible(false); + pcIpTextField.setVisible(false); + } + }); + } + + public boolean getExpertModeSelected(){ + return expertModeCb.isSelected(); + } + public boolean isNsIpValidate(){ return validateNSHostNameCb.isSelected(); } +} diff --git a/src/main/java/nsusbloader/NET/NETCommunications.java b/src/main/java/nsusbloader/NET/NETCommunications.java new file mode 100644 index 0000000..12aa4dd --- /dev/null +++ b/src/main/java/nsusbloader/NET/NETCommunications.java @@ -0,0 +1,62 @@ +package nsusbloader.NET; + +import javafx.concurrent.Task; + +import java.io.*; +import java.net.*; + +public class NETCommunications extends Task { // todo: thows IOException + + private String hostIP; + private String switchIP; + + private ServerSocket serverSocket; + + public NETCommunications(String switchIP){ + this.switchIP = switchIP; + try{ // todo: check other method if internet unavaliable + DatagramSocket socket = new DatagramSocket(); + socket.connect(InetAddress.getByName("8.8.8.8"), 10002); //193.0.14.129 RIPE NCC + hostIP = socket.getLocalAddress().getHostAddress(); + System.out.println(hostIP); + socket.close(); + } + catch (SocketException | UnknownHostException e){ + e.printStackTrace(); + } + + try { + serverSocket = new ServerSocket(6000); // TODO: randomize + //System.out.println(serverSocket.getInetAddress()); 0.0.0.0 + } + catch (IOException ioe){ + ioe.printStackTrace(); + System.out.println("unable to use socket"); + } + } + + @Override + protected Void call() throws Exception { + Socket clientSocket = serverSocket.accept(); + + InputStream is = clientSocket.getInputStream(); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + + OutputStream os = clientSocket.getOutputStream(); + OutputStreamWriter osr = new OutputStreamWriter(os); + PrintWriter pw = new PrintWriter(osr); + + String line; + while ((line = br.readLine()) != null) { + if (line.equals("hello world")) { + pw.write("stop doing it!"); + pw.flush(); + break; + } + System.out.println(line); + } + serverSocket.close(); + return null; + } +} diff --git a/src/main/resources/NSLMain.fxml b/src/main/resources/NSLMain.fxml index 1ce9f82..82a76bd 100644 --- a/src/main/resources/NSLMain.fxml +++ b/src/main/resources/NSLMain.fxml @@ -3,10 +3,12 @@ + + @@ -30,6 +32,9 @@ + +