trunk contents moved to root

This commit is contained in:
Jindra Petřík
2014-05-10 20:50:57 +02:00
parent 1b851e66a8
commit 199a4d0c2b
2296 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,111 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache;
import com.jpexs.helpers.LimitedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import java.util.zip.InflaterInputStream;
/**
*
* @author JPEXS
*/
public abstract class CacheEntry {
public abstract String getRequestURL();
public abstract Map<String, String> getResponseHeaders();
public abstract String getStatusLine();
public abstract String getRequestMethod();
public abstract InputStream getResponseRawDataStream();
public InputStream getResponseDataStream() {
String contentLengthStr = getHeader("Content-Length");
int contentLength = -1;
if (contentLengthStr != null) {
try {
contentLength = Integer.parseInt(contentLengthStr);
} catch (NumberFormatException nex) {
}
}
final InputStream rawIs = getResponseRawDataStream();
InputStream is = rawIs;
if (contentLength > -1) {
is = new LimitedInputStream(is, contentLength);
}
String encoding = getHeader("Content-Encoding");
if (encoding != null) {
switch (encoding) {
case "gzip":
try {
is = new GZIPInputStream(is);
} catch (IOException ex) {
is = null;
//ignore
}
break;
case "deflate":
is = new InflaterInputStream(is);
break;
default: //unknown
return null;
}
}
if ("chunked".equals(getHeader("Transfer-Encoding"))) {
is = new ChunkedInputStream(is);
}
return is;
}
@Override
public String toString() {
return getRequestURL();
}
public int getStatusCode() {
String st = getStatusLine();
if (st == null) {
return 0;
}
String parts[] = st.split(" ");
try {
return Integer.parseInt(parts[1]);
} catch (NumberFormatException nfe) {
return 0;
}
}
public String getHeader(String header) {
Map<String, String> m = getResponseHeaders();
if (m == null) {
return null;
}
for (String k : m.keySet()) {
if (k.toLowerCase().equals(header.toLowerCase())) {
return m.get(k);
}
}
return null;
}
}

View File

@@ -0,0 +1,30 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache;
import java.util.List;
/**
*
* @author JPEXS
*/
public interface CacheImplementation {
public List<CacheEntry> getEntries();
public void refresh();
}

View File

@@ -0,0 +1,45 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache;
import com.jpexs.browsers.cache.chrome.ChromeCache;
import com.jpexs.browsers.cache.firefox.FirefoxCache;
/**
*
* @author JPEXS
*/
public class CacheReader {
public static final String BROWSER_FIREFOX = "firefox";
public static final String BROWSER_CHROME = "chrome";
public static String[] availableBrowsers() {
return new String[]{BROWSER_FIREFOX, BROWSER_CHROME};
}
public static CacheImplementation getBrowserCache(String browser) {
switch (browser) {
case BROWSER_CHROME:
return ChromeCache.getInstance();
case BROWSER_FIREFOX:
return FirefoxCache.getInstance();
default:
throw new IllegalArgumentException("Invalid browser:" + browser);
}
}
}

View File

@@ -0,0 +1,96 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache;
import java.io.IOException;
import java.io.InputStream;
/**
*
* @author JPEXS
*/
public class ChunkedInputStream extends InputStream {
private final InputStream is;
private int chunkPos = 0;
private int chunkLen = 0;
private boolean end = false;
private boolean first = true;
public ChunkedInputStream(InputStream is) {
this.is = is;
}
@Override
public int read() throws IOException {
if (end) {
return -1;
}
if (chunkPos >= chunkLen) {
if (!first) {
if (is.read() != '\r') {
throw new IOException("Invalid chunk");
}
if (is.read() != '\n') {
throw new IOException("Invalid chunk");
}
}
String lenStr = readLine();
try {
chunkLen = Integer.parseInt(lenStr);
} catch (NumberFormatException nfe) {
throw new IOException("Invalid chunk");
}
if (chunkLen == 0) {
is.read(); // \r
is.read(); // \n
end = true;
return -1;
}
chunkPos = 0;
first = false;
}
chunkPos++;
return is.read();
}
private String readLine() throws IOException {
int i;
boolean inr = false;
String ret = "";
while ((i = is.read()) > -1) {
if (inr) {
inr = false;
if (i == '\n') {
break;
} else {
ret += "\r";
}
}
if (i == '\r') {
inr = true;
continue;
}
ret += (char) i;
}
if (inr) {
ret += "\r";
}
return ret;
}
}

View File

@@ -0,0 +1,48 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class RafInputStream extends InputStream {
private final RandomAccessFile raf;
private long pos = 0;
public RafInputStream(RandomAccessFile raf) {
this.raf = raf;
try {
pos = raf.getFilePointer();
} catch (IOException ex) {
Logger.getLogger(RafInputStream.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
public int read() throws IOException {
raf.seek(pos++);
return raf.read();
}
}

View File

@@ -0,0 +1,69 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache.chrome;
import java.io.IOException;
import java.io.InputStream;
/**
*
* @author JPEXS
*/
public class BlockFileHeader {
static final int kBlockHeaderSize = 8192; // Two pages: almost 64k entries
static final int kMaxBlocks = (kBlockHeaderSize - 80) * 8;
long magic; // c3 ca 04 c1
long version; // 00 00 02 00
int this_file;
int next_file;
int entry_size;
int num_entries;
int max_entries;
int empty[] = new int[4];
int hints[] = new int[4];
int updating;
int user[] = new int[5];
long allocation_map[] = new long[kMaxBlocks / 32];
public BlockFileHeader(InputStream is) throws IOException {
IndexInputStream iis = new IndexInputStream(is);
magic = iis.readUInt32();
version = iis.readUInt32();
this_file = iis.readInt16();
next_file = iis.readInt16();
entry_size = iis.readInt32();
num_entries = iis.readInt32();
max_entries = iis.readInt32();
empty = new int[4];
for (int i = 0; i < 4; i++) {
empty[i] = iis.readInt32();
}
hints = new int[4];
for (int i = 0; i < 4; i++) {
hints[i] = iis.readInt32();
}
updating = iis.readInt32();
user = new int[5];
for (int i = 0; i < 5; i++) {
user[i] = iis.readInt32();
}
for (int i = 0; i < allocation_map.length; i++) {
allocation_map[i] = iis.readUInt32();
}
}
}

View File

@@ -0,0 +1,122 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache.chrome;
import com.jpexs.browsers.cache.RafInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.Map;
/**
*
* @author JPEXS
*/
public class CacheAddr {
public static final int EXTERNAL = 0;
public static final int RANKINGS = 1;
public static final int BLOCK_256 = 2;
public static final int BLOCK_1K = 3;
public static final int BLOCK_4K = 4;
public static final int BLOCK_FILES = 5;
public static final int BLOCK_ENTRIES = 6;
public static final int BLOCK_EVICTED = 7;
public static final String blockNames[] = new String[]{"EXTERNAL", "RANKINGS", "BLOCK_256", "BLOCK_1K", "BLOCK_4K", "BLOCK_FILES", "BLOCK_ENTRIES", "BLOCK_EVICTED"};
public static final int blockSizes[] = new int[]{0, 36, 256, 1024, 4096, 8, 104, 48};
public static final long kInitializedMask = 0x80000000L;
public static final long kFileTypeMask = 0x70000000L;
public static final int kFileTypeOffset = 28;
public static final long kReservedBitsMask = 0x0c000000L;
public static final long kNumBlocksMask = 0x03000000L;
public static final int kNumBlocksOffset = 24;
public static final long kFileSelectorMask = 0x00ff0000L;
public static final int FileSelectorOffset = 16;
public static final long kStartBlockMask = 0x0000FFFFL;
public static final long kFileNameMask = 0x0FFFFFFFL;
public boolean initialized;
public int fileType;
public int numBlocks;
public int fileSelector;
public int startBlock;
public int fileName;
public long val;
public File rootPath;
private final Map<Integer, RandomAccessFile> dataFiles;
private final File externalFilesDir;
public CacheAddr(InputStream is, File rootPath, Map<Integer, RandomAccessFile> dataFiles, File externalFilesDir) throws IOException {
this.dataFiles = dataFiles;
this.rootPath = rootPath;
this.externalFilesDir = externalFilesDir;
IndexInputStream iis = new IndexInputStream(is);
val = iis.readUInt32();
initialized = (val & kInitializedMask) == kInitializedMask;
fileType = (int) ((val & kFileTypeMask) >> kFileTypeOffset);
if (fileType == EXTERNAL) {
fileName = (int) (val & kFileNameMask);
} else {
numBlocks = (int) ((val & kNumBlocksMask) >> kNumBlocksOffset);
fileSelector = (int) ((val & kFileSelectorMask) >> FileSelectorOffset);
startBlock = (int) (val & kStartBlockMask);
}
}
@Override
public String toString() {
String ft = blockNames[fileType];
if (fileType == EXTERNAL) {
return ft + ":" + fileName;
}
if (!initialized) {
return "uninitialized";
}
return ft + ": numBlocks " + numBlocks + " fileSelector " + fileSelector + " startBlock " + startBlock;
}
public InputStream getInputStream() throws IOException {
if (!initialized) {
return null;
}
switch (fileType) {
case EXTERNAL:
String fileNameStr = Long.toHexString(fileName);
while (fileNameStr.length() < 6) {
fileNameStr = "0" + fileNameStr;
}
fileNameStr = "f_" + fileNameStr;
return new RafInputStream(new RandomAccessFile(new File(externalFilesDir, fileNameStr), "r"));
case BLOCK_1K:
case BLOCK_256:
case BLOCK_4K:
RandomAccessFile raf;
if (dataFiles.containsKey(fileSelector)) {
raf = dataFiles.get(fileSelector);
} else {
raf = new RandomAccessFile(rootPath + "\\data_" + fileSelector, "r");
dataFiles.put(fileSelector, raf);
}
raf.seek(BlockFileHeader.kBlockHeaderSize + startBlock * blockSizes[fileType]);
return new RafInputStream(raf);
}
return null;
}
}

View File

@@ -0,0 +1,194 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache.chrome;
import com.jpexs.browsers.cache.CacheEntry;
import com.jpexs.browsers.cache.CacheImplementation;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class ChromeCache implements CacheImplementation {
private static ChromeCache instance;
private File tempDir;
private List<File> dataFiles;
private File indexFile;
private ChromeCache() {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
free();
}
});
}
public static ChromeCache getInstance() {
if (instance == null) {
instance = new ChromeCache();
}
return instance;
}
private boolean loaded = false;
private Index index;
@Override
public List<CacheEntry> getEntries() {
if (!loaded) {
refresh();
}
if (!loaded) {
return null;
}
List<CacheEntry> ret = new ArrayList<>();
try {
List<EntryStore> entries = index.getEntries();
for (EntryStore en : entries) {
if (en.state == EntryStore.ENTRY_NORMAL) {
String key = en.getKey();
if (key != null && !key.trim().isEmpty()) {
ret.add(en);
}
}
}
} catch (IOException ex) {
Logger.getLogger(ChromeCache.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
return ret;
}
@Override
public void refresh() {
free();
File cacheDir = null;
try {
cacheDir = getCacheDirectory();
} catch (IOException ex) {
Logger.getLogger(ChromeCache.class.getName()).log(Level.SEVERE, null, ex);
}
if (cacheDir == null) {
return;
}
File systemTempDir = new File(System.getProperty("java.io.tmpdir"));
File originalIndexFile = new File(cacheDir + File.separator + "index");
tempDir = new File(systemTempDir, "cacheView" + System.identityHashCode(this));
tempDir.mkdir();
indexFile = new File(tempDir, "index");
try {
Files.copy(originalIndexFile.toPath(), indexFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ex) {
Logger.getLogger(ChromeCache.class.getName()).log(Level.SEVERE, null, ex);
return;
}
File originalDataFile;
dataFiles = new ArrayList<>();
for (int i = 0; (originalDataFile = new File(cacheDir, "data_" + i)).exists(); i++) {
File dataFile = new File(tempDir, "data_" + i);
dataFiles.add(dataFile);
try {
Files.copy(originalDataFile.toPath(), dataFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ex) {
Logger.getLogger(ChromeCache.class.getName()).log(Level.SEVERE, null, ex);
return;
}
}
try {
index = new Index(indexFile, cacheDir);
} catch (IOException ex) {
Logger.getLogger(ChromeCache.class.getName()).log(Level.SEVERE, null, ex);
}
loaded = true;
}
private enum OSId {
WINDOWS, OSX, UNIX
}
private static OSId getOSId() {
PrivilegedAction<String> doGetOSName = new PrivilegedAction<String>() {
@Override
public String run() {
return System.getProperty("os.name");
}
};
OSId id = OSId.UNIX;
String osName = AccessController.doPrivileged(doGetOSName);
if (osName != null) {
if (osName.toLowerCase().startsWith("mac os x")) {
id = OSId.OSX;
} else if (osName.contains("Windows")) {
id = OSId.WINDOWS;
}
}
return id;
}
public static File getCacheDirectory() throws IOException {
String userHome = null;
File ret = null;
try {
userHome = System.getProperty("user.home");
} catch (SecurityException ignore) {
}
if (userHome != null) {
OSId osId = getOSId();
if (osId == OSId.WINDOWS) {
ret = new File(userHome + "\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Cache\\");
if (!ret.exists()) {
ret = new File(userHome + "\\Local Settings\\Application Data\\Google\\Chrome\\User Data\\Default\\Cache");
}
} else if (osId == OSId.OSX) {
ret = new File(userHome + "/Library/Caches/Google/Chrome/Default/Cache");
} else {
ret = new File(userHome + "/.config/google-chrome/Default/Application Cache/Cache/");
if (!ret.exists()) {
ret = new File(userHome + "/.cache/chromium/Default/Cache");
}
}
}
if ((ret != null) && !ret.exists()) {
return null;
}
return ret;
}
private void free() {
if (loaded) {
index.free();
indexFile.delete();
for (File d : dataFiles) {
d.delete();
}
tempDir.delete();
}
}
}

View File

@@ -0,0 +1,27 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache.chrome;
/**
*
* @author JPEXS
*/
public class EntryFlags {
public static final int PARENT_ENTRY = 1;
public static final int CHILD_ENTRY = 1 << 1;
}

View File

@@ -0,0 +1,28 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache.chrome;
/**
*
* @author JPEXS
*/
public class EntryState {
public static final int ENTRY_NORMAL = 0;
public static final int ENTRY_EVICTED = 1;
public static final int ENTRY_DOOMED = 2;
}

View File

@@ -0,0 +1,153 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache.chrome;
import com.jpexs.browsers.cache.CacheEntry;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class EntryStore extends CacheEntry {
public static final int ENTRY_NORMAL = 0;
public static final int ENTRY_EVICTED = 1; // The entry was recently evicted from the cache.
public static final int ENTRY_DOOMED = 2; // The entry was doomed
public static final int PARENT_ENTRY = 1; // This entry has children (sparse) entries.
public static final int CHILD_ENTRY = 1 << 1;
public long hash; // Full hash of the key.
public CacheAddr next; // Next entry with the same hash or bucket.
public CacheAddr rankings_node; // Rankings node for this entry.
public int reuse_count; // How often is this entry used.
public int refetch_count; // How often is this fetched from the net.
public int state; // Current state.
public long creation_time;
public int key_len;
public CacheAddr long_key; // Optional address of a long key.
public int data_size[] = new int[4]; // We can store up to 4 data streams for each
public CacheAddr data_addr[] = new CacheAddr[4]; // entry.
public long flags; // Any combination of EntryFlags.
public int pad[] = new int[4];
public long self_hash; // The hash of EntryStore up to this point.
public byte key[] = new byte[256 - 24 * 4]; // null terminated
public EntryStore(InputStream is, File rootDir, Map<Integer, RandomAccessFile> dataFiles, File externalFilesDir) throws IOException {
IndexInputStream iis = new IndexInputStream(is);
hash = iis.readUInt32();
next = new CacheAddr(is, rootDir, dataFiles, externalFilesDir);
rankings_node = new CacheAddr(is, rootDir, dataFiles, externalFilesDir);
reuse_count = iis.readInt32();
refetch_count = iis.readInt32();
state = iis.readInt32();
creation_time = iis.readUInt64();
key_len = iis.readInt32();
long_key = new CacheAddr(is, rootDir, dataFiles, externalFilesDir);
data_size = new int[4];
for (int i = 0; i < 4; i++) {
data_size[i] = iis.readInt32();
}
data_addr = new CacheAddr[4];
for (int i = 0; i < 4; i++) {
data_addr[i] = new CacheAddr(is, rootDir, dataFiles, externalFilesDir);
}
flags = iis.readUInt32();
pad = new int[4];
for (int i = 0; i < 4; i++) {
pad[i] = iis.readInt32();
}
self_hash = iis.readUInt32();
key = new byte[256 - 24 * 4];
iis.read(key);
}
public HttpResponseInfo getResponseInfo() {
try {
InputStream is = data_addr[0].getInputStream();
if (is == null) {
return null;
}
return new HttpResponseInfo(is);
} catch (IOException ex) {
Logger.getLogger(EntryStore.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
public int getResponseDataSize() {
return data_size[1];
}
@Override
public InputStream getResponseRawDataStream() {
try {
return data_addr[1].getInputStream();
} catch (IOException ex) {
Logger.getLogger(EntryStore.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
public String getKey() {
if (key_len < 0) {
return null;
}
return new String(key, 0, key_len > key.length || key_len < 0 ? key.length : key_len);
}
@Override
public String getRequestURL() {
return getKey();
}
@Override
public Map<String, String> getResponseHeaders() {
HttpResponseInfo ri = getResponseInfo();
if (ri == null) {
return new HashMap<>();
}
List<String> headers = ri.headers;
Map<String, String> ret = new HashMap<>();
for (int h = 1; h < headers.size(); h++) {
String hs = headers.get(h);
if (hs.contains(":")) {
String hp[] = hs.split(":");
ret.put(hp[0].trim(), hp[1].trim());
}
}
return ret;
}
@Override
public String getStatusLine() {
HttpResponseInfo ri = getResponseInfo();
return ri.headers.get(0);
}
@Override
public String getRequestMethod() {
return "GET";
}
}

View File

@@ -0,0 +1,107 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache.chrome;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author JPEXS
*/
public class HttpResponseInfo {
public long flags;
public int version;
public long request_time;
public long response_time;
public long payload_size;
public List<String> headers;
// The version of the response info used when persisting response info.
public static final int RESPONSE_INFO_VERSION = 3;
// The minimum version supported for deserializing response info.
public static final int RESPONSE_INFO_MINIMUM_VERSION = 1;
// We reserve up to 8 bits for the version number.
public static final int RESPONSE_INFO_VERSION_MASK = 0xFF;
// This bit is set if the response info has a cert at the end.
// Version 1 serialized only the end-entity certificate, while subsequent
// versions include the available certificate chain.
public static final int RESPONSE_INFO_HAS_CERT = 1 << 8;
// This bit is set if the response info has a security-bits field (security
// strength, in bits, of the SSL connection) at the end.
public static final int RESPONSE_INFO_HAS_SECURITY_BITS = 1 << 9;
// This bit is set if the response info has a cert status at the end.
public static final int RESPONSE_INFO_HAS_CERT_STATUS = 1 << 10;
// This bit is set if the response info has vary header data.
public static final int RESPONSE_INFO_HAS_VARY_DATA = 1 << 11;
// This bit is set if the request was cancelled before completion.
public static final int RESPONSE_INFO_TRUNCATED = 1 << 12;
// This bit is set if the response was received via SPDY.
public static final int RESPONSE_INFO_WAS_SPDY = 1 << 13;
// This bit is set if the request has NPN negotiated.
public static final int RESPONSE_INFO_WAS_NPN = 1 << 14;
// This bit is set if the request was fetched via an explicit proxy.
public static final int RESPONSE_INFO_WAS_PROXY = 1 << 15;
// This bit is set if the response info has an SSL connection status field.
// This contains the ciphersuite used to fetch the resource as well as the
// protocol version, compression method and whether SSLv3 fallback was used.
public static final int RESPONSE_INFO_HAS_SSL_CONNECTION_STATUS = 1 << 16;
// This bit is set if the response info has protocol version.
public static final int RESPONSE_INFO_HAS_NPN_NEGOTIATED_PROTOCOL = 1 << 17;
// This bit is set if the response info has connection info.
public static final int RESPONSE_INFO_HAS_CONNECTION_INFO = 1 << 18;
// This bit is set if the request has http authentication.
public static final int RESPONSE_INFO_USE_HTTP_AUTHENTICATION = 1 << 19;
public String getHeaderValue(String header) {
for (String h : headers) {
if (h.contains(":")) {
String keyval[] = h.split(":");
String key = keyval[0].trim().toLowerCase();
String val = keyval[1].trim();
if (header.toLowerCase().equals(key)) {
return val;
}
}
}
return null;
}
public HttpResponseInfo(InputStream is) throws IOException {
IndexInputStream iis = new IndexInputStream(is);
payload_size = iis.readUInt32();
flags = iis.readInt();
version = (int) (flags & RESPONSE_INFO_VERSION_MASK);
if (version < RESPONSE_INFO_MINIMUM_VERSION || version > RESPONSE_INFO_VERSION) {
throw new RuntimeException("unexpected response info version: " + version);
}
request_time = iis.readInt64();
response_time = iis.readInt64();
String headersStr = iis.readString();
headers = new ArrayList<>();
int nulpos;
while ((nulpos = headersStr.indexOf(0)) > 0) {
String h = headersStr.substring(0, nulpos);
headersStr = headersStr.substring(nulpos + 1);
headers.add(h);
}
//TODO: Read SSL info
}
}

View File

@@ -0,0 +1,79 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache.chrome;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
* @author JPEXS
*/
public class Index {
IndexHeader header;
CacheAddr table[];
public static final int kIndexTablesize = 0x10000;
public File rootDir;
private final Map<Integer, RandomAccessFile> dataFiles;
private final File externalFilesDir;
public void free() {
for (RandomAccessFile r : dataFiles.values()) {
try {
r.close();
} catch (IOException ex) {
}
}
}
public List<EntryStore> getEntries() throws IOException {
List<EntryStore> ret = new ArrayList<>();
for (CacheAddr ca : table) {
InputStream is = ca.getInputStream();
if (is != null) {
EntryStore es = new EntryStore(is, rootDir, dataFiles, externalFilesDir);
ret.add(es);
}
}
return ret;
}
public Index(File file, File externalFilesDir) throws IOException {
dataFiles = new HashMap<>();
this.externalFilesDir = externalFilesDir;
try (FileInputStream is = new FileInputStream(file)) {
rootDir = file.getParentFile();
header = new IndexHeader(is, rootDir, dataFiles, externalFilesDir);
int tsize = kIndexTablesize;
if (header.table_len > 0) {
tsize = header.table_len;
}
table = new CacheAddr[tsize];
for (int i = 0; i < tsize; i++) {
table[i] = new CacheAddr(is, rootDir, dataFiles, externalFilesDir);
}
}
}
}

View File

@@ -0,0 +1,64 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache.chrome;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.Map;
/**
*
* @author JPEXS
*/
public class IndexHeader {
long magic; //c3 ca 03 c1
long version; //01 00 02 00
int num_entries;
int num_bytes;
int last_file;
int this_id;
CacheAddr stats;
int table_len;
int crash;
int experiment;
long create_time;
int pad[] = new int[52];
LruData lru;
public IndexHeader(InputStream is, File rootDir, Map<Integer, RandomAccessFile> dataFiles, File externalFilesDir) throws IOException {
IndexInputStream iis = new IndexInputStream(is);
magic = iis.readUInt32();
version = iis.readUInt32();
num_entries = iis.readInt32();
num_bytes = iis.readInt32();
last_file = iis.readInt32();
this_id = iis.readInt32();
stats = new CacheAddr(iis, rootDir, dataFiles, externalFilesDir);
table_len = iis.readInt32();
crash = iis.readInt32();
experiment = iis.readInt32();
create_time = iis.readUInt64();
pad = new int[52];
for (int i = 0; i < 52; i++) {
pad[i] = iis.readInt32();
}
lru = new LruData(is, rootDir, dataFiles, externalFilesDir);
}
}

View File

@@ -0,0 +1,79 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache.chrome;
import java.io.IOException;
import java.io.InputStream;
/**
*
* @author JPEXS
*/
public class IndexInputStream extends InputStream {
private final InputStream is;
public long pos = 0;
public long getPos() {
return pos;
}
public IndexInputStream(InputStream is) {
this.is = is;
}
@Override
public int read() throws IOException {
int r = is.read();
//System.out.print("$"+Integer.toHexString(r));
pos++;
return r;
}
public long readUInt32() throws IOException {
long r = (((long) read()) + ((long) (read() << 8)) + ((long) (read() << 16)) + ((long) (read() << 24))) & 0xffffffffL;
//System.out.println("");
return r;
}
public long readUInt64() throws IOException {
return readUInt32() + (readUInt32() << 32);
}
public long readInt64() throws IOException {
return readUInt64(); //FIXME
}
public int readInt32() throws IOException {
return (int) readUInt32();
}
public int readInt16() throws IOException {
return (short) ((int) read() + (int) (read() << 8));
}
public long readInt() throws IOException {
return readInt32();
}
public String readString() throws IOException {
int len = (int) readInt();
byte data[] = new byte[len];
read(data);
return new String(data);
}
}

View File

@@ -0,0 +1,71 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache.chrome;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.Map;
/**
*
* @author JPEXS
*/
public class LruData {
int pad1[] = new int[2];
int filled;
int sizes[] = new int[5];
CacheAddr heads[] = new CacheAddr[5];
CacheAddr tails[] = new CacheAddr[5];
CacheAddr transaction;
int operation;
int operation_list;
int pad2[] = new int[7];
public LruData(InputStream is, File rootDir, Map<Integer, RandomAccessFile> dataFiles, File externalFilesDir) throws IOException {
IndexInputStream iis = new IndexInputStream(is);
pad1 = new int[2];
pad1[0] = iis.readInt32();
pad1[1] = iis.readInt32();
filled = iis.readInt32();
sizes = new int[5];
for (int i = 0; i < 5; i++) {
sizes[i] = iis.readInt32();
}
sizes = new int[5];
for (int i = 0; i < 5; i++) {
sizes[i] = iis.readInt32();
}
heads = new CacheAddr[5];
for (int i = 0; i < 5; i++) {
heads[i] = new CacheAddr(is, rootDir, dataFiles, externalFilesDir);
}
tails = new CacheAddr[5];
for (int i = 0; i < 5; i++) {
tails[i] = new CacheAddr(is, rootDir, dataFiles, externalFilesDir);
}
transaction = new CacheAddr(is, rootDir, dataFiles, externalFilesDir);
operation = iis.readInt32();
operation_list = iis.readInt32();
pad2 = new int[7];
for (int i = 0; i < 7; i++) {
pad2[i] = iis.readInt32();
}
}
}

View File

@@ -0,0 +1,32 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache.chrome;
/**
*
* @author JPEXS
*/
public class RankingsNode {
public long last_used;
public long last_modified;
CacheAddr next;
CacheAddr prev;
CacheAddr contents;
int dirty;
long self_hash;
}

View File

@@ -0,0 +1,51 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache.firefox;
import java.io.IOException;
import java.io.InputStream;
/**
*
* @author JPEXS
*/
public class CacheInputStream extends InputStream {
private final InputStream is;
@Override
public int available() throws IOException {
return is.available();
}
public CacheInputStream(InputStream is) {
this.is = is;
}
@Override
public int read() throws IOException {
return is.read();
}
public long readInt32() throws IOException {
return (read() << 24) + (read() << 16) + (read() << 8) + read();
}
public int readInt16() throws IOException {
return (read() << 8) + read();
}
}

View File

@@ -0,0 +1,72 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache.firefox;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
* @author JPEXS
*/
public class CacheMap {
public long version;
public long datasize;
public long entryCount;
public long dirtyFlag;
public long recordCount;
public long evictionRank[];
public long bucketUsage[];
public List<MapBucket> mapBuckets;
public CacheMap(File file) throws IOException {
File cacheDir = file.getParentFile();
CacheInputStream cis = new CacheInputStream(new FileInputStream(file));
version = cis.readInt32();
datasize = cis.readInt32();
entryCount = cis.readInt32();
dirtyFlag = cis.readInt32();
recordCount = cis.readInt32();
evictionRank = new long[32];
for (int i = 0; i < evictionRank.length; i++) {
evictionRank[i] = cis.readInt32();
}
bucketUsage = new long[32];
for (int i = 0; i < bucketUsage.length; i++) {
bucketUsage[i] = cis.readInt32();
}
mapBuckets = new ArrayList<>();
Map<Integer, RandomAccessFile> cacheFiles = new HashMap<>();
for (int i = 1; i <= 3; i++) {
cacheFiles.put(i, new RandomAccessFile(new File(cacheDir, "_CACHE_00" + i + "_"), "r"));
}
while (cis.available() > 0) {
MapBucket mb = new MapBucket(cis, cacheDir, cacheFiles);
if (mb.hash == 0) {
continue;
}
mapBuckets.add(mb);
}
}
}

View File

@@ -0,0 +1,161 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache.firefox;
import com.jpexs.browsers.cache.CacheEntry;
import com.jpexs.browsers.cache.CacheImplementation;
import java.io.File;
import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class FirefoxCache implements CacheImplementation {
private static FirefoxCache instance;
private FirefoxCache() {
}
public static FirefoxCache getInstance() {
if (instance == null) {
instance = new FirefoxCache();
}
return instance;
}
private boolean loaded = false;
private CacheMap map;
@Override
public void refresh() {
File dir = getCacheDirectory();
if (dir == null) {
return;
}
File cacheMapFile = new File(dir, "_CACHE_MAP_");
try {
map = new CacheMap(cacheMapFile);
} catch (IOException ex) {
Logger.getLogger(FirefoxCache.class.getName()).log(Level.SEVERE, null, ex);
}
loaded = true;
}
@Override
public List<CacheEntry> getEntries() {
if (!loaded) {
refresh();
}
if (map == null) {
return null;
}
List<CacheEntry> ret = new ArrayList<>();
ret.addAll(map.mapBuckets);
return ret;
}
private enum OSId {
WINDOWS, OSX, UNIX
}
private static OSId getOSId() {
PrivilegedAction<String> doGetOSName = new PrivilegedAction<String>() {
@Override
public String run() {
return System.getProperty("os.name");
}
};
OSId id = OSId.UNIX;
String osName = AccessController.doPrivileged(doGetOSName);
if (osName != null) {
if (osName.toLowerCase().startsWith("mac os x")) {
id = OSId.OSX;
} else if (osName.contains("Windows")) {
id = OSId.WINDOWS;
}
}
return id;
}
public static File getProfileDirectory() {
File profilesDir = getProfilesDirectory();
if (profilesDir == null) {
return null;
}
File profiles[] = profilesDir.listFiles();
File profileDir = null;
for (File f : profiles) {
if (f.isDirectory()) {
if (f.getName().matches("[a-z0-9]+\\.default")) {
profileDir = f;
break;
}
}
}
return profileDir;
}
public static File getCacheDirectory() {
File profileDir = getProfileDirectory();
File cacheDir = null;
if (profileDir != null) {
cacheDir = new File(profileDir, "Cache");
}
if (cacheDir == null) {
return null;
}
if (!cacheDir.exists()) {
return null;
}
return cacheDir;
}
public static File getProfilesDirectory() {
String userHome = null;
File profilesDir = null;
try {
userHome = System.getProperty("user.home");
} catch (SecurityException ignore) {
}
if (userHome != null) {
OSId osId = getOSId();
if (osId == OSId.WINDOWS) {
profilesDir = new File(userHome + "\\AppData\\Local\\Mozilla\\Firefox\\Profiles");
if (!profilesDir.exists()) {
profilesDir = new File(userHome + "\\Local Settings\\Application Data\\Mozilla\\Firefox\\Profiles");
}
} else if (osId == OSId.OSX) {
profilesDir = new File(userHome + "/Library/Caches/Firefox/Profiles");
} else {
profilesDir = new File(userHome + "/.mozilla/firefox");
}
}
if ((profilesDir == null) || !profilesDir.exists()) {
return null;
}
return profilesDir;
}
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright (C) 2010-2014 etrik
*
* 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.browsers.cache.firefox;
/**
*
* @author petrik
*/
public class IncompatibleVersionException extends Exception {
public IncompatibleVersionException(int version) {
super("Incompatible version: " + version);
}
}

View File

@@ -0,0 +1,116 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache.firefox;
import com.jpexs.browsers.cache.RafInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.Map;
/**
*
* @author JPEXS
*/
public class Location {
public int locationSelector;
public int extraBlocks;
public long blockNumber;
public int fileGeneration;
public int fileSize;
public boolean isMetadata;
public long hash;
private final File rootDir;
public static final long eReservedMask = 0x4C000000L;
public static final long eLocationSelectorMask = 0x30000000L;
public static final int eLocationSelectorOffset = 28;
public static final long eExtraBlocksMask = 0x03000000L;
public static final int eExtraBlocksOffset = 24;
public static final long eBlockNumberMask = 0x00FFFFFFL;
public static final long eFileGenerationMask = 0x000000FFL;
public static final long eFileSizeMask = 0x00FFFF00L;
public static final int eFileSizeOffset = 8;
public static final long eFileReservedMask = 0x4F000000L;
public static int size_shift(int idx) {
return (2 * ((idx) - 1));
}
public static int bitmapSizeForIndex(int idx) {
return ((idx > 0) ? (131072 >> size_shift(idx)) : 0);
}
public static int blockSizeForIndex(int idx) {
return ((idx > 0) ? (256 << size_shift(idx)) : 0);
}
/*
#define BLOCK_SIZE_FOR_INDEX(idx) ((idx) ? (256 << SIZE_SHIFT(idx)) : 0)
#define BITMAP_SIZE_FOR_INDEX(idx) ((idx) ? (131072 >> SIZE_SHIFT(idx)) : 0)
*/
private final Map<Integer, RandomAccessFile> dataFiles;
public InputStream getInputStream() throws IOException {
String fileName = getFileName();
if (locationSelector > 0) {
RandomAccessFile raf = dataFiles.get(locationSelector);
raf.seek(bitmapSizeForIndex(locationSelector) / 8 + blockSizeForIndex(locationSelector) * blockNumber);
return new RafInputStream(raf);
}
return new FileInputStream(new File(rootDir, fileName));
}
public Location(long val, boolean isMetadata, long hash, File rootDir, Map<Integer, RandomAccessFile> dataFiles) {
this.hash = hash;
this.dataFiles = dataFiles;
this.rootDir = rootDir;
this.isMetadata = isMetadata;
locationSelector = (int) ((val & eLocationSelectorMask) >> eLocationSelectorOffset);
if (locationSelector > 0) {
extraBlocks = (int) ((val & eExtraBlocksMask) >> eExtraBlocksOffset);
blockNumber = (int) (val & eBlockNumberMask);
} else {
fileSize = (int) ((val & eFileSizeMask) >> eFileSizeOffset);
fileGeneration = (int) (val & eFileGenerationMask);
}
}
public String getFileName() {
if (locationSelector > 0) {
return "_CACHE_00" + locationSelector + "_";
}
String hashHex = Long.toHexString(hash & 0xffffffffL).toUpperCase();
while (hashHex.length() < 8) {
hashHex = "0" + hashHex;
}
String genHex = Integer.toHexString(fileGeneration);
while (genHex.length() < 2) {
genHex = "0" + genHex;
}
return hashHex.charAt(0) + File.separator + hashHex.substring(1, 1 + 2) + File.separator + hashHex.substring(3) + (isMetadata ? "m" : "d") + genHex;
}
@Override
public String toString() {
if (locationSelector > 0) {
return getFileName() + " block " + blockNumber + " extraBlocks " + extraBlocks;
}
return getFileName();
}
}

View File

@@ -0,0 +1,129 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache.firefox;
import com.jpexs.browsers.cache.CacheEntry;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class MapBucket extends CacheEntry {
public long hash;
public long enviction;
public Location dataLocation;
public Location metadataLocation;
private MetaData metadata;
public MapBucket(InputStream is, File rootDir, Map<Integer, RandomAccessFile> dataFiles) throws IOException {
CacheInputStream cis = new CacheInputStream(is);
hash = cis.readInt32();
enviction = cis.readInt32();
dataLocation = new Location(cis.readInt32(), false, hash, rootDir, dataFiles);
metadataLocation = new Location(cis.readInt32(), true, hash, rootDir, dataFiles);
}
public InputStream getMetaDataStream() throws IOException {
return metadataLocation.getInputStream();
}
public MetaData getMetaData() {
if (metadata == null) {
try {
metadata = new MetaData(getMetaDataStream());
} catch (IncompatibleVersionException ie) {
} catch (IOException ex) {
Logger.getLogger(MapBucket.class.getName()).log(Level.SEVERE, null, ex);
}
}
return metadata;
}
@Override
public String getRequestURL() {
String req = null;
MetaData m = getMetaData();
if (m == null) {
return null;
}
req = m.request;
if (req == null) {
return null;
}
if (req.startsWith("HTTP:")) {
req = req.substring("HTTP:".length());
}
return req;
}
@Override
public Map<String, String> getResponseHeaders() {
MetaData m = getMetaData();
if (m == null) {
return null;
}
String responseHead = m.response.get("response-head");
if (responseHead == null) {
return null;
}
String headers[] = responseHead.split("\r\n");
Map<String, String> ret = new HashMap<>();
for (int h = 1; h < headers.length; h++) {
String hs = headers[h];
if (hs.contains(":")) {
String hp[] = hs.split(":");
ret.put(hp[0].trim(), hp[1].trim());
}
}
return ret;
}
@Override
public String getStatusLine() {
MetaData m = getMetaData();
if (m == null) {
return null;
}
String responseHead = m.response.get("response-head");
String headers[] = responseHead.split("\r\n");
return headers[0];
}
@Override
public String getRequestMethod() {
return "GET"; //No POST caching in Firefox
}
@Override
public InputStream getResponseRawDataStream() {
try {
return dataLocation.getInputStream();
} catch (IOException ex) {
Logger.getLogger(MapBucket.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
}

View File

@@ -0,0 +1,79 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.browsers.cache.firefox;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author JPEXS
*/
public class MetaData {
public int majorVersion;
public int minorVersion;
public long location;
public long fetchCount;
public long firstFetchTime;
public long lastFetchTime;
public long expireTime;
public long dataSize;
public long requestSize;
public long infoSize;
public String request;
public Map<String, String> response;
public MetaData(InputStream is) throws IOException, IncompatibleVersionException {
CacheInputStream cis = new CacheInputStream(is);
majorVersion = cis.readInt16();
if (majorVersion != 1) {
throw new IncompatibleVersionException(majorVersion);
}
minorVersion = cis.readInt16();
location = cis.readInt32();
fetchCount = cis.readInt32();
firstFetchTime = cis.readInt32();
lastFetchTime = cis.readInt32();
expireTime = cis.readInt32();
dataSize = cis.readInt32();
requestSize = cis.readInt32();
infoSize = cis.readInt32();
byte req[] = new byte[(int) requestSize];
cis.read(req);
request = new String(req, 0, (int) requestSize - 1/*Ends with char 0*/);
byte res[] = new byte[(int) infoSize];
cis.read(res);
String responseStr = new String(res);
int nulpos;
boolean inKey = true;
String key = null;
response = new HashMap<>();
while ((nulpos = responseStr.indexOf(0)) > 0) {
String v = responseStr.substring(0, nulpos);
responseStr = responseStr.substring(nulpos + 1);
if (inKey) {
key = v;
} else {
response.put(key, v);
}
inKey = !inKey;
}
}
}

View File

@@ -0,0 +1,33 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
/**
*
* @author JPEXS
*/
public interface AbortRetryIgnoreHandler {
public static int UNDEFINED = -1;
public static int ABORT = 0;
public static int RETRY = 1;
public static int IGNORE = 2;
public int handle(Throwable thrown);
public AbortRetryIgnoreHandler getNewInstance();
}

View File

@@ -0,0 +1,56 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
import java.util.ResourceBundle;
/**
*
* @author JPEXS
*/
public class AppStrings {
private static Class resourceClass;
private static ResourceBundle resourceBundle;
public static void setResourceClass(Class cls) {
resourceClass = cls;
updateLanguage();
}
public static String getResourcePath(Class cls) {
String name = cls.getName();
if (name.startsWith("com.jpexs.decompiler.flash.gui.")) {
name = name.substring("com.jpexs.decompiler.flash.gui.".length());
name = "com.jpexs.decompiler.flash.gui.locales." + name;
}
return name;
}
public static String translate(String key) {
return resourceBundle.getString(key);
}
public static String translate(String bundle, String key) {
ResourceBundle b = ResourceBundle.getBundle(bundle);
return b.getString(key);
}
public static void updateLanguage() {
resourceBundle = ResourceBundle.getBundle(getResourcePath(resourceClass));
}
}

View File

@@ -0,0 +1,64 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
import java.io.IOException;
import java.util.Properties;
/**
*
* @author JPEXS
*/
public class ApplicationInfo {
public static final String APPLICATION_NAME = "JPEXS Free Flash Decompiler";
public static final String SHORT_APPLICATION_NAME = "FFDec";
public static final String VENDOR = "JPEXS";
public static String version = "";
public static String build = "";
public static boolean nightly = false;
public static String applicationVerName;
public static String shortApplicationVerName;
public static final String PROJECT_PAGE = "http://www.free-decompiler.com/flash";
public static String updatePageStub = "http://www.free-decompiler.com/flash/update.html?currentVersion=";
public static String updatePage;
static {
loadProperties();
}
private static void loadProperties() {
Properties prop = new Properties();
try {
prop.load(ApplicationInfo.class.getResourceAsStream("/project.properties"));
version = prop.getProperty("version");
build = prop.getProperty("build");
nightly = prop.getProperty("nightly").equals("true");
if (nightly) {
version = version + " nightly build " + build;
}
} catch (IOException | NullPointerException ex) {
//ignore
version = "unknown";
}
applicationVerName = APPLICATION_NAME + " v." + version;
updatePage = updatePageStub + version;
shortApplicationVerName = SHORT_APPLICATION_NAME + " v." + version;
}
}

View File

@@ -0,0 +1,25 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
/**
*
* @author JPEXS
*/
public abstract class BaseLocalData {
}

View File

@@ -0,0 +1,85 @@
/*
* 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.decompiler.flash;
import com.jpexs.helpers.SwfHeaderStreamSearch;
import com.jpexs.helpers.streams.SeekableInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
*
* @author JPEXS
*/
public class BinarySWFBundle implements SWFBundle {
private final SWFSearch search;
public BinarySWFBundle(InputStream is, boolean noCheck, SearchMode searchMode) {
search = new SWFSearch(new SwfHeaderStreamSearch(is), noCheck, searchMode);
search.process();
}
@Override
public int length() {
return search.length();
}
@Override
public Set<String> getKeys() {
Set<String> ret = new HashSet<>();
for (Long address : search.getAddresses()) {
ret.add("[" + address + "]");
}
return ret;
}
@Override
public SeekableInputStream getSWF(String key) {
if (!key.startsWith("[")) {
return null;
}
if (!key.endsWith("]")) {
return null;
}
key = key.substring(1, key.length() - 1);
try {
int address = Integer.parseInt(key);
return search.get(null, address);
} catch (IOException | NumberFormatException iex) {
return null;
}
}
@Override
public Map<String, SeekableInputStream> getAll() {
Map<String, SeekableInputStream> ret = new HashMap<>();
for (String key : getKeys()) {
ret.put(key, getSWF(key));
}
return ret;
}
@Override
public String getExtension() {
return "bin";
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
/**
*
* @author JPEXS
*/
public interface DisassemblyListener {
public void progress(String phase, long pos, long total);
}

View File

@@ -0,0 +1,28 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
/**
*
* @author JPEXS
*/
public class EndOfStreamException extends RuntimeException {
public EndOfStreamException() {
super("Premature end of the stream reached");
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
/**
*
* @author JPEXS
*/
public interface EventListener {
public void handleEvent(String event, Object data);
}

View File

@@ -0,0 +1,32 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
import java.util.HashSet;
/**
*
* @author JPEXS
*/
public class FinalProcessLocalData {
public final HashSet<Integer> temporaryRegisters;
public FinalProcessLocalData() {
temporaryRegisters = new HashSet<>();
}
}

View File

@@ -0,0 +1,55 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
import java.io.IOException;
/**
*
* @author JPEXS
*/
public class RetryTask {
private final RunnableIOEx r;
private final AbortRetryIgnoreHandler handler;
public Object result;
public RetryTask(RunnableIOEx r, AbortRetryIgnoreHandler handler) {
this.r = r;
this.handler = handler;
}
public void run() throws IOException {
boolean retry;
do {
retry = false;
try {
r.run();
} catch (Exception ex) {
switch (handler.handle(ex)) {
case AbortRetryIgnoreHandler.ABORT:
throw ex;
case AbortRetryIgnoreHandler.RETRY:
retry = true;
break;
case AbortRetryIgnoreHandler.IGNORE:
break;
}
}
} while (retry);
}
}

View File

@@ -0,0 +1,28 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
import java.io.IOException;
/**
*
* @author JPEXS
*/
public interface RunnableIOEx {
public void run() throws IOException;
}

View File

@@ -0,0 +1,27 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
/**
*
* @param <T>
* @author JPEXS
*/
public abstract class RunnableIOExResult<T> implements RunnableIOEx {
public T result;
}

View 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.decompiler.flash;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
*
* @author JPEXS
*/
public class SWC extends ZippedSWFBundle {
public SWC(InputStream is) throws IOException {
super(is);
keySet.clear();
this.is.reset();
ZipInputStream zip = new ZipInputStream(this.is);
ZipEntry entry;
try {
while ((entry = zip.getNextEntry()) != null) {
if (entry.getName().equals("catalog.xml")) {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
DefaultHandler handler = new DefaultHandler() {
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (qName.equalsIgnoreCase("library")) {
String path = attributes.getValue("path");
if (path != null) {
keySet.add(path);
}
}
}
};
saxParser.parse(zip, handler);
} catch (Exception ex) {
}
return;
}
}
} catch (IOException ex) {
Logger.getLogger(ZippedSWFBundle.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
public String getExtension() {
return "swc";
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
/*
* 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.decompiler.flash;
import com.jpexs.helpers.streams.SeekableInputStream;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
/**
*
* @author JPEXS
*/
public interface SWFBundle {
public int length();
public Set<String> getKeys();
public SeekableInputStream getSWF(String key) throws IOException;
public Map<String, SeekableInputStream> getAll() throws IOException;
public String getExtension();
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,151 @@
/*
* 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.decompiler.flash;
import com.jpexs.helpers.MemoryInputStream;
import com.jpexs.helpers.PosMarkedInputStream;
import com.jpexs.helpers.ProgressListener;
import com.jpexs.helpers.Searchable;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
*
* @author JPEXS
*/
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, SearchMode searchMode) {
this.s = s;
this.noCheck = noCheck;
this.searchMode = searchMode;
}
public void addProgressListener(ProgressListener l) {
listeners.add(l);
}
public void removeProgressListener(ProgressListener l) {
listeners.remove(l);
}
private void setProgress(int p) {
for (ProgressListener l : listeners) {
l.progress(p);
}
}
public void process() {
Map<Long, InputStream> ret = new HashMap<>();
ret = s.search(new ProgressListener() {
@Override
public void progress(int p) {
setProgress(p);
}
},
"FWS".getBytes(), //Uncompressed Flash
"CWS".getBytes(), //ZLib compressed Flash
"ZWS".getBytes(), //LZMA compressed Flash
"GFX".getBytes(), //Uncompressed ScaleForm GFx
"CFX".getBytes()); //Compressed ScaleForm GFx
int pos = 0;
long biggestSize = 0;
long smallestSize = Long.MAX_VALUE;
addressLoop:
for (Long addr : ret.keySet()) {
setProgress(pos * 100 / ret.size());
pos++;
try {
MemoryInputStream mis = (MemoryInputStream) ret.get(addr);
mis.reset();
PosMarkedInputStream pmi = new PosMarkedInputStream(mis);
SWF swf = noCheck ? new SWF(pmi) : new SWF(pmi, null, false, true);
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);
}
break;
case SMALLEST:
if (limit < smallestSize) {
smallestSize = limit;
swfStreams.clear();
swfStreams.put(addr, is);
}
break;
case FIRST:
swfStreams.put(addr, is);
break addressLoop;
case LAST:
swfStreams.clear();
swfStreams.put(addr, is);
break;
}
}
} catch (OutOfMemoryError ome) {
System.gc();
} catch (Exception | Error ex) {
}
}
setProgress(100);
processed = true;
}
public MemoryInputStream get(ProgressListener listener, long address) throws IOException {
if (!processed) {
return null;
}
if (!swfStreams.containsKey(address)) {
return null;
}
return swfStreams.get(address);
}
public Set<Long> getAddresses() {
return swfStreams.keySet();
}
public int length() {
if (!processed) {
return 0;
}
return swfStreams.size();
}
}

View File

@@ -0,0 +1,95 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
import com.jpexs.helpers.Path;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
*
* @author JPEXS
*/
public class SWFSourceInfo {
private final InputStream inputStream;
private final String file;
private final String fileTitle;
public SWFSourceInfo(InputStream inputStream, String file, String fileTitle) {
this.inputStream = inputStream;
this.file = file;
this.fileTitle = fileTitle;
}
public InputStream getInputStream() {
return inputStream;
}
public String getFile() {
return file;
}
public String getFileTitle() {
return fileTitle;
}
/**
* Get title of the file
*
* @return file title
*/
public String getFileTitleOrName() {
if (fileTitle != null) {
return fileTitle;
}
return file;
}
public boolean isBundle() {
if (inputStream == null) {
File fileObj = new File(file);
String fileName = fileObj.getName();
if (fileName.startsWith("asdec_") && fileName.endsWith(".tmp")) {
return false;
}
String extension = Path.getExtension(fileObj);
return !(extension.equals(".swf") || extension.equals(".gfx"));
}
return false;
}
public SWFBundle getBundle(boolean noCheck, SearchMode searchMode) throws IOException {
if (!isBundle()) {
return null;
}
String extension = Path.getExtension(new File(file));
InputStream is = new BufferedInputStream(new FileInputStream(file));
switch (extension) {
case ".swc":
return new SWC(is);
case ".zip":
return new ZippedSWFBundle(is);
default:
return new BinarySWFBundle(is, noCheck, searchMode);
}
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
/**
*
* @author JPEXS
*/
public enum SearchMode {
ALL, BIGGEST, SMALLEST, FIRST, LAST
}

View File

@@ -0,0 +1,60 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
import com.jpexs.decompiler.flash.abc.types.ABCException;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.ScriptInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
* @author JPEXS
*/
public class SourceGeneratorLocalData implements Serializable {
public HashMap<String, Integer> registerVars;
public Integer inFunction;
public Boolean inMethod;
public Integer forInLevel;
//TODO: handle AVM2 separately
public List<ABCException> exceptions = new ArrayList<>();
public List<Integer> finallyCatches = new ArrayList<Integer>();
public Map<Integer, Integer> finallyCounter = new HashMap<>();
public int finallyRegister = -1;
public String currentClass;
public int activationReg = 0;
public List<MethodBody> callStack = new ArrayList<>();
public Map<MethodBody, List<Integer>> traitUsages = new HashMap<>();
public String pkg = "";
public List<GraphTargetItem> scopeStack = new ArrayList<GraphTargetItem>();
public boolean documentClass;
public ScriptInfo currentScript;
public SourceGeneratorLocalData(HashMap<String, Integer> registerVars, Integer inFunction, Boolean inMethod, Integer forInLevel) {
this.registerVars = registerVars;
this.inFunction = inFunction;
this.inMethod = inMethod;
this.forInLevel = forInLevel;
}
}

View File

@@ -0,0 +1,39 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
* @author JPEXS
*/
public class Version {
public int versionId;
public String revision;
public String versionName;
public String longVersionName;
public String releaseDate;
public String appName;
public String appFullName;
public String updateLink;
public boolean nightly;
public Map<String, List<String>> changes = new HashMap<>();
}

View File

@@ -0,0 +1,110 @@
/*
* 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.decompiler.flash;
import com.jpexs.helpers.Helper;
import com.jpexs.helpers.MemoryInputStream;
import com.jpexs.helpers.ReReadableInputStream;
import com.jpexs.helpers.streams.SeekableInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
*
* @author JPEXS
*/
public class ZippedSWFBundle implements SWFBundle {
protected Set<String> keySet = new HashSet<>();
private final Map<String, SeekableInputStream> cachedSWFs = new HashMap<>();
protected ReReadableInputStream is;
public ZippedSWFBundle(InputStream is) {
this.is = new ReReadableInputStream(is);
ZipInputStream zip = new ZipInputStream(this.is);
ZipEntry entry;
try {
while ((entry = zip.getNextEntry()) != null) {
if (entry.getName().toLowerCase().endsWith(".swf")
|| entry.getName().toLowerCase().endsWith(".gfx")) {
keySet.add(entry.getName());
}
//streamMap.put(, is)
}
} catch (IOException ex) {
Logger.getLogger(ZippedSWFBundle.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
public int length() {
return keySet.size();
}
@Override
public Set<String> getKeys() {
return keySet;
}
@Override
public SeekableInputStream getSWF(String key) throws IOException {
if (!keySet.contains(key)) {
return null;
}
if (!cachedSWFs.containsKey(key)) {
this.is.reset();
ZipInputStream zip = new ZipInputStream(this.is);
ZipEntry entry;
try {
while ((entry = zip.getNextEntry()) != null) {
if (entry.getName().equals(key)) {
MemoryInputStream mis = new MemoryInputStream(Helper.readStream(zip));
cachedSWFs.put(key, mis);
break;
}
zip.closeEntry();
}
} catch (IOException ex) {
Logger.getLogger(ZippedSWFBundle.class.getName()).log(Level.SEVERE, null, ex);
}
}
return cachedSWFs.get(key);
}
@Override
public Map<String, SeekableInputStream> getAll() throws IOException {
for (String key : getKeys()) { //cache everything first
getSWF(key);
}
return cachedSWFs;
}
@Override
public String getExtension() {
return "zip";
}
}

View File

@@ -0,0 +1,948 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc;
import com.jpexs.decompiler.flash.EventListener;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Deobfuscation;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.UnknownInstructionCode;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallPropertyIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushStringIns;
import com.jpexs.decompiler.flash.abc.types.ABCException;
import com.jpexs.decompiler.flash.abc.types.ClassInfo;
import com.jpexs.decompiler.flash.abc.types.InstanceInfo;
import com.jpexs.decompiler.flash.abc.types.MetadataInfo;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.flash.abc.types.Namespace;
import com.jpexs.decompiler.flash.abc.types.NamespaceSet;
import com.jpexs.decompiler.flash.abc.types.ScriptInfo;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.abc.types.traits.TraitClass;
import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction;
import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter;
import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst;
import com.jpexs.decompiler.flash.abc.types.traits.Traits;
import com.jpexs.decompiler.flash.abc.usages.ClassNameMultinameUsage;
import com.jpexs.decompiler.flash.abc.usages.ConstVarNameMultinameUsage;
import com.jpexs.decompiler.flash.abc.usages.ConstVarTypeMultinameUsage;
import com.jpexs.decompiler.flash.abc.usages.ExtendsMultinameUsage;
import com.jpexs.decompiler.flash.abc.usages.ImplementsMultinameUsage;
import com.jpexs.decompiler.flash.abc.usages.MethodBodyMultinameUsage;
import com.jpexs.decompiler.flash.abc.usages.MethodNameMultinameUsage;
import com.jpexs.decompiler.flash.abc.usages.MethodParamsMultinameUsage;
import com.jpexs.decompiler.flash.abc.usages.MethodReturnTypeMultinameUsage;
import com.jpexs.decompiler.flash.abc.usages.MultinameUsage;
import com.jpexs.decompiler.flash.abc.usages.TypeNameMultinameUsage;
import com.jpexs.decompiler.flash.helpers.collections.MyEntry;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.helpers.utf8.Utf8PrintWriter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ABC {
public int major_version = 46;
public int minor_version = 16;
public ConstantPool constants = new ConstantPool();
public List<MethodInfo> method_info = new ArrayList<>();
public List<MetadataInfo> metadata_info = new ArrayList<>();
public List<InstanceInfo> instance_info = new ArrayList<>();
public List<ClassInfo> class_info = new ArrayList<>();
public List<ScriptInfo> script_info = new ArrayList<>();
public List<MethodBody> bodies = new ArrayList<>();
private List<Integer> bodyIdxFromMethodIdx = new ArrayList<>();
public long[] stringOffsets;
public static final int MINORwithDECIMAL = 17;
protected Set<EventListener> listeners = new HashSet<>();
private static final Logger logger = Logger.getLogger(ABC.class.getName());
private final AVM2Deobfuscation deobfuscation;
public SWF swf;
public ABCContainerTag parentTag;
public ABC(SWF swf) {
this.deobfuscation = null;
this.swf = swf;
constants.constant_double.add(null);
constants.constant_int.add(null);
constants.constant_uint.add(null);
constants.constant_string.add(null);
constants.constant_multiname.add(null);
constants.constant_namespace.add(null);
constants.constant_namespace_set.add(null);
}
public int addMethodBody(MethodBody body) {
bodies.add(body);
if (body.method_info >= bodyIdxFromMethodIdx.size()) {
int newlen = body.method_info + 1;
int oldlen = bodyIdxFromMethodIdx.size();
for (int i = oldlen; i < newlen; i++) {
bodyIdxFromMethodIdx.add(-1);
}
bodyIdxFromMethodIdx.set(body.method_info, bodies.size() - 1);
}
return bodies.size() - 1;
}
public int addMethodInfo(MethodInfo mi) {
method_info.add(mi);
return method_info.size() - 1;
}
public void addEventListener(EventListener listener) {
listeners.add(listener);
}
public void removeEventListener(EventListener listener) {
listeners.remove(listener);
}
protected void informListeners(String event, Object data) {
for (EventListener listener : listeners) {
listener.handleEvent(event, data);
}
}
public int removeTraps() throws InterruptedException {
int rem = 0;
for (int s = 0; s < script_info.size(); s++) {
rem += script_info.get(s).removeTraps(s, this, "");
}
return rem;
}
public int removeDeadCode() throws InterruptedException {
int rem = 0;
for (MethodBody body : bodies) {
rem += body.removeDeadCode(constants, null/*FIXME*/, method_info.get(body.method_info));
}
return rem;
}
public void restoreControlFlow() throws InterruptedException {
for (MethodBody body : bodies) {
body.restoreControlFlow(constants, null/*FIXME*/, method_info.get(body.method_info));
}
}
public Set<Integer> getNsStringUsages() {
Set<Integer> ret = new HashSet<>();
for (int n = 1; n < constants.getNamespaceCount(); n++) {
ret.add(constants.getNamespace(n).name_index);
}
return ret;
}
public Set<Integer> getStringUsages() {
Set<Integer> ret = new HashSet<>();
for (MethodBody body : bodies) {
for (AVM2Instruction ins : body.code.code) {
for (int i = 0; i < ins.definition.operands.length; i++) {
if (ins.definition.operands[i] == AVM2Code.DAT_STRING_INDEX) {
ret.add(ins.operands[i]);
}
}
}
}
return ret;
}
private void setStringUsageType(Map<Integer, String> ret, int strIndex, String usageType) {
if (ret.containsKey(strIndex)) {
if (!"name".equals(usageType)) {
if (!ret.get(strIndex).equals(usageType)) {
ret.put(strIndex, "name");
}
}
} else {
ret.put(strIndex, usageType);
}
}
private void getStringUsageTypes(Map<Integer, String> ret, Traits traits, boolean classesOnly) {
for (Trait t : traits.traits) {
int strIndex = constants.getMultiname(t.name_index).name_index;
String usageType = "";
if (t instanceof TraitClass) {
TraitClass tc = (TraitClass) t;
getStringUsageTypes(ret, class_info.get(tc.class_info).static_traits, classesOnly);
getStringUsageTypes(ret, instance_info.get(tc.class_info).instance_traits, classesOnly);
if (instance_info.get(tc.class_info).name_index != 0) {
setStringUsageType(ret, constants.getMultiname(instance_info.get(tc.class_info).name_index).name_index, "class");
}
if (instance_info.get(tc.class_info).super_index != 0) {
setStringUsageType(ret, constants.getMultiname(instance_info.get(tc.class_info).super_index).name_index, "class");
}
usageType = "class";
}
if (t instanceof TraitMethodGetterSetter) {
TraitMethodGetterSetter tm = (TraitMethodGetterSetter) t;
usageType = "method";
MethodBody body = findBody(tm.method_info);
if (body != null) {
getStringUsageTypes(ret, body.traits, classesOnly);
}
}
if (t instanceof TraitFunction) {
TraitFunction tf = (TraitFunction) t;
MethodBody body = findBody(tf.method_info);
if (body != null) {
getStringUsageTypes(ret, body.traits, classesOnly);
}
usageType = "function";
}
if (t instanceof TraitSlotConst) {
TraitSlotConst ts = (TraitSlotConst) t;
if (ts.isVar()) {
usageType = "var";
}
if (ts.isConst()) {
usageType = "const";
}
}
if (usageType.equals("class") || (!classesOnly)) {
setStringUsageType(ret, strIndex, usageType);
}
}
}
public void getStringUsageTypes(Map<Integer, String> ret, boolean classesOnly) {
for (ScriptInfo script : script_info) {
getStringUsageTypes(ret, script.traits, classesOnly);
}
}
public void renameMultiname(int multinameIndex, String newname) {
if (multinameIndex <= 0 || multinameIndex >= constants.getMultinameCount()) {
throw new IllegalArgumentException("Multiname with index " + multinameIndex + " does not exist");
}
Set<Integer> stringUsages = getStringUsages();
Set<Integer> namespaceUsages = getNsStringUsages();
int strIndex = constants.getMultiname(multinameIndex).name_index;
if (stringUsages.contains(strIndex) || namespaceUsages.contains(strIndex)) { //name is used elsewhere as string literal
strIndex = constants.getStringId(newname, true);
constants.getMultiname(multinameIndex).name_index = strIndex;
} else {
constants.setString(strIndex, newname);
}
}
public void deobfuscateIdentifiers(HashMap<String, String> namesMap, RenameType renameType, boolean classesOnly) {
Set<Integer> stringUsages = getStringUsages();
Set<Integer> namespaceUsages = getNsStringUsages();
Map<Integer, String> stringUsageTypes = new HashMap<>();
informListeners("deobfuscate", "Getting usage types...");
getStringUsageTypes(stringUsageTypes, classesOnly);
for (int i = 0; i < instance_info.size(); i++) {
informListeners("deobfuscate", "class " + i + "/" + instance_info.size());
InstanceInfo insti = instance_info.get(i);
if (insti.name_index != 0) {
constants.getMultiname(insti.name_index).name_index = deobfuscation.deobfuscateName(stringUsageTypes, stringUsages, namespaceUsages, namesMap, constants.getMultiname(insti.name_index).name_index, true, renameType);
if (constants.getMultiname(insti.name_index).namespace_index != 0) {
constants.getNamespace(constants.getMultiname(insti.name_index).namespace_index).name_index
= deobfuscation.deobfuscatePackageName(stringUsageTypes, stringUsages, namesMap, constants.getNamespace(constants.getMultiname(insti.name_index).namespace_index).name_index, renameType);
}
}
if (insti.super_index != 0) {
constants.getMultiname(insti.super_index).name_index = deobfuscation.deobfuscateName(stringUsageTypes, stringUsages, namespaceUsages, namesMap, constants.getMultiname(insti.super_index).name_index, true, renameType);
}
}
if (classesOnly) {
return;
}
for (int i = 1; i < constants.getMultinameCount(); i++) {
informListeners("deobfuscate", "name " + i + "/" + constants.getMultinameCount());
constants.getMultiname(i).name_index = deobfuscation.deobfuscateName(stringUsageTypes, stringUsages, namespaceUsages, namesMap, constants.getMultiname(i).name_index, false, renameType);
}
for (int i = 1; i < constants.getNamespaceCount(); i++) {
informListeners("deobfuscate", "namespace " + i + "/" + constants.getNamespaceCount());
if (constants.getNamespace(i).kind != Namespace.KIND_PACKAGE) { //only packages
continue;
}
constants.getNamespace(i).name_index = deobfuscation.deobfuscatePackageName(stringUsageTypes, stringUsages, namesMap, constants.getNamespace(i).name_index, renameType);
}
//process reflection using getDefinitionByName too
for (MethodBody body : bodies) {
for (int ip = 0; ip < body.code.code.size(); ip++) {
if (body.code.code.get(ip).definition instanceof CallPropertyIns) {
int mIndex = body.code.code.get(ip).operands[0];
if (mIndex > 0) {
Multiname m = constants.getMultiname(mIndex);
if (m.getNameWithNamespace(constants).equals("flash.utils.getDefinitionByName")) {
if (ip > 0) {
if (body.code.code.get(ip - 1).definition instanceof PushStringIns) {
int strIndex = body.code.code.get(ip - 1).operands[0];
String fullname = constants.getString(strIndex);
String pkg = "";
String name = fullname;
if (fullname.contains(".")) {
pkg = fullname.substring(0, fullname.lastIndexOf('.'));
name = fullname.substring(fullname.lastIndexOf('.') + 1);
}
if (!pkg.isEmpty()) {
int pkgStrIndex = constants.getStringId(pkg, true);
pkgStrIndex = deobfuscation.deobfuscatePackageName(stringUsageTypes, stringUsages, namesMap, pkgStrIndex, renameType);
pkg = constants.getString(pkgStrIndex);
}
int nameStrIndex = constants.getStringId(name, true);
nameStrIndex = deobfuscation.deobfuscateName(stringUsageTypes, stringUsages, namespaceUsages, namesMap, nameStrIndex, true, renameType);
name = constants.getString(nameStrIndex);
String fullChanged = "";
if (!pkg.isEmpty()) {
fullChanged = pkg + ".";
}
fullChanged += name;
strIndex = constants.getStringId(fullChanged, true);
body.code.code.get(ip - 1).operands[0] = strIndex;
}
}
}
}
}
}
}
}
public ABC(InputStream is, SWF swf, ABCContainerTag tag) throws IOException {
this.swf = swf;
this.parentTag = tag;
ABCInputStream ais = new ABCInputStream(is);
minor_version = ais.readU16();
major_version = ais.readU16();
logger.log(Level.FINE, "ABC minor_version: {0}, major_version: {1}", new Object[]{minor_version, major_version});
constants = new ConstantPool();
deobfuscation = new AVM2Deobfuscation(constants);
//constant integers
int constant_int_pool_count = ais.readU30();
constants.constant_int = new ArrayList<>(constant_int_pool_count);
if (constant_int_pool_count > 0) {
constants.addInt(0);
}
for (int i = 1; i < constant_int_pool_count; i++) { //index 0 not used. Values 1..n-1
constants.addInt(ais.readS32());
}
//constant unsigned integers
int constant_uint_pool_count = ais.readU30();
constants.constant_uint = new ArrayList<>(constant_uint_pool_count);
if (constant_uint_pool_count > 0) {
constants.addUInt(0);
}
for (int i = 1; i < constant_uint_pool_count; i++) { //index 0 not used. Values 1..n-1
constants.addUInt(ais.readU32());
}
//constant double
int constant_double_pool_count = ais.readU30();
constants.constant_double = new ArrayList<>(constant_double_pool_count);
if (constant_double_pool_count > 0) {
constants.addDouble(0);
}
for (int i = 1; i < constant_double_pool_count; i++) { //index 0 not used. Values 1..n-1
constants.addDouble(ais.readDouble());
}
//constant decimal
if (minor_version >= MINORwithDECIMAL) {
int constant_decimal_pool_count = ais.readU30();
constants.constant_decimal = new ArrayList<>(constant_decimal_pool_count);
if (constant_decimal_pool_count > 0) {
constants.addDecimal(null);
}
for (int i = 1; i < constant_decimal_pool_count; i++) { //index 0 not used. Values 1..n-1
constants.addDecimal(ais.readDecimal());
}
} else {
constants.constant_decimal = new ArrayList<>(0);
}
//constant string
int constant_string_pool_count = ais.readU30();
constants.constant_string = new ArrayList<>(constant_string_pool_count);
stringOffsets = new long[constant_string_pool_count];
if (constant_string_pool_count > 0) {
constants.addString("");
}
for (int i = 1; i < constant_string_pool_count; i++) { //index 0 not used. Values 1..n-1
long pos = ais.getPosition();
constants.addString(ais.readString());
stringOffsets[i] = pos;
}
//constant namespace
int constant_namespace_pool_count = ais.readU30();
constants.constant_namespace = new ArrayList<>(constant_namespace_pool_count);
if (constant_namespace_pool_count > 0) {
constants.addNamespace(null);
}
for (int i = 1; i < constant_namespace_pool_count; i++) { //index 0 not used. Values 1..n-1
constants.addNamespace(ais.readNamespace());
}
//constant namespace set
int constant_namespace_set_pool_count = ais.readU30();
constants.constant_namespace_set = new ArrayList<>(constant_namespace_set_pool_count);
if (constant_namespace_set_pool_count > 0) {
constants.addNamespaceSet(null);
}
for (int i = 1; i < constant_namespace_set_pool_count; i++) { //index 0 not used. Values 1..n-1
constants.addNamespaceSet(new NamespaceSet());
int namespace_count = ais.readU30();
constants.getNamespaceSet(i).namespaces = new int[namespace_count];
for (int j = 0; j < namespace_count; j++) {
constants.getNamespaceSet(i).namespaces[j] = ais.readU30();
}
}
//constant multiname
int constant_multiname_pool_count = ais.readU30();
constants.constant_multiname = new ArrayList<>(constant_multiname_pool_count);
if (constant_multiname_pool_count > 0) {
constants.addMultiname(null);
}
for (int i = 1; i < constant_multiname_pool_count; i++) { //index 0 not used. Values 1..n-1
constants.addMultiname(ais.readMultiname());
}
//method info
int methods_count = ais.readU30();
method_info = new ArrayList<>();//MethodInfo[methods_count];
bodyIdxFromMethodIdx = new ArrayList<>(); //[methods_count];
for (int i = 0; i < methods_count; i++) {
method_info.add(ais.readMethodInfo());
bodyIdxFromMethodIdx.add(-1);
}
//metadata info
int metadata_count = ais.readU30();
metadata_info = new ArrayList<>();
for (int i = 0; i < metadata_count; i++) {
int name_index = ais.readU30();
int values_count = ais.readU30();
int[] keys = new int[values_count];
for (int v = 0; v < values_count; v++) {
keys[v] = ais.readU30();
}
int[] values = new int[values_count];
for (int v = 0; v < values_count; v++) {
values[v] = ais.readU30();
}
metadata_info.add(new MetadataInfo(name_index, keys, values));
}
int class_count = ais.readU30();
instance_info = new ArrayList<>(); //InstanceInfo[class_count];
for (int i = 0; i < class_count; i++) {
instance_info.add(ais.readInstanceInfo());
}
class_info = new ArrayList<>(); //ClassInfo[class_count];
for (int i = 0; i < class_count; i++) {
ClassInfo ci = new ClassInfo();
ci.cinit_index = ais.readU30();
ci.static_traits = ais.readTraits();
class_info.add(ci);
}
int script_count = ais.readU30();
script_info = new ArrayList<>(); //ScriptInfo[script_count];
for (int i = 0; i < script_count; i++) {
ScriptInfo si = new ScriptInfo();
si.init_index = ais.readU30();
si.traits = ais.readTraits();
script_info.add(si);
}
int bodies_count = ais.readU30();
bodies = new ArrayList<>(); //MethodBody[bodies_count];
for (int i = 0; i < bodies_count; i++) {
MethodBody mb = new MethodBody();
mb.method_info = ais.readU30();
mb.max_stack = ais.readU30();
mb.max_regs = ais.readU30();
mb.init_scope_depth = ais.readU30();
mb.max_scope_depth = ais.readU30();
int code_length = ais.readU30();
mb.codeBytes = ais.readBytes(code_length);
try {
mb.code = new AVM2Code(new ByteArrayInputStream(mb.codeBytes));
} catch (UnknownInstructionCode re) {
mb.code = new AVM2Code();
Logger.getLogger(ABC.class.getName()).log(Level.SEVERE, null, re);
}
mb.code.compact();
int ex_count = ais.readU30();
mb.exceptions = new ABCException[ex_count];
for (int j = 0; j < ex_count; j++) {
ABCException abce = new ABCException();
abce.start = ais.readU30();
abce.end = ais.readU30();
abce.target = ais.readU30();
abce.type_index = ais.readU30();
abce.name_index = ais.readU30();
mb.exceptions[j] = abce;
}
mb.traits = ais.readTraits();
bodies.add(mb);
method_info.get(mb.method_info).setBody(mb);
bodyIdxFromMethodIdx.set(mb.method_info, i);
}
loadNamespaceMap();
/*for(int i=0;i<script_count;i++){
MethodBody bod=bodies.get(bodyIdxFromMethodIdx.get(script_info.get(i).init_index));
GraphTextWriter t=new HilightedTextWriter(Configuration.getCodeFormatting(),false);
try {
bod.toString("script", ScriptExportMode.PCODE, false,i, 0, this, null, constants, method_info, new Stack<GraphTargetItem>(), false, t ,new ArrayList<String>(), null);
} catch (InterruptedException ex) {
Logger.getLogger(ABC.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(""+t.toString());
}
System.exit(0);*/
}
public void saveToStream(OutputStream os) throws IOException {
ABCOutputStream aos = new ABCOutputStream(os);
aos.writeU16(minor_version);
aos.writeU16(major_version);
aos.writeU30(constants.getIntCount());
for (int i = 1; i < constants.getIntCount(); i++) {
aos.writeS32(constants.getInt(i));
}
aos.writeU30(constants.getUIntCount());
for (int i = 1; i < constants.getUIntCount(); i++) {
aos.writeU32(constants.getUInt(i));
}
aos.writeU30(constants.getDoubleCount());
for (int i = 1; i < constants.getDoubleCount(); i++) {
aos.writeDouble(constants.getDouble(i));
}
if (minor_version >= MINORwithDECIMAL) {
aos.writeU30(constants.getDecimalCount());
for (int i = 1; i < constants.getDecimalCount(); i++) {
aos.writeDecimal(constants.getDecimal(i));
}
}
aos.writeU30(constants.getStringCount());
for (int i = 1; i < constants.getStringCount(); i++) {
aos.writeString(constants.getString(i));
}
aos.writeU30(constants.getNamespaceCount());
for (int i = 1; i < constants.getNamespaceCount(); i++) {
aos.writeNamespace(constants.getNamespace(i));
}
aos.writeU30(constants.getNamespaceSetCount());
for (int i = 1; i < constants.getNamespaceSetCount(); i++) {
aos.writeU30(constants.getNamespaceSet(i).namespaces.length);
for (int j = 0; j < constants.getNamespaceSet(i).namespaces.length; j++) {
aos.writeU30(constants.getNamespaceSet(i).namespaces[j]);
}
}
aos.writeU30(constants.getMultinameCount());
for (int i = 1; i < constants.getMultinameCount(); i++) {
aos.writeMultiname(constants.getMultiname(i));
}
aos.writeU30(method_info.size());
for (MethodInfo mi : method_info) {
aos.writeMethodInfo(mi);
}
aos.writeU30(metadata_info.size());
for (MetadataInfo mi : metadata_info) {
aos.writeU30(mi.name_index);
aos.writeU30(mi.values.length);
for (int j = 0; j < mi.values.length; j++) {
aos.writeU30(mi.keys[j]);
}
for (int j = 0; j < mi.values.length; j++) {
aos.writeU30(mi.values[j]);
}
}
aos.writeU30(class_info.size());
for (InstanceInfo ii : instance_info) {
aos.writeInstanceInfo(ii);
}
for (ClassInfo ci : class_info) {
aos.writeU30(ci.cinit_index);
aos.writeTraits(ci.static_traits);
}
aos.writeU30(script_info.size());
for (ScriptInfo si : script_info) {
aos.writeU30(si.init_index);
aos.writeTraits(si.traits);
}
aos.writeU30(bodies.size());
for (MethodBody mb : bodies) {
aos.writeU30(mb.method_info);
aos.writeU30(mb.max_stack);
aos.writeU30(mb.max_regs);
aos.writeU30(mb.init_scope_depth);
aos.writeU30(mb.max_scope_depth);
byte[] codeBytes = mb.code.getBytes();
aos.writeU30(codeBytes.length);
aos.write(codeBytes);
aos.writeU30(mb.exceptions.length);
for (int j = 0; j < mb.exceptions.length; j++) {
aos.writeU30(mb.exceptions[j].start);
aos.writeU30(mb.exceptions[j].end);
aos.writeU30(mb.exceptions[j].target);
aos.writeU30(mb.exceptions[j].type_index);
aos.writeU30(mb.exceptions[j].name_index);
}
aos.writeTraits(mb.traits);
}
}
public MethodBody findBody(int methodInfo) {
if (methodInfo < 0) {
return null;
}
return method_info.get(methodInfo).getBody();
}
public int findBodyIndex(int methodInfo) {
if (methodInfo == -1) {
return -1;
}
return bodyIdxFromMethodIdx.get(methodInfo);
}
public MethodBody findBodyByClassAndName(String className, String methodName) {
for (int i = 0; i < instance_info.size(); i++) {
if (className.equals(constants.getMultiname(instance_info.get(i).name_index).getName(constants, new ArrayList<String>()))) {
for (Trait t : instance_info.get(i).instance_traits.traits) {
if (t instanceof TraitMethodGetterSetter) {
TraitMethodGetterSetter t2 = (TraitMethodGetterSetter) t;
if (methodName.equals(t2.getName(this).getName(constants, new ArrayList<String>()))) {
for (MethodBody body : bodies) {
if (body.method_info == t2.method_info) {
return body;
}
}
}
}
}
//break;
}
}
for (int i = 0; i < class_info.size(); i++) {
if (className.equals(constants.getMultiname(instance_info.get(i).name_index).getName(constants, new ArrayList<String>()))) {
for (Trait t : class_info.get(i).static_traits.traits) {
if (t instanceof TraitMethodGetterSetter) {
TraitMethodGetterSetter t2 = (TraitMethodGetterSetter) t;
if (methodName.equals(t2.getName(this).getName(constants, new ArrayList<String>()))) {
for (MethodBody body : bodies) {
if (body.method_info == t2.method_info) {
return body;
}
}
}
}
}
//break;
}
}
return null;
}
public boolean isStaticTraitId(int classIndex, int traitId) {
if (traitId < class_info.get(classIndex).static_traits.traits.size()) {
return true;
} else if (traitId < class_info.get(classIndex).static_traits.traits.size() + instance_info.get(classIndex).instance_traits.traits.size()) {
return false;
} else {
return true; //Can be class or instance initializer
}
}
public Trait findTraitByTraitId(int classIndex, int traitId) {
if (classIndex == -1) {
return null;
}
if (traitId < class_info.get(classIndex).static_traits.traits.size()) {
return class_info.get(classIndex).static_traits.traits.get(traitId);
} else if (traitId < class_info.get(classIndex).static_traits.traits.size() + instance_info.get(classIndex).instance_traits.traits.size()) {
traitId -= class_info.get(classIndex).static_traits.traits.size();
return instance_info.get(classIndex).instance_traits.traits.get(traitId);
} else {
return null; //Can be class or instance initializer
}
}
public int findMethodIdByTraitId(int classIndex, int traitId) {
if (classIndex == -1) {
return -1;
}
if (traitId < class_info.get(classIndex).static_traits.traits.size()) {
if (class_info.get(classIndex).static_traits.traits.get(traitId) instanceof TraitMethodGetterSetter) {
return ((TraitMethodGetterSetter) class_info.get(classIndex).static_traits.traits.get(traitId)).method_info;
} else {
return -1;
}
} else if (traitId < class_info.get(classIndex).static_traits.traits.size() + instance_info.get(classIndex).instance_traits.traits.size()) {
traitId -= class_info.get(classIndex).static_traits.traits.size();
if (instance_info.get(classIndex).instance_traits.traits.get(traitId) instanceof TraitMethodGetterSetter) {
return ((TraitMethodGetterSetter) instance_info.get(classIndex).instance_traits.traits.get(traitId)).method_info;
} else {
return -1;
}
} else {
traitId -= class_info.get(classIndex).static_traits.traits.size() + instance_info.get(classIndex).instance_traits.traits.size();
if (traitId == 0) {
return instance_info.get(classIndex).iinit_index;
} else if (traitId == 1) {
return class_info.get(classIndex).cinit_index;
} else {
return -1;
}
}
}
/* Map from multiname index of namespace value to namespace name**/
private HashMap<String, String> namespaceMap;
private void loadNamespaceMap() {
namespaceMap = new HashMap<>();
for (ScriptInfo si : script_info) {
for (Trait t : si.traits.traits) {
if (t instanceof TraitSlotConst) {
TraitSlotConst s = ((TraitSlotConst) t);
if (s.isNamespace()) {
String key = constants.getNamespace(s.value_index).getName(constants); //assume not null
String val = constants.getMultiname(s.name_index).getNameWithNamespace(constants);
namespaceMap.put(key, val);
}
}
}
}
}
public String nsValueToName(String value) {
if (namespaceMap.containsKey(value)) {
return namespaceMap.get(value);
} else {
String ns = deobfuscation.builtInNs(value);
if (ns == null) {
return "";
} else {
return ns;
}
}
}
public List<MyEntry<ClassPath, ScriptPack>> getScriptPacks() {
List<MyEntry<ClassPath, ScriptPack>> ret = new ArrayList<>();
for (int i = 0; i < script_info.size(); i++) {
ret.addAll(script_info.get(i).getPacks(this, i));
}
return ret;
}
public void dump(OutputStream os) {
Utf8PrintWriter output;
output = new Utf8PrintWriter(os);
constants.dump(output);
for (int i = 0; i < method_info.size(); i++) {
output.println("MethodInfo[" + i + "]:" + method_info.get(i).toString(constants, new ArrayList<String>()));
}
for (int i = 0; i < metadata_info.size(); i++) {
output.println("MetadataInfo[" + i + "]:" + metadata_info.get(i).toString(constants));
}
for (int i = 0; i < instance_info.size(); i++) {
output.println("InstanceInfo[" + i + "]:" + instance_info.get(i).toString(this, new ArrayList<String>()));
}
for (int i = 0; i < class_info.size(); i++) {
output.println("ClassInfo[" + i + "]:" + class_info.get(i).toString(this, new ArrayList<String>()));
}
for (int i = 0; i < script_info.size(); i++) {
output.println("ScriptInfo[" + i + "]:" + script_info.get(i).toString(this, new ArrayList<String>()));
}
for (int i = 0; i < bodies.size(); i++) {
output.println("MethodBody[" + i + "]:"); //+ bodies[i].toString(this, constants, method_info));
}
}
private void checkMultinameUsedInMethod(int multinameIndex, int methodInfo, List<MultinameUsage> ret, int classIndex, int traitIndex, boolean isStatic, boolean isInitializer, Traits traits, int parentTraitIndex) {
for (int p = 0; p < method_info.get(methodInfo).param_types.length; p++) {
if (method_info.get(methodInfo).param_types[p] == multinameIndex) {
ret.add(new MethodParamsMultinameUsage(multinameIndex, classIndex, traitIndex, isStatic, isInitializer, traits, parentTraitIndex));
break;
}
}
if (method_info.get(methodInfo).ret_type == multinameIndex) {
ret.add(new MethodReturnTypeMultinameUsage(multinameIndex, classIndex, traitIndex, isStatic, isInitializer, traits, parentTraitIndex));
}
MethodBody body = findBody(methodInfo);
if (body != null) {
findMultinameUsageInTraits(body.traits, multinameIndex, isStatic, classIndex, ret, traitIndex);
for (ABCException e : body.exceptions) {
if ((e.name_index == multinameIndex) || (e.type_index == multinameIndex)) {
ret.add(new MethodBodyMultinameUsage(multinameIndex, classIndex, traitIndex, isStatic, isInitializer, traits, parentTraitIndex));
return;
}
}
for (AVM2Instruction ins : body.code.code) {
for (int o = 0; o < ins.definition.operands.length; o++) {
if (ins.definition.operands[o] == AVM2Code.DAT_MULTINAME_INDEX) {
if (ins.operands[o] == multinameIndex) {
ret.add(new MethodBodyMultinameUsage(multinameIndex, classIndex, traitIndex, isStatic, isInitializer, traits, parentTraitIndex));
return;
}
}
}
}
}
}
private void findMultinameUsageInTraits(Traits traits, int multinameIndex, boolean isStatic, int classIndex, List<MultinameUsage> ret, int parentTraitIndex) {
for (int t = 0; t < traits.traits.size(); t++) {
if (traits.traits.get(t) instanceof TraitSlotConst) {
TraitSlotConst tsc = (TraitSlotConst) traits.traits.get(t);
if (tsc.name_index == multinameIndex) {
ret.add(new ConstVarNameMultinameUsage(multinameIndex, classIndex, t, isStatic, traits, parentTraitIndex));
}
if (tsc.type_index == multinameIndex) {
ret.add(new ConstVarTypeMultinameUsage(multinameIndex, classIndex, t, isStatic, traits, parentTraitIndex));
}
}
if (traits.traits.get(t) instanceof TraitMethodGetterSetter) {
TraitMethodGetterSetter tmgs = (TraitMethodGetterSetter) traits.traits.get(t);
if (tmgs.name_index == multinameIndex) {
ret.add(new MethodNameMultinameUsage(multinameIndex, classIndex, t, isStatic, false, traits, parentTraitIndex));
}
checkMultinameUsedInMethod(multinameIndex, tmgs.method_info, ret, classIndex, t, isStatic, false, traits, parentTraitIndex);
}
}
}
public List<MultinameUsage> findMultinameUsage(int multinameIndex) {
List<MultinameUsage> ret = new ArrayList<>();
if (multinameIndex == 0) {
return ret;
}
for (int c = 0; c < instance_info.size(); c++) {
if (instance_info.get(c).name_index == multinameIndex) {
ret.add(new ClassNameMultinameUsage(multinameIndex, c));
}
if (instance_info.get(c).super_index == multinameIndex) {
ret.add(new ExtendsMultinameUsage(multinameIndex, c));
}
for (int i = 0; i < instance_info.get(c).interfaces.length; i++) {
if (instance_info.get(c).interfaces[i] == multinameIndex) {
ret.add(new ImplementsMultinameUsage(multinameIndex, c));
}
}
checkMultinameUsedInMethod(multinameIndex, instance_info.get(c).iinit_index, ret, c, 0, false, true, null, -1);
checkMultinameUsedInMethod(multinameIndex, class_info.get(c).cinit_index, ret, c, 0, true, true, null, -1);
findMultinameUsageInTraits(instance_info.get(c).instance_traits, multinameIndex, false, c, ret, -1);
findMultinameUsageInTraits(class_info.get(c).static_traits, multinameIndex, true, c, ret, -1);
}
loopm:
for (int m = 1; m < constants.getMultinameCount(); m++) {
if (constants.getMultiname(m).kind == Multiname.TYPENAME) {
if (constants.getMultiname(m).qname_index == multinameIndex) {
ret.add(new TypeNameMultinameUsage(m));
continue;
}
for (int mp : constants.getMultiname(m).params) {
if (mp == multinameIndex) {
ret.add(new TypeNameMultinameUsage(m));
continue loopm;
}
}
}
}
return ret;
}
public int findMethodInfoByName(int classId, String methodName) {
if (classId > -1) {
for (Trait t : instance_info.get(classId).instance_traits.traits) {
if (t instanceof TraitMethodGetterSetter) {
if (t.getName(this).getName(constants, new ArrayList<String>()).equals(methodName)) {
return ((TraitMethodGetterSetter) t).method_info;
}
}
}
}
return -1;
}
public int findMethodBodyByName(int classId, String methodName) {
if (classId > -1) {
for (Trait t : instance_info.get(classId).instance_traits.traits) {
if (t instanceof TraitMethodGetterSetter) {
if (t.getName(this).getName(constants, new ArrayList<String>()).equals(methodName)) {
return findBodyIndex(((TraitMethodGetterSetter) t).method_info);
}
}
}
}
return -1;
}
public int findMethodBodyByName(String className, String methodName) {
int classId = findClassByName(className);
return findMethodBodyByName(classId, methodName);
}
public int findClassByName(String name) {
for (int c = 0; c < instance_info.size(); c++) {
String s = constants.getMultiname(instance_info.get(c).name_index).getNameWithNamespace(constants);
if (name.equals(s)) {
return c;
}
}
return -1;
}
public ScriptPack findScriptPackByPath(String name) {
List<MyEntry<ClassPath, ScriptPack>> packs = getScriptPacks();
for (MyEntry<ClassPath, ScriptPack> en : packs) {
if (en.key.toString().equals(name)) {
return en.value;
}
}
return null;
}
}

View File

@@ -0,0 +1,391 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc;
import com.jpexs.decompiler.flash.abc.types.Decimal;
import com.jpexs.decompiler.flash.abc.types.InstanceInfo;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.flash.abc.types.Namespace;
import com.jpexs.decompiler.flash.abc.types.ValueKind;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.abc.types.traits.TraitClass;
import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction;
import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter;
import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst;
import com.jpexs.decompiler.flash.abc.types.traits.Traits;
import com.jpexs.helpers.utf8.Utf8Helper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class ABCInputStream extends InputStream {
private static final int CLASS_PROTECTED_NS = 8;
private static final int ATTR_METADATA = 4;
private final InputStream is;
private long bytesRead = 0;
private ByteArrayOutputStream bufferOs = null;
public static final boolean DEBUG_READ = false;
public void startBuffer() {
if (bufferOs == null) {
bufferOs = new ByteArrayOutputStream();
} else {
bufferOs.reset();
}
}
public byte[] stopBuffer() {
if (bufferOs == null) {
return new byte[0];
}
byte[] ret = bufferOs.toByteArray();
bufferOs.reset();
return ret;
}
public ABCInputStream(InputStream is) {
this.is = is;
}
@Override
public int read() throws IOException {
bytesRead++;
int i = is.read();
if (DEBUG_READ) {
System.out.println("Read:0x" + Integer.toHexString(i));
}
if (bufferOs != null) {
if (i != -1) {
bufferOs.write(i);
}
}
return i;
}
@Override
public int read(byte[] b) throws IOException {
int currBytesRead = is.read(b);
bytesRead += currBytesRead;
if (DEBUG_READ) {
StringBuilder sb = new StringBuilder("Read[");
sb.append(currBytesRead);
sb.append('/');
sb.append(b.length);
sb.append("]: ");
for (int jj = 0; jj < currBytesRead; jj++) {
sb.append("0x");
sb.append(Integer.toHexString(b[jj]));
sb.append(' ');
}
System.out.println(sb.toString());
}
if (bufferOs != null) {
if (currBytesRead > 0) {
bufferOs.write(b, 0, currBytesRead);
}
}
return currBytesRead;
}
;
public int readU8() throws IOException {
return read();
}
public long readU32() throws IOException {
int i;
long ret = 0;
int bytePos = 0;
int byteCount = 0;
boolean nextByte;
do {
i = read();
nextByte = (i >> 7) == 1;
i &= 0x7f;
ret += (((long) i) << bytePos);
byteCount++;
bytePos += 7;
} while (nextByte);
return ret;
}
public int readU30() throws IOException {
return (int) readU32();
}
public int readS24() throws IOException {
int ret = (read()) + (read() << 8) + (read() << 16);
if ((ret >> 23) == 1) {
ret |= 0xff000000;
}
return ret;
}
public int readU16() throws IOException {
return (read()) + (read() << 8);
}
public long readS32() throws IOException {
int i;
long ret = 0;
int bytePos = 0;
int byteCount = 0;
boolean nextByte;
do {
i = read();
nextByte = (i >> 7) == 1;
i &= 0x7f;
ret += (i << bytePos);
byteCount++;
bytePos += 7;
if (bytePos == 35) {
if ((ret >> 31) == 1) {
ret = -(ret & 0x7fffffff);
}
break;
}
} while (nextByte);
return ret;
}
@Override
public int available() throws IOException {
return is.available();
}
public final long readLong() throws IOException {
byte[] readBuffer = safeRead(8);
return (((long) readBuffer[7] << 56)
+ ((long) (readBuffer[6] & 255) << 48)
+ ((long) (readBuffer[5] & 255) << 40)
+ ((long) (readBuffer[4] & 255) << 32)
+ ((long) (readBuffer[3] & 255) << 24)
+ ((readBuffer[2] & 255) << 16)
+ ((readBuffer[1] & 255) << 8)
+ ((readBuffer[0] & 255)));
}
public double readDouble() throws IOException {
long el = readLong();
double ret = Double.longBitsToDouble(el);
return ret;
}
private byte[] safeRead(int count) throws IOException {
byte[] ret = new byte[count];
for (int i = 0; i < count; i++) {
ret[i] = (byte) read();
}
return ret;
}
public Namespace readNamespace() throws IOException {
int kind = read();
int name_index = 0;
for (int k = 0; k < Namespace.nameSpaceKinds.length; k++) {
if (Namespace.nameSpaceKinds[k] == kind) {
name_index = readU30();
break;
}
}
return new Namespace(kind, name_index);
}
public Multiname readMultiname() throws IOException {
int kind = readU8();
int namespace_index = 0;
int name_index = 0;
int namespace_set_index = 0;
int qname_index = 0;
List<Integer> params = new ArrayList<>();
if ((kind == Multiname.QNAME) || (kind == Multiname.QNAMEA)) {
namespace_index = readU30();
name_index = readU30();
} else if ((kind == Multiname.RTQNAME) || (kind == Multiname.RTQNAMEA)) {
name_index = readU30();
} else if ((kind == Multiname.RTQNAMEL) || (kind == Multiname.RTQNAMELA)) {
} else if ((kind == Multiname.MULTINAME) || (kind == Multiname.MULTINAMEA)) {
name_index = readU30();
namespace_set_index = readU30();
} else if ((kind == Multiname.MULTINAMEL) || (kind == Multiname.MULTINAMELA)) {
namespace_set_index = readU30();
} else if (kind == Multiname.TYPENAME) {
qname_index = readU30(); //Multiname index!!!
int paramsLength = readU30();
for (int i = 0; i < paramsLength; i++) {
params.add(readU30()); //multiname indices!
}
} else {
throw new IOException("Unknown kind of Multiname:0x" + Integer.toHexString(kind));
}
return new Multiname(kind, name_index, namespace_index, namespace_set_index, qname_index, params);
}
public MethodInfo readMethodInfo() throws IOException {
int param_count = readU30();
int ret_type = readU30();
int[] param_types = new int[param_count];
for (int i = 0; i < param_count; i++) {
param_types[i] = readU30();
}
int name_index = readU30();
int flags = read();
//// 1=need_arguments, 2=need_activation, 4=need_rest 8=has_optional (16=ignore_rest, 32=explicit,) 64=setsdxns, 128=has_paramnames
ValueKind[] optional = new ValueKind[0];
if ((flags & 8) == 8) { //if has_optional
int optional_count = readU30();
optional = new ValueKind[optional_count];
for (int i = 0; i < optional_count; i++) {
optional[i] = new ValueKind(readU30(), read());
}
}
int[] param_names = new int[param_count];
if ((flags & 128) == 128) { //if has_paramnames
for (int i = 0; i < param_count; i++) {
param_names[i] = readU30();
}
}
return new MethodInfo(param_types, ret_type, name_index, flags, optional, param_names);
}
public Trait readTrait() throws IOException {
long pos = getPosition();
startBuffer();
int name_index = readU30();
int kind = read();
int kindType = 0xf & kind;
int kindFlags = kind >> 4;
Trait trait;
switch (kindType) {
case 0: //slot
case 6: //const
TraitSlotConst t1 = new TraitSlotConst();
t1.slot_id = readU30();
t1.type_index = readU30();
t1.value_index = readU30();
if (t1.value_index != 0) {
t1.value_kind = read();
}
trait = t1;
break;
case 1: //method
case 2: //getter
case 3: //setter
TraitMethodGetterSetter t2 = new TraitMethodGetterSetter();
t2.disp_id = readU30();
t2.method_info = readU30();
trait = t2;
break;
case 4: //class
TraitClass t3 = new TraitClass();
t3.slot_id = readU30();
t3.class_info = readU30();
trait = t3;
break;
case 5: //function
TraitFunction t4 = new TraitFunction();
t4.slot_id = readU30();
t4.method_info = readU30();
trait = t4;
break;
default:
throw new IOException("Unknown trait kind:" + kind);
}
trait.fileOffset = pos;
trait.kindType = kindType;
trait.kindFlags = kindFlags;
trait.name_index = name_index;
if ((kindFlags & ATTR_METADATA) != 0) {
int metadata_count = readU30();
trait.metadata = new int[metadata_count];
for (int i = 0; i < metadata_count; i++) {
trait.metadata[i] = readU30();
}
}
trait.bytes = stopBuffer();
return trait;
}
public Traits readTraits() throws IOException {
int count = readU30();
Traits traits = new Traits();
traits.traits = new ArrayList<>();
for (int i = 0; i < count; i++) {
traits.traits.add(readTrait());
}
return traits;
}
public byte[] readBytes(int count) throws IOException {
byte[] ret = new byte[count];
for (int i = 0; i < count; i++) {
ret[i] = (byte) read();
}
return ret;
}
public Decimal readDecimal() throws IOException {
byte[] data = readBytes(16);
return new Decimal(data);
}
public InstanceInfo readInstanceInfo() throws IOException {
InstanceInfo ret = new InstanceInfo();
ret.name_index = readU30();
ret.super_index = readU30();
ret.flags = read();
if ((ret.flags & CLASS_PROTECTED_NS) != 0) {
ret.protectedNS = readU30();
}
int interfaces_count = readU30();
ret.interfaces = new int[interfaces_count];
for (int i = 0; i < interfaces_count; i++) {
ret.interfaces[i] = readU30();
}
ret.iinit_index = readU30();
ret.instance_traits = readTraits();
return ret;
}
public String readString() throws IOException {
int length = readU30();
byte[] b = safeRead(length);
String r = new String(b, Utf8Helper.charset);
return r;
}
/*public void markStart(){
bytesRead=0;
}*/
public long getPosition() {
return bytesRead;
}
}

View File

@@ -0,0 +1,286 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc;
import com.jpexs.decompiler.flash.abc.types.Decimal;
import com.jpexs.decompiler.flash.abc.types.InstanceInfo;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.flash.abc.types.Namespace;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.abc.types.traits.TraitClass;
import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction;
import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter;
import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst;
import com.jpexs.decompiler.flash.abc.types.traits.Traits;
import com.jpexs.helpers.utf8.Utf8Helper;
import java.io.IOException;
import java.io.OutputStream;
public class ABCOutputStream extends OutputStream {
private final OutputStream os;
public ABCOutputStream(OutputStream os) {
this.os = os;
}
@Override
public void write(int b) throws IOException {
os.write(b);
}
public void writeU30(long value) throws IOException {
writeS32(value);
/*boolean loop = true;
boolean underZero=value<0;
if(underZero){
value = value & 0xFFFFFFFF;
}else{
value = value & 0x7FFFFFFF;
}
do {
int ret = (int) (value & 0x7F);
if (value < 0x80) {
loop = false;
}
if (value > 0x7F) {
ret += 0x80;
}
write(ret);
value = value >> 7;
} while (loop);
*/
}
public void writeU32(long value) throws IOException {
boolean loop = true;
value &= 0xFFFFFFFF;
do {
int ret = (int) (value & 0x7F);
if (value < 0x80) {
loop = false;
}
if (value > 0x7F) {
ret += 0x80;
}
write(ret);
value >>= 7;
} while (loop);
}
public void writeS24(long value) throws IOException {
int ret = (int) (value & 0xff);
write(ret);
value >>= 8;
ret = (int) (value & 0xff);
write(ret);
value >>= 8;
ret = (int) (value & 0xff);
write(ret);
}
public void writeS32(long value) throws IOException {
boolean belowZero = value < 0;
/*if (belowZero) {
value = -value;
}*/
int bitcount = 0;
boolean loop = true;
//value = value & 0xFFFFFFFF;
do {
bitcount += 7;
int ret = (int) (value & 0x7F);
if (value < 0x80) {
if (belowZero) { //&& bitcount < 35
ret += 0x80;
} else {
loop = false;
}
} else {
ret += 0x80;
}
if (bitcount == 35) {
ret &= 0xf;
}
write(ret);
if (bitcount == 35) {
break;
}
value >>= 7;
} while (loop);
}
public void writeLong(long value) throws IOException {
byte[] writeBuffer = new byte[8];
writeBuffer[7] = (byte) (value >>> 56);
writeBuffer[6] = (byte) (value >>> 48);
writeBuffer[5] = (byte) (value >>> 40);
writeBuffer[4] = (byte) (value >>> 32);
writeBuffer[3] = (byte) (value >>> 24);
writeBuffer[2] = (byte) (value >>> 16);
writeBuffer[1] = (byte) (value >>> 8);
writeBuffer[0] = (byte) (value);
write(writeBuffer);
}
public void writeDouble(double value) throws IOException {
writeLong(Double.doubleToLongBits(value));
}
public void writeU8(int value) throws IOException {
write(value);
}
public void writeU16(int value) throws IOException {
write(value & 0xff);
write((value >> 8) & 0xff);
}
public void writeString(String s) throws IOException {
byte[] sbytes = Utf8Helper.getBytes(s);
writeU30(sbytes.length);
write(sbytes);
}
public void writeNamespace(Namespace ns) throws IOException {
write(ns.kind);
boolean found = false;
for (int k = 0; k < Namespace.nameSpaceKinds.length; k++) {
if (Namespace.nameSpaceKinds[k] == ns.kind) {
writeU30(ns.name_index);
found = true;
break;
}
}
if (!found) {
throw new RuntimeException("Invalid ns kind:" + ns.kind);
}
}
public void writeMultiname(Multiname m) throws IOException {
writeU8(m.kind);
if ((m.kind == 7) || (m.kind == 0xd)) { // CONSTANT_QName and CONSTANT_QNameA.
writeU30(m.namespace_index);
writeU30(m.name_index);
}
if ((m.kind == 9) || (m.kind == 0xe)) { // CONSTANT_Multiname and CONSTANT_MultinameA.
writeU30(m.name_index);
writeU30(m.namespace_set_index);
}
if ((m.kind == 0xf) || (m.kind == 0x10)) { //CONSTANT_RTQName and CONSTANT_RTQNameA
writeU30(m.name_index);
}
if ((m.kind == 0x1B) || (m.kind == 0x1C)) { //CONSTANT_MultinameL and CONSTANT_MultinameLA
writeU30(m.namespace_set_index);
}
if (m.kind == 0x1D) {
writeU30(m.qname_index);
writeU30(m.params.size());
for (int i = 0; i < m.params.size(); i++) {
writeU30(m.params.get(i));
}
}
//kind==0x11,0x12 nothing CONSTANT_RTQNameL and CONSTANT_RTQNameLA.
}
public void writeMethodInfo(MethodInfo mi) throws IOException {
writeU30(mi.param_types.length);
writeU30(mi.ret_type);
for (int i = 0; i < mi.param_types.length; i++) {
writeU30(mi.param_types[i]);
}
writeU30(mi.name_index);
write(mi.flags);
if ((mi.flags & 8) == 8) {
writeU30(mi.optional.length);
for (int i = 0; i < mi.optional.length; i++) {
writeU30(mi.optional[i].value_index);
write(mi.optional[i].value_kind);
}
}
if ((mi.flags & 128) == 128) { //if has_paramnames
for (int i = 0; i < mi.paramNames.length; i++) {
writeU30(mi.paramNames[i]);
}
}
}
public void writeTrait(Trait t) throws IOException {
writeU30(t.name_index);
write((t.kindFlags << 4) + t.kindType);
if (t instanceof TraitSlotConst) {
TraitSlotConst t1 = (TraitSlotConst) t;
writeU30(t1.slot_id);
writeU30(t1.type_index);
writeU30(t1.value_index);
if (t1.value_index != 0) {
write(t1.value_kind);
}
}
if (t instanceof TraitMethodGetterSetter) {
TraitMethodGetterSetter t2 = (TraitMethodGetterSetter) t;
writeU30(t2.disp_id);
writeU30(t2.method_info);
}
if (t instanceof TraitClass) {
TraitClass t3 = (TraitClass) t;
writeU30(t3.slot_id);
writeU30(t3.class_info);
}
if (t instanceof TraitFunction) {
TraitFunction t4 = (TraitFunction) t;
writeU30(t4.slot_id);
writeU30(t4.method_info);
}
if ((t.kindFlags & 4) == 4) {
writeU30(t.metadata.length);
for (int i = 0; i < t.metadata.length; i++) {
writeU30(t.metadata[i]);
}
}
}
public void writeTraits(Traits t) throws IOException {
writeU30(t.traits.size());
for (int i = 0; i < t.traits.size(); i++) {
writeTrait(t.traits.get(i));
}
}
public void writeInstanceInfo(InstanceInfo ii) throws IOException {
writeU30(ii.name_index);
writeU30(ii.super_index);
write(ii.flags);
if ((ii.flags & 8) == 8) {
writeU30(ii.protectedNS);
}
writeU30(ii.interfaces.length);
for (int i = 0; i < ii.interfaces.length; i++) {
writeU30(ii.interfaces[i]);
}
writeU30(ii.iinit_index);
writeTraits(ii.instance_traits);
}
public void writeDecimal(Decimal value) throws IOException {
write(value.data);
}
}

View File

@@ -0,0 +1,80 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc;
import com.jpexs.decompiler.flash.BaseLocalData;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.types.ABCException;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
/**
*
* @author JPEXS
*/
public class AVM2LocalData extends BaseLocalData {
public Boolean isStatic;
public Integer classIndex;
public HashMap<Integer, GraphTargetItem> localRegs;
public Stack<GraphTargetItem> scopeStack;
public ConstantPool constants;
public List<MethodInfo> methodInfo;
public MethodBody methodBody;
public ABC abc;
public HashMap<Integer, String> localRegNames;
public List<String> fullyQualifiedNames;
public ArrayList<ABCException> parsedExceptions;
public ArrayList<Integer> finallyJumps;
public ArrayList<Integer> ignoredSwitches;
public Integer scriptIndex;
public HashMap<Integer, Integer> localRegAssignmentIps;
public Integer ip;
public HashMap<Integer, List<Integer>> refs;
public AVM2Code code;
public AVM2LocalData() {
}
public AVM2LocalData(AVM2LocalData localData) {
isStatic = localData.isStatic;
classIndex = localData.classIndex;
localRegs = localData.localRegs;
scopeStack = localData.scopeStack;
constants = localData.constants;
methodInfo = localData.methodInfo;
methodBody = localData.methodBody;
abc = localData.abc;
localRegNames = localData.localRegNames;
fullyQualifiedNames = localData.fullyQualifiedNames;
parsedExceptions = localData.parsedExceptions;
finallyJumps = localData.finallyJumps;
ignoredSwitches = localData.ignoredSwitches;
scriptIndex = localData.scriptIndex;
localRegAssignmentIps = localData.localRegAssignmentIps;
ip = localData.ip;
refs = localData.refs;
code = localData.code;
}
}

View File

@@ -0,0 +1,65 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc;
import java.util.Objects;
/**
*
* @author JPEXS
*/
public class ClassPath {
public String packageStr;
public String className;
public ClassPath(String packageStr, String className) {
this.packageStr = packageStr;
this.className = className;
}
@Override
public String toString() {
return (packageStr == null || packageStr.isEmpty()) ? className : packageStr + "." + className;
}
@Override
public int hashCode() {
int hash = 7;
hash = 37 * hash + Objects.hashCode(this.packageStr);
hash = 37 * hash + Objects.hashCode(this.className);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final ClassPath other = (ClassPath) obj;
if (!Objects.equals(this.packageStr, other.packageStr)) {
return false;
}
if (!Objects.equals(this.className, other.className)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,73 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class CopyOutputStream extends OutputStream {
private final OutputStream os;
private final InputStream is;
private long pos = 0;
private final int TEMPSIZE = 5;
private final int[] temp = new int[TEMPSIZE];
private int tempPos = 0;
public int ignoreFirst = 0;
public CopyOutputStream(OutputStream os, InputStream is) {
this.os = os;
this.is = is;
}
@Override
public void write(int b) throws IOException {
temp[tempPos] = b;
tempPos = (tempPos + 1) % TEMPSIZE;
pos++;
int r = is.read();
if ((b & 0xff) != r) {
if (ignoreFirst <= 0) {
os.flush();
boolean output = true;
if (output) {
System.out.println("Position: " + pos);
System.out.print("Last written:");
for (int i = 0; i < TEMPSIZE; i++) {
System.out.print("" + Integer.toHexString(temp[(tempPos + i) % TEMPSIZE]) + " ");
}
System.out.println("");
System.out.println("More expected:");
for (int i = 0; i < TEMPSIZE; i++) {
System.out.println("" + Integer.toHexString(is.read()));
}
System.out.println("");
System.out.println(Integer.toHexString(r) + " expected but " + Integer.toHexString(b) + " found");
}
throw new NotSameException(pos);
} else {
ignoreFirst--;
}
}
os.write(b);
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc;
import com.jpexs.helpers.Helper;
public class NotSameException extends RuntimeException {
public NotSameException(long pos) {
super("Streams are not the same at pos " + Helper.formatHex((int) pos, 8));
}
}

View File

@@ -0,0 +1,27 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc;
/**
*
* @author JPEXS
*/
public enum RenameType {
TYPENUMBER,
RANDOMWORD
}

View File

@@ -0,0 +1,201 @@
/*
* Copyright (C) 2012-2013 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.decompiler.flash.abc;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.flash.abc.types.Namespace;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.helpers.FileTextWriter;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.treeitems.TreeElementItem;
import com.jpexs.helpers.CancellableWorker;
import com.jpexs.helpers.Helper;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author JPEXS
*/
public class ScriptPack implements TreeElementItem {
public ABC abc;
public int scriptIndex;
public List<Integer> traitIndices;
private final ClassPath path;
@Override
public SWF getSwf() {
return abc.swf;
}
public ClassPath getPath() {
return path;
}
public ScriptPack(ClassPath path, ABC abc, int scriptIndex, List<Integer> traitIndices) {
this.abc = abc;
this.scriptIndex = scriptIndex;
this.traitIndices = traitIndices;
this.path = path;
}
public String getPathPackage() {
String packageName = "";
for (int t : traitIndices) {
Multiname name = abc.script_info.get(scriptIndex).traits.traits.get(t).getName(abc);
Namespace ns = name.getNamespace(abc.constants);
if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) {
packageName = ns.getName(abc.constants); //assume not null
}
}
return packageName;
}
public String getPathScriptName() {
String scriptName = "";
for (int t : traitIndices) {
Multiname name = abc.script_info.get(scriptIndex).traits.traits.get(t).getName(abc);
Namespace ns = name.getNamespace(abc.constants);
if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) {
scriptName = name.getName(abc.constants, new ArrayList<String>());
}
}
return scriptName;
}
/*public String getPath() {
String packageName = "";
String scriptName = "";
for (int t : traitIndices) {
Multiname name = abc.script_info[scriptIndex].traits.traits.get(t).getName(abc);
Namespace ns = name.getNamespace(abc.constants);
if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) {
packageName = ns.getName(abc.constants);
scriptName = name.getName(abc.constants, new ArrayList<String>());
}
}
return packageName.equals("") ? scriptName : packageName + "." + scriptName;
}*/
private static String makeDirPath(String packageName) {
if (packageName.isEmpty()) {
return "";
}
String[] pathParts;
if (packageName.contains(".")) {
pathParts = packageName.split("\\.");
} else {
pathParts = new String[]{packageName};
}
for (int i = 0; i < pathParts.length; i++) {
pathParts[i] = Helper.makeFileName(pathParts[i]);
}
return Helper.joinStrings(pathParts, File.separator);
}
public void convert(final NulWriter writer, final List<ABCContainerTag> abcList, final List<Trait> traits, final ScriptExportMode exportMode, final boolean parallel) throws InterruptedException {
for (int t : traitIndices) {
Trait trait = traits.get(t);
Multiname name = trait.getName(abc);
Namespace ns = name.getNamespace(abc.constants);
if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) {
trait.convertPackaged(null, "", abcList, abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<String>(), parallel);
} else {
trait.convert(null, "", abcList, abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<String>(), parallel);
}
}
}
public void appendTo(GraphTextWriter writer, List<ABCContainerTag> abcList, List<Trait> traits, ScriptExportMode exportMode, boolean parallel) throws InterruptedException {
for (int t : traitIndices) {
Trait trait = traits.get(t);
Multiname name = trait.getName(abc);
Namespace ns = name.getNamespace(abc.constants);
if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) {
trait.toStringPackaged(null, "", abcList, abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<String>(), parallel);
} else {
trait.toString(null, "", abcList, abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<String>(), parallel);
}
}
}
public void toSource(GraphTextWriter writer, final List<ABCContainerTag> abcList, final List<Trait> traits, final ScriptExportMode exportMode, final boolean parallel) throws InterruptedException {
writer.suspendMeasure();
int timeout = Configuration.decompilationTimeoutFile.get();
try {
CancellableWorker.call(new Callable<Void>() {
@Override
public Void call() throws Exception {
convert(new NulWriter(), abcList, traits, exportMode, parallel);
return null;
}
}, timeout, TimeUnit.SECONDS);
} catch (TimeoutException ex) {
writer.continueMeasure();
Logger.getLogger(MethodBody.class.getName()).log(Level.SEVERE, "Decompilation error", ex);
Helper.appendTimeoutComment(writer, timeout);
return;
} catch (ExecutionException ex) {
writer.continueMeasure();
Logger.getLogger(MethodBody.class.getName()).log(Level.SEVERE, "Decompilation error", ex);
Helper.appendErrorComment(writer, ex);
return;
}
writer.continueMeasure();
appendTo(writer, abcList, traits, exportMode, parallel);
}
public File export(String directory, List<ABCContainerTag> abcList, ScriptExportMode exportMode, boolean parallel) throws IOException {
String scriptName = getPathScriptName();
String packageName = getPathPackage();
File outDir = new File(directory + File.separatorChar + makeDirPath(packageName));
if (!outDir.exists()) {
if (!outDir.mkdirs()) {
if (!outDir.exists()) {
throw new IOException("cannot create directory " + outDir);
}
}
}
String fileName = outDir.toString() + File.separator + Helper.makeFileName(scriptName) + ".as";
File file = new File(fileName);
try (FileTextWriter writer = new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(file))) {
try {
toSource(writer, abcList, abc.script_info.get(scriptIndex).traits.traits, exportMode, parallel);
} catch (InterruptedException ex) {
Logger.getLogger(ScriptPack.class.getName()).log(Level.SEVERE, null, ex);
}
}
return file;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,246 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2;
import com.jpexs.decompiler.flash.abc.RenameType;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.regex.Pattern;
/**
*
* @author JPEXS
*/
public class AVM2Deobfuscation {
private static final Random rnd = new Random();
private static final int DEFAULT_FOO_SIZE = 10;
public static final String[] reservedWords = {
"as", "break", "case", "catch", "class", "const", "continue", "default", "delete", "do", "each", "else",
"extends", "false", "finally", "for", "function", "get", "if", "implements", "import", "in", "instanceof",
"interface", "internal", "is", "native", "new", "null", "override", "package", "private", "protected", "public",
"return", "set", "super", "switch", "this", "throw", "true", "try", "typeof", "use", "var", /*"void",*/ "while",
"with", "dynamic", "default", "final", "in", "static"};
public static final String VALID_FIRST_CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
public static final String VALID_NEXT_CHARACTERS = VALID_FIRST_CHARACTERS + "0123456789";
public static final String VALID_NS_CHARACTERS = ".:$";
public static final String FOO_CHARACTERS = "bcdfghjklmnpqrstvwz";
public static final String FOO_JOIN_CHARACTERS = "aeiouy";
private final ConstantPool constants;
private final Map<String, Integer> usageTypesCount = new HashMap<>();
public AVM2Deobfuscation(ConstantPool constants) {
this.constants = constants;
}
private static boolean isReserved(String s) {
for (String rw : reservedWords) {
if (rw.equals(s.trim())) {
return true;
}
}
return false;
}
private boolean isValidNSPart(String s) {
boolean isValid = true;
if (isReserved(s)) {
isValid = false;
}
if (isValid) {
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) > 127) {
isValid = false;
break;
}
}
}
if (isValid) {
Pattern pat = Pattern.compile("^([" + Pattern.quote(VALID_FIRST_CHARACTERS) + "]" + "[" + Pattern.quote(VALID_FIRST_CHARACTERS + VALID_NEXT_CHARACTERS + VALID_NS_CHARACTERS) + "]*)*$");
if (!pat.matcher(s).matches()) {
isValid = false;
}
}
return isValid;
}
public String builtInNs(String ns) {
if (ns == null) {
return null;
}
if (ns.equals("http://www.adobe.com/2006/actionscript/flash/proxy")) {
return "flash.utils.flash_proxy";
}
if (ns.equals("http://adobe.com/AS3/2006/builtin")) {
return "-";
}
return null;
}
private String fooString(HashMap<String, String> deobfuscated, String orig, boolean firstUppercase, int rndSize, String usageType, RenameType renameType) {
boolean exists;
String ret;
int pos = 0;
if (usageType == null) {
usageType = "name";
}
if (usageTypesCount.containsKey(usageType)) {
pos = usageTypesCount.get(usageType);
}
loopfoo:
do {
exists = false;
ret = "";
if (renameType == RenameType.TYPENUMBER) {
pos++;
ret = usageType + "_" + pos;
} else if (renameType == RenameType.RANDOMWORD) {
int len = 3 + rnd.nextInt(rndSize - 3);
for (int i = 0; i < len; i++) {
String c = "";
if ((i % 2) == 0) {
c = "" + FOO_CHARACTERS.charAt(rnd.nextInt(FOO_CHARACTERS.length()));
} else {
c = "" + FOO_JOIN_CHARACTERS.charAt(rnd.nextInt(FOO_JOIN_CHARACTERS.length()));
}
if (i == 0 && firstUppercase) {
c = c.toUpperCase(Locale.ENGLISH);
}
ret += c;
}
}
for (int i = 1; i < constants.getStringCount(); i++) {
if (constants.getString(i).equals(ret)) {
exists = true;
rndSize += 1;
continue loopfoo;
}
}
if (isReserved(ret)) {
exists = true;
rndSize += 1;
continue;
}
if (deobfuscated.containsValue(ret)) {
exists = true;
rndSize += 1;
continue;
}
} while (exists);
usageTypesCount.put(usageType, pos);
deobfuscated.put(orig, ret);
return ret;
}
public int deobfuscatePackageName(Map<Integer, String> stringUsageTypes, Set<Integer> stringUsages, HashMap<String, String> namesMap, int strIndex, RenameType renameType) {
if (strIndex <= 0) {
return strIndex;
}
String s = constants.getString(strIndex);
if (builtInNs(s) != null) {
return strIndex;
}
boolean isValid = isValidNSPart(s);
if (!isValid) {
String newName;
if (namesMap.containsKey(s)) {
newName = constants.setString(strIndex, namesMap.get(s));
} else {
String[] parts = null;
if (s.contains(".")) {
parts = s.split("\\.");
} else {
parts = new String[]{s};
}
String ret = "";
for (int p = 0; p < parts.length; p++) {
if (p > 0) {
ret += ".";
}
if (!isValidNSPart(parts[p])) {
ret += fooString(namesMap, parts[p], false, DEFAULT_FOO_SIZE, "package", renameType);
} else {
ret += parts[p];
}
}
newName = ret;
namesMap.put(s, newName);
}
if (stringUsages.contains(strIndex)) {
strIndex = constants.addString(newName);
} else {
constants.setString(strIndex, newName);
}
}
return strIndex;
}
public int deobfuscateName(Map<Integer, String> stringUsageTypes, Set<Integer> stringUsages, Set<Integer> namespaceUsages, HashMap<String, String> namesMap, int strIndex, boolean firstUppercase, RenameType renameType) {
if (strIndex <= 0) {
return strIndex;
}
String s = constants.getString(strIndex);
boolean isValid = true;
if (isReserved(s)) {
isValid = false;
}
if (isValid) {
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) > 127) {
isValid = false;
break;
}
}
}
if (isValid) {
Pattern pat = Pattern.compile("^[" + Pattern.quote(VALID_FIRST_CHARACTERS) + "]" + "[" + Pattern.quote(VALID_FIRST_CHARACTERS + VALID_NEXT_CHARACTERS) + "]*$");
if (!pat.matcher(s).matches()) {
isValid = false;
}
}
if (!isValid) {
String newname;
if (namesMap.containsKey(s)) {
newname = namesMap.get(s);
} else {
newname = fooString(namesMap, constants.getString(strIndex), firstUppercase, DEFAULT_FOO_SIZE, stringUsageTypes.get(strIndex), renameType);
}
if (stringUsages.contains(strIndex) || namespaceUsages.contains(strIndex)) { //this name is already referenced as String
strIndex = constants.addString(s); //add new index
}
constants.setString(strIndex, newname);
if (!namesMap.containsKey(s)) {
namesMap.put(s, constants.getString(strIndex));
}
}
return strIndex;
}
}

View File

@@ -0,0 +1,59 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.graph.model.LocalData;
import java.util.List;
/**
*
* @author JPEXS
*/
public class CodeStats {
public int maxstack = 0;
public int maxscope = 0;
public int maxlocal = 1;
public int initscope = 0;
public boolean has_set_dxns = false;
public boolean has_activation = false;
public InstructionStats[] instructionStats;
public GraphTextWriter toString(GraphTextWriter writer, ABC abc, List<String> fullyQualifiedNames) {
writer.appendNoHilight("Stats: maxstack=" + maxstack + ", maxscope=" + maxscope + ", maxlocal=" + maxlocal).newLine();
int i = 0;
int ms = 0;
for (InstructionStats stats : instructionStats) {
int deltastack = stats.ins.definition.getStackDelta(stats.ins, abc);
if (stats.stackpos > ms) {
ms = stats.stackpos;
}
writer.appendNoHilight(i + ":" + stats.stackpos + (deltastack >= 0 ? "+" + deltastack : deltastack) + "," + stats.scopepos + " " + stats.ins.toString(writer, LocalData.create(abc.constants, null, fullyQualifiedNames))).newLine();
i++;
}
return writer;
}
public CodeStats(AVM2Code code) {
instructionStats = new InstructionStats[code.code.size()];
for (int i = 0; i < code.code.size(); i++) {
instructionStats[i] = new InstructionStats(code.code.get(i));
}
}
}

View File

@@ -0,0 +1,391 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2;
import com.jpexs.decompiler.flash.abc.types.Decimal;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.flash.abc.types.Namespace;
import com.jpexs.decompiler.flash.abc.types.NamespaceSet;
import com.jpexs.helpers.utf8.Utf8PrintWriter;
import java.util.ArrayList;
import java.util.List;
public class ConstantPool {
public List<Long> constant_int = new ArrayList<>();
public List<Long> constant_uint = new ArrayList<>();
public List<Double> constant_double = new ArrayList<>();
/* Only for some minor versions */
public List<Decimal> constant_decimal = new ArrayList<>();
public List<String> constant_string = new ArrayList<>();
public List<Namespace> constant_namespace = new ArrayList<>();
public List<NamespaceSet> constant_namespace_set = new ArrayList<>();
public List<Multiname> constant_multiname = new ArrayList<>();
public synchronized int addInt(long value) {
constant_int.add(value);
return constant_int.size() - 1;
}
public synchronized int addNamespace(Namespace ns) {
constant_namespace.add(ns);
return constant_namespace.size() - 1;
}
public synchronized int addNamespaceSet(NamespaceSet nss) {
constant_namespace_set.add(nss);
return constant_namespace_set.size() - 1;
}
public synchronized int addMultiname(Multiname m) {
constant_multiname.add(m);
return constant_multiname.size() - 1;
}
public synchronized int addUInt(long value) {
constant_uint.add(value);
return constant_uint.size() - 1;
}
public synchronized int addDouble(double value) {
constant_double.add(value);
return constant_double.size() - 1;
}
public synchronized int addDecimal(Decimal value) {
constant_decimal.add(value);
return constant_decimal.size() - 1;
}
public synchronized int addString(String value) {
constant_string.add(value);
return constant_string.size() - 1;
}
public long setInt(int index, long value) {
constant_int.set(index, value);
return value;
}
public Namespace setNamespace(int index, Namespace ns) {
constant_namespace.set(index, ns);
return ns;
}
public NamespaceSet setNamespaceSet(int index, NamespaceSet nss) {
constant_namespace_set.set(index, nss);
return nss;
}
public Multiname setMultiname(int index, Multiname m) {
constant_multiname.set(index, m);
return m;
}
public long setUInt(int index, long value) {
constant_uint.set(index, value);
return value;
}
public double setDouble(int index, double value) {
constant_double.set(index, value);
return value;
}
public Decimal setDecimal(int index, Decimal value) {
constant_decimal.set(index, value);
return value;
}
public String setString(int index, String value) {
constant_string.set(index, value);
return value;
}
public long getInt(int index) {
return constant_int.get(index);
}
public Namespace getNamespace(int index) {
return constant_namespace.get(index);
}
public NamespaceSet getNamespaceSet(int index) {
return constant_namespace_set.get(index);
}
public Multiname getMultiname(int index) {
return constant_multiname.get(index);
}
public long getUInt(int index) {
return constant_uint.get(index);
}
public double getDouble(int index) {
return constant_double.get(index);
}
public Decimal getDecimal(int index) {
return constant_decimal.get(index);
}
public String getString(int index) {
return constant_string.get(index);
}
public int getIntCount() {
return constant_int.size();
}
public int getNamespaceCount() {
return constant_namespace.size();
}
public int getNamespaceSetCount() {
return constant_namespace_set.size();
}
public int getMultinameCount() {
return constant_multiname.size();
}
public int getUIntCount() {
return constant_uint.size();
}
public int getDoubleCount() {
return constant_double.size();
}
public int getDecimalCount() {
return constant_decimal.size();
}
public int getStringCount() {
return constant_string.size();
}
public int getNamespaceId(Namespace val, int index) {
for (int n = 1; n < constant_namespace.size(); n++) {
Namespace ns = constant_namespace.get(n);
if (ns.name_index == val.name_index && (ns.kind == val.kind)) {
if (index == 0) {
return n;
}
index--;
}
}
return 0;
}
public int getIntId(long value) {
for (int i = 1; i < constant_int.size(); i++) {
if (constant_int.get(i) == value) {
return i;
}
}
return 0;
}
public int getUIntId(long value) {
for (int i = 1; i < constant_uint.size(); i++) {
if (constant_uint.get(i) == value) {
return i;
}
}
return 0;
}
public int getDoubleId(double value) {
for (int i = 1; i < constant_double.size(); i++) {
if(Double.isNaN(value) && Double.isNaN(constant_double.get(i))){
return i;
}
if (Double.compare(constant_double.get(i), value) == 0) {
return i;
}
}
return 0;
}
public int getStringId(String val) {
if (val == null) {
return 0;
}
for (int i = 1; i < constant_string.size(); i++) {
if (constant_string.get(i).equals(val)) {
return i;
}
}
return 0;
}
public int getMultinameId(Multiname val) {
loopm:
for (int m = 1; m < constant_multiname.size(); m++) {
Multiname mul = constant_multiname.get(m);
if (mul.kind == val.kind && mul.name_index == val.name_index && mul.namespace_index == val.namespace_index && mul.namespace_set_index == val.namespace_set_index && mul.qname_index == val.qname_index && mul.params.size() == val.params.size()) {
for (int p = 0; p < mul.params.size(); p++) {
if (mul.params.get(p) != val.params.get(p)) {
continue loopm;
}
}
return m;
}
}
return 0;
}
public int getQnameId(String name, int namespaceKind, String namespaceName, boolean add) {
return getMultinameId(new Multiname(Multiname.QNAME, getStringId(name, add), getNamespaceId(new Namespace(namespaceKind, getStringId(namespaceName, add)), 0, add), -1, -1, new ArrayList<Integer>()), add);
}
public int getPublicQnameId(String name, boolean add) {
return getQnameId(name, Namespace.KIND_PACKAGE, "", add);
}
public int getMultinameId(Multiname val, boolean add) {
int id = getMultinameId(val);
if (add && id == 0) {
id = addMultiname(val);
}
return id;
}
public int getStringId(String val, boolean add) {
if (val == null) {
return 0;
}
int id = getStringId(val);
if (add && id == 0) {
id = addString(val);
}
return id;
}
public int getIntId(long val, boolean add) {
int id = getIntId(val);
if (add && id == 0) {
id = addInt(val);
}
return id;
}
public int getNamespaceId(Namespace val, int index, boolean add) {
int id = getNamespaceId(val, index);
if (add && id == 0) {
id = addNamespace(val);
}
return id;
}
public int getNamespaceSetId(NamespaceSet val) {
loopi:
for (int i = 1; i < constant_namespace_set.size(); i++) {
NamespaceSet ts = constant_namespace_set.get(i);
if (ts.namespaces.length != val.namespaces.length) {
continue;
}
for (int j = 0; j < val.namespaces.length; j++) {
boolean found = false;
for (int k = 0; k < val.namespaces.length; k++) {
if (ts.namespaces[j] == val.namespaces[k]) {
found = true;
break;
}
}
if (!found) {
continue loopi;
}
}
return i;
}
return 0;
}
public int getNamespaceSetId(NamespaceSet val, boolean add) {
int id = getNamespaceSetId(val);
if (add && id == 0) {
id = addNamespaceSet(val);
}
return id;
}
public int getUIntId(long val, boolean add) {
int id = getUIntId(val);
if (add && id == 0) {
id = addUInt(val);
}
return id;
}
public int getDoubleId(double val, boolean add) {
int id = getDoubleId(val);
if (add && id == 0) {
id = addDouble(val);
}
return id;
}
public void dump(Utf8PrintWriter writer) {
String s = "";
for (int i = 1; i < constant_int.size(); i++) {
writer.println("INT[" + i + "]=" + constant_int.get(i));
}
for (int i = 1; i < constant_uint.size(); i++) {
writer.println("UINT[" + i + "]=" + constant_uint.get(i));
}
for (int i = 1; i < constant_double.size(); i++) {
writer.println("Double[" + i + "]=" + constant_double.get(i));
}
for (int i = 1; i < constant_string.size(); i++) {
writer.println("String[" + i + "]=" + constant_string.get(i));
}
for (int i = 1; i < constant_namespace.size(); i++) {
writer.println("Namespace[" + i + "]=" + constant_namespace.get(i).toString(this));
}
for (int i = 1; i < constant_namespace_set.size(); i++) {
writer.println("NamespaceSet[" + i + "]=" + constant_namespace_set.get(i).toString(this));
}
for (int i = 1; i < constant_multiname.size(); i++) {
writer.println("Multiname[" + i + "]=" + constant_multiname.get(i).toString(this, new ArrayList<String>()));
}
}
public String multinameToString(int index) {
if (index == 0) {
return "null";
}
return constant_multiname.get(index).toString(this, new ArrayList<String>());
}
public String namespaceToString(int index) {
if (index == 0) {
return "null";
}
return constant_namespace.get(index).toString(this);
}
public String namespaceSetToString(int index) {
if (index == 0) {
return "null";
}
return constant_namespace_set.get(index).toString(this);
}
}

View File

@@ -0,0 +1,27 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2;
public class ConvertException extends RuntimeException {
public int line;
public ConvertException(String s, int line) {
super(s + " on line " + line);
this.line = line;
}
}

View File

@@ -0,0 +1,36 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.List;
import java.util.Stack;
/**
*
* @author JPEXS
*/
public class ConvertOutput {
public Stack<GraphTargetItem> stack;
public List<GraphTargetItem> output;
public ConvertOutput(Stack<GraphTargetItem> stack, List<GraphTargetItem> output) {
this.stack = stack;
this.output = output;
}
}

View File

@@ -0,0 +1,37 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
/**
*
* @author JPEXS
*/
public class InstructionStats {
public boolean seen = false;
public int stackpos = 0;
public int scopepos = 0;
public int stackpos_after = 0;
public int scopepos_after = 0;
public AVM2Instruction ins;
public InstructionStats(AVM2Instruction ins) {
this.ins = ins;
}
}

View File

@@ -0,0 +1,24 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2;
public class InvalidInstructionArguments extends RuntimeException {
public InvalidInstructionArguments() {
super("Invalid method arguments");
}
}

View File

@@ -0,0 +1,27 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2;
import java.util.HashMap;
import java.util.Stack;
public class LocalDataArea {
public Stack<Object> operandStack = new Stack<>();
public Stack<Object> scopeStack = new Stack<>();
public HashMap<Integer, Object> localRegisters = new HashMap<>();
}

View File

@@ -0,0 +1,27 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2;
public class UnknownInstructionCode extends RuntimeException {
public int code;
public UnknownInstructionCode(int code) {
super("Unknown instruction code: 0x" + Integer.toHexString(code));
this.code = code;
}
}

View File

@@ -0,0 +1,39 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.List;
import java.util.Stack;
public class UnknownJumpException extends RuntimeException {
public Stack stack;
public int ip;
public List<GraphTargetItem> output;
public UnknownJumpException(Stack stack, int ip, List<GraphTargetItem> output) {
this.stack = stack;
this.ip = ip;
this.output = output;
}
@Override
public String toString() {
return "Unknown jump to " + ip;
}
}

View File

@@ -0,0 +1,813 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.graph;
import com.jpexs.decompiler.flash.BaseLocalData;
import com.jpexs.decompiler.flash.FinalProcessLocalData;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.AVM2LocalData;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfStrictEqIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfStrictNeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.LookupSwitchIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocalTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.KillIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushIntegerTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.model.FilteredCheckAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.HasNextAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.InAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.NextNameAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.NextValueAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.ReturnValueAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.ReturnVoidAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.SetPropertyAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.SetTypeAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.WithAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ExceptionAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.clauses.FilterAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForEachInAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForInAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.clauses.TryAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.operations.StrictEqAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.operations.StrictNeqAVM2Item;
import com.jpexs.decompiler.flash.abc.types.ABCException;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.ecma.EcmaScript;
import com.jpexs.decompiler.graph.Graph;
import com.jpexs.decompiler.graph.GraphPart;
import com.jpexs.decompiler.graph.GraphPartMulti;
import com.jpexs.decompiler.graph.GraphSource;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.Loop;
import com.jpexs.decompiler.graph.model.BreakItem;
import com.jpexs.decompiler.graph.model.IfItem;
import com.jpexs.decompiler.graph.model.LoopItem;
import com.jpexs.decompiler.graph.model.NotItem;
import com.jpexs.decompiler.graph.model.SwitchItem;
import com.jpexs.decompiler.graph.model.WhileItem;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
/**
*
* @author JPEXS
*/
public class AVM2Graph extends Graph {
private final AVM2Code avm2code;
private final ABC abc;
private final MethodBody body;
public AVM2Code getCode() {
return avm2code;
}
public AVM2Graph(AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> scopeStack, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, HashMap<Integer, Integer> localRegAssigmentIps, HashMap<Integer, List<Integer>> refs) {
super(new AVM2GraphSource(code, isStatic, scriptIndex, classIndex, localRegs, scopeStack, abc, body, localRegNames, fullyQualifiedNames, localRegAssigmentIps, refs), body.getExceptionEntries());
this.avm2code = code;
this.abc = abc;
this.body = body;
/*heads = makeGraph(code, new ArrayList<GraphPart>(), body);
this.code = code;
this.abc = abc;
this.body = body;
for (GraphPart head : heads) {
fixGraph(head);
makeMulti(head, new ArrayList<GraphPart>());
}*/
}
public static List<GraphTargetItem> translateViaGraph(String path, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> scopeStack, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, int staticOperation, HashMap<Integer, Integer> localRegAssigmentIps, HashMap<Integer, List<Integer>> refs) throws InterruptedException {
AVM2Graph g = new AVM2Graph(code, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, fullyQualifiedNames, localRegAssigmentIps, refs);
AVM2LocalData localData = new AVM2LocalData();
localData.isStatic = isStatic;
localData.classIndex = classIndex;
localData.localRegs = localRegs;
localData.scopeStack = scopeStack;
localData.constants = abc.constants;
localData.methodInfo = abc.method_info;
localData.methodBody = body;
localData.abc = abc;
localData.localRegNames = localRegNames;
localData.fullyQualifiedNames = fullyQualifiedNames;
localData.parsedExceptions = new ArrayList<>();
localData.finallyJumps = new ArrayList<>();
localData.ignoredSwitches = new ArrayList<>();
localData.scriptIndex = scriptIndex;
localData.localRegAssignmentIps = new HashMap<>();
localData.ip = 0;
localData.refs = refs;
localData.code = code;
g.init(localData);
List<GraphPart> allParts = new ArrayList<>();
for (GraphPart head : g.heads) {
populateParts(head, allParts);
}
return g.translate(localData, staticOperation, path);
}
@Override
protected void checkGraph(List<GraphPart> allBlocks) {
for (ABCException ex : body.exceptions) {
int startIp = avm2code.adr2pos(ex.start);
int endIp = avm2code.adr2pos(ex.end);
int targetIp = avm2code.adr2pos(ex.target);
GraphPart target = null;
for (GraphPart p : allBlocks) {
if (p.start == targetIp) {
target = p;
break;
}
}
for (GraphPart p : allBlocks) {
if (p.start >= startIp && p.end <= endIp) {
p.throwParts.add(target);
target.refs.add(p);
}
}
}
/*for(ABCException ex:body.exceptions){
for(GraphPart p:allBlocks){
boolean next_is_ex_start=false;
for(GraphPart n:p.nextParts){
if(n.start==code.adr2pos(ex.start)){
next_is_ex_start = true;
break;
}
}
if(next_is_ex_start){
for(GraphPart q:allBlocks){ //find target part
if(q.start==code.adr2pos(ex.target)){
p.nextParts.add(q);
break;
}
}
}
}
}*/
}
@Override
protected List<GraphTargetItem> check(GraphSource code, BaseLocalData localData, List<GraphPart> allParts, Stack<GraphTargetItem> stack, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<Loop> loops, List<GraphTargetItem> output, Loop currentLoop, int staticOperation, String path) throws InterruptedException {
List<GraphTargetItem> ret = null;
AVM2LocalData aLocalData = (AVM2LocalData) localData;
List<ABCException> parsedExceptions = aLocalData.parsedExceptions;
List<Integer> finallyJumps = aLocalData.finallyJumps;
List<Integer> ignoredSwitches = aLocalData.ignoredSwitches;
int ip = part.start;
int addr = this.avm2code.fixAddrAfterDebugLine(this.avm2code.pos2adr(part.start));
int maxend = -1;
List<ABCException> catchedExceptions = new ArrayList<>();
for (int e = 0; e < body.exceptions.length; e++) {
if (addr == this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].start)) {
if (!body.exceptions[e].isFinally()) {
if (((body.exceptions[e].end) > maxend) && (!parsedExceptions.contains(body.exceptions[e]))) {
catchedExceptions.clear();
maxend = this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end);
catchedExceptions.add(body.exceptions[e]);
} else if (this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) == maxend) {
catchedExceptions.add(body.exceptions[e]);
}
}
}
}
if (catchedExceptions.size() > 0) {
/*if (currentLoop != null) {
//currentLoop.phase=0;
}*/
parsedExceptions.addAll(catchedExceptions);
int endpos = code.adr2pos(this.avm2code.fixAddrAfterDebugLine(catchedExceptions.get(0).end));
int endposStartBlock = code.adr2pos(catchedExceptions.get(0).end);
List<List<GraphTargetItem>> catchedCommands = new ArrayList<>();
if (this.avm2code.code.get(endpos).definition instanceof JumpIns) {
int afterCatchAddr = this.avm2code.pos2adr(endpos + 1) + this.avm2code.code.get(endpos).operands[0];
int afterCatchPos = this.avm2code.adr2pos(afterCatchAddr);
final AVM2Graph t = this;
Collections.sort(catchedExceptions, new Comparator<ABCException>() {
@Override
public int compare(ABCException o1, ABCException o2) {
return t.avm2code.fixAddrAfterDebugLine(o1.target) - t.avm2code.fixAddrAfterDebugLine(o2.target);
}
});
List<GraphTargetItem> finallyCommands = new ArrayList<>();
int returnPos = afterCatchPos;
for (int e = 0; e < body.exceptions.length; e++) {
if (body.exceptions[e].isFinally()) {
if (addr == this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].start)) {
if (afterCatchPos + 1 == code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end))) {
AVM2Instruction jmpIns = this.avm2code.code.get(code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end)));
if (jmpIns.definition instanceof JumpIns) {
int finStart = code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) + jmpIns.getBytes().length + jmpIns.operands[0]);
GraphPart fpart = null;
for (GraphPart p : allParts) {
if (p.start == finStart) {
fpart = p;
break;
}
}
int swPos = -1;
for (int f = finStart; f < this.avm2code.code.size(); f++) {
if (this.avm2code.code.get(f).definition instanceof LookupSwitchIns) {
AVM2Instruction swins = this.avm2code.code.get(f);
if (swins.operands.length >= 3) {
if (swins.operands[0] == swins.getBytes().length) {
if (code.adr2pos(code.pos2adr(f) + swins.operands[2]) < finStart) {
stack.push(new ExceptionAVM2Item(body.exceptions[e]));
GraphPart fepart = null;
for (GraphPart p : allParts) {
if (p.start == f + 1) {
fepart = p;
break;
}
}
//this.code.code.get(f).ignored = true;
//ignoredSwitches.add(f);
swPos = f;
List<GraphPart> stopPart2 = new ArrayList<>(stopPart);
stopPart2.add(fepart);
//finallyCommands = printGraph(new ArrayList<GraphPart>(), localData, stack, allParts, parent, fpart, stopPart2, loops, staticOperation, path);
returnPos = f + 1;
break;
}
}
}
}
}
//ignoredSwitches.add(-1);
//int igs_size=ignoredSwitches.size();
List<Integer> oldFinallyJumps = new ArrayList<>(finallyJumps);
finallyJumps.clear();
ignoredSwitches.add(swPos);
finallyCommands = printGraph(localData, stack, allParts, parent, fpart, null, loops, staticOperation, path);
//ignoredSwitches.remove(igs_size-1);
finallyJumps.addAll(oldFinallyJumps);
finallyJumps.add(finStart);
break;
}
}
}
}
}
GraphPart retPart = null;
for (GraphPart p : allParts) {
if (p.start == returnPos) {
retPart = p;
break;
}
}
List<GraphPart> catchParts = new ArrayList<>();
for (int e = 0; e < catchedExceptions.size(); e++) {
int eendpos;
if (e < catchedExceptions.size() - 1) {
eendpos = code.adr2pos(this.avm2code.fixAddrAfterDebugLine(catchedExceptions.get(e + 1).target)) - 2;
} else {
eendpos = afterCatchPos - 1;
}
GraphPart npart = null;
int findpos = code.adr2pos(catchedExceptions.get(e).target);
for (GraphPart p : allParts) {
if (p.start == findpos) {
npart = p;
catchParts.add(p);
break;
}
}
GraphPart nepart = null;
for (GraphPart p : allParts) {
if (p.start == eendpos + 1) {
nepart = p;
break;
}
}
stack.add(new ExceptionAVM2Item(catchedExceptions.get(e)));
AVM2LocalData localData2 = new AVM2LocalData(aLocalData);
localData2.scopeStack = new Stack<>();
List<GraphPart> stopPart2 = new ArrayList<>(stopPart);
stopPart2.add(nepart);
if (retPart != null) {
stopPart2.add(retPart);
}
catchedCommands.add(printGraph(localData2, stack, allParts, parent, npart, stopPart2, loops, staticOperation, path));
}
GraphPart nepart = null;
for (GraphPart p : allParts) {
if (p.start == endposStartBlock) {
nepart = p;
break;
}
}
List<GraphPart> stopPart2 = new ArrayList<>(stopPart);
stopPart2.add(nepart);
stopPart2.addAll(catchParts);
if (retPart != null) {
stopPart2.add(retPart);
}
List<GraphTargetItem> tryCommands = printGraph(localData, stack, allParts, parent, part, stopPart2, loops, staticOperation, path);
output.clear();
output.add(new TryAVM2Item(tryCommands, catchedExceptions, catchedCommands, finallyCommands));
ip = returnPos;
}
}
if (ip != part.start) {
part = null;
for (GraphPart p : allParts) {
List<GraphPart> ps = p.getSubParts();
for (GraphPart p2 : ps) {
if (p2.start == ip) {
part = p2;
break;
}
}
}
ret = new ArrayList<>();
ret.addAll(output);
GraphTargetItem lop = checkLoop(part, stopPart, loops);
if (lop == null) {
ret.addAll(printGraph(localData, stack, allParts, null, part, stopPart, loops, staticOperation, path));
} else {
ret.add(lop);
}
return ret;
}
if (part.nextParts.isEmpty()) {
if (this.avm2code.code.get(part.end).definition instanceof ReturnValueIns) { //returns in finally clause
if (part.getHeight() >= 3) {
if (this.avm2code.code.get(part.getPosAt(part.getHeight() - 2)).definition instanceof KillIns) {
if (this.avm2code.code.get(part.getPosAt(part.getHeight() - 3)).definition instanceof GetLocalTypeIns) {
if (output.size() >= 2) {
if (output.get(output.size() - 2) instanceof SetLocalAVM2Item) {
ret = new ArrayList<>();
ret.addAll(output);
ret.remove(ret.size() - 1);
ret.add(new ReturnValueAVM2Item(this.avm2code.code.get(part.end), ((SetLocalAVM2Item) output.get(output.size() - 2)).value));
return ret;
}
}
}
}
}
}
}
if ((this.avm2code.code.get(part.end).definition instanceof LookupSwitchIns) && ignoredSwitches.contains(part.end)) {
ret = new ArrayList<>();
ret.addAll(output);
return ret;
}
if (((part.nextParts.size() == 2)
&& (!stack.isEmpty())
&& (stack.peek() instanceof StrictEqAVM2Item)
&& (part.nextParts.get(0).getHeight() >= 2)
&& (this.avm2code.code.get(this.avm2code.fixIPAfterDebugLine(part.nextParts.get(0).start)).definition instanceof PushIntegerTypeIns)
&& (!part.nextParts.get(0).nextParts.isEmpty())
&& (this.avm2code.code.get(part.nextParts.get(0).nextParts.get(0).end).definition instanceof LookupSwitchIns))
|| ((part.nextParts.size() == 2)
&& (!stack.isEmpty())
&& (stack.peek() instanceof StrictNeqAVM2Item)
&& (part.nextParts.get(1).getHeight() >= 2)
&& (this.avm2code.code.get(this.avm2code.fixIPAfterDebugLine(part.nextParts.get(1).start)).definition instanceof PushIntegerTypeIns)
&& (!part.nextParts.get(1).nextParts.isEmpty())
&& (this.avm2code.code.get(part.nextParts.get(1).nextParts.get(0).end).definition instanceof LookupSwitchIns))) {
if (stack.peek() instanceof StrictEqAVM2Item) {
ignoredSwitches.add(part.nextParts.get(0).nextParts.get(0).end);
} else {
ignoredSwitches.add(part.nextParts.get(1).nextParts.get(0).end);
}
ret = new ArrayList<>();
ret.addAll(output);
boolean reversed = false;
if (stack.peek() instanceof StrictEqAVM2Item) {
reversed = true;
}
GraphTargetItem switchedObject = null;
if (!output.isEmpty()) {
if (output.get(output.size() - 1) instanceof SetLocalAVM2Item) {
switchedObject = ((SetLocalAVM2Item) output.get(output.size() - 1)).value;
}
}
if (switchedObject == null) {
switchedObject = new NullAVM2Item(null);
}
HashMap<Integer, GraphTargetItem> caseValuesMap = new HashMap<>();
GraphTargetItem tar = stack.pop();
if (tar instanceof StrictEqAVM2Item) {
tar = ((StrictEqAVM2Item) tar).leftSide;
}
if (tar instanceof StrictNeqAVM2Item) {
tar = ((StrictNeqAVM2Item) tar).leftSide;
}
caseValuesMap.put(this.avm2code.code.get(part.nextParts.get(reversed ? 0 : 1).start).operands[0], tar);
GraphPart switchLoc = part.nextParts.get(reversed ? 0 : 1).nextParts.get(0);
while ((this.avm2code.code.get(part.nextParts.get(reversed ? 1 : 0).end).definition instanceof IfStrictNeIns)
|| (this.avm2code.code.get(part.nextParts.get(reversed ? 1 : 0).end).definition instanceof IfStrictEqIns)) {
part = part.nextParts.get(reversed ? 1 : 0);
translatePart(localData, part, stack, staticOperation, null);
tar = stack.pop();
if (tar instanceof StrictEqAVM2Item) {
tar = ((StrictEqAVM2Item) tar).leftSide;
}
if (tar instanceof StrictNeqAVM2Item) {
tar = ((StrictNeqAVM2Item) tar).leftSide;
}
if (this.avm2code.code.get(part.end).definition instanceof IfStrictNeIns) {
reversed = false;
} else {
reversed = true;
}
GraphPart numPart = part.nextParts.get(reversed ? 0 : 1);
AVM2Instruction ins = null;
Stack<GraphTargetItem> sstack = new Stack<>();
do {
for (int n = 0; n < numPart.getHeight(); n++) {
ins = this.avm2code.code.get(numPart.getPosAt(n));
if (ins.definition instanceof LookupSwitchIns) {
break;
}
ins.translate(localData, sstack, new ArrayList<GraphTargetItem>(), staticOperation, path);
}
if (numPart.nextParts.size() > 1) {
break;
} else {
numPart = numPart.nextParts.get(0);
}
} while (!(this.avm2code.code.get(numPart.end).definition instanceof LookupSwitchIns));
GraphTargetItem nt = sstack.peek();
if (!(nt instanceof IntegerValueAVM2Item)) {
throw new RuntimeException("Invalid integer value in Switch");
}
IntegerValueAVM2Item iv = (IntegerValueAVM2Item) nt;
caseValuesMap.put((int) (long) iv.value, tar);
while (this.avm2code.code.get(part.nextParts.get(reversed ? 1 : 0).start).definition instanceof JumpIns) {
reversed = false;
part = part.nextParts.get(reversed ? 1 : 0);
if (part instanceof GraphPartMulti) {
part = ((GraphPartMulti) part).parts.get(0);
}
}
}
boolean hasDefault = false;
GraphPart dp = part.nextParts.get(reversed ? 1 : 0);
while (this.avm2code.code.get(dp.start).definition instanceof JumpIns) {
if (dp instanceof GraphPartMulti) {
dp = ((GraphPartMulti) dp).parts.get(0);
}
dp = dp.nextParts.get(0);
}
GraphPart numPart = dp;
AVM2Instruction ins = null;
Stack<GraphTargetItem> sstack = new Stack<>();
do {
for (int n = 0; n < numPart.getHeight(); n++) {
ins = this.avm2code.code.get(numPart.getPosAt(n));
if (ins.definition instanceof LookupSwitchIns) {
break;
}
ins.translate(localData, sstack, new ArrayList<GraphTargetItem>(), staticOperation, path);
}
if (numPart.nextParts.size() > 1) {
break;
} else {
numPart = numPart.nextParts.get(0);
}
} while (!(this.avm2code.code.get(numPart.end).definition instanceof LookupSwitchIns));
GraphTargetItem nt = sstack.peek();
if (nt instanceof IntegerValueAVM2Item) {
hasDefault = true;
}
List<GraphTargetItem> caseValues = new ArrayList<>();
for (int i = 0; i < switchLoc.nextParts.size() - 1; i++) {
if (caseValuesMap.containsKey(i)) {
caseValues.add(caseValuesMap.get(i));
} else {
continue;
}
}
List<List<GraphTargetItem>> caseCommands = new ArrayList<>();
GraphPart next = null;
next = getMostCommonPart(localData, switchLoc.nextParts, loops);//getNextPartPath(loopContinues);
currentLoop = new Loop(loops.size(), null, next);
currentLoop.phase = 1;
loops.add(currentLoop);
//switchLoc.getNextPartPath(new ArrayList<GraphPart>());
List<Integer> valuesMapping = new ArrayList<>();
List<GraphPart> caseBodies = new ArrayList<>();
for (int i = 0; i < caseValues.size(); i++) {
GraphPart cur = switchLoc.nextParts.get(1 + i);
if (!caseBodies.contains(cur)) {
caseBodies.add(cur);
}
valuesMapping.add(caseBodies.indexOf(cur));
}
List<GraphTargetItem> defaultCommands = new ArrayList<>();
GraphPart defaultPart = null;
if (hasDefault) {
defaultPart = switchLoc.nextParts.get(switchLoc.nextParts.size() - 1);
List<GraphPart> stopPart2 = new ArrayList<>(stopPart);
stopPart2.add(next);
defaultCommands = printGraph(localData, stack, allParts, switchLoc, defaultPart, stopPart2, loops, staticOperation, path);
if (!defaultCommands.isEmpty()) {
if (defaultCommands.get(defaultCommands.size() - 1) instanceof BreakItem) {
if (((BreakItem) defaultCommands.get(defaultCommands.size() - 1)).loopId == currentLoop.id) {
defaultCommands.remove(defaultCommands.size() - 1);
}
}
}
}
List<GraphPart> ignored = new ArrayList<>();
for (Loop l : loops) {
ignored.add(l.loopContinue);
}
for (int i = 0; i < caseBodies.size(); i++) {
List<GraphTargetItem> cc = new ArrayList<>();
List<GraphPart> stopPart2 = new ArrayList<>(stopPart);
for (int j = 0; j < caseBodies.size(); j++) {
if (caseBodies.get(j) != caseBodies.get(i)) {
stopPart2.add(caseBodies.get(j));
}
}
if (hasDefault) {
stopPart2.add(defaultPart);
}
cc.addAll(0, printGraph(localData, stack, allParts, switchLoc, caseBodies.get(i), stopPart2, loops, staticOperation, path));
caseCommands.add(cc);
}
SwitchItem sti = new SwitchItem(null, currentLoop, switchedObject, caseValues, caseCommands, defaultCommands, valuesMapping);
ret.add(sti);
//loops.remove(currentLoop);
if (next != null) {
/*if (ti != null) {
ret.add(ti);
} else {*/
currentLoop.phase = 2;
ret.addAll(printGraph(localData, stack, allParts, null, next, stopPart, loops, staticOperation, path));
//}
}
}
return ret;
}
@Override
protected GraphPart checkPart(Stack<GraphTargetItem> stack, BaseLocalData localData, GraphPart next, List<GraphPart> allParts) {
AVM2LocalData aLocalData = (AVM2LocalData) localData;
List<Integer> finallyJumps = aLocalData.finallyJumps;
List<Integer> ignoredSwitches = aLocalData.ignoredSwitches;
GraphPart ret = next;
for (int f = 0; f < finallyJumps.size(); f++) {
int fip = finallyJumps.get(f);
int swip = ignoredSwitches.get(f);
if (next.start == fip) {
if (stack != null && swip != -1) {
AVM2Instruction swIns = avm2code.code.get(swip);
GraphTargetItem t = stack.pop();
Double dval = EcmaScript.toNumber(t.getResult());
int val = (int) (double) dval;
if (swIns.definition instanceof LookupSwitchIns) {
List<Integer> branches = swIns.getBranches(code);
int nip = branches.get(0);
if (val >= 0 && val < branches.size() - 1) {
nip = branches.get(1 + val);
}
for (GraphPart p : allParts) {
if (p.start == nip) {
return p;
}
}
ret = null;
}
}
ret = null;
}
}
if (ret != next) {
return ret;
}
int pos = next.start;
int addr = this.avm2code.fixAddrAfterDebugLine(avm2code.pos2adr(pos));
for (int e = 0; e < body.exceptions.length; e++) {
if (body.exceptions[e].isFinally()) {
if (addr == this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].start)) {
if (true) { //afterCatchPos + 1 == code.adr2pos(this.code.fixAddrAfterDebugLine(body.exceptions[e].end))) {
AVM2Instruction jmpIns = this.avm2code.code.get(avm2code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end)));
if (jmpIns.definition instanceof JumpIns) {
int finStart = avm2code.adr2pos(this.avm2code.fixAddrAfterDebugLine(body.exceptions[e].end) + jmpIns.getBytes().length + jmpIns.operands[0]);
finallyJumps.add(finStart);
ignoredSwitches.add(-1);
break;
}
}
}
}
}
return next;
}
@Override
protected GraphTargetItem checkLoop(LoopItem loopItem, BaseLocalData localData, List<Loop> loops) {
AVM2LocalData aLocalData = (AVM2LocalData) localData;
if (loopItem instanceof WhileItem) {
WhileItem w = (WhileItem) loopItem;
if ((!w.expression.isEmpty()) && (w.expression.get(w.expression.size() - 1) instanceof HasNextAVM2Item)) {
if (((HasNextAVM2Item) w.expression.get(w.expression.size() - 1)).collection != null) {
if (((HasNextAVM2Item) w.expression.get(w.expression.size() - 1)).collection.getNotCoerced().getThroughRegister() instanceof FilteredCheckAVM2Item) {
//GraphTargetItem gti = ((HasNextAVM2Item) ((HasNextAVM2Item) w.expression.get(w.expression.size() - 1))).collection.getNotCoerced().getThroughRegister();
if (w.commands.size() >= 3) { //((w.commands.size() == 3) || (w.commands.size() == 4)) {
int pos = 0;
while (w.commands.get(pos) instanceof SetLocalAVM2Item) {
pos++;
}
GraphTargetItem ft = w.commands.get(pos);
if (ft instanceof WithAVM2Item) {
ft = w.commands.get(pos + 1);
if (ft instanceof IfItem) {
IfItem ift = (IfItem) ft;
if (ift.onTrue.size() > 0) {
ft = ift.onTrue.get(0);
if (ft instanceof SetPropertyAVM2Item) {
SetPropertyAVM2Item spt = (SetPropertyAVM2Item) ft;
if (spt.object instanceof LocalRegAVM2Item) {
int regIndex = ((LocalRegAVM2Item) spt.object).regIndex;
HasNextAVM2Item iti = (HasNextAVM2Item) w.expression.get(w.expression.size() - 1);
HashMap<Integer, GraphTargetItem> localRegs = aLocalData.localRegs;
localRegs.put(regIndex, new FilterAVM2Item(null, iti.collection.getThroughRegister(), ift.expression));
return null;
}
}
}
}
}
}
} else if (!w.commands.isEmpty()) {
if (w.commands.get(0) instanceof SetTypeAVM2Item) {
SetTypeAVM2Item sti = (SetTypeAVM2Item) w.commands.remove(0);
GraphTargetItem gti = sti.getValue().getNotCoerced();
if (gti instanceof NextValueAVM2Item) {
return new ForEachInAVM2Item(w.src, w.loop, new InAVM2Item(null, sti.getObject(), ((HasNextAVM2Item) w.expression.get(w.expression.size() - 1)).collection), w.commands);
} else if (gti instanceof NextNameAVM2Item) {
return new ForInAVM2Item(w.src, w.loop, new InAVM2Item(null, sti.getObject(), ((HasNextAVM2Item) w.expression.get(w.expression.size() - 1)).collection), w.commands);
}
}
}
}
}
}
return loopItem;
}
@Override
protected void finalProcess(List<GraphTargetItem> list, int level, FinalProcessLocalData localData) {
if (level == 0) {
if (!list.isEmpty()) {
if (list.get(list.size() - 1) instanceof ReturnVoidAVM2Item) {
list.remove(list.size() - 1);
}
}
}
/*for (int i = 0; i < list.size(); i++) {
if (list.get(i) instanceof WhileItem) {
WhileItem w = (WhileItem) list.get(i);
}
}*/
List<GraphTargetItem> ret = avm2code.clearTemporaryRegisters(list);
if (ret != list) {
list.clear();
list.addAll(ret);
}
for (int i = 0; i < list.size(); i++) {
if (list.get(i) instanceof SetTypeAVM2Item) {
if (((SetTypeAVM2Item) list.get(i)).getValue() instanceof ExceptionAVM2Item) {
list.remove(i);
i--;
continue;
}
}
if (list.get(i) instanceof IfItem) {
IfItem ifi = (IfItem) list.get(i);
if (((ifi.expression instanceof HasNextAVM2Item)
|| ((ifi.expression instanceof NotItem)
&& (((NotItem) ifi.expression).getOriginal() instanceof HasNextAVM2Item)))) {
HasNextAVM2Item hnt = null;
List<GraphTargetItem> body = new ArrayList<>();
List<GraphTargetItem> nextbody = new ArrayList<>();
if (ifi.expression instanceof NotItem) {
hnt = (HasNextAVM2Item) ((NotItem) ifi.expression).getOriginal();
body.addAll(ifi.onFalse);
for (int j = i + 1; j < list.size();) {
body.add(list.remove(i + 1));
}
nextbody = ifi.onTrue;
} else {
hnt = (HasNextAVM2Item) ifi.expression;
body = ifi.onTrue;
nextbody = ifi.onFalse;
}
if (!body.isEmpty()) {
if (body.get(0) instanceof SetTypeAVM2Item) {
SetTypeAVM2Item sti = (SetTypeAVM2Item) body.remove(0);
GraphTargetItem gti = sti.getValue().getNotCoerced();
GraphTargetItem repl = null;
if (gti instanceof NextValueAVM2Item) {
repl = new ForEachInAVM2Item(ifi.src, new Loop(0, null, null), new InAVM2Item(null, sti.getObject(), hnt.collection), body);
} else if (gti instanceof NextNameAVM2Item) {
repl = new ForInAVM2Item(ifi.src, new Loop(0, null, null), new InAVM2Item(null, sti.getObject(), hnt.collection), body);
}
if (repl != null) {
list.remove(i);
list.add(i, repl);
list.addAll(i + 1, nextbody);
}
}
}
}
}
}
}
@Override
protected boolean isEmpty(List<GraphTargetItem> output) {
if (super.isEmpty(output)) {
return true;
}
for (GraphTargetItem i : output) {
if (i instanceof SetLocalAVM2Item) {
if (avm2code.isKilled(((SetLocalAVM2Item) i).regIndex, 0, avm2code.code.size() - 1)) {
continue;
}
}
return false;
}
return true;
}
@Override
public AVM2LocalData prepareBranchLocalData(BaseLocalData localData) {
AVM2LocalData aLocalData = (AVM2LocalData) localData;
AVM2LocalData ret = new AVM2LocalData(aLocalData);
Stack<GraphTargetItem> copyScopeStack = new Stack<>();
copyScopeStack.addAll(ret.scopeStack);
ret.scopeStack = copyScopeStack;
return ret;
}
}

View File

@@ -0,0 +1,105 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.graph;
import com.jpexs.decompiler.flash.BaseLocalData;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.AVM2LocalData;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConvertOutput;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.graph.GraphPart;
import com.jpexs.decompiler.graph.GraphSource;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
/**
*
* @author JPEXS
*/
public class AVM2GraphSource extends GraphSource {
private final AVM2Code code;
boolean isStatic;
int classIndex;
int scriptIndex;
HashMap<Integer, GraphTargetItem> localRegs;
Stack<GraphTargetItem> scopeStack;
ABC abc;
MethodBody body;
HashMap<Integer, String> localRegNames;
List<String> fullyQualifiedNames;
HashMap<Integer, Integer> localRegAssigmentIps;
HashMap<Integer, List<Integer>> refs;
public AVM2Code getCode() {
return code;
}
public AVM2GraphSource(AVM2Code code, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> scopeStack, ABC abc, MethodBody body, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, HashMap<Integer, Integer> localRegAssigmentIp, HashMap<Integer, List<Integer>> refs) {
this.code = code;
this.isStatic = isStatic;
this.classIndex = classIndex;
this.localRegs = localRegs;
this.scopeStack = scopeStack;
this.abc = abc;
this.body = body;
this.localRegNames = localRegNames;
this.fullyQualifiedNames = fullyQualifiedNames;
this.scriptIndex = scriptIndex;
this.localRegAssigmentIps = localRegAssigmentIp;
this.refs = refs;
}
@Override
public int size() {
return code.code.size();
}
@Override
public AVM2Instruction get(int pos) {
return code.code.get(pos);
}
@Override
public boolean isEmpty() {
return code.code.isEmpty();
}
@Override
public List<GraphTargetItem> translatePart(GraphPart part, BaseLocalData localData, Stack<GraphTargetItem> stack, int start, int end, int staticOperation, String path) throws InterruptedException {
List<GraphTargetItem> ret = new ArrayList<>();
Stack<GraphTargetItem> newstack = ((AVM2LocalData) localData).scopeStack;
ConvertOutput co = code.toSourceOutput(path, part, false, isStatic, scriptIndex, classIndex, localRegs, stack, newstack, abc, abc.constants, abc.method_info, body, start, end, localRegNames, fullyQualifiedNames, new boolean[size()], localRegAssigmentIps, refs);
ret.addAll(co.output);
return ret;
}
@Override
public int adr2pos(long adr) {
return code.adr2pos(adr);
}
@Override
public long pos2adr(int pos) {
return code.pos2adr(pos);
}
}

View File

@@ -0,0 +1,364 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions;
import com.jpexs.decompiler.flash.BaseLocalData;
import com.jpexs.decompiler.flash.abc.ABCOutputStream;
import com.jpexs.decompiler.flash.abc.AVM2LocalData;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.LookupSwitchIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnVoidIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ThrowIns;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.graph.GraphSource;
import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.model.LocalData;
import com.jpexs.helpers.Helper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class AVM2Instruction implements Serializable, GraphSourceItem {
public static final long serialVersionUID = 1L;
public InstructionDefinition definition;
public int[] operands;
public long offset;
public byte[] bytes;
public String comment;
public boolean ignored = false;
public String labelname;
public long mappedOffset = -1;
public int changeJumpTo = -1;
public AVM2Instruction(long offset, InstructionDefinition definition, int[] operands, byte[] bytes) {
this.definition = definition;
this.operands = operands;
this.offset = offset;
this.bytes = bytes;
}
public byte[] getBytes() {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
ABCOutputStream aos = new ABCOutputStream(bos);
aos.write(definition.instructionCode);
for (int i = 0; i < definition.operands.length; i++) {
int opt = definition.operands[i] & 0xff00;
switch (opt) {
case AVM2Code.OPT_S24:
aos.writeS24(operands[i]);
break;
case AVM2Code.OPT_U30:
aos.writeU30(operands[i]);
break;
case AVM2Code.OPT_U8:
aos.writeU8(operands[i]);
break;
case AVM2Code.OPT_BYTE:
aos.writeU8(0xff & operands[i]);
break;
case AVM2Code.OPT_CASE_OFFSETS:
aos.writeU30(operands[i]); //case count
for (int j = i + 1; j < operands.length; j++) {
aos.writeS24(operands[j]);
}
break;
}
}
} catch (IOException ex) {
//ignored
}
return bos.toByteArray();
}
@Override
public String toString() {
StringBuilder s = new StringBuilder();
s.append(definition.instructionName);
for (int i = 0; i < operands.length; i++) {
s.append(" ");
s.append(operands[i]);
}
return s.toString();
}
public List<Long> getOffsets() {
List<Long> ret = new ArrayList<>();
String s = "";
for (int i = 0; i < definition.operands.length; i++) {
switch (definition.operands[i]) {
case AVM2Code.DAT_OFFSET:
ret.add(offset + operands[i] + getBytes().length);
break;
case AVM2Code.DAT_CASE_BASEOFFSET:
ret.add(offset + operands[i]);
break;
case AVM2Code.OPT_CASE_OFFSETS:
for (int j = i + 1; j < operands.length; j++) {
ret.add(offset + operands[j]);
}
break;
}
}
return ret;
}
public List<Object> getParamsAsList(ConstantPool constants) {
List<Object> s = new ArrayList<>();
for (int i = 0; i < definition.operands.length; i++) {
switch (definition.operands[i]) {
case AVM2Code.DAT_MULTINAME_INDEX:
s.add(constants.getMultiname(operands[i]));
break;
case AVM2Code.DAT_STRING_INDEX:
s.add(constants.getString(operands[i]));
break;
case AVM2Code.DAT_INT_INDEX:
s.add(Long.valueOf(constants.getInt(operands[i])));
break;
case AVM2Code.DAT_UINT_INDEX:
s.add(new Long(constants.getUInt(operands[i])));
break;
case AVM2Code.DAT_DOUBLE_INDEX:
s.add(Double.valueOf(constants.getDouble(operands[i])));
break;
case AVM2Code.DAT_OFFSET:
s.add(new Long(offset + operands[i] + getBytes().length));
break;
case AVM2Code.DAT_CASE_BASEOFFSET:
s.add(new Long(offset + operands[i]));
break;
case AVM2Code.OPT_CASE_OFFSETS:
s.add(new Long(operands[i]));
for (int j = i + 1; j < operands.length; j++) {
s.add(new Long(offset + operands[j]));
}
break;
default:
s.add(new Long(operands[i]));
}
}
return s;
}
public String getParams(ConstantPool constants, List<String> fullyQualifiedNames) {
StringBuilder s = new StringBuilder();
for (int i = 0; i < definition.operands.length; i++) {
switch (definition.operands[i]) {
case AVM2Code.DAT_MULTINAME_INDEX:
if (operands[i] == 0) {
s.append(" null");
} else {
s.append(" ");
s.append(constants.getMultiname(operands[i]).toString(constants, fullyQualifiedNames));
}
/*s.append(" m[");
s.append(operands[i]);
s.append("]\"");
if (constants.constant_multiname[operands[i]] == null) {
s.append("");
} else {
s.append(Helper.escapeString(constants.constant_multiname[operands[i]].toString(constants, fullyQualifiedNames)));
}
s.append("\"");*/
break;
case AVM2Code.DAT_STRING_INDEX:
if (operands[i] == 0) {
s.append(" null");
} else {
s.append(" \"");
s.append(Helper.escapeString(constants.getString(operands[i])));
s.append("\"");
}
break;
case AVM2Code.DAT_INT_INDEX:
if (operands[i] == 0) {
s.append(" null");
} else {
s.append(" ");
s.append(constants.getInt(operands[i]));
}
break;
case AVM2Code.DAT_UINT_INDEX:
if (operands[i] == 0) {
s.append(" null");
} else {
s.append(" ");
s.append(constants.getUInt(operands[i]));
}
break;
case AVM2Code.DAT_DOUBLE_INDEX:
if (operands[i] == 0) {
s.append(" null");
} else {
s.append(" ");
s.append(constants.getDouble(operands[i]));
}
break;
case AVM2Code.DAT_OFFSET:
s.append(" ");
s.append("ofs");
s.append(Helper.formatAddress(offset + operands[i] + getBytes().length));
break;
case AVM2Code.DAT_CASE_BASEOFFSET:
s.append(" ");
s.append("ofs");
s.append(Helper.formatAddress(offset + operands[i]));
break;
case AVM2Code.OPT_CASE_OFFSETS:
s.append(" ");
s.append(operands[i]);
for (int j = i + 1; j < operands.length; j++) {
s.append(" ");
s.append("ofs");
s.append(Helper.formatAddress(offset + operands[j]));
}
break;
default:
s.append(" ");
s.append(operands[i]);
}
}
return s.toString();
}
public String getComment() {
if (ignored) {
return " ;ignored";
}
if ((comment == null) || comment.isEmpty()) {
return "";
}
return " ;" + comment;
}
@Override
public boolean isIgnored() {
return ignored;
}
public GraphTextWriter toString(GraphTextWriter writer, LocalData localData) {
writer.appendNoHilight(Helper.formatAddress(offset) + " " + Helper.padSpaceRight(Helper.byteArrToString(getBytes()), 30) + definition.instructionName);
writer.appendNoHilight(getParams(localData.constantsAvm2, localData.fullyQualifiedNames) + getComment());
return writer;
}
public String toStringNoAddress(ConstantPool constants, List<String> fullyQualifiedNames) {
String s = definition.instructionName;
s += getParams(constants, fullyQualifiedNames) + getComment();
return s;
}
public List<Object> replaceWith;
@Override
public void translate(BaseLocalData localData, Stack<GraphTargetItem> stack, List<GraphTargetItem> output, int staticOperation, String path) throws InterruptedException {
AVM2LocalData aLocalData = (AVM2LocalData) localData;
definition.translate(aLocalData.isStatic,
aLocalData.scriptIndex,
aLocalData.classIndex,
aLocalData.localRegs,
stack,
aLocalData.scopeStack,
aLocalData.constants, this, aLocalData.methodInfo, output, aLocalData.methodBody, aLocalData.abc, aLocalData.localRegNames, aLocalData.fullyQualifiedNames, null, aLocalData.localRegAssignmentIps, aLocalData.ip, aLocalData.refs, aLocalData.code);
}
@Override
public boolean isJump() {
return (definition instanceof JumpIns) || (fixedBranch > -1);
}
@Override
public boolean isBranch() {
if (fixedBranch > -1) {
return false;
}
return (definition instanceof IfTypeIns) || (definition instanceof LookupSwitchIns);
}
@Override
public boolean isExit() {
return (definition instanceof ReturnValueIns) || (definition instanceof ReturnVoidIns) || (definition instanceof ThrowIns);
}
@Override
public long getOffset() {
return mappedOffset > -1 ? mappedOffset : offset;
}
@Override
public List<Integer> getBranches(GraphSource code) {
List<Integer> ret = new ArrayList<>();
if (definition instanceof IfTypeIns) {
if (fixedBranch == -1 || fixedBranch == 0) {
ret.add(code.adr2pos(offset + getBytes().length + operands[0]));
}
if (!(definition instanceof JumpIns)) {
if (fixedBranch == -1 || fixedBranch == 1) {
ret.add(code.adr2pos(offset + getBytes().length));
}
}
}
if (definition instanceof LookupSwitchIns) {
if (fixedBranch == -1 || fixedBranch == 0) {
ret.add(code.adr2pos(offset + operands[0]));
}
for (int k = 2; k < operands.length; k++) {
if (fixedBranch == -1 || fixedBranch == k - 1) {
ret.add(code.adr2pos(offset + operands[k]));
}
}
}
return ret;
}
@Override
public boolean ignoredLoops() {
return false;
}
@Override
public void setIgnored(boolean ignored, int pos) {
this.ignored = ignored;
}
public void setFixBranch(int pos) {
this.fixedBranch = pos;
}
private int fixedBranch = -1;
public int getFixBranch() {
return fixedBranch;
}
@Override
public boolean isDeobfuscatePop() {
return definition instanceof DeobfuscatePopIns;
}
}

View File

@@ -0,0 +1,30 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions;
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns;
/**
*
* @author JPEXS
*/
public class DeobfuscatePopIns extends PopIns {
public DeobfuscatePopIns() {
instructionName = "ffdec_deobfuscatepop";
}
}

View File

@@ -0,0 +1,25 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.Stack;
public interface IfTypeIns {
public abstract void translateInverted(java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, AVM2Instruction ins);
}

View File

@@ -0,0 +1,165 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.DecLocalIIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.DecLocalIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Stack;
public class InstructionDefinition implements Serializable {
public static final long serialVersionUID = 1L;
public int[] operands;
public String instructionName = "";
public int instructionCode = 0;
public InstructionDefinition(int instructionCode, String instructionName, int[] operands) {
this.instructionCode = instructionCode;
this.instructionName = instructionName;
this.operands = operands;
}
@Override
public String toString() {
StringBuilder s = new StringBuilder();
s.append(instructionName);
for (int i = 0; i < operands.length; i++) {
if ((operands[i] & 0xff00) == AVM2Code.OPT_U30) {
s.append(" U30");
}
if ((operands[i] & 0xff00) == AVM2Code.OPT_U8) {
s.append(" U8");
}
if ((operands[i] & 0xff00) == AVM2Code.OPT_BYTE) {
s.append(" BYTE");
}
if ((operands[i] & 0xff00) == AVM2Code.OPT_S24) {
s.append(" S24");
}
if ((operands[i] & 0xff00) == AVM2Code.OPT_CASE_OFFSETS) {
s.append(" U30 S24,[S24]...");
}
}
return s.toString();
}
public void execute(LocalDataArea lda, ConstantPool constants, List<Object> arguments) {
throw new UnsupportedOperationException("Instruction " + instructionName + " not implemented");
}
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) throws InterruptedException {
}
protected FullMultinameAVM2Item resolveMultiname(Stack<GraphTargetItem> stack, ConstantPool constants, int multinameIndex, AVM2Instruction ins) {
GraphTargetItem ns = null;
GraphTargetItem name = null;
if (constants.getMultiname(multinameIndex).needsName()) {
name = (GraphTargetItem) stack.pop();
}
if (constants.getMultiname(multinameIndex).needsNs()) {
ns = (GraphTargetItem) stack.pop();
}
return new FullMultinameAVM2Item(ins, multinameIndex, name, ns);
}
protected int resolvedCount(ConstantPool constants, int multinameIndex) {
int pos = 0;
if (constants.getMultiname(multinameIndex).needsNs()) {
pos++;
}
if (constants.getMultiname(multinameIndex).needsName()) {
pos++;
}
return pos;
}
protected String resolveMultinameNoPop(int pos, Stack<AVM2Item> stack, ConstantPool constants, int multinameIndex, AVM2Instruction ins, List<String> fullyQualifiedNames) {
String ns = "";
String name;
if (constants.getMultiname(multinameIndex).needsNs()) {
ns = "[" + stack.get(pos) + "]";
pos++;
}
if (constants.getMultiname(multinameIndex).needsName()) {
name = stack.get(pos).toString();
} else {
name = GraphTextWriter.hilighOffset(constants.getMultiname(multinameIndex).getName(constants, fullyQualifiedNames), ins.offset);
}
return name + ns;
}
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return 0;
}
public int getScopeStackDelta(AVM2Instruction ins, ABC abc) {
return 0;
}
protected boolean isRegisterCompileTime(int regId, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
Set<Integer> previous = new HashSet<>();
AVM2Code.getPreviousReachableIps(ip, refs, previous, new HashSet<Integer>());
for (int p : previous) {
if (p < 0) {
continue;
}
if (p >= code.code.size()) {
continue;
}
AVM2Instruction sins = code.code.get(p);
if (code.code.get(p).definition instanceof SetLocalTypeIns) {
SetLocalTypeIns sl = (SetLocalTypeIns) sins.definition;
if (sl.getRegisterId(sins) == regId) {
if (!AVM2Code.isDirectAncestor(ip, p, refs)) {
return false;
}
}
}
if ((code.code.get(p).definition instanceof IncLocalIns)
|| (code.code.get(p).definition instanceof IncLocalIIns)
|| (code.code.get(p).definition instanceof DecLocalIns)
|| (code.code.get(p).definition instanceof DecLocalIIns)) {
if (sins.operands[0] == regId) {
if (!AVM2Code.isDirectAncestor(ip, p, refs)) {
return false;
}
}
}
}
return true;
}
}

View File

@@ -0,0 +1,29 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public interface SetTypeIns {
public abstract String getObject(Stack<AVM2Item> stack, ABC abc, AVM2Instruction ins, List<AVM2Item> output, MethodBody body, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames) throws InterruptedException;
}

View File

@@ -0,0 +1,30 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions;
/**
*
* @author JPEXS
*/
public class TagInstruction extends InstructionDefinition {
public static final long serialVersionUID = 1L;
public TagInstruction(String tagName) {
super(-1, tagName, new int[0]);
}
}

View File

@@ -0,0 +1,57 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
/**
*
* @author JPEXS
*/
public class Lf32Ins extends InstructionDefinition {
public Lf32Ins() {
super(0x38, "lf32", new int[]{});
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return 1 - 1;
}
@Override
public int getScopeStackDelta(AVM2Instruction ins, ABC abc) {
return 0;
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
GraphTargetItem ofs = stack.pop();
stack.push(new AlchemyLoadAVM2Item(ins, ofs, instructionName));
}
}

View File

@@ -0,0 +1,57 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
/**
*
* @author JPEXS
*/
public class Lf64Ins extends InstructionDefinition {
public Lf64Ins() {
super(0x39, "lf64", new int[]{});
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return 1 - 1;
}
@Override
public int getScopeStackDelta(AVM2Instruction ins, ABC abc) {
return 0;
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
GraphTargetItem ofs = stack.pop();
stack.push(new AlchemyLoadAVM2Item(ins, ofs, instructionName));
}
}

View File

@@ -0,0 +1,57 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
/**
*
* @author JPEXS
*/
public class Li16Ins extends InstructionDefinition {
public Li16Ins() {
super(0x36, "li16", new int[]{});
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return 1 - 1;
}
@Override
public int getScopeStackDelta(AVM2Instruction ins, ABC abc) {
return 0;
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
GraphTargetItem ofs = stack.pop();
stack.push(new AlchemyLoadAVM2Item(ins, ofs, instructionName));
}
}

View File

@@ -0,0 +1,57 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
/**
*
* @author JPEXS
*/
public class Li32Ins extends InstructionDefinition {
public Li32Ins() {
super(0x37, "li32", new int[]{});
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return 1 - 1;
}
@Override
public int getScopeStackDelta(AVM2Instruction ins, ABC abc) {
return 0;
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
GraphTargetItem ofs = stack.pop();
stack.push(new AlchemyLoadAVM2Item(ins, ofs, instructionName));
}
}

View File

@@ -0,0 +1,57 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyLoadAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
/**
*
* @author JPEXS
*/
public class Li8Ins extends InstructionDefinition {
public Li8Ins() {
super(0x35, "li8", new int[]{});
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return 1 - 1;
}
@Override
public int getScopeStackDelta(AVM2Instruction ins, ABC abc) {
return 0;
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
GraphTargetItem ofs = stack.pop();
stack.push(new AlchemyLoadAVM2Item(ins, ofs, instructionName));
}
}

View File

@@ -0,0 +1,58 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
/**
*
* @author JPEXS
*/
public class Sf32Ins extends InstructionDefinition {
public Sf32Ins() {
super(0x3D, "sf32", new int[]{});
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2;
}
@Override
public int getScopeStackDelta(AVM2Instruction ins, ABC abc) {
return 0;
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
GraphTargetItem ofs = stack.pop();
GraphTargetItem value = stack.pop();
stack.push(new AlchemyStoreAVM2Item(ins, value, ofs, instructionName));
}
}

View File

@@ -0,0 +1,58 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
/**
*
* @author JPEXS
*/
public class Sf64Ins extends InstructionDefinition {
public Sf64Ins() {
super(0x3E, "sf64", new int[]{});
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2;
}
@Override
public int getScopeStackDelta(AVM2Instruction ins, ABC abc) {
return 0;
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
GraphTargetItem ofs = stack.pop();
GraphTargetItem value = stack.pop();
stack.push(new AlchemyStoreAVM2Item(ins, value, ofs, instructionName));
}
}

View File

@@ -0,0 +1,58 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
/**
*
* @author JPEXS
*/
public class Si16Ins extends InstructionDefinition {
public Si16Ins() {
super(0x3B, "si16", new int[]{});
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2;
}
@Override
public int getScopeStackDelta(AVM2Instruction ins, ABC abc) {
return 0;
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
GraphTargetItem ofs = stack.pop();
GraphTargetItem value = stack.pop();
stack.push(new AlchemyStoreAVM2Item(ins, value, ofs, instructionName));
}
}

View File

@@ -0,0 +1,58 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
/**
*
* @author JPEXS
*/
public class Si32Ins extends InstructionDefinition {
public Si32Ins() {
super(0x3C, "si32", new int[]{});
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2;
}
@Override
public int getScopeStackDelta(AVM2Instruction ins, ABC abc) {
return 0;
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
GraphTargetItem ofs = stack.pop();
GraphTargetItem value = stack.pop();
stack.push(new AlchemyStoreAVM2Item(ins, value, ofs, instructionName));
}
}

View File

@@ -0,0 +1,58 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.AlchemyStoreAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
/**
*
* @author JPEXS
*/
public class Si8Ins extends InstructionDefinition {
public Si8Ins() {
super(0x3A, "si8", new int[]{});
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2;
}
@Override
public int getScopeStackDelta(AVM2Instruction ins, ABC abc) {
return 0;
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
GraphTargetItem ofs = stack.pop();
GraphTargetItem value = stack.pop();
stack.push(new AlchemyStoreAVM2Item(ins, value, ofs, instructionName));
}
}

View File

@@ -0,0 +1,57 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.AlchemySignExtendAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
/**
*
* @author JPEXS
*/
public class Sxi16Ins extends InstructionDefinition {
public Sxi16Ins() {
super(0x52, "sxi_16", new int[]{});
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return 1 - 1;
}
@Override
public int getScopeStackDelta(AVM2Instruction ins, ABC abc) {
return 0;
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
GraphTargetItem value = stack.pop();
stack.push(new AlchemySignExtendAVM2Item(ins, value, instructionName));
}
}

View File

@@ -0,0 +1,57 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.AlchemySignExtendAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
/**
*
* @author JPEXS
*/
public class Sxi1Ins extends InstructionDefinition {
public Sxi1Ins() {
super(0x50, "sxi_1", new int[]{});
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return 1 - 1;
}
@Override
public int getScopeStackDelta(AVM2Instruction ins, ABC abc) {
return 0;
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
GraphTargetItem value = stack.pop();
stack.push(new AlchemySignExtendAVM2Item(ins, value, instructionName));
}
}

View File

@@ -0,0 +1,57 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.AlchemySignExtendAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
/**
*
* @author JPEXS
*/
public class Sxi8Ins extends InstructionDefinition {
public Sxi8Ins() {
super(0x51, "sxi_8", new int[]{});
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return 1 - 1;
}
@Override
public int getScopeStackDelta(AVM2Instruction ins, ABC abc) {
return 0;
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
GraphTargetItem value = stack.pop();
stack.push(new AlchemySignExtendAVM2Item(ins, value, instructionName));
}
}

View File

@@ -0,0 +1,49 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.model.operations.AddAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class AddIIns extends AddIns {
public AddIIns() {
instructionName = "add_i";
instructionCode = 0xc5;
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
GraphTargetItem v2 = (GraphTargetItem) stack.pop();
GraphTargetItem v1 = (GraphTargetItem) stack.pop();
stack.push(new AddAVM2Item(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}

View File

@@ -0,0 +1,72 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.operations.AddAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class AddIns extends InstructionDefinition {
public AddIns() {
super(0xa0, "add", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List<Object> arguments) {
Object o1 = lda.operandStack.pop();
Object o2 = lda.operandStack.pop();
if ((o1 instanceof Long) && ((o2 instanceof Long))) {
Long ret = Long.valueOf(((Long) o1).longValue() + ((Long) o2).longValue());
lda.operandStack.push(ret);
} else if ((o1 instanceof Double) && ((o2 instanceof Double))) {
Double ret = Double.valueOf(((Double) o1).doubleValue() + ((Double) o2).doubleValue());
lda.operandStack.push(ret);
} else if ((o1 instanceof Long) && ((o2 instanceof Double))) {
Double ret = new Double(((Long) o1).longValue() + ((Double) o2).doubleValue());
lda.operandStack.push(ret);
} else if ((o1 instanceof Double) && ((o2 instanceof Long))) {
Double ret = new Double(((Double) o1).doubleValue() + ((Long) o2).longValue());
lda.operandStack.push(ret);
} else {
String s = o1.toString() + o2.toString();
lda.operandStack.push(s);
}
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
GraphTargetItem v2 = (GraphTargetItem) stack.pop();
GraphTargetItem v1 = (GraphTargetItem) stack.pop();
stack.push(new AddAVM2Item(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}

View File

@@ -0,0 +1,66 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.DecrementAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class DecrementIIns extends InstructionDefinition {
public DecrementIIns() {
super(0xc1, "decrement_i", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List<Object> arguments) {
Object obj = lda.operandStack.pop();
if (obj instanceof Long) {
Long obj2 = ((Long) obj).longValue() - 1;
lda.operandStack.push(obj2);
} else if (obj instanceof Double) {
Double obj2 = ((Double) obj).doubleValue() - 1;
lda.operandStack.push(obj2);
}
if (obj instanceof String) {
Double obj2 = Double.parseDouble((String) obj) - 1;
lda.operandStack.push(obj2);
} else {
throw new RuntimeException("Cannot decrement local register");
}
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
stack.push(new DecrementAVM2Item(ins, (GraphTargetItem) stack.pop()));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1 + 1;
}
}

View File

@@ -0,0 +1,66 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.DecrementAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class DecrementIns extends InstructionDefinition {
public DecrementIns() {
super(0x93, "decrement", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List<Object> arguments) {
Object obj = lda.operandStack.pop();
if (obj instanceof Long) {
Long obj2 = ((Long) obj).longValue() - 1;
lda.operandStack.push(obj2);
} else if (obj instanceof Double) {
Double obj2 = ((Double) obj).doubleValue() - 1;
lda.operandStack.push(obj2);
}
if (obj instanceof String) {
Double obj2 = Double.parseDouble((String) obj) - 1;
lda.operandStack.push(obj2);
} else {
throw new RuntimeException("Cannot decrement local register");
}
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
stack.push(new DecrementAVM2Item(ins, (GraphTargetItem) stack.pop()));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1 + 1;
}
}

View File

@@ -0,0 +1,71 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.operations.DivideAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class DivideIns extends InstructionDefinition {
public DivideIns() {
super(0xa3, "divide", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List<Object> arguments) {
Object o2 = lda.operandStack.pop();
Object o1 = lda.operandStack.pop();
if ((o1 instanceof Long) && ((o2 instanceof Long))) {
Long ret = Long.valueOf(((Long) o1).longValue() / ((Long) o2).longValue());
lda.operandStack.push(ret);
} else if ((o1 instanceof Double) && ((o2 instanceof Double))) {
Double ret = Double.valueOf(((Double) o1).doubleValue() / ((Double) o2).doubleValue());
lda.operandStack.push(ret);
} else if ((o1 instanceof Long) && ((o2 instanceof Double))) {
Double ret = new Double(((Long) o1).longValue() / ((Double) o2).doubleValue());
lda.operandStack.push(ret);
} else if ((o1 instanceof Double) && ((o2 instanceof Long))) {
Double ret = new Double(((Double) o1).doubleValue() / ((Long) o2).longValue());
lda.operandStack.push(ret);
} else {
throw new RuntimeException("Cannot divide");
}
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
GraphTargetItem v2 = (GraphTargetItem) stack.pop();
GraphTargetItem v1 = (GraphTargetItem) stack.pop();
stack.push(new DivideAVM2Item(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}

View File

@@ -0,0 +1,47 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.IncrementAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class IncrementIIns extends InstructionDefinition {
public IncrementIIns() {
super(0xc0, "increment_i", new int[]{});
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
stack.push(new IncrementAVM2Item(ins, (GraphTargetItem) stack.pop()));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1 + 1;
}
}

View File

@@ -0,0 +1,47 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.IncrementAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class IncrementIns extends InstructionDefinition {
public IncrementIns() {
super(0x91, "increment", new int[]{});
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
stack.push(new IncrementAVM2Item(ins, (GraphTargetItem) stack.pop()));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1 + 1;
}
}

View File

@@ -0,0 +1,63 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.operations.ModuloAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class ModuloIns extends InstructionDefinition {
public ModuloIns() {
super(0xa4, "modulo", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List<Object> arguments) {
Object o1 = lda.operandStack.pop();
Object o2 = lda.operandStack.pop();
if ((o1 instanceof Long) && ((o2 instanceof Long))) {
Long ret = Long.valueOf(((Long) o2).longValue() % ((Long) o1).longValue());
lda.operandStack.push(ret);
} else {
throw new RuntimeException("Cannot modulo");
}
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
GraphTargetItem v2 = (GraphTargetItem) stack.pop();
GraphTargetItem v1 = (GraphTargetItem) stack.pop();
stack.push(new ModuloAVM2Item(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}

View File

@@ -0,0 +1,49 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.operations.MultiplyAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class MultiplyIIns extends InstructionDefinition {
public MultiplyIIns() {
super(0xc7, "multiply_i", new int[]{});
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
GraphTargetItem v2 = (GraphTargetItem) stack.pop();
GraphTargetItem v1 = (GraphTargetItem) stack.pop();
stack.push(new MultiplyAVM2Item(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}

View File

@@ -0,0 +1,71 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.operations.MultiplyAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class MultiplyIns extends InstructionDefinition {
public MultiplyIns() {
super(0xa2, "multiply", new int[]{});
}
@Override
public void execute(LocalDataArea lda, ConstantPool constants, List<Object> arguments) {
Object o1 = lda.operandStack.pop();
Object o2 = lda.operandStack.pop();
if ((o1 instanceof Long) && ((o2 instanceof Long))) {
Long ret = Long.valueOf(((Long) o1).longValue() * ((Long) o2).longValue());
lda.operandStack.push(ret);
} else if ((o1 instanceof Double) && ((o2 instanceof Double))) {
Double ret = Double.valueOf(((Double) o1).doubleValue() * ((Double) o2).doubleValue());
lda.operandStack.push(ret);
} else if ((o1 instanceof Long) && ((o2 instanceof Double))) {
Double ret = new Double(((Long) o1).longValue() * ((Double) o2).doubleValue());
lda.operandStack.push(ret);
} else if ((o1 instanceof Double) && ((o2 instanceof Long))) {
Double ret = new Double(((Double) o1).doubleValue() * ((Long) o2).longValue());
lda.operandStack.push(ret);
} else {
throw new RuntimeException("Cannot multiply");
}
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
GraphTargetItem v2 = (GraphTargetItem) stack.pop();
GraphTargetItem v1 = (GraphTargetItem) stack.pop();
stack.push(new MultiplyAVM2Item(ins, v1, v2));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -2 + 1;
}
}

View File

@@ -0,0 +1,48 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.operations.NegAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class NegateIIns extends InstructionDefinition {
public NegateIIns() {
super(0xc4, "negate_i", new int[]{});
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
GraphTargetItem v = (GraphTargetItem) stack.pop();
stack.push(new NegAVM2Item(ins, v));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1 + 1;
}
}

View File

@@ -0,0 +1,48 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.operations.NegAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
public class NegateIns extends InstructionDefinition {
public NegateIns() {
super(0x90, "negate", new int[]{});
}
@Override
public void translate(boolean isStatic, int scriptIndex, int classIndex, java.util.HashMap<Integer, GraphTargetItem> localRegs, Stack<GraphTargetItem> stack, java.util.Stack<GraphTargetItem> scopeStack, ConstantPool constants, AVM2Instruction ins, List<MethodInfo> method_info, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<String> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code) {
GraphTargetItem v = (GraphTargetItem) stack.pop();
stack.push(new NegAVM2Item(ins, v));
}
@Override
public int getStackDelta(AVM2Instruction ins, ABC abc) {
return -1 + 1;
}
}

Some files were not shown because too many files have changed in this diff Show More