From 31045683e459829d5594c43471b86ee35f376905 Mon Sep 17 00:00:00 2001 From: Dmitry Isaenko Date: Tue, 19 Mar 2019 03:10:00 +0300 Subject: [PATCH] v0.3 UI is ready --- .../Controllers/SettingsController.java | 39 ++++++---- .../{USB => ModelControllers}/LogPrinter.java | 23 ++++-- .../MessagesConsumer.java | 2 +- .../nsusbloader/NET/NETCommunications.java | 53 ++++++++++++-- src/main/java/nsusbloader/NET/NETPacket.java | 32 +++++++- .../java/nsusbloader/USB/PFS/PFSProvider.java | 2 +- .../nsusbloader/USB/UsbCommunications.java | 4 +- src/main/resources/SettingsTab.fxml | 73 +++++++++++++++---- src/main/resources/locale.properties | 9 ++- src/main/resources/locale_fra.properties | 9 ++- src/main/resources/locale_rus.properties | 9 ++- src/main/resources/locale_ukr.properties | 11 ++- 12 files changed, 206 insertions(+), 60 deletions(-) rename src/main/java/nsusbloader/{USB => ModelControllers}/LogPrinter.java (77%) rename src/main/java/nsusbloader/{USB => ModelControllers}/MessagesConsumer.java (98%) diff --git a/src/main/java/nsusbloader/Controllers/SettingsController.java b/src/main/java/nsusbloader/Controllers/SettingsController.java index 243ab3d..eb0b73e 100644 --- a/src/main/java/nsusbloader/Controllers/SettingsController.java +++ b/src/main/java/nsusbloader/Controllers/SettingsController.java @@ -5,6 +5,7 @@ import javafx.fxml.Initializable; import javafx.scene.control.CheckBox; import javafx.scene.control.Label; import javafx.scene.control.TextField; +import javafx.scene.layout.VBox; import nsusbloader.AppPreferences; @@ -16,30 +17,36 @@ public class SettingsController implements Initializable { @FXML private CheckBox validateNSHostNameCb; @FXML - private TextField pcIpTextField; - @FXML private CheckBox expertModeCb; @FXML - private Label hostIpLbl; + private CheckBox autoDetectIpCb; + @FXML + private CheckBox randPortCb; + + @FXML + private TextField pcIpTextField; + @FXML + private TextField pcPortTextField; + @FXML + private TextField pcPostfixTextField; + + @FXML + private CheckBox dontServeCb; + + @FXML + private VBox expertSettingsVBox; @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); - } + expertSettingsVBox.setDisable(AppPreferences.getInstance().getExpertMode()); + expertModeCb.setOnAction(e->{ - if (expertModeCb.isSelected()){ - hostIpLbl.setVisible(true); - pcIpTextField.setVisible(true); - } - else { - hostIpLbl.setVisible(false); - pcIpTextField.setVisible(false); - } + if (expertModeCb.isSelected()) + expertSettingsVBox.setDisable(false); + else + expertSettingsVBox.setDisable(true); }); } diff --git a/src/main/java/nsusbloader/USB/LogPrinter.java b/src/main/java/nsusbloader/ModelControllers/LogPrinter.java similarity index 77% rename from src/main/java/nsusbloader/USB/LogPrinter.java rename to src/main/java/nsusbloader/ModelControllers/LogPrinter.java index 6faed8a..8a6edb7 100644 --- a/src/main/java/nsusbloader/USB/LogPrinter.java +++ b/src/main/java/nsusbloader/ModelControllers/LogPrinter.java @@ -1,4 +1,4 @@ -package nsusbloader.USB; +package nsusbloader.ModelControllers; import nsusbloader.NSLDataTypes.EFileStatus; import nsusbloader.NSLDataTypes.EMsgType; @@ -14,7 +14,7 @@ public class LogPrinter { private BlockingQueue progressQueue; private HashMap statusMap; // BlockingQueue for literally one object. TODO: read more books ; replace to hashMap - LogPrinter(){ + public LogPrinter(){ this.msgQueue = new LinkedBlockingQueue<>(); this.progressQueue = new LinkedBlockingQueue<>(); this.statusMap = new HashMap<>(); @@ -53,11 +53,22 @@ public class LogPrinter { progressQueue.put(value); } /** - * When we're done + * When we're done - update status * */ - public void updateAndClose(HashMap nspMap, EFileStatus status){ - for (String fileName: nspMap.keySet()) - statusMap.put(fileName, status); + public void update(HashMap nspMap, EFileStatus status){ + for (File file: nspMap.values()) + statusMap.putIfAbsent(file.getName(), status); + } + /** + * When we're done - update status + * */ + public void update(File file, EFileStatus status){ + statusMap.putIfAbsent(file.getName(), status); + } + /** + * When we're done - close it + * */ + public void close(){ msgConsumer.interrupt(); } } diff --git a/src/main/java/nsusbloader/USB/MessagesConsumer.java b/src/main/java/nsusbloader/ModelControllers/MessagesConsumer.java similarity index 98% rename from src/main/java/nsusbloader/USB/MessagesConsumer.java rename to src/main/java/nsusbloader/ModelControllers/MessagesConsumer.java index d8bd818..9ffb253 100644 --- a/src/main/java/nsusbloader/USB/MessagesConsumer.java +++ b/src/main/java/nsusbloader/ModelControllers/MessagesConsumer.java @@ -1,4 +1,4 @@ -package nsusbloader.USB; +package nsusbloader.ModelControllers; import javafx.animation.AnimationTimer; import javafx.scene.control.ProgressBar; diff --git a/src/main/java/nsusbloader/NET/NETCommunications.java b/src/main/java/nsusbloader/NET/NETCommunications.java index fc24c5a..e71745c 100644 --- a/src/main/java/nsusbloader/NET/NETCommunications.java +++ b/src/main/java/nsusbloader/NET/NETCommunications.java @@ -1,15 +1,13 @@ package nsusbloader.NET; import javafx.concurrent.Task; -import nsusbloader.NSLMain; +import nsusbloader.NSLDataTypes.EFileStatus; +import nsusbloader.ModelControllers.LogPrinter; import java.io.*; import java.net.*; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -19,6 +17,8 @@ import java.util.List; public class NETCommunications extends Task { // todo: thows IOException? + private LogPrinter logPrinter; + private String hostIP; private int hostPort; private String switchIP; @@ -29,6 +29,7 @@ public class NETCommunications extends Task { // todo: thows IOException? private ServerSocket serverSocket; public NETCommunications(List filesList, String switchIP){ + this.logPrinter = new LogPrinter(); this.switchIP = switchIP; this.nspMap = new HashMap<>(); try { @@ -117,6 +118,8 @@ write in first 4 bytes String line; LinkedList tcpPackeet = new LinkedList<>(); while ((line = br.readLine()) != null) { + if (isCancelled()) // TODO: notice everywhere + break; System.out.println(line); // TODO: remove DBG if (line.trim().isEmpty()) { // If TCP packet is ended handleRequest(tcpPackeet, pw); // Proceed required things @@ -132,22 +135,56 @@ write in first 4 bytes catch (IOException ioe){ ioe.printStackTrace(); // TODO: fix } - + logPrinter.update(nspMap, EFileStatus.UNKNOWN); + logPrinter.close(); return null; } - // 200 206 400 (inv range) 404 + // 200 206 400 (inv range) 404 416 (416 Range Not Satisfiable ) private void handleRequest(LinkedList packet, PrintWriter pw){ + File requestedFile; if (packet.get(0).startsWith("HEAD")){ - File requestedFile = nspMap.get(packet.get(0).replaceAll("(^[A-z\\s]+/)|(\\s+?.*$)", "")); + requestedFile = nspMap.get(packet.get(0).replaceAll("(^[A-z\\s]+/)|(\\s+?.*$)", "")); if (requestedFile == null || !requestedFile.exists()){ - return; //todo: send 404 + pw.write(NETPacket.getCode404()); + pw.flush(); + logPrinter.update(requestedFile, EFileStatus.FAILED); } else { pw.write(NETPacket.getCode200(requestedFile.length())); pw.flush(); System.out.println(requestedFile.getAbsolutePath()+"\n"+NETPacket.getCode200(requestedFile.length())); } + return; + } + if (packet.get(0).startsWith("GET")) { + requestedFile = nspMap.get(packet.get(0).replaceAll("(^[A-z\\s]+/)|(\\s+?.*$)", "")); + if (requestedFile == null || !requestedFile.exists()){ + pw.write(NETPacket.getCode404()); + pw.flush(); + logPrinter.update(requestedFile, EFileStatus.FAILED); + } + else { + for (String line: packet) + if (line.toLowerCase().startsWith("range")){ + String[] rangeStr = line.toLowerCase().replaceAll("^range:\\s+?bytes=", "").split("-", 2); + if (!rangeStr[0].isEmpty() && !rangeStr[1].isEmpty()){ // If both ranges defined: Read requested + + } + else if (!rangeStr[0].isEmpty()){ // If only START defined: Read all + + } + else if (!rangeStr[1].isEmpty()){ // If only END defined: Try to read last 500 bytes + + } + else { + pw.write(NETPacket.getCode400()); + pw.flush(); + logPrinter.update(requestedFile, EFileStatus.FAILED); + //logPrinter.print(); // TODO: INFORM + } + } + } } } } diff --git a/src/main/java/nsusbloader/NET/NETPacket.java b/src/main/java/nsusbloader/NET/NETPacket.java index c6348e8..3470b06 100644 --- a/src/main/java/nsusbloader/NET/NETPacket.java +++ b/src/main/java/nsusbloader/NET/NETPacket.java @@ -25,12 +25,40 @@ public class NETPacket { "Content-Range: bytes %d-%d/%d\r\n"+ "Content-Length: %d\r\n"+ "Last-Modified: Mon, 18 Mar 2019 12:57:33 GMT\r\n\r\n"; - + private static final String CODE_400 = + "HTTP/1.0 400 invalid range\r\n"+ + "Server: NS-USBloader-"+NSLMain.appVersion+"\r\n" + + "Date: %s\r\n" + + "Connection: close\r\n"+ + "Content-Type: text/html;charset=utf-8\r\n"+ + "Content-Length: 0\r\b\r\n"; + private static final String CODE_404 = + "HTTP/1.0 404 Not Found\r\n"+ + "Server: NS-USBloader-"+NSLMain.appVersion+"\r\n" + + "Date: %s\r\n" + + "Connection: close\r\n"+ + "Content-Type: text/html;charset=utf-8\r\n"+ + "Content-Length: 0\r\b\r\n"; + private static final String CODE_416 = + "HTTP/1.0 416 Requested Range Not Satisfiable\r\n"+ + "Server: NS-USBloader-"+NSLMain.appVersion+"\r\n" + + "Date: %s\r\n" + + "Connection: close\r\n"+ + "Content-Type: text/html;charset=utf-8\r\n"+ + "Content-Length: 0\r\b\r\n"; public static String getCode200(long nspFileSize){ return String.format(CODE_200, ZonedDateTime.now(ZoneId.of("GMT")).format(DateTimeFormatter.RFC_1123_DATE_TIME), nspFileSize-1, nspFileSize, nspFileSize); } public static String getCode206(long nspFileSize, long startPos, long endPos){ return String.format(CODE_206, ZonedDateTime.now(ZoneId.of("GMT")).format(DateTimeFormatter.RFC_1123_DATE_TIME), startPos, endPos, nspFileSize, endPos-startPos+1); } - + public static String getCode404(){ + return String.format(CODE_404, ZonedDateTime.now(ZoneId.of("GMT")).format(DateTimeFormatter.RFC_1123_DATE_TIME)); + } + public static String getCode416(){ + return String.format(CODE_416, ZonedDateTime.now(ZoneId.of("GMT")).format(DateTimeFormatter.RFC_1123_DATE_TIME)); + } + public static String getCode400(){ + return String.format(CODE_400, ZonedDateTime.now(ZoneId.of("GMT")).format(DateTimeFormatter.RFC_1123_DATE_TIME)); + } } diff --git a/src/main/java/nsusbloader/USB/PFS/PFSProvider.java b/src/main/java/nsusbloader/USB/PFS/PFSProvider.java index bd627cc..0ce87ad 100644 --- a/src/main/java/nsusbloader/USB/PFS/PFSProvider.java +++ b/src/main/java/nsusbloader/USB/PFS/PFSProvider.java @@ -1,6 +1,6 @@ package nsusbloader.USB.PFS; -import nsusbloader.USB.LogPrinter; +import nsusbloader.ModelControllers.LogPrinter; import nsusbloader.NSLDataTypes.EMsgType; import nsusbloader.ServiceWindow; diff --git a/src/main/java/nsusbloader/USB/UsbCommunications.java b/src/main/java/nsusbloader/USB/UsbCommunications.java index e63c0b2..1bc7761 100644 --- a/src/main/java/nsusbloader/USB/UsbCommunications.java +++ b/src/main/java/nsusbloader/USB/UsbCommunications.java @@ -1,6 +1,7 @@ package nsusbloader.USB; import javafx.concurrent.Task; +import nsusbloader.ModelControllers.LogPrinter; import nsusbloader.NSLDataTypes.EFileStatus; import nsusbloader.NSLDataTypes.EMsgType; import nsusbloader.USB.PFS.PFSProvider; @@ -707,7 +708,8 @@ public class UsbCommunications extends Task { } // Report status and close - logPrinter.updateAndClose(nspMap, status); + logPrinter.update(nspMap, status); + logPrinter.close(); } /** * Sending any byte array to USB device diff --git a/src/main/resources/SettingsTab.fxml b/src/main/resources/SettingsTab.fxml index 962e445..413848c 100644 --- a/src/main/resources/SettingsTab.fxml +++ b/src/main/resources/SettingsTab.fxml @@ -3,33 +3,74 @@ + + + - + - + - - - - - - - + + + + + - - - - + diff --git a/src/main/resources/locale.properties b/src/main/resources/locale.properties index a9fc03b..8f69c2f 100644 --- a/src/main/resources/locale.properties +++ b/src/main/resources/locale.properties @@ -21,11 +21,16 @@ tableSizeLbl=Size tableUploadLbl=Upload? contextMenuBtnDelete=Remove contextMenuBtnDeleteAll=Remove all -netTabHostIPlbl=Host IP +netTabHostIPLbl=Host IP NSIPlable=NS IP: netTabValidateNSHostNameCb=Always validate NS IP input. windowBodyBadIp=Are you sure that you entered NS IP address correctly? windowTitleBadIp=IP address of NS most likely incorrect -netTabExpertModeCB=Expert mode (I have issues with NET isntallations). +netTabExpertModeCb=Expert mode windowTitleExpectModeIncomplete=Check your settings windowBodyExpectModeIncomplete=You selected 'Expert Mode' in settings and have mistakes in parameters\nDouble check if settings valid. +netTabHostPortLbl=port +netTabAutoDetectIpCb=Auto-detect IP +netTabRandSelectPortCb=Randomly get port +netTabDontServeRequestsCb=Don't serve requests +netTabDontServeRequestsDescription=If selected, this computer won't reply to NSP files requests coming from NS (over the net) and use defined host settings to tell TinFoil where should it look for files. diff --git a/src/main/resources/locale_fra.properties b/src/main/resources/locale_fra.properties index 465188d..bb12d01 100644 --- a/src/main/resources/locale_fra.properties +++ b/src/main/resources/locale_fra.properties @@ -20,12 +20,17 @@ tableFileNameLbl=Nom de fichier tableStatusLbl=Statut contextMenuBtnDelete=Supprimer contextMenuBtnDeleteAll=Supprimer tout -netTabHostIPlbl=IP de l'ordinateur <-FIX +netTabHostIPLbl=IP de l'ordinateur <-FIX NSIPlable=IP de NS: netTabValidateNSHostNameCb=Always validate NS IP input. <-FIX windowTitleBadIp=IP address of NS most likely incorrect <-FIX windowBodyBadIp=Are you sure that you entered NS IP address correctly? <-FIX -netTabExpertModeCB=Expert mode (I have issues with NET isntallations). <- FIX +netTabExpertModeCb=Expert mode<- FIX windowTitleExpectModeIncomplete=Check your settings <- FIX windowBodyExpectModeIncomplete=You selected 'Expert Mode' in settings and have mistakes in parameters\nDouble check if settings valid. <- FIX +netTabHostPortLbl=port <- fix +netTabAutoDetectIpCb=Auto-detect IP <- FIX +netTabRandSelectPortCb=Randomly get port <- FIX +netTabDontServeRequestsCb=Don't serve requests <- FIX +netTabDontServeRequestsDescription=If selected, this computer won't reply to NSP files requests coming from NS (over the net) and use defined host settings to tell TinFoil where should it look for files. <- Fix diff --git a/src/main/resources/locale_rus.properties b/src/main/resources/locale_rus.properties index 14be61a..9243049 100644 --- a/src/main/resources/locale_rus.properties +++ b/src/main/resources/locale_rus.properties @@ -22,12 +22,17 @@ tableFileNameLbl=\u0418\u043C\u044F \u0444\u0430\u0439\u043B\u0430 tableStatusLbl=\u0421\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435 contextMenuBtnDelete=\u0423\u0434\u0430\u043B\u0438\u0442\u044C contextMenuBtnDeleteAll=\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0432\u0441\u0451 -netTabHostIPlbl=IP \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0430 +netTabHostIPLbl=IP \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440\u0430 NSIPlable=NS IP: netTabValidateNSHostNameCb=\u0412\u0441\u0435\u0433\u0434\u0430 \u043F\u0440\u043E\u0432\u0435\u0440\u044F\u0442\u044C \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E\u0441\u0442\u044C NS IP. windowTitleBadIp=IP \u0430\u0434\u0440\u0435\u0441 NS \u043F\u043E\u0445\u043E\u0436\u0435 \u043D\u0435\u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u044B\u0439 windowBodyBadIp=\u0412\u044B \u0443\u0432\u0435\u0440\u0435\u043D\u044B \u0447\u0442\u043E IP \u0430\u0434\u0440\u0435\u0441 NS \u0432\u0432\u0435\u0434\u0451\u043D \u0431\u0435\u0437 \u043E\u0448\u0438\u0431\u043E\u043A? -netTabExpertModeCB=\u0420\u0435\u0436\u0438\u043C \u044D\u043A\u0441\u043F\u0435\u0440\u0442\u0430 (\u0423 \u043C\u0435\u043D\u044F \u043F\u0440\u043E\u0431\u043B\u0435\u043C\u044B \u0441 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u043E\u0439 \u043F\u043E-\u0441\u0435\u0442\u0438). +netTabExpertModeCb=\u0420\u0435\u0436\u0438\u043C \u044D\u043A\u0441\u043F\u0435\u0440\u0442\u0430 windowTitleExpectModeIncomplete=\u041F\u0440\u043E\u0432\u0435\u0440\u044C\u0442\u0435 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E\u0441\u0442\u044C \u043D\u0430\u0441\u0442\u0440\u043E\u0435\u043A windowBodyExpectModeIncomplete=\u0412\u044B \u0432\u044B\u0431\u0440\u0430\u043B\u0438 \u00AB\u0420\u0435\u0436\u0438\u043C \u044D\u043A\u0441\u043F\u0435\u0440\u0442\u0430\u00BB \u0432 \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430\u0445 \u0438 \u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043B\u0438 \u043E\u0448\u0438\u0431\u043A\u0438 \u0432 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u0430\u0445\n\u041F\u0440\u043E\u0432\u0435\u0440\u044C\u0442\u0435 \u0438\u0445 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E\u0441\u0442\u044C \u0435\u0449\u0451 \u0440\u0430\u0437. +netTabHostPortLbl=\u043F\u043E\u0440\u0442 +netTabAutoDetectIpCb=\u0410\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438 \u043E\u043F\u0440\u0435\u0434\u0435\u043B\u044F\u0442\u044C IP +netTabRandSelectPortCb=\u041E\u043F\u0440\u0435\u0434\u0435\u043B\u044F\u0442\u044C \u043F\u043E\u0440\u0442 \u0441\u043B\u0443\u0447\u0430\u0439\u043D\u044B\u043C \u043E\u0431\u0440\u0430\u0437\u043E\u043C +netTabDontServeRequestsCb=\u041D\u0435 \u043E\u0431\u0440\u0430\u0431\u0430\u0442\u044B\u0432\u0430\u0442\u044C \u0437\u0430\u043F\u0440\u043E\u0441\u044B +netTabDontServeRequestsDescription=\u0415\u0441\u043B\u0438 \u0432\u044B\u0431\u0440\u0430\u043D\u043E, \u0442\u043E\u0433\u0434\u0430 \u044D\u0442\u043E\u0442 \u043A\u043E\u043C\u043F\u044C\u044E\u0442\u0435\u0440 \u043D\u0435 \u0431\u0443\u0434\u0435\u0442 \u043E\u0442\u0432\u0435\u0447\u0430\u0442\u044C \u043D\u0430 \u0437\u0430\u043F\u0440\u043E\u0441\u044B NSP \u0444\u0430\u0439\u043B\u043E\u0432. \u0411\u0443\u0434\u0443\u0442 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u044C\u0441\u044F \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438 \u0445\u043E\u0441\u0442\u0430 \u0447\u0442\u043E\u0431\u044B \u0443\u043A\u0430\u0437\u0430\u0442\u044C TinFoil \u043E\u0442\u043A\u0443\u0434\u0430 \u0435\u043C\u0443 \u0441\u043B\u0435\u0434\u0443\u0435\u0442 \u0431\u0440\u0430\u0442\u044C \u0444\u0430\u0439\u043B\u044B. diff --git a/src/main/resources/locale_ukr.properties b/src/main/resources/locale_ukr.properties index 6657ba8..7fe3bc8 100644 --- a/src/main/resources/locale_ukr.properties +++ b/src/main/resources/locale_ukr.properties @@ -21,11 +21,16 @@ tableSizeLbl=\u0420\u043E\u0437\u043C\u0456\u0440 tableUploadLbl=\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436.? contextMenuBtnDelete=\u0412\u0438\u0434\u0430\u043B\u0438\u0442\u0438 contextMenuBtnDeleteAll=\u0412\u0438\u0434\u0430\u043B\u0438\u0442\u0438 \u0432\u0441\u0435 -netTabHostIPlbl=IP \u043A\u043E\u043C\u043F'\u044E\u0442\u0435\u0440\u0443 +netTabHostIPLbl=IP \u043A\u043E\u043C\u043F'\u044E\u0442\u0435\u0440\u0443 NSIPlable=NS IP: netTabValidateNSHostNameCb=\u0417\u0430\u0432\u0436\u0434\u0438 \u043F\u0435\u0440\u0435\u0432\u0456\u0440\u044F\u0442\u0438 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0456\u0441\u0442\u044C NS IP. windowTitleBadIp=IP \u0430\u0434\u0440\u0435\u0441\u0430 NS \u0441\u043A\u043E\u0440\u0456\u0448 \u0437\u0430 \u0432\u0441\u0435 \u043D\u0435\u0432\u0456\u0440\u043D\u0430 windowBodyBadIp=\u0412\u0438 \u0432\u043F\u0435\u0432\u043D\u0435\u043D\u0456 \u0449\u043E IP \u0430\u0434\u0440\u0435\u0441\u0430 NS \u0432\u0432\u0435\u0434\u0435\u043D\u0430 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u043E? -netTabExpertModeCB=\u0420\u0435\u0436\u0438\u043C \u0435\u043A\u0441\u043F\u0435\u0440\u0442\u0430 (\u0412 \u043C\u0435\u043D\u0435 \u043F\u0440\u043E\u0431\u043B\u0435\u043C\u0438 \u0437 \u0432\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044F\u043C \u043F\u043E \u043C\u0435\u0440\u0435\u0436\u0456). +netTabExpertModeCb=\u0420\u0435\u0436\u0438\u043C \u0435\u043A\u0441\u043F\u0435\u0440\u0442\u0430 windowTitleExpectModeIncomplete=\u041F\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0456\u0441\u0442\u044C \u043D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u044C -windowBodyExpectModeIncomplete=\u0412\u0438 \u0432\u0438\u0431\u0440\u0430\u043B\u0438 "\u0420\u0435\u0436\u0438\u043C \u0454\u043A\u0441\u043F\u0435\u0440\u0442\u0430" \u0432 \u043D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F\u0445 \u0442\u0430 \u0437\u0440\u043E\u0431\u0438\u043B\u0438 \u043F\u043E\u043C\u0438\u043B\u043A\u0438 \u0432 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u0430\u0445\n\u041F\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u0457\u0445 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0456\u0441\u0442\u044C \u0449\u0435 \u0440\u0430\u0437. \ No newline at end of file +windowBodyExpectModeIncomplete=\u0412\u0438 \u0432\u0438\u0431\u0440\u0430\u043B\u0438 "\u0420\u0435\u0436\u0438\u043C \u0454\u043A\u0441\u043F\u0435\u0440\u0442\u0430" \u0432 \u043D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F\u0445 \u0442\u0430 \u0437\u0440\u043E\u0431\u0438\u043B\u0438 \u043F\u043E\u043C\u0438\u043B\u043A\u0438 \u0432 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u0430\u0445\n\u041F\u0435\u0440\u0435\u0432\u0456\u0440\u0442\u0435 \u0457\u0445 \u043F\u0440\u0430\u0432\u0438\u043B\u044C\u043D\u0456\u0441\u0442\u044C \u0449\u0435 \u0440\u0430\u0437. +netTabHostPortLbl=\u043F\u043E\u0440\u0442 +netTabAutoDetectIpCb=\u0410\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u043D\u043E \u0432\u0438\u0437\u043D\u0430\u0447\u0430\u0442\u0438 IP +netTabRandSelectPortCb=\u0412\u0438\u0437\u043D\u0430\u0447\u0430\u0442\u0438 \u043F\u043E\u0440\u0442 \u0432\u0438\u043F\u0430\u0434\u043A\u043E\u0432\u0438\u043C \u0447\u0438\u043D\u043E\u043C +netTabDontServeRequestsCb=\u041D\u0435 \u043E\u0431\u0440\u043E\u0431\u043B\u044F\u0442\u0438 \u0437\u0430\u043F\u0438\u0442\u0438 +netTabDontServeRequestsDescription=\u042F\u043A\u0449\u043E \u0432\u0438\u0431\u0440\u0430\u043D\u043E, \u0442\u043E\u0434\u0456 \u0446\u0435\u0439 \u043A\u043E\u043C\u043F'\u044E\u0442\u0435\u0440 \u043D\u0435 \u0432\u0456\u0434\u043F\u043E\u0432\u0456\u0434\u0430\u0442\u0438\u043C\u0435 \u043D\u0430 \u0437\u0430\u043F\u0438\u0442\u0438 NSP \u0444\u0430\u0439\u043B\u0456\u0432. \u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u043E\u0432\u0443\u0432\u0430\u0442\u0438\u043C\u0443\u0442\u044C\u0441\u044F \u043D\u0430\u043B\u0430\u0448\u0442\u0443\u0432\u0430\u043D\u043D\u044F \u0445\u043E\u0441\u0442\u0430 \u0434\u043B\u044F \u0432\u043A\u0430\u0437\u0430\u043D\u043D\u044F TinFoil \u043C\u0456\u0441\u0446\u044F \u0437\u0432\u0456\u0434\u043A\u0438 \u0444\u0430\u0439\u043B\u0438 \u043C\u0430\u044E\u0442\u044C \u0431\u0440\u0430\u0442\u0438\u0441\u044F. \ No newline at end of file