mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-27 01:00:46 +00:00
swf extracting fixed
This commit is contained in:
@@ -33,8 +33,8 @@ public class BinarySWFBundle implements SWFBundle {
|
||||
|
||||
private final SWFSearch search;
|
||||
|
||||
public BinarySWFBundle(InputStream is, boolean noCheck) {
|
||||
search = new SWFSearch(new StreamSearch(is), noCheck);
|
||||
public BinarySWFBundle(InputStream is, boolean noCheck, SearchMode searchMode) {
|
||||
search = new SWFSearch(new StreamSearch(is), noCheck, searchMode);
|
||||
search.process();
|
||||
}
|
||||
|
||||
|
||||
@@ -413,6 +413,10 @@ public final class SWF implements TreeItem {
|
||||
frameRate = sis.readUI8();
|
||||
frameCount = sis.readUI16();
|
||||
if (skipTagReading) {
|
||||
long toRead = fileSize - sis.getPos();
|
||||
if (toRead > 0) {
|
||||
sis.readBytes(toRead);
|
||||
}
|
||||
return;
|
||||
}
|
||||
tags = sis.readTagList(this, 0, parallelRead, true, !checkOnly, gfx);
|
||||
|
||||
@@ -35,13 +35,15 @@ public class SWFSearch {
|
||||
|
||||
protected Searchable s;
|
||||
private final boolean noCheck;
|
||||
private final SearchMode searchMode;
|
||||
private boolean processed = false;
|
||||
private final Set<ProgressListener> listeners = new HashSet<>();
|
||||
private final Map<Long, MemoryInputStream> swfStreams = new HashMap<>();
|
||||
|
||||
public SWFSearch(Searchable s, boolean noCheck) {
|
||||
public SWFSearch(Searchable s, boolean noCheck, SearchMode searchMode) {
|
||||
this.s = s;
|
||||
this.noCheck = noCheck;
|
||||
this.searchMode = searchMode;
|
||||
}
|
||||
|
||||
public void addProgressListener(ProgressListener l) {
|
||||
@@ -72,6 +74,7 @@ public class SWFSearch {
|
||||
"GFX".getBytes(), //Uncompressed ScaleForm GFx
|
||||
"CFX".getBytes()); //Compressed ScaleForm GFx
|
||||
int pos = 0;
|
||||
long biggestSize = 0;
|
||||
for (Long addr : ret.keySet()) {
|
||||
setProgress(pos * 100 / ret.size());
|
||||
pos++;
|
||||
@@ -80,17 +83,29 @@ public class SWFSearch {
|
||||
mis.reset();
|
||||
PosMarkedInputStream pmi = new PosMarkedInputStream(mis);
|
||||
SWF swf = new SWF(pmi, null, false, true, noCheck);
|
||||
long limit = pmi.getPos();
|
||||
MemoryInputStream is = new MemoryInputStream(mis.getAllRead(), (int) (long) addr, (int) limit);
|
||||
if (swf.fileSize > 0 && swf.version > 0 && !swf.tags.isEmpty() && swf.version < 25/*Needs to be fixed when SWF versions reaches this value*/) {
|
||||
swfStreams.put(addr, is);
|
||||
boolean valid = swf.fileSize > 0
|
||||
&& swf.version > 0
|
||||
&& (!swf.tags.isEmpty() || noCheck)
|
||||
&& swf.version < 25; // Needs to be fixed when SWF versions reaches this value
|
||||
if (valid) {
|
||||
long limit = pmi.getPos();
|
||||
MemoryInputStream is = new MemoryInputStream(mis.getAllRead(), (int) (long) addr, (int) limit);
|
||||
switch (searchMode) {
|
||||
case ALL:
|
||||
swfStreams.put(addr, is);
|
||||
break;
|
||||
case BIGGEST:
|
||||
if (limit > biggestSize) {
|
||||
biggestSize = limit;
|
||||
swfStreams.clear();
|
||||
swfStreams.put(addr, is);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (OutOfMemoryError ome) {
|
||||
System.gc();
|
||||
} catch (Exception | Error ex) {
|
||||
}
|
||||
|
||||
}
|
||||
setProgress(100);
|
||||
processed = true;
|
||||
|
||||
@@ -76,7 +76,7 @@ public class SWFSourceInfo {
|
||||
return false;
|
||||
}
|
||||
|
||||
public SWFBundle getBundle(boolean noCheck) throws IOException {
|
||||
public SWFBundle getBundle(boolean noCheck, SearchMode searchMode) throws IOException {
|
||||
if (!isBundle()) {
|
||||
return null;
|
||||
}
|
||||
@@ -89,7 +89,7 @@ public class SWFSourceInfo {
|
||||
case ".zip":
|
||||
return new ZippedSWFBundle(is);
|
||||
default:
|
||||
return new BinarySWFBundle(is, noCheck);
|
||||
return new BinarySWFBundle(is, noCheck, searchMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -14,13 +14,13 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.console;
|
||||
package com.jpexs.decompiler.flash;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public enum ExtractMode {
|
||||
|
||||
public enum SearchMode {
|
||||
|
||||
ALL, BIGGEST
|
||||
}
|
||||
@@ -22,6 +22,7 @@ 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.SearchMode;
|
||||
import com.jpexs.decompiler.flash.abc.RenameType;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.configuration.ConfigurationItem;
|
||||
@@ -754,7 +755,7 @@ public class CommandLineArgumentParser {
|
||||
}
|
||||
|
||||
String fileName = args.remove();
|
||||
ExtractMode mode = ExtractMode.ALL;
|
||||
SearchMode mode = SearchMode.ALL;
|
||||
|
||||
boolean noCheck = false;
|
||||
if (args.size() > 0) {
|
||||
@@ -768,7 +769,7 @@ public class CommandLineArgumentParser {
|
||||
String modeStr = args.remove().toLowerCase();
|
||||
switch (modeStr) {
|
||||
case "biggest":
|
||||
mode = ExtractMode.BIGGEST;
|
||||
mode = SearchMode.BIGGEST;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -779,36 +780,25 @@ public class CommandLineArgumentParser {
|
||||
System.err.println("Error: <infile> should be a bundle. (ZIP or non SWF binary file)");
|
||||
System.exit(1);
|
||||
}
|
||||
SWFBundle bundle = sourceInfo.getBundle(noCheck);
|
||||
SWFBundle bundle = sourceInfo.getBundle(noCheck, mode);
|
||||
List<Map.Entry<String, SeekableInputStream>> streamsToExtract = new ArrayList<>();
|
||||
Map.Entry<String, SeekableInputStream> biggest = null;
|
||||
int biggestSize = 0;
|
||||
for (Map.Entry<String, SeekableInputStream> 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);
|
||||
streamsToExtract.add(streamEntry);
|
||||
}
|
||||
|
||||
for (Map.Entry<String, SeekableInputStream> streamEntry : streamsToExtract) {
|
||||
InputStream stream = streamEntry.getValue();
|
||||
stream.reset();
|
||||
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(streamEntry.getKey() + ".swf"))) {
|
||||
String fileNameOut;
|
||||
if (mode == SearchMode.BIGGEST) {
|
||||
fileNameOut = Helper.getWithoutExtension(new File(fileName)) + ".swf";
|
||||
} else {
|
||||
fileNameOut = streamEntry.getKey() + ".swf";
|
||||
}
|
||||
|
||||
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(fileNameOut))) {
|
||||
byte[] swfData = new byte[stream.available()];
|
||||
int cnt = stream.read(swfData);
|
||||
fos.write(swfData, 0, cnt);
|
||||
|
||||
@@ -22,6 +22,7 @@ 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.SearchMode;
|
||||
import com.jpexs.decompiler.flash.Version;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
@@ -230,7 +231,7 @@ public class Main {
|
||||
SWFBundle bundle = null;
|
||||
if (inputStream == null) {
|
||||
inputStream = new BufferedInputStream(new FileInputStream(sourceInfo.getFile()));
|
||||
bundle = sourceInfo.getBundle(false);
|
||||
bundle = sourceInfo.getBundle(false, SearchMode.ALL);
|
||||
logger.log(Level.INFO, "Load file: {0}", sourceInfo.getFile());
|
||||
} else if (inputStream instanceof SeekableInputStream
|
||||
|| inputStream instanceof BufferedInputStream) {
|
||||
|
||||
@@ -772,6 +772,17 @@ public class Helper {
|
||||
return ext;
|
||||
}
|
||||
|
||||
public static String getWithoutExtension(File f) {
|
||||
String ext = null;
|
||||
String s = f.getName();
|
||||
int i = s.lastIndexOf('.');
|
||||
|
||||
if (i > 0 && i < s.length() - 1) {
|
||||
ext = s.substring(0, i).toLowerCase();
|
||||
}
|
||||
return ext;
|
||||
}
|
||||
|
||||
public static void appendTimeoutComment(GraphTextWriter writer, int timeout) {
|
||||
writer.appendNoHilight("/*").newLine();
|
||||
writer.appendNoHilight(" * ").appendNoHilight(AppStrings.translate("decompilationError")).newLine();
|
||||
|
||||
Reference in New Issue
Block a user