From 856765011ccb6b093e5b605034a51a2bb233de47 Mon Sep 17 00:00:00 2001 From: Honfika Date: Mon, 24 Feb 2014 23:09:19 +0100 Subject: [PATCH] Issue #513: command line option to extract swf from binary file --- .../console/CommandLineArgumentParser.java | 82 +++++++++++++++++-- .../decompiler/flash/console/ExtractMode.java | 26 ++++++ 2 files changed, 102 insertions(+), 6 deletions(-) create mode 100644 trunk/src/com/jpexs/decompiler/flash/console/ExtractMode.java diff --git a/trunk/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java b/trunk/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java index 9bbb9d5ef..94ab90d4c 100644 --- a/trunk/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java +++ b/trunk/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler; import com.jpexs.decompiler.flash.ApplicationInfo; import com.jpexs.decompiler.flash.EventListener; import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFBundle; import com.jpexs.decompiler.flash.SWFSourceInfo; import com.jpexs.decompiler.flash.abc.RenameType; import com.jpexs.decompiler.flash.configuration.Configuration; @@ -28,6 +29,7 @@ import com.jpexs.decompiler.flash.gui.Main; import com.jpexs.decompiler.flash.xfl.FLAVersion; import com.jpexs.decompiler.graph.ExportMode; import com.jpexs.helpers.Helper; +import com.jpexs.helpers.streams.SeekableInputStream; import com.sun.jna.Platform; import com.sun.jna.platform.win32.Kernel32; import java.io.BufferedInputStream; @@ -120,9 +122,11 @@ public class CommandLineArgumentParser { System.out.println(" ...Compress SWF and save it to "); System.out.println(" 8) -decompress "); System.out.println(" ...Decompress and save it to "); - System.out.println(" 9) -renameInvalidIdentifiers (typeNumber|randomWord) e"); + System.out.println(" 9) -extract [(all|biggest)]"); + System.out.println(" ...Extracts SWF files from ZIP or other binary files"); + System.out.println(" 10) -renameInvalidIdentifiers (typeNumber|randomWord) e"); System.out.println(" ...Renames the invalid identifiers in and save it to "); - System.out.println(" 10) -config key=value[,key2=value2][,key3=value3...] [other parameters]"); + System.out.println(" 11) -config key=value[,key2=value2][,key3=value3...] [other parameters]"); System.out.print(" ...Sets configuration values. Available keys[current setting]:"); for (ConfigurationItem item : commandlineConfigBoolean) { System.out.print(" " + item + "[" + item.get() + "]"); @@ -131,13 +135,13 @@ public class CommandLineArgumentParser { System.out.println(" Values are boolean, you can use 0/1, true/false, on/off or yes/no."); System.out.println(" If no other parameters passed, configuration is saved. Otherwise it is used only once."); System.out.println(" DO NOT PUT space between comma (,) and next value."); - System.out.println(" 11) -onerror (abort|retryN|ignore)"); + System.out.println(" 12) -onerror (abort|retryN|ignore)"); System.out.println(" ...error handling mode. \"abort\" stops the exporting, \"retry\" tries the exporting N times, \"ignore\" ignores the current file"); - System.out.println(" 12) -timeout "); + System.out.println(" 13) -timeout "); System.out.println(" ...decompilation timeout for a single method in AS3 or single action in AS1/2 in seconds"); - System.out.println(" 13) -exportTimeout "); + System.out.println(" 14) -exportTimeout "); System.out.println(" ...total export timeout in seconds"); - System.out.println(" 14) -exportFileTimeout "); + System.out.println(" 15) -exportFileTimeout "); System.out.println(" ...export timeout for a single AS3 class in seconds"); System.out.println(); System.out.println("Examples:"); @@ -236,6 +240,8 @@ public class CommandLineArgumentParser { parseCompress(args); } else if (nextParam.equals("-decompress")) { parseDecompress(args); + } else if (nextParam.equals("-extract")) { + parseExtract(args); } else if (nextParam.equals("-renameinvalididentifiers")) { parseRenameInvalidIdentifiers(args); } else if (nextParam.equals("-dumpswf")) { @@ -742,6 +748,70 @@ public class CommandLineArgumentParser { System.exit(0); } + private static void parseExtract(Queue args) { + if (args.size() < 1) { + badArguments(); + } + + String fileName = args.remove(); + ExtractMode mode = ExtractMode.ALL; + if (args.size() > 0) { + String modeStr = args.remove().toLowerCase(); + switch (modeStr) { + case "biggest": + mode = ExtractMode.BIGGEST; + break; + } + } + + try { + SWFSourceInfo sourceInfo = new SWFSourceInfo(null, fileName, null); + if (!sourceInfo.isBundle()) { + System.err.println("Error: should be a bundle. (ZIP or non SWF binary file)"); + System.exit(1); + } + SWFBundle bundle = sourceInfo.getBundle(); + List> streamsToExtract = new ArrayList<>(); + Map.Entry biggest = null; + int biggestSize = 0; + for (Map.Entry streamEntry : bundle.getAll().entrySet()) { + InputStream stream = streamEntry.getValue(); + stream.reset(); + switch (mode) { + case ALL: + streamsToExtract.add(streamEntry); + break; + case BIGGEST: + byte[] swfData = new byte[stream.available()]; + int available = stream.read(swfData); // stream.available() reports wrong value + if (available > biggestSize) { + biggest = streamEntry; + biggestSize = available; + } + break; + } + } + + if (mode == ExtractMode.BIGGEST && biggest != null) { + streamsToExtract.add(biggest); + } + + for (Map.Entry streamEntry : streamsToExtract) { + InputStream stream = streamEntry.getValue(); + stream.reset(); + try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(streamEntry.getKey() + ".swf"))) { + byte[] swfData = new byte[stream.available()]; + int cnt = stream.read(swfData); + fos.write(swfData, 0, cnt); + } + } + } catch (IOException ex) { + Logger.getLogger(CommandLineArgumentParser.class.getName()).log(Level.SEVERE, null, ex); + } + + System.exit(0); + } + private static void parseRenameInvalidIdentifiers(Queue args) { if (args.size() < 3) { badArguments(); diff --git a/trunk/src/com/jpexs/decompiler/flash/console/ExtractMode.java b/trunk/src/com/jpexs/decompiler/flash/console/ExtractMode.java new file mode 100644 index 000000000..fd1ccfd88 --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/console/ExtractMode.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2010-2014 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; + +/** + * + * @author JPEXS + */ +public enum ExtractMode { + + ALL, BIGGEST +}