hexedit AS3 code

This commit is contained in:
Honfika
2013-11-06 21:39:43 +01:00
parent c00c13e9d7
commit 72a9f59da6
5 changed files with 86 additions and 54 deletions
@@ -19,10 +19,12 @@ package com.jpexs.decompiler.flash.gui.abc;
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.UnknownInstructionCode;
import com.jpexs.decompiler.flash.abc.avm2.graph.AVM2Graph;
import com.jpexs.decompiler.flash.abc.avm2.parser.ASM3Parser;
import com.jpexs.decompiler.flash.abc.avm2.parser.MissingSymbolHandler;
import com.jpexs.decompiler.flash.abc.avm2.parser.ParseException;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.gui.GraphFrame;
import com.jpexs.decompiler.flash.gui.View;
@@ -86,9 +88,11 @@ public class ASMSourceEditorPane extends LineMarkedEditorPane implements CaretLi
setText(textWithHex);
} else {
if (textHexOnly == null) {
textHexOnly = new HilightedText(Helper.byteArrToString(abc.bodies[bodyIndex].code.getBytes()));
HilightedTextWriter writer = new HilightedTextWriter(true);
Helper.byteArrayToHex(writer, abc.bodies[bodyIndex].code.getBytes());
textHexOnly = new HilightedText(writer);
}
setText(textWithHex);
setText(textHexOnly);
}
hilighOffset(oldOffset);
}
@@ -176,30 +180,44 @@ public class ASMSourceEditorPane extends LineMarkedEditorPane implements CaretLi
public boolean save(ConstantPool constants) {
try {
AVM2Code acode = ASM3Parser.parse(new ByteArrayInputStream(getText().getBytes("UTF-8")), constants, trait, new MissingSymbolHandler() {
//no longer ask for adding new constants
@Override
public boolean missingString(String value) {
return true;
String text = getText();
if (text.trim().startsWith("#hexdata")) {
byte[] data = Helper.getBytesFromHexaText(text);
MethodBody mb = abc.bodies[bodyIndex];
mb.codeBytes = data;
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();
} else {
AVM2Code acode = ASM3Parser.parse(new ByteArrayInputStream(text.getBytes("UTF-8")), constants, trait, new MissingSymbolHandler() {
//no longer ask for adding new constants
@Override
public boolean missingString(String value) {
return true;
}
@Override
public boolean missingInt(long value) {
return true;
}
@Override
public boolean missingInt(long value) {
return true;
}
@Override
public boolean missingUInt(long value) {
return true;
}
@Override
public boolean missingUInt(long value) {
return true;
}
@Override
public boolean missingDouble(double value) {
return true;
}
}, abc.bodies[bodyIndex], abc.method_info[abc.bodies[bodyIndex].method_info]);
acode.getBytes(abc.bodies[bodyIndex].codeBytes);
abc.bodies[bodyIndex].code = acode;
@Override
public boolean missingDouble(double value) {
return true;
}
}, abc.bodies[bodyIndex], abc.method_info[abc.bodies[bodyIndex].method_info]);
acode.getBytes(abc.bodies[bodyIndex].codeBytes);
abc.bodies[bodyIndex].code = acode;
}
} catch (IOException ex) {
} catch (ParseException ex) {
View.showMessageDialog(this, (ex.text + " on line " + ex.line));
@@ -108,14 +108,12 @@ public class MethodCodePanel extends JPanel implements ActionListener {
hexButton.setToolTipText(AppStrings.translate("button.viewhex"));
hexButton.setMargin(new Insets(3, 3, 3, 3));
// todo: find icon, and set visible
// todo: find icon
hexOnlyButton = new JToggleButton(View.getIcon("hex16"));
hexOnlyButton.setActionCommand("HEXONLY");
hexOnlyButton.addActionListener(this);
hexOnlyButton.setToolTipText(AppStrings.translate("button.viewhex"));
hexOnlyButton.setMargin(new Insets(3, 3, 3, 3));
hexOnlyButton.setVisible(false);
buttonsPanel.add(graphButton);
buttonsPanel.add(hexButton);
@@ -137,6 +135,11 @@ public class MethodCodePanel extends JPanel implements ActionListener {
}
if (e.getActionCommand().equals("HEX") || e.getActionCommand().equals("HEXONLY")) {
if (e.getActionCommand().equals("HEX")) {
hexOnlyButton.setSelected(false);
} else {
hexButton.setSelected(false);
}
sourceTextArea.setHex(getExportMode(), false);
}
}
@@ -148,10 +151,10 @@ public class MethodCodePanel extends JPanel implements ActionListener {
}
public void setEditMode(boolean val) {
ExportMode exportMode = getExportMode();
if (val) {
sourceTextArea.setHex(ExportMode.PCODE, false);
sourceTextArea.setHex(exportMode == ExportMode.HEX ? ExportMode.HEX : ExportMode.PCODE, false);
} else {
ExportMode exportMode = getExportMode();
if (exportMode != ExportMode.PCODE) {
sourceTextArea.setHex(exportMode, false);
}
@@ -306,7 +306,9 @@ public class ActionPanel extends JPanel implements ActionListener {
}
} else {
if (srcHexOnly == null) {
srcHexOnly = new HilightedText(Helper.byteArrToString(src.getActionBytes()));
HilightedTextWriter writer = new HilightedTextWriter(true);
Helper.byteArrayToHex(writer, src.getActionBytes());
srcHexOnly = new HilightedText(writer);
}
setText(srcHexOnly);
}
@@ -443,13 +445,12 @@ public class ActionPanel extends JPanel implements ActionListener {
hexButton.setToolTipText(AppStrings.translate("button.viewhex"));
hexButton.setMargin(new Insets(3, 3, 3, 3));
// todo: find icon, and set visible
// todo: find icon
hexOnlyButton = new JToggleButton(View.getIcon("hex16"));
hexOnlyButton.setActionCommand("HEXONLY");
hexOnlyButton.addActionListener(this);
hexOnlyButton.setToolTipText(AppStrings.translate("button.viewhex"));
hexOnlyButton.setMargin(new Insets(3, 3, 3, 3));
//hexOnlyButton.setVisible(false);
topButtonsPan = new JPanel();
topButtonsPan.setLayout(new BoxLayout(topButtonsPan, BoxLayout.X_AXIS));
@@ -618,8 +619,7 @@ public class ActionPanel extends JPanel implements ActionListener {
}
public void setEditMode(boolean val) {
// todo: create UI for editing raw data
final boolean rawEdit = false;
boolean rawEdit = hexOnlyButton.isSelected();
if (val) {
setText(rawEdit ? srcHexOnly : srcNoHex);
@@ -630,7 +630,7 @@ public class ActionPanel extends JPanel implements ActionListener {
editor.getCaret().setVisible(true);
asmLabel.setIcon(View.getIcon("editing16"));
} else {
setText(hexButton.isSelected() ? srcWithHex : srcNoHex);
setHex(getExportMode());
editor.setEditable(false);
saveButton.setVisible(false);
editButton.setVisible(true);
@@ -714,6 +714,11 @@ public class ActionPanel extends JPanel implements ActionListener {
} else if (e.getActionCommand().equals("EDITACTION")) {
setEditMode(true);
} else if (e.getActionCommand().equals("HEX") || e.getActionCommand().equals("HEXONLY")) {
if (e.getActionCommand().equals("HEX")) {
hexOnlyButton.setSelected(false);
} else {
hexButton.setSelected(false);
}
setHex(getExportMode());
} else if (e.getActionCommand().equals("CANCELACTION")) {
setEditMode(false);
@@ -722,7 +727,7 @@ public class ActionPanel extends JPanel implements ActionListener {
try {
String text = editor.getText();
if (text.trim().startsWith("#hexdata")) {
src.setActionBytes(getBytesFromHexaText(text));
src.setActionBytes(Helper.getBytesFromHexaText(text));
} else {
src.setActions(ASMParser.parse(0, src.getPos(), true, text, SWF.DEFAULT_VERSION, false), SWF.DEFAULT_VERSION);
}
@@ -763,26 +768,6 @@ public class ActionPanel extends JPanel implements ActionListener {
return exportMode;
}
public byte[] getBytesFromHexaText(String text) {
Scanner scanner = new Scanner(text);
scanner.nextLine(); // ignore first line
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if (line.startsWith(";")) {
continue;
}
line = line.replace(" ", "");
for (int i = 0; i < line.length() / 2; i++) {
String hexStr = line.substring(i * 2, (i + 1) * 2);
byte b = (byte) Integer.parseInt(hexStr, 16);
baos.write(b);
}
}
byte[] data = baos.toByteArray();
return data;
}
public void updateSearchPos() {
searchPos.setText((foundPos + 1) + "/" + found.size());
setSource(found.get(foundPos), true);
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.helpers;
import com.jpexs.decompiler.flash.helpers.hilight.Highlighting;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
@@ -61,5 +62,10 @@ public class HilightedText implements Serializable {
public HilightedText(String text) {
this.text = text;
this.traitHilights = new ArrayList<>();
this.classHilights = new ArrayList<>();
this.methodHilights = new ArrayList<>();
this.instructionHilights = new ArrayList<>();
this.specialHilights = new ArrayList<>();
}
}
+20
View File
@@ -604,6 +604,26 @@ public class Helper {
return writer.toString();
}
public static byte[] getBytesFromHexaText(String text) {
Scanner scanner = new Scanner(text);
scanner.nextLine(); // ignore first line
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if (line.startsWith(";")) {
continue;
}
line = line.replace(" ", "");
for (int i = 0; i < line.length() / 2; i++) {
String hexStr = line.substring(i * 2, (i + 1) * 2);
byte b = (byte) Integer.parseInt(hexStr, 16);
baos.write(b);
}
}
byte[] data = baos.toByteArray();
return data;
}
public static <T> T timedCall(Callable<T> c, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
FutureTask<T> task = new FutureTask<>(c);
THREAD_POOL.execute(task);