diff --git a/CHANGELOG.md b/CHANGELOG.md index bc1e1dea7..7ce6ef519 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file. - [#1649] Moving SWF files (and bundles) up and down (comtext menuitem + ALT up/down shortcut) - Moving tags up and down in the taglist view (context menuitem + ALT up/down shortcut) - [#1701] Setting charset for SWF files with version 5 or lower +- [#1864] Commandline: Allow to set special value "/dev/stdin" for input files to read from stdin (even on Windows) ### Fixed - Exception when bundle selected @@ -2544,6 +2545,7 @@ All notable changes to this project will be documented in this file. [alpha 7]: https://github.com/jindrapetrik/jpexs-decompiler/releases/tag/alpha7 [#1649]: https://www.free-decompiler.com/flash/issues/1649 [#1701]: https://www.free-decompiler.com/flash/issues/1701 +[#1864]: https://www.free-decompiler.com/flash/issues/1864 [#1863]: https://www.free-decompiler.com/flash/issues/1863 [#1414]: https://www.free-decompiler.com/flash/issues/1414 [#1755]: https://www.free-decompiler.com/flash/issues/1755 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/SwfXmlImporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/SwfXmlImporter.java index d89006c8a..4a80d3ad8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/SwfXmlImporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/SwfXmlImporter.java @@ -116,6 +116,7 @@ import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; import java.io.Reader; import java.io.StringReader; import java.lang.reflect.Array; @@ -208,11 +209,11 @@ public class SwfXmlImporter { return cls != null && (cls.isArray() || List.class.isAssignableFrom(cls)); } - public void importSwf(SWF swf, File inFile) throws IOException { + public void importSwf(SWF swf, InputStream in) throws IOException { XMLInputFactory xmlFactory = XMLInputFactory.newInstance(); try { - try(Reader reader = new Utf8InputStreamReader(new BufferedInputStream(new FileInputStream(inFile)))) { + try(Reader reader = new Utf8InputStreamReader(new BufferedInputStream(in))) { XMLStreamReader xmlReader = xmlFactory.createXMLStreamReader(reader); xmlReader.nextTag(); diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/SwfXmlExportImportTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/SwfXmlExportImportTest.java index 4c0dfefaa..7a2c91e33 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/SwfXmlExportImportTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/SwfXmlExportImportTest.java @@ -97,7 +97,9 @@ public class SwfXmlExportImportTest extends FileTestBase { new SwfXmlExporter().exportXml(swf, outFile); SWF swf2 = new SWF(); - new SwfXmlImporter().importSwf(swf2, outFile); + try (FileInputStream fis = new FileInputStream(outFile)) { + new SwfXmlImporter().importSwf(swf2, fis); + } if (swf.getTags().size() != swf2.getTags().size()) { throw new NotSameException(0); diff --git a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java index a106191a6..ccca2b193 100644 --- a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java +++ b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java @@ -667,6 +667,8 @@ public class CommandLineArgumentParser { } printCmdLineUsageExamples(out, filter); + + System.out.println("You can use special value \"/dev/stdin\" for input files to read data from standard input (even on Windows)"); } private static void printCmdLineUsageExamples(PrintStream out, String filter) { @@ -760,13 +762,13 @@ public class CommandLineArgumentParser { if (filter == null || filter.equals("swf2exe")) { out.println(PREFIX + "-swf2exe wrapper result.exe myfile.swf"); } - + if (!exampleFound) { out.println("Sorry, no example found for command " + filter + ", Let us know in issue tracker when you need it."); } out.println(); - out.println("Instead of \"java -jar ffdec.jar\" you can use ffdec.bat on Windows, ffdec.sh on Linux/MacOs"); + out.println("Instead of \"java -jar ffdec.jar\" you can use ffdec.bat on Windows, ffdec.sh on Linux/MacOs"); } /** @@ -2155,8 +2157,9 @@ public class CommandLineArgumentParser { long startTime = System.currentTimeMillis(); File outDirBase = new File(args.pop()); - File inFileOrFolder = new File(args.pop()); - if (!inFileOrFolder.exists()) { + String inFileOrFolderStr = args.pop(); + File inFileOrFolder = new File(inFileOrFolderStr); + if (!StdInAwareFileInputStream.STDIN_PATH.equals(inFileOrFolderStr) && !inFileOrFolder.exists()) { System.err.println("Input SWF file does not exist!"); badArguments("export"); } @@ -2210,7 +2213,7 @@ public class CommandLineArgumentParser { SWFSourceInfo sourceInfo = new SWFSourceInfo(null, inFile.getAbsolutePath(), inFile.getName()); SWF swf; try { - swf = new SWF(new FileInputStream(inFile), sourceInfo.getFile(), sourceInfo.getFileTitle(), Configuration.parallelSpeedUp.get()); + swf = new SWF(new StdInAwareFileInputStream(inFile), sourceInfo.getFile(), sourceInfo.getFileTitle(), Configuration.parallelSpeedUp.get()); } catch (FileNotFoundException | SwfOpenException ex) { // FileNotFoundException when anti virus software blocks to open the file logger.log(Level.SEVERE, "Failed to open swf: " + inFile.getName(), ex); @@ -2506,7 +2509,7 @@ public class CommandLineArgumentParser { System.exit(1); } } - try (FileInputStream is = new FileInputStream(inFile); + try (StdInAwareFileInputStream is = new StdInAwareFileInputStream(inFile); FileOutputStream fos = new FileOutputStream(outFile)) { SWF swf = new SWF(is, Configuration.parallelSpeedUp.get()); if (!swf.isAS3()) { @@ -2562,7 +2565,7 @@ public class CommandLineArgumentParser { } } - try (InputStream fis = new BufferedInputStream(new FileInputStream(args.pop())); + try (InputStream fis = new BufferedInputStream(new StdInAwareFileInputStream(args.pop())); OutputStream fos = new BufferedOutputStream(new FileOutputStream(args.pop()))) { result = SWF.compress(fis, fos, compression); System.out.println(result ? "OK" : "FAIL"); @@ -2584,7 +2587,7 @@ public class CommandLineArgumentParser { boolean result = false; try { - try (InputStream fis = new BufferedInputStream(new FileInputStream(args.pop())); + try (InputStream fis = new BufferedInputStream(new StdInAwareFileInputStream(args.pop())); OutputStream fos = new BufferedOutputStream(new FileOutputStream(args.pop()))) { result = SWF.decompress(fis, fos); System.out.println(result ? "OK" : "FAIL"); @@ -2605,7 +2608,7 @@ public class CommandLineArgumentParser { } try { - try (FileInputStream is = new FileInputStream(args.pop())) { + try (StdInAwareFileInputStream is = new StdInAwareFileInputStream(args.pop())) { SWF swf = new SWF(is, Configuration.parallelSpeedUp.get()); new SwfXmlExporter().exportXml(swf, new File(args.pop())); } catch (FileNotFoundException ex) { @@ -2627,9 +2630,10 @@ public class CommandLineArgumentParser { } try { - File inFile = new File(args.pop()); SWF swf = new SWF(); - new SwfXmlImporter().importSwf(swf, inFile); + try (StdInAwareFileInputStream in = new StdInAwareFileInputStream(args.pop())) { + new SwfXmlImporter().importSwf(swf, in); + } try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(new File(args.pop())))) { swf.saveTo(fos); } @@ -2834,7 +2838,7 @@ public class CommandLineArgumentParser { boolean result = false; try { - try (InputStream fis = new BufferedInputStream(new FileInputStream(args.pop())); + try (InputStream fis = new BufferedInputStream(new StdInAwareFileInputStream(args.pop())); OutputStream fos = new BufferedOutputStream(new FileOutputStream(args.pop()))) { result = SWF.renameInvalidIdentifiers(renameType, fis, fos); System.out.println(result ? "OK" : "FAIL"); @@ -2879,7 +2883,7 @@ public class CommandLineArgumentParser { File outFile = new File(args.pop()); printHeader(); - try (FileInputStream is = new FileInputStream(inFile)) { + try (StdInAwareFileInputStream is = new StdInAwareFileInputStream(inFile)) { PDFJob job = null; @@ -2976,7 +2980,7 @@ public class CommandLineArgumentParser { } try { - try (FileInputStream is = new FileInputStream(inFile)) { + try (StdInAwareFileInputStream is = new StdInAwareFileInputStream(inFile)) { SWF swf = new SWF(is, Configuration.parallelSpeedUp.get()); while (true) { String objectToReplace = args.pop(); @@ -3149,7 +3153,7 @@ public class CommandLineArgumentParser { File inFile = new File(args.pop()); File outFile = new File(args.pop()); try { - try (FileInputStream is = new FileInputStream(inFile)) { + try (StdInAwareFileInputStream is = new StdInAwareFileInputStream(inFile)) { SWF swf = new SWF(is, Configuration.parallelSpeedUp.get()); while (true) { String objectToReplace = args.pop(); @@ -3205,7 +3209,7 @@ public class CommandLineArgumentParser { File inFile = new File(args.pop()); File outFile = new File(args.pop()); try { - try (FileInputStream is = new FileInputStream(inFile)) { + try (StdInAwareFileInputStream is = new StdInAwareFileInputStream(inFile)) { SWF swf = new SWF(is, Configuration.parallelSpeedUp.get()); while (true) { String objectToReplace = args.pop(); @@ -3267,7 +3271,7 @@ public class CommandLineArgumentParser { File inFile = new File(args.pop()); File outFile = new File(args.pop()); try { - try (FileInputStream is = new FileInputStream(inFile)) { + try (StdInAwareFileInputStream is = new StdInAwareFileInputStream(inFile)) { SWF swf = new SWF(is, Configuration.parallelSpeedUp.get()); String arg = args.pop().toLowerCase(Locale.ENGLISH); if (arg.equals("pack")) { @@ -3323,7 +3327,7 @@ public class CommandLineArgumentParser { File inFile = new File(args.pop()); File outFile = new File(args.pop()); try { - try (FileInputStream is = new FileInputStream(inFile)) { + try (StdInAwareFileInputStream is = new StdInAwareFileInputStream(inFile)) { SWF swf = new SWF(is, Configuration.parallelSpeedUp.get()); String objectToConvert = args.pop(); @@ -3390,7 +3394,7 @@ public class CommandLineArgumentParser { File inFile = new File(args.pop()); File outFile = new File(args.pop()); try { - try (FileInputStream is = new FileInputStream(inFile)) { + try (StdInAwareFileInputStream is = new StdInAwareFileInputStream(inFile)) { SWF swf = new SWF(is, Configuration.parallelSpeedUp.get()); List tagNumbersToRemove = new ArrayList<>(); while (true) { @@ -3521,7 +3525,7 @@ public class CommandLineArgumentParser { File inFile = new File(args.pop()); File outFile = new File(args.pop()); try { - try (FileInputStream is = new FileInputStream(inFile)) { + try (StdInAwareFileInputStream is = new StdInAwareFileInputStream(inFile)) { SWF swf = new SWF(is, Configuration.parallelSpeedUp.get()); while (true) { String objectToRemove = args.pop(); @@ -3576,7 +3580,7 @@ public class CommandLineArgumentParser { File inFile = new File(args.pop()); File outFile = new File(args.pop()); try { - try (FileInputStream is = new FileInputStream(inFile)) { + try (StdInAwareFileInputStream is = new StdInAwareFileInputStream(inFile)) { SWF swf = new SWF(is, Configuration.parallelSpeedUp.get()); String scriptsFolder = Path.combine(args.pop(), ScriptExportSettings.EXPORT_FOLDER_NAME); new AS2ScriptImporter().importScripts(scriptsFolder, swf.getASMs(true)); @@ -3817,7 +3821,7 @@ public class CommandLineArgumentParser { System.err.println("No SWFs found in \"" + file + "\""); } } else { - FileInputStream fis = new FileInputStream(file); + StdInAwareFileInputStream fis = new StdInAwareFileInputStream(file); BufferedInputStream inputStream = new BufferedInputStream(fis); InputStream fInputStream = inputStream; @@ -3950,7 +3954,7 @@ public class CommandLineArgumentParser { } File file = new File(args.pop()); try { - try (FileInputStream is = new FileInputStream(file)) { + try (StdInAwareFileInputStream is = new StdInAwareFileInputStream(file)) { SWF swf = new SWF(is, Configuration.parallelSpeedUp.get()); Map asms = swf.getASMs(false); for (String as2 : asms.keySet()) { @@ -3996,7 +4000,7 @@ public class CommandLineArgumentParser { String outfile = args.pop(); try { System.out.print("Working..."); - FileInputStream fis = new FileInputStream(file); + StdInAwareFileInputStream fis = new StdInAwareFileInputStream(file); SWF swf = new SWF(fis, Configuration.parallelSpeedUp.get()); fis.close(); if (swf.isAS3()) { @@ -4009,7 +4013,7 @@ public class CommandLineArgumentParser { fos.close(); if (!swf.isAS3()) { if (generateSwd) { - fis = new FileInputStream(outfile); + fis = new StdInAwareFileInputStream(outfile); swf = new SWF(fis, Configuration.parallelSpeedUp.get()); fis.close(); String outSwd = outfile; @@ -4051,7 +4055,7 @@ public class CommandLineArgumentParser { } File file = new File(args.pop()); try { - try (FileInputStream is = new FileInputStream(file)) { + try (StdInAwareFileInputStream is = new StdInAwareFileInputStream(file)) { SWF swf = new SWF(is, Configuration.parallelSpeedUp.get()); List packs = swf.getAS3Packs(); for (ScriptPack entry : packs) { @@ -4101,7 +4105,7 @@ public class CommandLineArgumentParser { stdout = System.out; } - try (FileInputStream is = new FileInputStream(inFile)) { + try (StdInAwareFileInputStream is = new StdInAwareFileInputStream(inFile)) { SWF swf = new SWF(is, Configuration.parallelSpeedUp.get()); action.swfAction(swf, stdout); } catch (FileNotFoundException ex) { @@ -4153,7 +4157,7 @@ public class CommandLineArgumentParser { System.exit(1); } } - try (FileInputStream is = new FileInputStream(inFile); + try (StdInAwareFileInputStream is = new StdInAwareFileInputStream(inFile); FileOutputStream fos = new FileOutputStream(outFile)) { SWF swf = new SWF(is, Configuration.parallelSpeedUp.get()); action.swfAction(swf, stdout); diff --git a/src/com/jpexs/decompiler/flash/console/StdInAwareFileInputStream.java b/src/com/jpexs/decompiler/flash/console/StdInAwareFileInputStream.java new file mode 100644 index 000000000..bffd0cef0 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/console/StdInAwareFileInputStream.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2022 JPEXS + * + * This program 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. + * + * This program 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 this program. If not, see . + */ +package com.jpexs.decompiler.flash.console; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +/** + * FileInputStream to which can be passed /dev/stdin as special file for stdin on Windows. + * On linux, standard /dev/stdin is used. + * @author JPEXS + */ +public class StdInAwareFileInputStream extends InputStream implements AutoCloseable { + + public static final String STDIN_PATH = "/dev/stdin"; + + private InputStream is; + + public StdInAwareFileInputStream(File file) throws FileNotFoundException { + String absPath = file.getPath().replace("\\", "/"); + if (absPath.equals(STDIN_PATH) && !file.exists()) { + is = System.in; + } else { + is = new FileInputStream(file); + } + } + + public StdInAwareFileInputStream(String file) throws FileNotFoundException { + this(new File(file)); + } + + @Override + public int read() throws IOException { + return is.read(); + } + + @Override + public int available() throws IOException { + return is.available(); + } + + @Override + public long skip(long n) throws IOException { + return is.skip(n); + } + + @Override + public synchronized void reset() throws IOException { + is.reset(); + } + + @Override + public void close() throws IOException { + is.close(); + } +} diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 6fcf14a61..0cff896de 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -3222,7 +3222,9 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se if (selectedFile != null) { File selfile = Helper.fixDialogFile(selectedFile); try { - new SwfXmlImporter().importSwf(swf, selfile); + try ( FileInputStream fis = new FileInputStream(selfile)) { + new SwfXmlImporter().importSwf(swf, fis); + } swf.clearAllCache(); swf.assignExportNamesToSymbols(); swf.assignClassesToSymbols();