Decompiler improvement, slightly recursive
This commit is contained in:
parent
a06423a6bc
commit
f75c7e0534
@ -12,7 +12,7 @@ import java.io.File;
|
||||
public class Main {
|
||||
public static void main(String[] args) throws Exception {
|
||||
FlashDecompiler decompiler = new FlashDecompiler();
|
||||
ShockwaveFile file = decompiler.loadFromFile(new File("D:\\Documents\\rtmpSpring\\static\\swf\\cache\\rus\\base[17].swf"));
|
||||
ShockwaveFile file = decompiler.loadFromFile(new File("D:\\Documents\\FlashProjects\\Untitled-2.swf")); // D:\Documents\rtmpSpring\static\swf\cache\rus\base[17].swf
|
||||
|
||||
DoAction da = (DoAction) file.getTags()
|
||||
.stream()
|
||||
|
@ -15,7 +15,9 @@ public enum ActionPushType {
|
||||
// these types are internal (used for decompiler's purposes)
|
||||
// they are not exist
|
||||
|
||||
INIT_OBJECT(-1);
|
||||
INIT_OBJECT(-1),
|
||||
GET_VARIABLE(-2),
|
||||
GET_MEMBER(-3);
|
||||
|
||||
public final int type;
|
||||
|
||||
|
@ -0,0 +1,25 @@
|
||||
package com.alterdekim.flash.decompiler.item.internal;
|
||||
|
||||
import com.alterdekim.flash.decompiler.item.ActionPushType;
|
||||
import com.alterdekim.flash.decompiler.item.ByteCodeItem;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
public class GetMemberItem extends ByteCodeItem {
|
||||
|
||||
private final ArrayDeque<String> hierarchy;
|
||||
|
||||
@Override
|
||||
public ActionPushType getType() {
|
||||
return ActionPushType.GET_MEMBER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayDeque<String> getValue() {
|
||||
return hierarchy;
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.alterdekim.flash.decompiler.item.internal;
|
||||
|
||||
import com.alterdekim.flash.decompiler.item.ActionPushType;
|
||||
import com.alterdekim.flash.decompiler.item.ByteCodeItem;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
public class GetVariableItem extends ByteCodeItem {
|
||||
private String name;
|
||||
|
||||
|
||||
@Override
|
||||
public ActionPushType getType() {
|
||||
return ActionPushType.GET_VARIABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return this.name;
|
||||
}
|
||||
}
|
@ -3,9 +3,11 @@ package com.alterdekim.flash.decompiler.item.internal;
|
||||
import com.alterdekim.flash.decompiler.item.ActionPushType;
|
||||
import com.alterdekim.flash.decompiler.item.ByteCodeItem;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@ToString
|
||||
@AllArgsConstructor
|
||||
public class InitObjectItem extends ByteCodeItem {
|
||||
|
||||
|
@ -3,9 +3,10 @@ package com.alterdekim.flash.decompiler.translator;
|
||||
import com.alterdekim.flash.decompiler.action.ActionPush;
|
||||
import com.alterdekim.flash.decompiler.item.*;
|
||||
import com.alterdekim.flash.decompiler.action.ByteCodeAction;
|
||||
import com.alterdekim.flash.decompiler.item.internal.GetMemberItem;
|
||||
import com.alterdekim.flash.decompiler.item.internal.GetVariableItem;
|
||||
import com.alterdekim.flash.decompiler.item.internal.InitObjectItem;
|
||||
import com.alterdekim.flash.decompiler.tag.DoAction;
|
||||
import com.alterdekim.flash.decompiler.util.ActionField;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.*;
|
||||
@ -16,7 +17,7 @@ public class Flash2Java {
|
||||
private final List<String> pool;
|
||||
private final List<ByteCodeAction> actions;
|
||||
private final Stack<ByteCodeItem> stack; // ByteCodeAction
|
||||
private final Map<String, FlashVar> vars;
|
||||
private final Map<String, Object> vars;
|
||||
|
||||
public Flash2Java(DoAction doAction) {
|
||||
this.pool = doAction.getActionPool();
|
||||
@ -25,12 +26,15 @@ public class Flash2Java {
|
||||
this.vars = new HashMap<>();
|
||||
}
|
||||
|
||||
public Map<String, FlashVar> convert() {
|
||||
// abolish the activeness of variable inside of an HashMap. Use stack instead.
|
||||
public Map<String, Object> convert() {
|
||||
// abolish the activeness of variable inside a HashMap. Use stack instead.
|
||||
for (ByteCodeAction action : actions) {
|
||||
// try {
|
||||
//log.info("Action type: " + action.getType().toString());
|
||||
switch (action.getType()) {
|
||||
case DefineLocal2:
|
||||
defineLocalWithoutAssign();
|
||||
break;
|
||||
case DefineLocal:
|
||||
defineLocal();
|
||||
break;
|
||||
@ -66,11 +70,11 @@ public class Flash2Java {
|
||||
}
|
||||
|
||||
private void initObject() {
|
||||
Integer numberOfEntries = (Integer) this.stack.pop().getValue();
|
||||
Integer numberOfEntries = (int) Double.parseDouble(this.stack.pop().getValue()+""); // harsh way
|
||||
HashMap<String, Object> obj = new HashMap<>();
|
||||
for( int i = 0; i < numberOfEntries; i++ ) {
|
||||
Object val = valConverter( this.stack.pop() );
|
||||
String key = (String) valConverter( this.stack.pop() );
|
||||
String key = valToString( this.stack.pop() );
|
||||
obj.put(key, val);
|
||||
}
|
||||
this.stack.push(new InitObjectItem(obj));
|
||||
@ -96,36 +100,62 @@ public class Flash2Java {
|
||||
}
|
||||
|
||||
private void getMember() {
|
||||
Object val = this.stack.pop().getValue();
|
||||
String name = (String) valConverter( this.stack.pop() );
|
||||
log.info("SetMember: {}", name);
|
||||
String key = this.vars.keySet().stream().filter(k -> this.vars.get(k).isActive()).findFirst().get();
|
||||
HashMap<String, Object> g = (HashMap<String, Object>) this.vars.get(key).getVal();
|
||||
g.put(name, val);
|
||||
this.vars.put(key, new FlashVar(true, g));
|
||||
}
|
||||
|
||||
private boolean hasActiveVariable() {
|
||||
return this.vars.keySet().stream().anyMatch(k -> this.vars.get(k).isActive());
|
||||
}
|
||||
|
||||
private String getActiveVarKey() {
|
||||
return this.vars.keySet().stream().filter(k -> this.vars.get(k).isActive()).findFirst().get();
|
||||
}
|
||||
|
||||
private void setMember() {
|
||||
log.info("GetMember: {}", this.stack);
|
||||
String property = valToString( this.stack.pop() );
|
||||
ByteCodeItem val = this.stack.pop();
|
||||
|
||||
if( this.stack.isEmpty() && this.hasActiveVariable() ) {
|
||||
String var = getActiveVarKey();
|
||||
|
||||
if( val.getType() == ActionPushType.GET_MEMBER ) {
|
||||
ArrayDeque<String> l = (ArrayDeque<String>) val.getValue();
|
||||
l.add(property);
|
||||
this.stack.push(new GetMemberItem(l));
|
||||
return;
|
||||
}
|
||||
Integer index = (Integer) this.stack.pop().getValue();
|
||||
String var = this.vars.keySet().stream().filter(k -> this.vars.get(k).isActive()).findFirst().get();
|
||||
Map<String, Object> m = (Map<String, Object>) this.vars.get(var).getVal();
|
||||
m.put(String.valueOf(index), val.getValue());
|
||||
this.vars.put(var, new FlashVar(false, m)); // this may cause a bug (false in FlashVar arg)
|
||||
String key = valToString(val);
|
||||
this.stack.push(new GetMemberItem(new ArrayDeque<>(List.of(key, property))));
|
||||
}
|
||||
|
||||
private void setMember() { // make recursive assignment.
|
||||
log.info("SetMember: {}", this.stack);
|
||||
ByteCodeItem val = this.stack.pop();
|
||||
String index = valToString( this.stack.pop() );
|
||||
ByteCodeItem varOrMember = this.stack.pop();
|
||||
if( varOrMember.getType() == ActionPushType.GET_VARIABLE ) {
|
||||
Map<String, Object> m = (Map<String, Object>) this.vars.get(valToString( varOrMember ));
|
||||
m.put(index, val.getValue());
|
||||
this.vars.put(valToString(varOrMember), m);
|
||||
return;
|
||||
}
|
||||
// GetMemberItem recursive
|
||||
Map<String, Object> m = recursiveGet((ArrayDeque<String>) varOrMember.getValue());
|
||||
m.put(index, val.getValue());
|
||||
}
|
||||
|
||||
private Map<String, Object> recursiveGet(Deque<String> l) {
|
||||
Map<String, Object> m = this.vars;
|
||||
Iterator<String> i = l.iterator();
|
||||
while(i.hasNext()) {
|
||||
m = (HashMap<String, Object>) m.get(i.next());
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
private GetMemberItem toGetMember(ByteCodeItem item) {
|
||||
switch (item.getType()) {
|
||||
case GET_MEMBER:
|
||||
return (GetMemberItem) item;
|
||||
case STRING:
|
||||
case POOL_INDEX:
|
||||
default:
|
||||
return new GetMemberItem(new ArrayDeque<>(List.of(valToString(item))));
|
||||
}
|
||||
}
|
||||
|
||||
private String valToString(ByteCodeItem item) {
|
||||
if ( item.getType() == ActionPushType.POOL_INDEX ) {
|
||||
return fromPool( (Integer) item.getValue() );
|
||||
} else if ( item.getType() == ActionPushType.STRING ) {
|
||||
return (String) item.getValue();
|
||||
}
|
||||
return String.valueOf( item.getValue() );
|
||||
}
|
||||
|
||||
private Object valConverter(ByteCodeItem item) {
|
||||
@ -139,29 +169,24 @@ public class Flash2Java {
|
||||
|
||||
private void setVariable() {
|
||||
Object val = this.stack.pop().getValue();
|
||||
String variableName = (String) valConverter( this.stack.pop() );
|
||||
vars.put(variableName, new FlashVar(false, val));
|
||||
String variableName = valToString( this.stack.pop() );
|
||||
vars.put(variableName, val);
|
||||
}
|
||||
|
||||
private void getVariable() {
|
||||
String variableName = (String) valConverter( this.stack.pop() );
|
||||
vars.keySet().forEach(k -> {
|
||||
FlashVar fv = vars.get(k);
|
||||
fv.setActive(false);
|
||||
vars.put(k, fv);
|
||||
});
|
||||
FlashVar v = vars.get(variableName);
|
||||
v.setActive(true);
|
||||
vars.put(variableName, v);
|
||||
String variableName = valToString( this.stack.pop() );
|
||||
this.stack.push(new GetVariableItem(variableName));
|
||||
}
|
||||
|
||||
private void defineLocalWithoutAssign() {
|
||||
String variableName = valToString( this.stack.pop() );
|
||||
}
|
||||
|
||||
private void defineLocal() {
|
||||
ByteCodeItem val = this.stack.pop();
|
||||
String name = (String) valConverter( this.stack.pop() );
|
||||
String name = valToString( this.stack.pop() );
|
||||
// todo: implement assignment ability (from one value to another)
|
||||
vars.put(name,
|
||||
new FlashVar(false, val.getValue())
|
||||
);
|
||||
vars.put(name, val.getValue());
|
||||
}
|
||||
|
||||
private String fromPool(int index) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user