diff --git a/README.md b/README.md index e35b462..710faef 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Sometimes I add new posts about this project [on my home page](https://developer * Italian by [unbranched](https://github.com/unbranched) * Korean by [DDinghoya](https://github.com/DDinghoya) * Portuguese by [almircanella](https://github.com/almircanella) -* Spanish by [/u/cokimaya007](https://www.reddit.com/u/cokimaya007) +* Spanish by [/u/cokimaya007](https://www.reddit.com/u/cokimaya007), Kuziel Alejandro ### System requirements diff --git a/pom.xml b/pom.xml index e7d571d..9b143f7 100644 --- a/pom.xml +++ b/pom.xml @@ -140,7 +140,7 @@ org.usb4java usb4java - 1.3.0 + 1.2.0 compile diff --git a/src/main/java/nsusbloader/USB/UsbCommunications.java b/src/main/java/nsusbloader/USB/UsbCommunications.java index 0cabb05..de52673 100644 --- a/src/main/java/nsusbloader/USB/UsbCommunications.java +++ b/src/main/java/nsusbloader/USB/UsbCommunications.java @@ -7,7 +7,6 @@ import nsusbloader.NSLDataTypes.EMsgType; import nsusbloader.RainbowHexDump; import org.usb4java.*; -import javax.swing.plaf.synth.SynthEditorPaneUI; import java.io.*; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -440,7 +439,6 @@ public class UsbCommunications extends Task { // CMD private final byte[] CMD_GLCO_SUCCESS = new byte[]{0x47, 0x4c, 0x43, 0x4F, 0x00, 0x00, 0x00, 0x00}; // used @ writeToUsb_GLCMD private final byte[] CMD_GLCO_FAILURE = new byte[]{0x47, 0x4c, 0x43, 0x4F, 0x64, (byte) 0xcb, 0x00, 0x00}; // used @ writeToUsb_GLCMD - private final byte[] CMD_GLCI = new byte[]{0x47, 0x4c, 0x43, 0x49}; // System.out.println((356 & 0x1FF) | ((1 + 100) & 0x1FFF) << 9); // 52068 // 0x00 0x00 0xCB 0x64 private final byte[] GL_OBJ_TYPE_FILE = new byte[]{0x01, 0x00, 0x00, 0x00}; @@ -457,6 +455,9 @@ public class UsbCommunications extends Task { private HashMap writeFilesMap; + private boolean isWindows; + private String homePath; + GoldLeaf(){ final byte CMD_GetDriveCount = 0x00; final byte CMD_GetDriveInfo = 0x01; @@ -475,6 +476,8 @@ public class UsbCommunications extends Task { final byte CMD_SelectFile = 0x0e;//14 // WTF? Ignoring for now. For future: execute another thread within this(?) context for FileChooser final byte CMD_Max = 0x0f;//15 // not used @ NS-UL & GT + final byte[] CMD_GLCI = new byte[]{0x47, 0x4c, 0x43, 0x49}; + logPrinter.print("============= GoldLeaf =============\n\tVIRT:/ equals files added into the application\n\tHOME:/ equals " +System.getProperty("user.home"), EMsgType.INFO); // Let's collect file names to the array to simplify our life @@ -486,6 +489,10 @@ public class UsbCommunications extends Task { status = EFileStatus.UNKNOWN; + isWindows = System.getProperty("os.name").contains("Windows"); + + homePath = System.getProperty("user.home")+File.separator; + // Go parse commands byte[] readByte; int someLength; @@ -715,15 +722,13 @@ public class UsbCommunications extends Task { } else if (path.startsWith("HOME:/")){ // Let's make it normal path - path = path.replaceFirst("HOME:/", System.getProperty("user.home")+File.separator) - .replaceAll("/", File.separator); // HANDLE 'PATH' SEPARATOR FOR WINDOWS + path = updateHomePath(path); // Open it File pathDir = new File(path); // Make sure it's exists and it's path - if ((! pathDir.exists() ) || (! pathDir.isDirectory()) ){ + if ((! pathDir.exists() ) || (! pathDir.isDirectory()) ) return writeGL_FAIL("GL Handle 'GetDirectoryOrFileCount' command [doesn't exist or not a folder]"); - } // Save recent dir path this.recentPath = path; String[] filesOrDirs; @@ -731,20 +736,20 @@ public class UsbCommunications extends Task { if (isGetDirectoryCount){ filesOrDirs = pathDir.list((current, name) -> { File dir = new File(current, name); - return (dir.isDirectory() && ! dir.getName().startsWith(".")); // TODO: FIX FOR WIN ? + return (dir.isDirectory() && ! dir.isHidden()); // TODO: FIX FOR WIN ? }); } else { if (nspFilterForGl){ filesOrDirs = pathDir.list((current, name) -> { File dir = new File(current, name); - return (! dir.isDirectory() && name.endsWith(".nsp")); // TODO: FIX FOR WIN ? + return (! dir.isDirectory() && name.toLowerCase().endsWith(".nsp")); // TODO: FIX FOR WIN ? }); } else { filesOrDirs = pathDir.list((current, name) -> { File dir = new File(current, name); - return (! dir.isDirectory() && (! name.startsWith("."))); // TODO: MOVE TO PROD + return (! dir.isDirectory() && (! dir.isHidden())); // TODO: MOVE TO PROD }); } } @@ -764,7 +769,6 @@ public class UsbCommunications extends Task { this.recentDirs = filesOrDirs; else this.recentFiles = filesOrDirs; - // Otherwise, let's tell how may folders are in there if (writeGL_PASS(intToArrLE(filesOrDirs.length))) { logPrinter.print("GL Handle 'GetDirectoryOrFileCount' command", EMsgType.FAIL); @@ -784,8 +788,7 @@ public class UsbCommunications extends Task { * */ private boolean getDirectory(String dirName, int subDirNo){ if (dirName.startsWith("HOME:/")) { - dirName = dirName.replaceFirst("HOME:/", System.getProperty("user.home")+File.separator) - .replaceAll("/", File.separator); + dirName = updateHomePath(dirName); List command = new LinkedList<>(); @@ -802,7 +805,7 @@ public class UsbCommunications extends Task { // Now collecting every folder or file inside this.recentDirs = pathDir.list((current, name) -> { File dir = new File(current, name); - return (dir.isDirectory() && ! dir.getName().startsWith(".")); // TODO: FIX FOR WIN ? + return (dir.isDirectory() && ! dir.isHidden()); // TODO: FIX FOR WIN ? }); // Check that we still don't have any fuckups if (this.recentDirs != null && this.recentDirs.length > subDirNo){ @@ -836,8 +839,7 @@ public class UsbCommunications extends Task { List command = new LinkedList<>(); if (dirName.startsWith("HOME:/")) { - dirName = dirName.replaceFirst("HOME:/", System.getProperty("user.home")+File.separator) - .replaceAll("/", File.separator); + dirName = updateHomePath(dirName); if (dirName.equals(recentPath) && recentFiles != null && recentFiles.length != 0){ byte[] fileNameBytes = recentFiles[subDirNo].getBytes(StandardCharsets.UTF_8); @@ -855,13 +857,13 @@ public class UsbCommunications extends Task { if (nspFilterForGl){ this.recentFiles = pathDir.list((current, name) -> { File dir = new File(current, name); - return (! dir.isDirectory() && name.endsWith(".nsp")); // TODO: FIX FOR WIN ? MOVE TO PROD + return (! dir.isDirectory() && name.toLowerCase().endsWith(".nsp")); // TODO: FIX FOR WIN ? MOVE TO PROD }); } else { this.recentFiles = pathDir.list((current, name) -> { File dir = new File(current, name); - return (! dir.isDirectory() && (! name.startsWith("."))); // TODO: FIX FOR WIN + return (! dir.isDirectory() && (! dir.isHidden())); // TODO: FIX FOR WIN }); } // Check that we still don't have any fuckups @@ -889,7 +891,6 @@ public class UsbCommunications extends Task { byte[] fileNameBytes = nspMapKeySetIndexes[subDirNo].getBytes(StandardCharsets.UTF_8); command.add(intToArrLE(fileNameBytes.length)); command.add(fileNameBytes); - if (writeGL_PASS(command)) { logPrinter.print("GL Handle 'GetFile' command.", EMsgType.FAIL); return true; @@ -906,13 +907,10 @@ public class UsbCommunications extends Task { * false if everything is ok * */ private boolean statPath(String filePath){ - //System.out.println(filePath+recentDirs[0]); // TODO: DEBUG List command = new LinkedList<>(); if (filePath.startsWith("HOME:/")){ - filePath = filePath.replaceFirst("HOME:/", System.getProperty("user.home")+File.separator) - .replaceAll("/", File.separator); - + filePath = updateHomePath(filePath); if (proxyForGL) return proxyStatPath(filePath); // dirty name @@ -933,7 +931,6 @@ public class UsbCommunications extends Task { } else if (filePath.startsWith("VIRT:/")) { filePath = filePath.replaceFirst("VIRT:/", ""); - if (nspMap.containsKey(filePath)){ command.add(GL_OBJ_TYPE_FILE); // THIS IS INT command.add(longToArrLE(nspMap.get(filePath).length())); // YES, THIS IS LONG! @@ -957,8 +954,9 @@ public class UsbCommunications extends Task { this.recentPath = null; this.recentFiles = null; this.recentDirs = null; - fileName = fileName.replaceFirst("HOME:/", System.getProperty("user.home")+File.separator).replaceAll("/", File.separator); - newFileName = newFileName.replaceFirst("HOME:/", System.getProperty("user.home")+File.separator).replaceAll("/", File.separator); + fileName = updateHomePath(fileName); + newFileName = updateHomePath(newFileName); + File currentFile = new File(fileName); File newFile = new File(newFileName); if (! newFile.exists()){ // Else, report error @@ -984,7 +982,8 @@ public class UsbCommunications extends Task { * */ private boolean delete(String fileName) { if (fileName.startsWith("HOME:/")) { - fileName = fileName.replaceFirst("HOME:/", System.getProperty("user.home")+File.separator).replaceAll("/", File.separator); + fileName = updateHomePath(fileName); + File fileToDel = new File(fileName); try { if (fileToDel.delete()){ @@ -1010,7 +1009,7 @@ public class UsbCommunications extends Task { * */ private boolean create(String fileName, byte type) { if (fileName.startsWith("HOME:/")) { - fileName = fileName.replaceFirst("HOME:/", System.getProperty("user.home")+File.separator).replaceAll("/", File.separator); + fileName = updateHomePath(fileName); File fileToCreate = new File(fileName); boolean result = false; if (type == 1){ @@ -1047,35 +1046,39 @@ public class UsbCommunications extends Task { * false if everything is ok * */ private boolean readFile(String fileName, long offset, long size) { - System.out.println(fileName+" "+offset+" "+size+" "); // TODO: DEBUG if (fileName.startsWith("VIRT:/")){ // Let's find out which file requested String fNamePath = nspMap.get(fileName.substring(6)).getAbsolutePath(); // NOTE: 6 = "VIRT:/".length // If we don't have this file opened, let's open it if (openReadFileNameAndPath == null || (! openReadFileNameAndPath.equals(fNamePath))) { // Try close what opened - try{ - randAccessFile.close(); - }catch (IOException ignored){} + if (openReadFileNameAndPath != null){ + try{ + randAccessFile.close(); + }catch (IOException ignored){} + } + // Open what has to be opened try{ randAccessFile = new RandomAccessFile(nspMap.get(fileName.substring(6)), "r"); openReadFileNameAndPath = fNamePath; } - catch (IOException ioe){ // TODO: MOVE THIS SHIT TO METHOD ALREADY! + catch (IOException ioe){ return writeGL_FAIL("GL Handle 'ReadFile' command\n\t"+ioe.getMessage()); } } } else { // Let's find out which file requested - fileName = fileName.replaceFirst("HOME:/", System.getProperty("user.home")+File.separator) - .replaceAll("/", File.separator); - // Try close what opened - try{ - randAccessFile.close(); - }catch (IOException ignored){} + fileName = updateHomePath(fileName); // If we don't have this file opened, let's open it if (openReadFileNameAndPath == null || (! openReadFileNameAndPath.equals(fileName))) { + // Try close what opened + if (openReadFileNameAndPath != null){ + try{ + randAccessFile.close(); + }catch (IOException ignored){} + } + // Open what has to be opened try{ randAccessFile = new RandomAccessFile(fileName, "r"); openReadFileNameAndPath = fileName; @@ -1090,27 +1093,30 @@ public class UsbCommunications extends Task { byte[] chunk = new byte[(int)size]; // WTF MAN? // Let's find out how much bytes we got int bytesRead = randAccessFile.read(chunk); + // Let's check that we read expected size + if (bytesRead != (int)size) + return writeGL_FAIL("GL Handle 'ReadFile' command [CMD] Requested = "+size+" Read from file = "+bytesRead); // Let's tell as a command about our result. - if (writeGL_PASS(intToArrLE(bytesRead))) { - logPrinter.print("GL Handle 'ReadFile' command [1/?]", EMsgType.FAIL); + if (writeGL_PASS(longToArrLE(size))) { + logPrinter.print("GL Handle 'ReadFile' command [CMD]", EMsgType.FAIL); return true; } if (bytesRead > 8388608){ // Let's bypass bytes we read part 1 if (writeToUsb(Arrays.copyOfRange(chunk, 0, 8388608))) { - logPrinter.print("GL Handle 'ReadFile' command [2/3]", EMsgType.FAIL); + logPrinter.print("GL Handle 'ReadFile' command [Data 1/2]", EMsgType.FAIL); return true; } // Let's bypass bytes we read part 2 if (writeToUsb(Arrays.copyOfRange(chunk, 8388608, chunk.length))) { - logPrinter.print("GL Handle 'ReadFile' command [2/3]", EMsgType.FAIL); + logPrinter.print("GL Handle 'ReadFile' command [Data 2/2]", EMsgType.FAIL); return true; } return false; } // Let's bypass bytes we read total if (writeToUsb(chunk)) { - logPrinter.print("GL Handle 'ReadFile' command [2/2]", EMsgType.FAIL); + logPrinter.print("GL Handle 'ReadFile' command [Data 1/1]", EMsgType.FAIL); return true; } return false; @@ -1144,8 +1150,7 @@ public class UsbCommunications extends Task { return true; } - fileName = fileName.replaceFirst("HOME:/", System.getProperty("user.home")+File.separator) - .replaceAll("/", File.separator); + fileName = updateHomePath(fileName); // Check if we didn't see this (or any) file during this session if (writeFilesMap.size() == 0 || (! writeFilesMap.containsKey(fileName))){ // Open what we have to open @@ -1174,7 +1179,6 @@ public class UsbCommunications extends Task { catch (IOException ioe){ return writeGL_FAIL("GL Handle 'WriteFile' command [1/1]\n\t"+ioe.getMessage()); } - System.out.println("READ COMLETE"); // Report we're good if (writeGL_PASS()) { logPrinter.print("GL Handle 'WriteFile' command", EMsgType.FAIL); @@ -1259,7 +1263,15 @@ public class UsbCommunications extends Task { /*----------------------------------------------------*/ /* GL HELPERS */ /*----------------------------------------------------*/ - + /** + * Convert path received from GL to normal + */ + private String updateHomePath(String glPath){ + if (isWindows) + glPath = glPath.replaceAll("/", "\\\\"); + glPath = homePath+glPath.substring(6); // Do not use replaceAll since it will consider \ as special directive + return glPath; + } /** * Convert INT (Little endian) value to bytes-array representation * */ @@ -1444,7 +1456,7 @@ public class UsbCommunications extends Task { * */ private byte[] readFromUsb(){ ByteBuffer readBuffer = ByteBuffer.allocateDirect(512); - // We can limit it to 32 bytes, but there is a non-zero chance to got OVERFLOW from libusb. + // We can limit it to 32 bytes, but there is a non-zero chance to got OVERFLOW from libusb. IntBuffer readBufTransferred = IntBuffer.allocate(1); int result; diff --git a/src/main/resources/locale_fra.properties b/src/main/resources/locale_fra.properties index 1c31c79..f64cbf6 100644 --- a/src/main/resources/locale_fra.properties +++ b/src/main/resources/locale_fra.properties @@ -1,7 +1,7 @@ btnFileOpen=Selectionner les fichiers .NSP btnUpload=Envoyer vers NS logsEnteredAsMsg1=Vous etes connect\u00E9 en tant que: -logsEnteredAsMsg2=Vous devez \u00EAtre administrateur ou avoir configur\u00E9 les r\u00E8gles 'udev' pour cet utilisateur afin d'\u00E9viter tout probl\u00E8me. +logsEnteredAsMsg2=Vous devez \u00EAtre root ou avoir configur\u00E9 les r\u00E8gles 'udev' pour cet utilisateur afin d'\u00E9viter tout probl\u00E8me. logsFilesToUploadTitle=Fichiers a envoyer: logsGreetingsMessage=Bienvenue sur NS-USBloader logsNoFolderFileSelected=Aucuns fichiers s\u00E9lectionn\u00E9s: Rien a envoyer. diff --git a/src/main/resources/locale_spa.properties b/src/main/resources/locale_spa.properties index 9ce2907..b4dd0b7 100644 --- a/src/main/resources/locale_spa.properties +++ b/src/main/resources/locale_spa.properties @@ -1,11 +1,11 @@ -btnFileOpen=Seleccione los archivos .NSP +btnFileOpen=Seleccionar los archivos .NSP btnUpload=Enviar a NS logsEnteredAsMsg1=Est\u00E1 conectado como: logsEnteredAsMsg2=Deber\u00EDa ser root o haber configurado las reglas 'udev' de este usuario para evitar problemas. logsFilesToUploadTitle=Archivos a subir: logsGreetingsMessage=Bienvenido a NS-USBloader -logsNoFolderFileSelected=No ha seleccionado ning\u00FAn archivo: nada se enviar\u00E1. -windowBodyConfirmExit=Transferencia de datos en progreso, cerrar la aplicaci\u00F3n lo interrumpir\u00E1.\nEs lo peor que puede hacer en este momento.\nInterrumpir proceso y salir? +logsNoFolderFileSelected=No ha seleccionado ning\u00FAn archivo: Nada se subir\u00E1. +windowBodyConfirmExit=Transferencia de datos en progreso, cerrar la aplicaci\u00F3n lo interrumpir\u00E1.\nNo se recomienda.\nInterrumpir proceso y salir? windowTitleConfirmExit=No, no haga esto! btnStop=Interrumpir logsGreetingsMessage2=--\n\ @@ -13,7 +13,7 @@ Source: https://github.com/developersu/ns-usbloader/\n\ Site: https://developersu.blogspot.com/search/label/NS-USBloader\n\ Dmitry Isaenko [developer.su] windowTitleConfirmWrongPFS0=Tipo de archivo incorrecto -windowBodyConfirmWrongPFS0=El archivo NSP seleccionado tiene car\u00E1cteres no v\u00E1lidos o esta corrupto.\n\ +windowBodyConfirmWrongPFS0=El archivo NSP seleccionado tiene car\u00E1cteres no v\u00E1lidos o est\u00E1 corrupto.\n\ Se recomienda interrumpir el proceso. Continuar de todas formas? tableStatusLbl=Estado tableFileNameLbl=Nombre del archivo @@ -23,25 +23,26 @@ contextMenuBtnDelete=Eliminar contextMenuBtnDeleteAll=Eliminar todo netTabHostIPLbl=IP del host NSIPlable=NS IP: -netTabValidateNSHostNameCb=Valida siempre la entrada de IP de la NS. +netTabValidateNSHostNameCb=Validar siempre la entrada de IP de la NS. windowBodyBadIp=Est\u00E1 seguro de que ha introducido la IP de la NS correctamente? windowTitleBadIp=Es posible que la direcci\u00F3n IP de la NS sea incorrecta netTabExpertModeCb=Modo Experto netTabHostPortLbl=Puerto -netTabAutoDetectIpCb=Detecta IP autom\u00E1ticamente -netTabRandSelectPortCb=Obt\u00E9n el puerto autom\u00E1ticamente -netTabDontServeRequestsCb=No contestar solicitud -netTabDontServeRequestsDescription=Si selecciona la opci\u00F3n, el ordenador no responder\u00E1 solicitudes de archivos NSP de la NS (en la red), y usar\u00E1 las configuraciones definidas por el host para comunicar a Tinfoil donde encontrar los archivos +netTabAutoDetectIpCb=Detectar IP autom\u00E1ticamente +netTabRandSelectPortCb=Obtener el puerto autom\u00E1ticamente +netTabDontServeRequestsCb=No contestar solicitudes +netTabDontServeRequestsDescription=Si habilita esta opci\u00F3n, el ordenador no responder\u00E1 solicitudes de archivos NSP de la NS (en la red), y usar\u00E1 las configuraciones definidas por el host para indicar a Tinfoil donde se encuentran los archivos netTabHostExtraLbl=Extra windowTitleErrorPort=Puerto asignado incorrectamente! windowBodyErrorPort=El puerto no puede ser 0 o mayor que 65535 -netTabAutoCheckForUpdates=Compruebe actualizaciones autom\u00E1ticamente +netTabAutoCheckForUpdates=Comprobar actualizaciones autom\u00E1ticamente windowTitleNewVersionAval=Actualizaci\u00F3n disponible windowTitleNewVersionNOTAval=No hay actualizaciones disponibles windowTitleNewVersionUnknown=No fue posible encontrar actualizaciones -windowBodyNewVersionUnknown=Algo fall\u00F3\nLa conexi\u00F3n a internet no funciona, o GitHub est\u00E1 ca\u00EDdo +windowBodyNewVersionUnknown=Algo fall\u00F3\nLa conexi\u00F3n a internet no funciona correctamente, o GitHub est\u00E1 ca\u00EDdo windowBodyNewVersionNOTAval=Est\u00E1s usando la \u00FAltima versi\u00F3n netTabAllowXciCb=Permite la selecci\u00F3n de archivos XCI para Tinfoil -netTabAllowXciTextField=Usado por algunas aplicaciones de terceros que soportan XCI y que utilizan el protocolo de transferencia de Tinfoil. Si no est\u00E1 seguro no cambie esto. +netTabAllowXciTextField=Usado por algunas aplicaciones de terceros que soportan XCI y que utilizan el protocolo de transferencia de Tinfoil. Si no est\u00E1 seguro no cambie la opci\u00F3n. netTabLanguage=Idioma -windowBodyRestartToApplyLang=Por favor, reinicie el programa para aplicar los cambios. \ No newline at end of file +windowBodyRestartToApplyLang=Por favor, reinicie el programa para aplicar los cambios. +netTabGLshowNSPonly=Mostrar solo *.nsp en GoldLeaf.