mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-20 06:55:54 +00:00
merge
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash;
|
||||
|
||||
import com.jpexs.helpers.StreamSearch;
|
||||
import com.jpexs.helpers.SwfHeaderStreamSearch;
|
||||
import com.jpexs.helpers.streams.SeekableInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -34,7 +34,7 @@ public class BinarySWFBundle implements SWFBundle {
|
||||
private final SWFSearch search;
|
||||
|
||||
public BinarySWFBundle(InputStream is, boolean noCheck, SearchMode searchMode) {
|
||||
search = new SWFSearch(new StreamSearch(is), noCheck, searchMode);
|
||||
search = new SWFSearch(new SwfHeaderStreamSearch(is), noCheck, searchMode);
|
||||
search.process();
|
||||
}
|
||||
|
||||
|
||||
@@ -335,9 +335,83 @@ public final class SWF implements TreeItem {
|
||||
* @throws java.lang.InterruptedException
|
||||
*/
|
||||
public SWF(InputStream is, ProgressListener listener, boolean parallelRead) throws IOException, InterruptedException {
|
||||
this(is, listener, parallelRead, false, false);
|
||||
this(is, listener, parallelRead, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Faster constructor to check SWF only
|
||||
* @param is
|
||||
*/
|
||||
public SWF(InputStream is) throws IOException {
|
||||
byte[] hdr = new byte[3];
|
||||
is.read(hdr);
|
||||
String shdr = new String(hdr, Utf8Helper.charset);
|
||||
if (!Arrays.asList(
|
||||
"FWS", //Uncompressed Flash
|
||||
"CWS", //ZLib compressed Flash
|
||||
"ZWS", //LZMA compressed Flash
|
||||
"GFX", //Uncompressed ScaleForm GFx
|
||||
"CFX" //Compressed ScaleForm GFx
|
||||
).contains(shdr)) {
|
||||
throw new IOException("Invalid SWF file");
|
||||
}
|
||||
version = is.read();
|
||||
fileSize = (is.read() + (is.read() << 8) + (is.read() << 16) + (is.read() << 24)) & 0xffffffff;
|
||||
|
||||
if (hdr[0] == 'C') {
|
||||
is = new InflaterInputStream(is);
|
||||
}
|
||||
|
||||
if (hdr[0] == 'Z') {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
//outSize
|
||||
is.read();
|
||||
is.read();
|
||||
is.read();
|
||||
is.read();
|
||||
int propertiesSize = 5;
|
||||
lzmaProperties = new byte[propertiesSize];
|
||||
if (is.read(lzmaProperties, 0, propertiesSize) != propertiesSize) {
|
||||
throw new IOException("LZMA:input .lzma file is too short");
|
||||
}
|
||||
long dictionarySize = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
dictionarySize += ((int) (lzmaProperties[1 + i]) & 0xFF) << (i * 8);
|
||||
if (dictionarySize > Runtime.getRuntime().freeMemory()) {
|
||||
throw new IOException("LZMA: Too large dictionary size");
|
||||
}
|
||||
}
|
||||
|
||||
SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder();
|
||||
if (!decoder.SetDecoderProperties(lzmaProperties)) {
|
||||
throw new IOException("LZMA:Incorrect stream properties");
|
||||
}
|
||||
|
||||
if (!decoder.Code(is, baos, fileSize - 8)) {
|
||||
throw new IOException("LZMA:Error in data stream");
|
||||
}
|
||||
} else {
|
||||
long toRead = fileSize - 8;
|
||||
if (toRead > 0) {
|
||||
byte[] bytes = new byte[4096];
|
||||
while (toRead > 4096) {
|
||||
int read = is.read(bytes);
|
||||
if (read == -1) {
|
||||
throw new IOException("Invalid SWF file");
|
||||
}
|
||||
toRead -= read;
|
||||
}
|
||||
while (toRead > 0) {
|
||||
int read = is.read(bytes, 0, (int) toRead);
|
||||
if (read == -1) {
|
||||
throw new IOException("Invalid SWF file");
|
||||
}
|
||||
toRead -= read;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct SWF from stream
|
||||
*
|
||||
@@ -345,11 +419,10 @@ public final class SWF implements TreeItem {
|
||||
* @param listener
|
||||
* @param parallelRead Use parallel threads?
|
||||
* @param checkOnly Check only file validity
|
||||
* @param skipTagReading
|
||||
* @throws IOException
|
||||
* @throws java.lang.InterruptedException
|
||||
*/
|
||||
public SWF(InputStream is, ProgressListener listener, boolean parallelRead, boolean checkOnly, boolean skipTagReading) throws IOException, InterruptedException {
|
||||
public SWF(InputStream is, ProgressListener listener, boolean parallelRead, boolean checkOnly) throws IOException, InterruptedException {
|
||||
byte[] hdr = new byte[3];
|
||||
is.read(hdr);
|
||||
String shdr = new String(hdr, Utf8Helper.charset);
|
||||
@@ -412,13 +485,6 @@ public final class SWF implements TreeItem {
|
||||
sis.readUI8(); //tmpFirstByetOfFrameRate
|
||||
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);
|
||||
if (!checkOnly) {
|
||||
Map<Long, Tag> tagMap = new HashMap<>();
|
||||
|
||||
@@ -82,7 +82,7 @@ public class SWFSearch {
|
||||
MemoryInputStream mis = (MemoryInputStream) ret.get(addr);
|
||||
mis.reset();
|
||||
PosMarkedInputStream pmi = new PosMarkedInputStream(mis);
|
||||
SWF swf = new SWF(pmi, null, false, true, noCheck);
|
||||
SWF swf = noCheck ? new SWF(pmi) : new SWF(pmi, null, false, true);
|
||||
boolean valid = swf.fileSize > 0
|
||||
&& swf.version > 0
|
||||
&& (!swf.tags.isEmpty() || noCheck)
|
||||
|
||||
@@ -173,7 +173,12 @@ public class CommandLineArgumentParser {
|
||||
*/
|
||||
public static String parseArguments(String[] arguments) throws IOException {
|
||||
Level traceLevel = Level.WARNING;
|
||||
Queue<String> args = new LinkedList<>(Arrays.asList(arguments));
|
||||
Queue<String> args = new LinkedList<>();
|
||||
for (String arg : arguments) {
|
||||
if (arg.length() > 0) {
|
||||
args.add(arg);
|
||||
}
|
||||
}
|
||||
AbortRetryIgnoreHandler handler = null;
|
||||
Map<String, String> format = new HashMap<>();
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ public class LoadFromMemoryFrame extends AppFrame implements ActionListener {
|
||||
try {
|
||||
PosMarkedInputStream pmi = new PosMarkedInputStream(ret.get(addr));
|
||||
ReReadableInputStream is = new ReReadableInputStream(pmi);
|
||||
SWF swf = new SWF(is, null, false, true, false);
|
||||
SWF swf = new SWF(is, null, false, true);
|
||||
long limit = pmi.getPos();
|
||||
is.seek(0);
|
||||
is = new ReReadableInputStream(new LimitedInputStream(is, limit));
|
||||
|
||||
@@ -428,10 +428,24 @@ filter.zip = ZIP komprimerade filer (*.zip)
|
||||
filter.binary = Bin\u00e4r s\u00f6kning - alla filer (*.*)
|
||||
|
||||
open.error = Fel
|
||||
open.error.fileNotFound = Filen kunde inte hittas
|
||||
open.error.fileNotFound = Filen hittades inte
|
||||
open.error.cannotOpen = Kan inte \u00f6ppna filen
|
||||
|
||||
node.others = andra
|
||||
|
||||
#after version 1.8.1
|
||||
menu.tools.search = Text S\u00f6kning
|
||||
|
||||
#after version 1.8.1u1
|
||||
menu.tools.timeline = Tidslinje
|
||||
|
||||
dialog.selectcolor.title = V\u00e4lj f\u00e4rg
|
||||
button.selectcolor.hint = Klicka f\u00f6r att v\u00e4lja f\u00e4rg
|
||||
|
||||
#default item name, will be used in following sentences
|
||||
generictag.array.item = artikel
|
||||
generictag.array.insertbeginning = Infoga %item% vid b\u00f6rjan
|
||||
generictag.array.insertbefore = Infoga %item% f\u00f6re
|
||||
generictag.array.remove = Tabort %item%
|
||||
generictag.array.insertafter = Infoga %item% efter
|
||||
generictag.array.insertend = Infoga %item% vid slutet
|
||||
|
||||
@@ -412,6 +412,10 @@ public class Helper {
|
||||
}
|
||||
|
||||
public static byte[] readStream(InputStream is) {
|
||||
if (is instanceof MemoryInputStream) {
|
||||
return ((MemoryInputStream) is).getAllRead();
|
||||
}
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try {
|
||||
byte[] buf = new byte[4096];
|
||||
|
||||
@@ -54,8 +54,8 @@ public class StreamSearch implements Searchable {
|
||||
try {
|
||||
is.seek(0);
|
||||
|
||||
byte buf[] = new byte[4096];
|
||||
byte last[] = null;
|
||||
byte[] buf = new byte[4096];
|
||||
byte[] last = null;
|
||||
int cnt = 0;
|
||||
long pos = 0;
|
||||
while ((cnt = is.read(buf)) > 0) {
|
||||
@@ -63,7 +63,7 @@ public class StreamSearch implements Searchable {
|
||||
for (int i = -maxFindLen + 1; i < cnt; i++) {
|
||||
|
||||
loopdata:
|
||||
for (byte onedata[] : data) {
|
||||
for (byte[] onedata : data) {
|
||||
boolean match = true;
|
||||
for (int d = 0; d < onedata.length; d++) {
|
||||
byte b;
|
||||
@@ -71,7 +71,7 @@ public class StreamSearch implements Searchable {
|
||||
if (last != null) {
|
||||
b = last[last.length + i + d];
|
||||
} else {
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
} else if (i + d >= buf.length) {
|
||||
continue;
|
||||
@@ -81,6 +81,7 @@ public class StreamSearch implements Searchable {
|
||||
|
||||
if (b != onedata[d]) {
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
@@ -90,7 +91,6 @@ public class StreamSearch implements Searchable {
|
||||
continue loopdata;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
pos = pos + cnt;
|
||||
}
|
||||
|
||||
79
trunk/src/com/jpexs/helpers/SwfHeaderStreamSearch.java
Normal file
79
trunk/src/com/jpexs/helpers/SwfHeaderStreamSearch.java
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.jpexs.helpers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class SwfHeaderStreamSearch implements Searchable {
|
||||
|
||||
private final MemoryInputStream is;
|
||||
|
||||
public SwfHeaderStreamSearch(InputStream is) {
|
||||
this.is = new MemoryInputStream(Helper.readStream(is));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Long, InputStream> search(byte[]... data) {
|
||||
return search(null, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Long, InputStream> search(ProgressListener progListener, byte[]... data) {
|
||||
// Ignore data parameter, find only FWS, CWS, ZWS, GFX and CFX
|
||||
|
||||
Map<Long, InputStream> ret = new HashMap<>();
|
||||
byte[] buf = is.getAllRead();
|
||||
byte byte2 = buf[0], byte3 = buf[1];
|
||||
boolean match = false;
|
||||
for (int i = 2; i < buf.length - 2; i++) {
|
||||
byte b = byte2;
|
||||
byte2 = byte3;
|
||||
byte3 = buf[i];
|
||||
if (byte2 == 'W' && byte3 == 'S') {
|
||||
if (b == 'F' || b == 'C' || b == 'Z') {
|
||||
match = true;
|
||||
}
|
||||
} else if (byte2 == 'F' && byte3 == 'X') {
|
||||
if (b == 'G' || b == 'C') {
|
||||
match = true;
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
// todo: support > 2GB files
|
||||
InputStream fis;
|
||||
try {
|
||||
fis = new MemoryInputStream(buf, i - 2);
|
||||
ret.put((long) i - 2, fis);
|
||||
match = false;
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(SwfHeaderStreamSearch.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user