Merge pull request #38 from jindrapetrik/flexcompile

Flex SDK compilation, AS3 metadata compile fixes
This commit is contained in:
Jindra Petřík
2016-08-20 19:15:42 +02:00
committed by GitHub
104 changed files with 8767 additions and 6050 deletions
@@ -2502,6 +2502,7 @@ public final class SWF implements SWFContainerItem, Timelined {
}
public void clearImageCache() {
jtt = null;
frameCache.clear();
rectCache.clear();
for (Tag tag : getTags()) {
@@ -2539,10 +2540,14 @@ public final class SWF implements SWFContainerItem, Timelined {
System.gc();
}
public void clearAbcListCache() {
abcList = null;
}
public void clearAllCache() {
characters = null;
characterIdTags = null;
abcList = null;
clearAbcListCache();
timeline = null;
clearReadOnlyListCache();
clearImageCache();
File diff suppressed because it is too large Load Diff
@@ -27,4 +27,27 @@ public class ABCVersion implements Comparable<ABCVersion> {
return "" + major + "." + minor;
}
@Override
public int hashCode() {
int hash = 7;
hash = 53 * hash + this.major;
hash = 53 * hash + this.minor;
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final ABCVersion other = (ABCVersion) obj;
return true;
}
}
@@ -200,12 +200,14 @@ public class ScriptPack extends AS3ClassTreeItem {
//TODO: handle this better in GUI(?)
writer.startTrait(GraphTextWriter.TRAIT_SCRIPT_INITIALIZER);
writer.startMethod(script_init);
if (!scriptInitializerIsEmpty) {
writer.startBlock();
abc.bodies.get(bodyIndex).toString(path +/*packageName +*/ "/.scriptinitializer", exportMode, abc, null, writer, new ArrayList<>());
writer.endBlock();
} else {
writer.append(" ");
if (exportMode != ScriptExportMode.AS_METHOD_STUBS) {
if (!scriptInitializerIsEmpty) {
writer.startBlock();
abc.bodies.get(bodyIndex).toString(path +/*packageName +*/ "/.scriptinitializer", exportMode, abc, null, writer, new ArrayList<>());
writer.endBlock();
} else {
writer.append(" ");
}
}
writer.endMethod();
writer.endTrait();
@@ -1100,6 +1100,11 @@ public class AVM2Code implements Cloneable {
}
}
public void setInstructionOperand(int ip, int operandIndex, int value, MethodBody body) {
int oldVal = code.get(ip).operands[ip];
code.get(ip).operands[ip] = value;
}
public byte[] getBytes() {
return getBytes(null);
}
@@ -1638,7 +1643,7 @@ public class AVM2Code implements Cloneable {
}
}//*/
/*if ((ip + 2 < code.size()) && (ins.definition instanceof NewCatchIns)) { // Filling local register in catch clause
/*if ((ip + 2 < code.size()) && (ins.definition instanceof NewCatchIns)) { // Filling local register in catch clause
if (code.get(ip + 1).definition instanceof DupIns) {
if (code.get(ip + 2).definition instanceof SetLocalTypeIns) {
ins.definition.translate(isStatic, classIndex, localRegs, stack, scopeStack, constants, ins, method_info, output, body, abc, localRegNames, fullyQualifiedNames);
@@ -2145,6 +2150,38 @@ public class AVM2Code implements Cloneable {
return list;
}
public void updateInstructionByteCountByAddr(long instructionAddress, int byteDelta, MethodBody body) {
if (byteDelta != 0) {
updateOffsets(new OffsetUpdater() {
@Override
public long updateInstructionOffset(long address) {
if (address > instructionAddress) {
return address + byteDelta;
}
return address;
}
@Override
public int updateOperandOffset(long insAddr, long targetAddress, int offset) {
if (targetAddress > instructionAddress && insAddr <= instructionAddress) {
return offset + byteDelta;
}
if (targetAddress <= instructionAddress && insAddr > instructionAddress) {
return offset - byteDelta;
}
return offset;
}
}, body);
body.setModified();
}
}
public void updateInstructionByteCount(int pos, int byteDelta, MethodBody body) {
AVM2Instruction instruction = code.get(pos);
updateInstructionByteCountByAddr(instruction.getAddress(), byteDelta, body);
}
public void updateOffsets(OffsetUpdater updater, MethodBody body) {
for (int i = 0; i < code.size(); i++) {
AVM2Instruction ins = code.get(i);
@@ -2172,6 +2209,7 @@ public class AVM2Code implements Cloneable {
}
}
ins.setAddress(updater.updateInstructionOffset(ins.getAddress()));
//Note: changing operands here does not change instruction byte length as offsets are always S24 (not variable length)
}
for (ABCException ex : body.exceptions) {
@@ -377,6 +377,14 @@ public class AVM2ConstantPool implements Cloneable {
return null;
}
public int getDecimalId(Decimal val, boolean add) {
int id = getDecimalId(val);
if (add && id == -1) {
id = addDecimal(val);
}
return id;
}
public Float getFloat(int index) {
try {
return constant_float.get(index);
@@ -514,6 +522,10 @@ public class AVM2ConstantPool implements Cloneable {
return constant_float4.indexOf(value);
}
private int getDecimalId(Decimal value) {
return constant_decimal.indexOf(value);
}
private int getStringId(String value) {
return constant_string.indexOf(value);
}
@@ -755,4 +767,132 @@ public class AVM2ConstantPool implements Cloneable {
}
return null;
}
/**
* Merges second constantpool into this one
*
* @param secondPool
* @param stringMap
* @param intMap
* @param uintMap
* @param doubleMap
* @param floatMap
* @param float4Map
* @param decimalMap
* @param namespaceMap
* @param namespaceSetMap
* @param multinameMap
*/
public void merge(AVM2ConstantPool secondPool, Map<Integer, Integer> stringMap, Map<Integer, Integer> intMap, Map<Integer, Integer> uintMap, Map<Integer, Integer> doubleMap, Map<Integer, Integer> floatMap, Map<Integer, Integer> float4Map, Map<Integer, Integer> decimalMap, Map<Integer, Integer> namespaceMap, Map<Integer, Integer> namespaceSetMap, Map<Integer, Integer> multinameMap) {
stringMap.put(0, 0);
for (int i = 1; i < secondPool.constant_string.size(); i++) {
String val = secondPool.constant_string.get(i);
stringMap.put(i, getStringId(val, true));
}
intMap.put(0, 0);
for (int i = 1; i < secondPool.constant_int.size(); i++) {
Long val = secondPool.constant_int.get(i);
intMap.put(i, getIntId(val, true));
}
uintMap.put(0, 0);
for (int i = 1; i < secondPool.constant_uint.size(); i++) {
Long val = secondPool.constant_uint.get(i);
uintMap.put(i, getUIntId(val, true));
}
doubleMap.put(0, 0);
for (int i = 1; i < secondPool.constant_double.size(); i++) {
Double val = secondPool.constant_double.get(i);
doubleMap.put(i, getDoubleId(val, true));
}
floatMap.put(0, 0);
for (int i = 1; i < secondPool.constant_float.size(); i++) {
Float val = secondPool.constant_float.get(i);
floatMap.put(i, getFloatId(val, true));
}
float4Map.put(0, 0);
for (int i = 1; i < secondPool.constant_float4.size(); i++) {
Float4 val = secondPool.constant_float4.get(i);
float4Map.put(i, getFloat4Id(val, true));
}
decimalMap.put(0, 0);
for (int i = 1; i < secondPool.constant_decimal.size(); i++) {
Decimal val = secondPool.constant_decimal.get(i);
decimalMap.put(i, getDecimalId(val, true));
}
namespaceMap.put(0, 0);
for (int i = 1; i < secondPool.constant_namespace.size(); i++) {
Namespace secondNamespace = secondPool.constant_namespace.get(i);
int mappedId;
int newNameIndex = stringMap.get(secondNamespace.name_index);
if (secondNamespace.kind == Namespace.KIND_PRIVATE) {//always add, this does not exists in this ABC. Conflicting private namespaces can have same names.
mappedId = addNamespace(secondNamespace.kind, newNameIndex);
} else {
mappedId = getNamespaceId(secondNamespace.kind, newNameIndex, 0, true);
}
namespaceMap.put(i, mappedId);
}
namespaceSetMap.put(0, 0);
for (int i = 1; i < secondPool.constant_namespace_set.size(); i++) {
NamespaceSet secondNamespaceSet = secondPool.constant_namespace_set.get(i);
int mappedsNss[] = new int[secondNamespaceSet.namespaces.length];
for (int n = 0; n < secondNamespaceSet.namespaces.length; n++) {
mappedsNss[n] = namespaceMap.get(secondNamespaceSet.namespaces[n]);
}
int mappedId = getNamespaceSetId(mappedsNss, true);
namespaceSetMap.put(i, mappedId);
}
multinameMap.put(0, 0);
for (int i = 1; i < secondPool.constant_multiname.size(); i++) {
Multiname secondMultiname = secondPool.constant_multiname.get(i);
Multiname newMultiname = null;
int newNameIndex = secondMultiname.name_index <= 0 ? secondMultiname.name_index : stringMap.get(secondMultiname.name_index);
int newNsIndex = secondMultiname.namespace_index <= 0 ? secondMultiname.namespace_index : namespaceMap.get(secondMultiname.namespace_index);
int newNssIndex = secondMultiname.namespace_set_index <= 0 ? secondMultiname.namespace_set_index : namespaceSetMap.get(secondMultiname.namespace_set_index);
switch (secondMultiname.kind) {
case Multiname.MULTINAME:
newMultiname = Multiname.createMultiname(false, newNameIndex, newNssIndex);
break;
case Multiname.MULTINAMEA:
newMultiname = Multiname.createMultiname(true, newNameIndex, newNssIndex);
break;
case Multiname.MULTINAMEL:
newMultiname = Multiname.createMultinameL(false, newNssIndex);
break;
case Multiname.MULTINAMELA:
newMultiname = Multiname.createMultinameL(true, newNssIndex);
break;
case Multiname.QNAME:
newMultiname = Multiname.createQName(false, newNameIndex, newNsIndex);
break;
case Multiname.QNAMEA:
newMultiname = Multiname.createQName(true, newNameIndex, newNsIndex);
break;
case Multiname.RTQNAME:
newMultiname = Multiname.createRTQName(false, newNameIndex);
break;
case Multiname.RTQNAMEA:
newMultiname = Multiname.createRTQName(true, newNameIndex);
break;
case Multiname.RTQNAMEL:
newMultiname = Multiname.createRTQNameL(false);
break;
case Multiname.RTQNAMELA:
newMultiname = Multiname.createRTQNameL(true);
break;
case Multiname.TYPENAME:
int newQnameIndex = multinameMap.get(secondMultiname.qname_index);
int newParams[] = new int[secondMultiname.params.length];
for (int p = 0; p < secondMultiname.params.length; p++) {
newParams[p] = multinameMap.get(secondMultiname.params[p]);
}
newMultiname = Multiname.createTypeName(newQnameIndex, newParams);
break;
}
int mappedId = getMultinameId(newMultiname, true);
multinameMap.put(i, mappedId);
}
}
}
@@ -220,7 +220,7 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple {
AVM2Instruction ins = code.code.get(idx);
InstructionDefinition def = ins.definition;
//System.err.println("" + idx + ": " + ins + " stack:" + stack.size());
//System.err.println("" + idx + ": " + ins + " stack:" + stack.size());
// do not throw EmptyStackException, much faster
int requiredStackSize = def.getStackPopCount(ins, abc);
@@ -161,7 +161,7 @@ public class AVM2DeobfuscatorSimpleOld extends SWFDecompilerAdapter {
AVM2Instruction ins = code.code.get(i);
if (ins.definition instanceof JumpIns) {
long address = ins.getTargetAddress();
jumpTargets.add( code.adr2pos(address) );
jumpTargets.add(code.adr2pos(address));
}
}
@@ -294,9 +294,8 @@ public class AVM2DeobfuscatorSimpleOld extends SWFDecompilerAdapter {
if (inlineIns.contains(ins)) {
if (def instanceof SetLocalTypeIns) {
InstructionDefinition prevDef = code.code.get(idx-1).definition;
if ((prevDef instanceof DupIns && !jumpTargets.contains(idx-2)) || !jumpTargets.contains(idx-1))
{
InstructionDefinition prevDef = code.code.get(idx - 1).definition;
if ((prevDef instanceof DupIns && !jumpTargets.contains(idx - 2)) || !jumpTargets.contains(idx - 1)) {
int regId = ((SetLocalTypeIns) def).getRegisterId(ins);
staticRegs.put(regId, localData.localRegs.get(regId).getNotCoerced());
code.replaceInstruction(idx, new AVM2Instruction(0, DeobfuscatePopIns.getInstance(), null), body);
@@ -27,6 +27,7 @@ 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.abc.types.Float4;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.graph.DottedChain;
@@ -488,4 +489,44 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
public String getFile() {
return file;
}
/**
* Set operand value the right way - update offsets neccessarily. Because
* some operand types are variable length (like U30)
*
* @param operandIndex
* @param newValue
* @param code
* @param body
*/
public void setOperand(int operandIndex, int newValue, AVM2Code code, MethodBody body) {
int oldByteCount = getBytesLength();
operands[operandIndex] = newValue;
int newByteCount = getBytesLength();
int byteDelta = newByteCount - oldByteCount;
if (byteDelta != 0) {
code.updateInstructionByteCountByAddr(address, byteDelta, body);
}
body.setModified();
}
/**
* Set operand values the right way - update offsets neccessarily. Because
* some operand types are variable length (like U30)
*
* @param operands
* @param code
* @param body
*/
public void setOperands(int operands[], AVM2Code code, MethodBody body) {
int oldByteCount = getBytesLength();
this.operands = operands;
int newByteCount = getBytesLength();
int byteDelta = newByteCount - oldByteCount;
if (byteDelta != 0) {
code.updateInstructionByteCountByAddr(address, byteDelta, body);
}
body.setModified();
}
}
@@ -108,8 +108,9 @@ public abstract class AVM2Item extends GraphTargetItem {
}
if (propertyName instanceof FullMultinameAVM2Item) {
if (((FullMultinameAVM2Item) propertyName).name != null) {
if (((FullMultinameAVM2Item) propertyName).namespace != null)
if (((FullMultinameAVM2Item) propertyName).namespace != null) {
writer.append(".");
}
return propertyName.toString(writer, localData);
} else {
writer.append(".");
@@ -77,7 +77,7 @@ public class ForEachInAVM2Item extends LoopItem implements Block {
*/
/*
/*
if (!commands.isEmpty()) {
GraphTargetItem firstAssign = commands.get(0);
if (firstAssign instanceof SetTypeAVM2Item) {
@@ -1,6 +1,6 @@
/* The following code was generated by JFlex 1.6.0 */
/*
/*
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
/* Flash assembler language lexer specification */
/* Flash assembler language lexer specification */
package com.jpexs.decompiler.flash.abc.avm2.parser.pcode;
import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException;
@@ -24,8 +24,7 @@ import java.util.Stack;
/**
* This class is a scanner generated by
* <a href="http://www.jflex.de/">JFlex</a> 1.6.0
* from the specification file
* <a href="http://www.jflex.de/">JFlex</a> 1.6.0 from the specification file
* <tt>C:/FFDec/jpexs-decompiler/libsrc/ffdec_lib/lexers/actionscript3_pcode.flex</tt>
*/
public final class Flasm3Lexer {
@@ -51,9 +50,8 @@ public final class Flasm3Lexer {
/**
* ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
* ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l
* at the beginning of a line
* l is of the form l = 2*k, k a non negative integer
* ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l at the
* beginning of a line l is of the form l = 2*k, k a non negative integer
*/
private static final int ZZ_LEXSTATE[] = {
0, 0, 1, 1, 2, 2
@@ -272,9 +270,11 @@ public final class Flasm3Lexer {
}
private static int zzUnpackAction(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -380,9 +380,11 @@ public final class Flasm3Lexer {
}
private static int zzUnpackRowMap(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -2479,9 +2481,11 @@ public final class Flasm3Lexer {
}
private static int zzUnpackTrans(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -2550,9 +2554,11 @@ public final class Flasm3Lexer {
}
private static int zzUnpackAttribute(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -2581,8 +2587,8 @@ public final class Flasm3Lexer {
private int zzLexicalState = YYINITIAL;
/**
* this buffer contains the current text to be matched and is
* the source of the yytext() string
* this buffer contains the current text to be matched and is the source of
* the yytext() string
*/
private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
@@ -2602,8 +2608,8 @@ public final class Flasm3Lexer {
private int zzStartRead;
/**
* endRead marks the last character in the buffer, that has been read
* from input
* endRead marks the last character in the buffer, that has been read from
* input
*/
private int zzEndRead;
@@ -2639,10 +2645,10 @@ public final class Flasm3Lexer {
private boolean zzEOFDone;
/**
* The number of occupied positions in zzBuffer beyond zzEndRead.
* When a lead/high surrogate has been read from the input stream
* into the final zzBuffer position, this will have a value of 1;
* otherwise, it will have a value of 0.
* The number of occupied positions in zzBuffer beyond zzEndRead. When a
* lead/high surrogate has been read from the input stream into the final
* zzBuffer position, this will have a value of 1; otherwise, it will have a
* value of 0.
*/
private int zzFinalHighSurrogate = 0;
@@ -2705,9 +2711,11 @@ public final class Flasm3Lexer {
*/
private static char[] zzUnpackCMap(String packed) {
char[] map = new char[0x110000];
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = 0; /* index in unpacked array */
int j = 0;
/* index in unpacked array */
while (i < 2916) {
int count = packed.charAt(i++);
@@ -2766,7 +2774,8 @@ public final class Flasm3Lexer {
if (totalRead > 0) {
zzEndRead += totalRead;
if (totalRead == requested) { /* possibly more input available */
if (totalRead == requested) {
/* possibly more input available */
if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) {
--zzEndRead;
@@ -2784,9 +2793,11 @@ public final class Flasm3Lexer {
* Closes the input stream.
*/
public final void yyclose() throws java.io.IOException {
zzAtEOF = true; /* indicate end of file */
zzAtEOF = true;
/* indicate end of file */
zzEndRead = zzStartRead; /* invalidate buffer */
zzEndRead = zzStartRead;
/* invalidate buffer */
if (zzReader != null) {
zzReader.close();
@@ -2794,12 +2805,12 @@ public final class Flasm3Lexer {
}
/**
* Resets the scanner to read from a new input stream.
* Does not close the old reader.
* Resets the scanner to read from a new input stream. Does not close the
* old reader.
*
* All internal variables are reset, the old input stream
* <b>cannot</b> be reused (internal buffer is discarded and lost).
* Lexical state is set to <tt>ZZ_INITIAL</tt>.
* <b>cannot</b> be reused (internal buffer is discarded and lost). Lexical
* state is set to <tt>ZZ_INITIAL</tt>.
*
* Internal scan buffer is resized down to its initial length, if it has
* grown.
@@ -2845,13 +2856,12 @@ public final class Flasm3Lexer {
}
/**
* Returns the character at position <tt>pos</tt> from the
* matched text.
* Returns the character at position <tt>pos</tt> from the matched text.
*
* It is equivalent to yytext().charAt(pos), but faster
*
* @param pos the position of the character to fetch.
* A value from 0 to yylength()-1.
* @param pos the position of the character to fetch. A value from 0 to
* yylength()-1.
*
* @return the character at position pos
*/
@@ -2869,14 +2879,13 @@ public final class Flasm3Lexer {
/**
* Reports an error that occured while scanning.
*
* In a wellformed scanner (no or only correct usage of
* yypushback(int) and a match-all fallback rule) this method
* will only be called with things that "Can't Possibly Happen".
* If this method is called, something is seriously wrong
* (e.g. a JFlex bug producing a faulty scanner etc.).
* In a wellformed scanner (no or only correct usage of yypushback(int) and
* a match-all fallback rule) this method will only be called with things
* that "Can't Possibly Happen". If this method is called, something is
* seriously wrong (e.g. a JFlex bug producing a faulty scanner etc.).
*
* Usual syntax/scanner level error handling should be done
* in error fallback rules.
* Usual syntax/scanner level error handling should be done in error
* fallback rules.
*
* @param errorCode the code of the errormessage to display
*/
@@ -2896,8 +2905,8 @@ public final class Flasm3Lexer {
*
* They will be read again by then next call of the scanning method
*
* @param number the number of characters to be read again.
* This number must not be greater than yylength()!
* @param number the number of characters to be read again. This number must
* not be greater than yylength()!
*/
public void yypushback(int number) {
if (number > yylength()) {
@@ -2908,8 +2917,8 @@ public final class Flasm3Lexer {
}
/**
* Resumes scanning until the next regular expression is matched,
* the end of input is encountered or an I/O-Error occurs.
* Resumes scanning until the next regular expression is matched, the end of
* input is encountered or an I/O-Error occurs.
*
* @return the next token
* @exception java.io.IOException if any I/O-Error occurs
@@ -1,6 +1,6 @@
/* The following code was generated by JFlex 1.6.0 */
/*
/*
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
@@ -26,8 +26,7 @@ import java.util.Stack;
/**
* This class is a scanner generated by
* <a href="http://www.jflex.de/">JFlex</a> 1.6.0
* from the specification file
* <a href="http://www.jflex.de/">JFlex</a> 1.6.0 from the specification file
* <tt>C:/FFDec/jpexs-decompiler/libsrc/ffdec_lib/lexers/actionscript3_script.flex</tt>
*/
public final class ActionScriptLexer {
@@ -69,9 +68,8 @@ public final class ActionScriptLexer {
/**
* ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
* ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l
* at the beginning of a line
* l is of the form l = 2*k, k a non negative integer
* ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l at the
* beginning of a line l is of the form l = 2*k, k a non negative integer
*/
private static final int ZZ_LEXSTATE[] = {
0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
@@ -295,9 +293,11 @@ public final class ActionScriptLexer {
}
private static int zzUnpackAction(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -383,9 +383,11 @@ public final class ActionScriptLexer {
}
private static int zzUnpackRowMap(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -833,9 +835,11 @@ public final class ActionScriptLexer {
}
private static int zzUnpackTrans(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -894,9 +898,11 @@ public final class ActionScriptLexer {
}
private static int zzUnpackAttribute(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -925,8 +931,8 @@ public final class ActionScriptLexer {
private int zzLexicalState = YYINITIAL;
/**
* this buffer contains the current text to be matched and is
* the source of the yytext() string
* this buffer contains the current text to be matched and is the source of
* the yytext() string
*/
private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
@@ -946,8 +952,8 @@ public final class ActionScriptLexer {
private int zzStartRead;
/**
* endRead marks the last character in the buffer, that has been read
* from input
* endRead marks the last character in the buffer, that has been read from
* input
*/
private int zzEndRead;
@@ -983,10 +989,10 @@ public final class ActionScriptLexer {
private boolean zzEOFDone;
/**
* The number of occupied positions in zzBuffer beyond zzEndRead.
* When a lead/high surrogate has been read from the input stream
* into the final zzBuffer position, this will have a value of 1;
* otherwise, it will have a value of 0.
* The number of occupied positions in zzBuffer beyond zzEndRead. When a
* lead/high surrogate has been read from the input stream into the final
* zzBuffer position, this will have a value of 1; otherwise, it will have a
* value of 0.
*/
private int zzFinalHighSurrogate = 0;
@@ -1080,9 +1086,11 @@ public final class ActionScriptLexer {
*/
private static char[] zzUnpackCMap(String packed) {
char[] map = new char[0x110000];
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = 0; /* index in unpacked array */
int j = 0;
/* index in unpacked array */
while (i < 3136) {
int count = packed.charAt(i++);
@@ -1141,7 +1149,8 @@ public final class ActionScriptLexer {
if (totalRead > 0) {
zzEndRead += totalRead;
if (totalRead == requested) { /* possibly more input available */
if (totalRead == requested) {
/* possibly more input available */
if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) {
--zzEndRead;
@@ -1159,9 +1168,11 @@ public final class ActionScriptLexer {
* Closes the input stream.
*/
public final void yyclose() throws java.io.IOException {
zzAtEOF = true; /* indicate end of file */
zzAtEOF = true;
/* indicate end of file */
zzEndRead = zzStartRead; /* invalidate buffer */
zzEndRead = zzStartRead;
/* invalidate buffer */
if (zzReader != null) {
zzReader.close();
@@ -1169,12 +1180,12 @@ public final class ActionScriptLexer {
}
/**
* Resets the scanner to read from a new input stream.
* Does not close the old reader.
* Resets the scanner to read from a new input stream. Does not close the
* old reader.
*
* All internal variables are reset, the old input stream
* <b>cannot</b> be reused (internal buffer is discarded and lost).
* Lexical state is set to <tt>ZZ_INITIAL</tt>.
* <b>cannot</b> be reused (internal buffer is discarded and lost). Lexical
* state is set to <tt>ZZ_INITIAL</tt>.
*
* Internal scan buffer is resized down to its initial length, if it has
* grown.
@@ -1220,13 +1231,12 @@ public final class ActionScriptLexer {
}
/**
* Returns the character at position <tt>pos</tt> from the
* matched text.
* Returns the character at position <tt>pos</tt> from the matched text.
*
* It is equivalent to yytext().charAt(pos), but faster
*
* @param pos the position of the character to fetch.
* A value from 0 to yylength()-1.
* @param pos the position of the character to fetch. A value from 0 to
* yylength()-1.
*
* @return the character at position pos
*/
@@ -1244,14 +1254,13 @@ public final class ActionScriptLexer {
/**
* Reports an error that occured while scanning.
*
* In a wellformed scanner (no or only correct usage of
* yypushback(int) and a match-all fallback rule) this method
* will only be called with things that "Can't Possibly Happen".
* If this method is called, something is seriously wrong
* (e.g. a JFlex bug producing a faulty scanner etc.).
* In a wellformed scanner (no or only correct usage of yypushback(int) and
* a match-all fallback rule) this method will only be called with things
* that "Can't Possibly Happen". If this method is called, something is
* seriously wrong (e.g. a JFlex bug producing a faulty scanner etc.).
*
* Usual syntax/scanner level error handling should be done
* in error fallback rules.
* Usual syntax/scanner level error handling should be done in error
* fallback rules.
*
* @param errorCode the code of the errormessage to display
*/
@@ -1271,8 +1280,8 @@ public final class ActionScriptLexer {
*
* They will be read again by then next call of the scanning method
*
* @param number the number of characters to be read again.
* This number must not be greater than yylength()!
* @param number the number of characters to be read again. This number must
* not be greater than yylength()!
*/
public void yypushback(int number) {
if (number > yylength()) {
@@ -1283,8 +1292,8 @@ public final class ActionScriptLexer {
}
/**
* Resumes scanning until the next regular expression is matched,
* the end of input is encountered or an I/O-Error occurs.
* Resumes scanning until the next regular expression is matched, the end of
* input is encountered or an I/O-Error occurs.
*
* @return the next token
* @exception java.io.IOException if any I/O-Error occurs
@@ -1380,7 +1389,8 @@ public final class ActionScriptLexer {
}
case 167:
break;
case 3: { /*ignore*/
case 3: {
/*ignore*/
}
case 168:
@@ -1794,7 +1804,8 @@ public final class ActionScriptLexer {
}
case 242:
break;
case 78: { /* ignore illegal character escape */
case 78: {
/* ignore illegal character escape */
}
case 243:
@@ -220,9 +220,9 @@ public class NameAVM2Item extends AssignableAVM2Item {
return toSourceMerge(localData, generator,
ins(AVM2Instructions.GetScopeObject, slotScope),
assignedValue, !(("" + assignedValue.returnType()).equals("" + type) && (basicTypes.contains("" + type))) ? generateCoerce(localData, generator, type) : null, needsReturn
? dupSetTemp(localData, generator, ret_temp) : null, generateSetLoc(regNumber), slotNumber > -1
? ins(AVM2Instructions.SetSlot, slotNumber)
: null,
? dupSetTemp(localData, generator, ret_temp) : null, generateSetLoc(regNumber), slotNumber > -1
? ins(AVM2Instructions.SetSlot, slotNumber)
: null,
needsReturn ? getTemp(localData, generator, ret_temp) : null,
killTemp(localData, generator, Arrays.asList(ret_temp)));
} else {
@@ -180,30 +180,28 @@ public class NamespacedAVM2Item extends AssignableAVM2Item {
killTemp(localData, generator, Arrays.asList(obj_temp))
);
}
} else if (assignedValue != null) {
return toSourceMerge(localData, generator,
obj == null ? ns : null, obj == null ? NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)) : null, obj != null ? obj : ins(AVM2Instructions.FindPropertyStrict, constants.getMultinameId(Multiname.createRTQName(attr, constants.getStringId(name, true)), true)),
ns, NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)), assignedValue,
needsReturn ? dupSetTemp(localData, generator, ret_temp) : null,
ins(AVM2Instructions.SetProperty, constants.getMultinameId(Multiname.createRTQName(attr, constants.getStringId(name, true)), true)),
needsReturn ? getTemp(localData, generator, ret_temp) : null,
killTemp(localData, generator, Arrays.asList(ns_temp, index_temp, ret_temp))
);
} else {
if (assignedValue != null) {
return toSourceMerge(localData, generator,
obj == null ? ns : null, obj == null ? NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)) : null, obj != null ? obj : ins(AVM2Instructions.FindPropertyStrict, constants.getMultinameId(Multiname.createRTQName(attr, constants.getStringId(name, true)), true)),
ns, NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)), assignedValue,
needsReturn ? dupSetTemp(localData, generator, ret_temp) : null,
ins(AVM2Instructions.SetProperty, constants.getMultinameId(Multiname.createRTQName(attr, constants.getStringId(name, true)), true)),
needsReturn ? getTemp(localData, generator, ret_temp) : null,
killTemp(localData, generator, Arrays.asList(ns_temp, index_temp, ret_temp))
);
} else {
return toSourceMerge(localData, generator,
obj == null ? ns : null, obj == null ? NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)) : null, obj != null ? obj : ins(AVM2Instructions.FindPropertyStrict, constants.getMultinameId(Multiname.createRTQName(attr, constants.getStringId(name, true)), true)),
call ? dupSetTemp(localData, generator, obj_temp) : null,
ns, NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)),
construct ? callargs : null,
ins(construct ? AVM2Instructions.ConstructProp : delete ? AVM2Instructions.DeleteProperty : AVM2Instructions.GetProperty, constants.getMultinameId(Multiname.createRTQName(attr, constants.getStringId(name, true)), true), construct ? callargs.size() : null),
call ? getTemp(localData, generator, obj_temp) : null,
call ? callargs : null,
call ? ins(AVM2Instructions.Call, callargs.size()) : null,
needsReturn ? null : ins(AVM2Instructions.Pop),
killTemp(localData, generator, Arrays.asList(obj_temp))
);
}
return toSourceMerge(localData, generator,
obj == null ? ns : null, obj == null ? NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)) : null, obj != null ? obj : ins(AVM2Instructions.FindPropertyStrict, constants.getMultinameId(Multiname.createRTQName(attr, constants.getStringId(name, true)), true)),
call ? dupSetTemp(localData, generator, obj_temp) : null,
ns, NameAVM2Item.generateCoerce(localData, generator, new TypeItem(DottedChain.NAMESPACE)),
construct ? callargs : null,
ins(construct ? AVM2Instructions.ConstructProp : delete ? AVM2Instructions.DeleteProperty : AVM2Instructions.GetProperty, constants.getMultinameId(Multiname.createRTQName(attr, constants.getStringId(name, true)), true), construct ? callargs.size() : null),
call ? getTemp(localData, generator, obj_temp) : null,
call ? callargs : null,
call ? ins(AVM2Instructions.Call, callargs.size()) : null,
needsReturn ? null : ins(AVM2Instructions.Pop),
killTemp(localData, generator, Arrays.asList(obj_temp))
);
}
}
@@ -116,12 +116,12 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item {
}
return -1;
}
/*
public GraphTargetItem getNs() {
return ns;
}
*/
public void appendName(String name) {
this.name = this.name.add(name);
}
@@ -1,6 +1,6 @@
/* The following code was generated by JFlex 1.6.0 */
/*
/*
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
@@ -16,13 +16,12 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
/* Method info lexer specification */
/* Method info lexer specification */
package com.jpexs.decompiler.flash.abc.methodinfo_parser;
/**
* This class is a scanner generated by
* <a href="http://www.jflex.de/">JFlex</a> 1.6.0
* from the specification file
* <a href="http://www.jflex.de/">JFlex</a> 1.6.0 from the specification file
* <tt>C:/FFDec/jpexs-decompiler/libsrc/ffdec_lib/lexers/actionscript3_methodinfo.flex</tt>
*/
public final class MethodInfoLexer {
@@ -46,9 +45,8 @@ public final class MethodInfoLexer {
/**
* ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
* ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l
* at the beginning of a line
* l is of the form l = 2*k, k a non negative integer
* ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l at the
* beginning of a line l is of the form l = 2*k, k a non negative integer
*/
private static final int ZZ_LEXSTATE[] = {
0, 0, 1, 1
@@ -231,9 +229,11 @@ public final class MethodInfoLexer {
}
private static int zzUnpackAction(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -279,9 +279,11 @@ public final class MethodInfoLexer {
}
private static int zzUnpackRowMap(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -466,9 +468,11 @@ public final class MethodInfoLexer {
}
private static int zzUnpackTrans(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -518,9 +522,11 @@ public final class MethodInfoLexer {
}
private static int zzUnpackAttribute(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -549,8 +555,8 @@ public final class MethodInfoLexer {
private int zzLexicalState = YYINITIAL;
/**
* this buffer contains the current text to be matched and is
* the source of the yytext() string
* this buffer contains the current text to be matched and is the source of
* the yytext() string
*/
private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
@@ -570,8 +576,8 @@ public final class MethodInfoLexer {
private int zzStartRead;
/**
* endRead marks the last character in the buffer, that has been read
* from input
* endRead marks the last character in the buffer, that has been read from
* input
*/
private int zzEndRead;
@@ -607,10 +613,10 @@ public final class MethodInfoLexer {
private boolean zzEOFDone;
/**
* The number of occupied positions in zzBuffer beyond zzEndRead.
* When a lead/high surrogate has been read from the input stream
* into the final zzBuffer position, this will have a value of 1;
* otherwise, it will have a value of 0.
* The number of occupied positions in zzBuffer beyond zzEndRead. When a
* lead/high surrogate has been read from the input stream into the final
* zzBuffer position, this will have a value of 1; otherwise, it will have a
* value of 0.
*/
private int zzFinalHighSurrogate = 0;
@@ -654,9 +660,11 @@ public final class MethodInfoLexer {
*/
private static char[] zzUnpackCMap(String packed) {
char[] map = new char[0x110000];
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = 0; /* index in unpacked array */
int j = 0;
/* index in unpacked array */
while (i < 2868) {
int count = packed.charAt(i++);
@@ -715,7 +723,8 @@ public final class MethodInfoLexer {
if (totalRead > 0) {
zzEndRead += totalRead;
if (totalRead == requested) { /* possibly more input available */
if (totalRead == requested) {
/* possibly more input available */
if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) {
--zzEndRead;
@@ -733,9 +742,11 @@ public final class MethodInfoLexer {
* Closes the input stream.
*/
public final void yyclose() throws java.io.IOException {
zzAtEOF = true; /* indicate end of file */
zzAtEOF = true;
/* indicate end of file */
zzEndRead = zzStartRead; /* invalidate buffer */
zzEndRead = zzStartRead;
/* invalidate buffer */
if (zzReader != null) {
zzReader.close();
@@ -743,12 +754,12 @@ public final class MethodInfoLexer {
}
/**
* Resets the scanner to read from a new input stream.
* Does not close the old reader.
* Resets the scanner to read from a new input stream. Does not close the
* old reader.
*
* All internal variables are reset, the old input stream
* <b>cannot</b> be reused (internal buffer is discarded and lost).
* Lexical state is set to <tt>ZZ_INITIAL</tt>.
* <b>cannot</b> be reused (internal buffer is discarded and lost). Lexical
* state is set to <tt>ZZ_INITIAL</tt>.
*
* Internal scan buffer is resized down to its initial length, if it has
* grown.
@@ -794,13 +805,12 @@ public final class MethodInfoLexer {
}
/**
* Returns the character at position <tt>pos</tt> from the
* matched text.
* Returns the character at position <tt>pos</tt> from the matched text.
*
* It is equivalent to yytext().charAt(pos), but faster
*
* @param pos the position of the character to fetch.
* A value from 0 to yylength()-1.
* @param pos the position of the character to fetch. A value from 0 to
* yylength()-1.
*
* @return the character at position pos
*/
@@ -818,14 +828,13 @@ public final class MethodInfoLexer {
/**
* Reports an error that occured while scanning.
*
* In a wellformed scanner (no or only correct usage of
* yypushback(int) and a match-all fallback rule) this method
* will only be called with things that "Can't Possibly Happen".
* If this method is called, something is seriously wrong
* (e.g. a JFlex bug producing a faulty scanner etc.).
* In a wellformed scanner (no or only correct usage of yypushback(int) and
* a match-all fallback rule) this method will only be called with things
* that "Can't Possibly Happen". If this method is called, something is
* seriously wrong (e.g. a JFlex bug producing a faulty scanner etc.).
*
* Usual syntax/scanner level error handling should be done
* in error fallback rules.
* Usual syntax/scanner level error handling should be done in error
* fallback rules.
*
* @param errorCode the code of the errormessage to display
*/
@@ -845,8 +854,8 @@ public final class MethodInfoLexer {
*
* They will be read again by then next call of the scanning method
*
* @param number the number of characters to be read again.
* This number must not be greater than yylength()!
* @param number the number of characters to be read again. This number must
* not be greater than yylength()!
*/
public void yypushback(int number) {
if (number > yylength()) {
@@ -857,8 +866,8 @@ public final class MethodInfoLexer {
}
/**
* Resumes scanning until the next regular expression is matched,
* the end of input is encountered or an I/O-Error occurs.
* Resumes scanning until the next regular expression is matched, the end of
* input is encountered or an I/O-Error occurs.
*
* @return the next token
* @exception java.io.IOException if any I/O-Error occurs
@@ -424,6 +424,10 @@ public final class MethodBody implements Cloneable {
@Override
public MethodBody clone() {
return clone(false);
}
public MethodBody clone(boolean deepTraits) {
try {
MethodBody ret = (MethodBody) super.clone();
if (code != null) {
@@ -437,10 +441,9 @@ public final class MethodBody implements Cloneable {
}
}
// maybe deep clone traits
/*if (traits != null) {
ret.traits = traits.clone();
}*/
if (deepTraits && traits != null) {
ret.traits = traits.clone();
}
ret.convertedItems = null;
ret.convertException = null;
@@ -386,4 +386,17 @@ public class MethodInfo {
}
return writer.hilightSpecial(rname, HighlightSpecialType.RETURNS);
}
public String getReturnTypeRaw(AVM2ConstantPool constants, List<DottedChain> fullyQualifiedNames) {
String rname = "*";
if (ret_type > 0) {
Multiname multiname = constants.getMultiname(ret_type);
if (multiname.kind != Multiname.TYPENAME && multiname.name_index > 0 && constants.getString(multiname.name_index).equals("void")) {
rname = "void";
} else {
rname = multiname.getName(constants, fullyQualifiedNames, false);
}
}
return rname;
}
}
@@ -25,7 +25,7 @@ import com.jpexs.helpers.Helper;
*/
public class ValueKind {
public static final int CONSTANT_Decimal = 0x02; //decimal
public static final int CONSTANT_DecimalOrFloat = 0x02; //decimal or float depending on ABC version
public static final int CONSTANT_Int = 0x03;// integer
@@ -57,6 +57,8 @@ public class ValueKind {
public static final int CONSTANT_PrivateNs = 0x05;// namespace
public static final int CONSTANT_Float4 = 0x1E;// float4
private static final int[] optionalKinds = new int[]{0x03, 0x04, 0x06, 0x02, 0x01, 0x0B, 0x0A, 0x0C, 0x00, 0x08, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x05};
private static final String[] optionalKindNames = new String[]{"Int", "UInt", "Double", "Decimal", "Utf8", "True", "False", "Null", "Undefined", "Namespace", "PackageNamespace", "PackageInternalNs", "ProtectedNamespace", "ExplicitNamespace", "StaticProtectedNs", "PrivateNamespace"};
@@ -137,7 +139,7 @@ public class ValueKind {
case CONSTANT_Double:
ret = "" + constants.getDouble(value_index);
break;
case CONSTANT_Decimal:
case CONSTANT_DecimalOrFloat:
ret = "" + constants.getDecimal(value_index);
break;
case CONSTANT_Utf8:
@@ -179,7 +181,7 @@ public class ValueKind {
case CONSTANT_Double:
ret = "Double(" + constants.getDouble(value_index) + ")";
break;
case CONSTANT_Decimal:
case CONSTANT_DecimalOrFloat:
ret = "Decimal(" + constants.getDecimal(value_index) + ")";
break;
case CONSTANT_Utf8:
@@ -42,6 +42,9 @@ import com.jpexs.decompiler.flash.abc.types.NamespaceSet;
import com.jpexs.decompiler.flash.abc.types.ScriptInfo;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.exporters.script.Dependency;
import com.jpexs.decompiler.flash.exporters.script.DependencyParser;
import com.jpexs.decompiler.flash.exporters.script.DependencyType;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
@@ -50,6 +53,8 @@ import com.jpexs.helpers.Helper;
import java.io.Serializable;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -169,129 +174,18 @@ public abstract class Trait implements Cloneable, Serializable {
return ret;
}
protected void parseImportsUsagesFromMultiname(String ignoredCustom, ABC abc, List<DottedChain> imports, List<String> uses, Multiname m, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
if (m != null) {
if (m.kind == Multiname.TYPENAME) {
if (m.qname_index != 0) {
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames);
}
for (Integer i : m.params) {
if (i != 0) {
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames);
}
}
return;
}
Namespace ns = m.getNamespace(abc.constants);
String name = m.getName(abc.constants, fullyQualifiedNames, true);
NamespaceSet nss = m.getNamespaceSet(abc.constants);
if (ns != null) {
parseImportsUsagesFromNS(ignoredCustom, abc, imports, uses, m.namespace_index, ignorePackage, name);
}
if (nss != null) {
for (int n : nss.namespaces) {
parseImportsUsagesFromNS(ignoredCustom, abc, imports, uses, n, ignorePackage, nss.namespaces.length > 1 ? "" : name);
}
}
}
}
private boolean parseUsagesFromNS(String ignoredCustom, ABC abc, List<DottedChain> imports, List<String> uses, int namespace_index, DottedChain ignorePackage, String name) {
Namespace ns = abc.constants.getNamespace(namespace_index);
if (ns.kind == Namespace.KIND_NAMESPACE) {
String nsVal = ns.getName(abc.constants).toRawString();
for (ABCContainerTag abcTag : abc.getAbcTags()) {
DottedChain nsimport = abcTag.getABC().nsValueToName(nsVal);
if (nsimport.equals(AVM2Deobfuscation.BUILTIN)) {
return true; //handled, but import/use not added
}
if (!nsimport.isEmpty()) {
if (!nsimport.getWithoutLast().equals(ignorePackage) && !imports.contains(nsimport)) {
imports.add(nsimport);
}
if (ignoredCustom != null && nsVal.equals(ignoredCustom)) {
return true;
}
if (!uses.contains(nsimport.getLast())) {
uses.add(nsimport.getLast());
}
return true;
}
}
}
return false;
}
protected void parseImportsUsagesFromNS(String ignoredCustom, ABC abc, List<DottedChain> imports, List<String> uses, int namespace_index, DottedChain ignorePackage, String name) {
Namespace ns = abc.constants.getNamespace(namespace_index);
if (name.isEmpty()) {
name = "*";
}
DottedChain newimport = ns.getName(abc.constants);
if (parseUsagesFromNS(ignoredCustom, abc, imports, uses, namespace_index, ignorePackage, name)) {
return;
} else if ((ns.kind != Namespace.KIND_PACKAGE) && (ns.kind != Namespace.KIND_PACKAGE_INTERNAL)) {
return;
}
newimport = newimport.add(name);
if (!imports.contains(newimport)) {
DottedChain pkg = newimport.getWithoutLast(); //.substring(0, newimport.lastIndexOf('.'));
if (pkg.equals(InitVectorAVM2Item.VECTOR_PACKAGE)) { //special case - is imported always
return;
}
if (!pkg.equals(ignorePackage)) {
imports.add(newimport);
}
}
//}
}
protected void parseUsagesFromMultiname(String ignoredCustom, ABC abc, List<DottedChain> imports, List<String> uses, Multiname m, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
if (m != null) {
if (m.kind == Multiname.TYPENAME) {
if (m.qname_index != 0) {
parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames);
}
for (Integer i : m.params) {
if (i != 0) {
parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames);
}
}
return;
}
Namespace ns = m.getNamespace(abc.constants);
String name = m.getName(abc.constants, fullyQualifiedNames, false);
NamespaceSet nss = m.getNamespaceSet(abc.constants);
if (ns != null) {
parseUsagesFromNS(ignoredCustom, abc, imports, uses, m.namespace_index, ignorePackage, name);
}
if (nss != null) {
if (nss.namespaces.length == 1) {
parseUsagesFromNS(ignoredCustom, abc, imports, uses, nss.namespaces[0], ignorePackage, name);
} else {
for (int n : nss.namespaces) {
parseUsagesFromNS(ignoredCustom, abc, imports, uses, n, ignorePackage, "");
}
}
}
}
}
protected DottedChain getPackage(ABC abc) {
return getName(abc).getNamespace(abc.constants).getName(abc.constants);
}
public void getImportsUsages(String ignoredCustom, ABC abc, List<DottedChain> imports, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
public void getDependencies(String ignoredCustom, ABC abc, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
if (ignoredCustom == null) {
Namespace n = getName(abc).getNamespace(abc.constants);
if (n.kind == Namespace.KIND_NAMESPACE) {
ignoredCustom = n.getName(abc.constants).toRawString();
}
}
parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, getName(abc), ignorePackage, fullyQualifiedNames);
DependencyParser.parseUsagesFromMultiname(ignoredCustom, abc, dependencies, uses, getName(abc), ignorePackage, fullyQualifiedNames, DependencyType.NAMESPACE);
}
private static final String[] builtInClasses = {"ArgumentError", "arguments", "Array", "Boolean", "Class", "Date", "DefinitionError", "Error", "EvalError", "Function", "int", "JSON", "Math", "Namespace", "Number", "Object", "QName", "RangeError", "ReferenceError", "RegExp", "SecurityError", "String", "SyntaxError", "TypeError", "uint", "URIError", "VerifyError", "XML", "XMLList"};
@@ -320,21 +214,34 @@ public abstract class Trait implements Cloneable, Serializable {
}
//imports
List<DottedChain> imports = new ArrayList<>();
List<Dependency> dependencies = new ArrayList<>();
List<String> uses = new ArrayList<>();
String customNs = null;
Namespace ns = getName(abc).getNamespace(abc.constants);
if (ns.kind == Namespace.KIND_NAMESPACE) {
customNs = ns.getName(abc.constants).toRawString();
}
getImportsUsages(customNs, abc, imports, uses, ignorePackage, new ArrayList<>());
getDependencies(customNs, abc, dependencies, uses, ignorePackage, new ArrayList<>());
List<DottedChain> imports = new ArrayList<>();
for (Dependency d : dependencies) {
if (!imports.contains(d.getId())) {
imports.add(d.getId());
}
}
List<String> importnames = new ArrayList<>();
importnames.addAll(namesInThisPackage);
importnames.addAll(Arrays.asList(builtInClasses));
for (int i = 0; i < imports.size(); i++) {
DottedChain ipath = imports.get(i);
if (ipath.getWithoutLast().equals(ignorePackage)) { //do not check classes from same package, they are imported automatically
imports.remove(i);
i--;
continue;
}
String name = ipath.getLast();
if (importnames.contains(name) || isBuiltInClass(name)) {
if (importnames.contains(name)) {
imports.remove(i);
i--;
fullyQualifiedNames.add(new DottedChain(name));
@@ -358,6 +265,7 @@ public abstract class Trait implements Cloneable, Serializable {
}
boolean hasImport = false;
Collections.sort(imports);
for (DottedChain imp : imports) {
if (imp.size() > 1) { //No imports from root package
writer.appendNoHilight("import " + imp.toPrintableString(true) + ";").newLine();
@@ -375,64 +283,6 @@ public abstract class Trait implements Cloneable, Serializable {
}
}
protected void parseImportsUsagesFromMethodInfo(String ignoredCustom, ABC abc, int method_index, List<DottedChain> imports, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames, List<Integer> visitedMethods) {
if ((method_index < 0) || (method_index >= abc.method_info.size())) {
return;
}
visitedMethods.add(method_index);
if (abc.method_info.get(method_index).ret_type != 0) {
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(abc.method_info.get(method_index).ret_type), ignorePackage, fullyQualifiedNames);
}
for (int t : abc.method_info.get(method_index).param_types) {
if (t != 0) {
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(t), ignorePackage, fullyQualifiedNames);
}
}
MethodBody body = abc.findBody(method_index);
if (body != null) {
body.traits.getImportsUsages(ignoredCustom, abc, imports, uses, ignorePackage, fullyQualifiedNames);
for (ABCException ex : body.exceptions) {
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(ex.type_index), ignorePackage, fullyQualifiedNames);
}
for (AVM2Instruction ins : body.getCode().code) {
if (ins.definition instanceof AlchemyTypeIns) {
DottedChain nimport = AlchemyTypeIns.ALCHEMY_PACKAGE.add(ins.definition.instructionName);
if (!imports.contains(nimport)) {
imports.add(nimport);
}
}
if (ins.definition instanceof NewFunctionIns) {
if (ins.operands[0] != method_index) {
if (!visitedMethods.contains(ins.operands[0])) {
parseImportsUsagesFromMethodInfo(ignoredCustom, abc, ins.operands[0], imports, uses, ignorePackage, fullyQualifiedNames, visitedMethods);
}
}
}
if ((ins.definition instanceof FindPropertyStrictIns)
|| (ins.definition instanceof FindPropertyIns)
|| (ins.definition instanceof GetLexIns)
|| (ins.definition instanceof CoerceIns)
|| (ins.definition instanceof AsTypeIns)) {
int m = ins.operands[0];
if (m != 0) {
if (m < abc.constants.getMultinameCount()) {
parseImportsUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(m), ignorePackage, fullyQualifiedNames);
}
}
} else {
for (int k = 0; k < ins.definition.operands.length; k++) {
if (ins.definition.operands[k] == AVM2Code.DAT_MULTINAME_INDEX) {
int multinameIndex = ins.operands[k];
if (multinameIndex < abc.constants.getMultinameCount()) {
parseUsagesFromMultiname(ignoredCustom, abc, imports, uses, abc.constants.getMultiname(multinameIndex), ignorePackage, fullyQualifiedNames);
}
}
}
}
}
}
}
public final GraphTextWriter getMetaData(Trait parent, ConvertData convertData, ABC abc, GraphTextWriter writer) {
List<Entry<String, Map<String, String>>> md = getMetaDataTable(parent, convertData, abc);
for (Entry<String, Map<String, String>> en : md) {
@@ -25,6 +25,9 @@ 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.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.exporters.script.Dependency;
import com.jpexs.decompiler.flash.exporters.script.DependencyParser;
import com.jpexs.decompiler.flash.exporters.script.DependencyType;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.graph.DottedChain;
@@ -48,22 +51,7 @@ public class TraitClass extends Trait implements TraitWithSlot {
@Override
public void delete(ABC abc, boolean d) {
ClassInfo classInfo = abc.class_info.get(class_info);
classInfo.deleted = d;
InstanceInfo instanceInfo = abc.instance_info.get(class_info);
instanceInfo.deleted = d;
classInfo.static_traits.delete(abc, d);
abc.method_info.get(classInfo.cinit_index).delete(abc, d);
instanceInfo.instance_traits.delete(abc, d);
abc.method_info.get(instanceInfo.iinit_index).delete(abc, d);
int protectedNS = instanceInfo.protectedNS;
if (protectedNS != 0) {
abc.constants.getNamespace(protectedNS).deleted = d;
}
abc.deleteClass(class_info, d);
abc.constants.getMultiname(name_index).deleted = d;
}
@@ -78,32 +66,31 @@ public class TraitClass extends Trait implements TraitWithSlot {
}
@Override
public void getImportsUsages(String customNs, ABC abc, List<DottedChain> imports, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
super.getImportsUsages(customNs, abc, imports, uses, ignorePackage == null ? getPackage(abc) : ignorePackage, fullyQualifiedNames);
public void getDependencies(String customNs, ABC abc, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
super.getDependencies(customNs, abc, dependencies, uses, ignorePackage == null ? getPackage(abc) : ignorePackage, fullyQualifiedNames);
ClassInfo classInfo = abc.class_info.get(class_info);
InstanceInfo instanceInfo = abc.instance_info.get(class_info);
DottedChain packageName = instanceInfo.getName(abc.constants).getNamespace(abc.constants).getName(abc.constants); //assume not null name
parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(instanceInfo.name_index), packageName, fullyQualifiedNames);
//DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, uses, abc.constants.getMultiname(instanceInfo.name_index), packageName, fullyQualifiedNames);
if (instanceInfo.super_index > 0) {
parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(instanceInfo.super_index), packageName, fullyQualifiedNames);
DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, uses, abc.constants.getMultiname(instanceInfo.super_index), packageName, fullyQualifiedNames, DependencyType.INHERITANCE);
}
for (int i : instanceInfo.interfaces) {
parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(i), packageName, fullyQualifiedNames);
DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, uses, abc.constants.getMultiname(i), packageName, fullyQualifiedNames, DependencyType.INHERITANCE);
}
//static
classInfo.static_traits.getImportsUsages(customNs, abc, imports, uses, packageName, fullyQualifiedNames);
classInfo.static_traits.getDependencies(customNs, abc, dependencies, uses, packageName, fullyQualifiedNames);
//static initializer
parseImportsUsagesFromMethodInfo(customNs, abc, classInfo.cinit_index, imports, uses, packageName, fullyQualifiedNames, new ArrayList<>());
DependencyParser.parseDependenciesFromMethodInfo(customNs, abc, classInfo.cinit_index, dependencies, uses, packageName, fullyQualifiedNames, new ArrayList<>());
//instance
instanceInfo.instance_traits.getImportsUsages(customNs, abc, imports, uses, packageName, fullyQualifiedNames);
instanceInfo.instance_traits.getDependencies(customNs, abc, dependencies, uses, packageName, fullyQualifiedNames);
//instance initializer
parseImportsUsagesFromMethodInfo(customNs, abc, instanceInfo.iinit_index, imports, uses, packageName, fullyQualifiedNames, new ArrayList<>());
DependencyParser.parseDependenciesFromMethodInfo(customNs, abc, instanceInfo.iinit_index, dependencies, uses, packageName, fullyQualifiedNames, new ArrayList<>());
}
@Override
@@ -144,14 +131,16 @@ public class TraitClass extends Trait implements TraitWithSlot {
if (bodyIndex != -1) {
writer.startTrait(GraphTextWriter.TRAIT_CLASS_INITIALIZER);
writer.startMethod(classInfo.cinit_index);
if (!classInitializerIsEmpty) {
writer.startBlock();
abc.bodies.get(bodyIndex).toString(path +/*packageName +*/ "/" + instanceInfoName + ".staticinitializer", exportMode, abc, this, writer, fullyQualifiedNames);
writer.endBlock();
} else {
//Note: There must be trait/method highlight even if the initializer is empty to TraitList in GUI to work correctly
//TODO: handle this better in GUI(?)
writer.append(" ").newLine();
if (exportMode != ScriptExportMode.AS_METHOD_STUBS) {
if (!classInitializerIsEmpty) {
writer.startBlock();
abc.bodies.get(bodyIndex).toString(path +/*packageName +*/ "/" + instanceInfoName + ".staticinitializer", exportMode, abc, this, writer, fullyQualifiedNames);
writer.endBlock();
} else {
//Note: There must be trait/method highlight even if the initializer is empty to TraitList in GUI to work correctly
//TODO: handle this better in GUI(?)
writer.append(" ").newLine();
}
}
writer.endMethod();
writer.endTrait();
@@ -191,8 +180,10 @@ public class TraitClass extends Trait implements TraitWithSlot {
MethodBody body = bodyIndex == -1 ? null : abc.bodies.get(bodyIndex);
abc.method_info.get(instanceInfo.iinit_index).getParamStr(writer, abc.constants, body, abc, fullyQualifiedNames);
writer.appendNoHilight(")").startBlock();
if (body != null) {
body.toString(path +/*packageName +*/ "/" + instanceInfoName + ".initializer", exportMode, abc, this, writer, fullyQualifiedNames);
if (exportMode != ScriptExportMode.AS_METHOD_STUBS) {
if (body != null) {
body.toString(path +/*packageName +*/ "/" + instanceInfoName + ".initializer", exportMode, abc, this, writer, fullyQualifiedNames);
}
}
writer.endBlock().newLine();
@@ -20,6 +20,8 @@ import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.types.ConvertData;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.exporters.script.Dependency;
import com.jpexs.decompiler.flash.exporters.script.DependencyParser;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType;
@@ -123,14 +125,14 @@ public class TraitFunction extends Trait implements TraitWithSlot {
}
@Override
public void getImportsUsages(String customNs, ABC abc, List<DottedChain> imports, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
public void getDependencies(String customNs, ABC abc, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
if (ignorePackage == null) {
ignorePackage = getPackage(abc);
}
super.getImportsUsages(customNs, abc, imports, uses, ignorePackage, fullyQualifiedNames);
super.getDependencies(customNs, abc, dependencies, uses, ignorePackage, fullyQualifiedNames);
//if (method_info != 0)
{
parseImportsUsagesFromMethodInfo(customNs, abc, method_info, imports, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
DependencyParser.parseDependenciesFromMethodInfo(customNs, abc, method_info, dependencies, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
}
}
}
@@ -23,8 +23,11 @@ import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.flash.abc.types.Namespace;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.exporters.script.Dependency;
import com.jpexs.decompiler.flash.exporters.script.DependencyParser;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.flash.helpers.hilight.HighlightData;
import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType;
import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.decompiler.graph.ScopeStack;
@@ -58,11 +61,11 @@ public class TraitMethodGetterSetter extends Trait {
}
@Override
public void getImportsUsages(String customNs, ABC abc, List<DottedChain> imports, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
public void getDependencies(String customNs, ABC abc, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
if (ignorePackage == null) {
ignorePackage = getPackage(abc);
}
super.getImportsUsages(customNs, abc, imports, uses, ignorePackage, fullyQualifiedNames);
super.getDependencies(customNs, abc, dependencies, uses, ignorePackage, fullyQualifiedNames);
if (customNs == null) {
Namespace n = getName(abc).getNamespace(abc.constants);
@@ -72,7 +75,7 @@ public class TraitMethodGetterSetter extends Trait {
}
//if (method_info != 0)
{
parseImportsUsagesFromMethodInfo(customNs, abc, method_info, imports, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
DependencyParser.parseDependenciesFromMethodInfo(customNs, abc, method_info, dependencies, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
}
}
@@ -110,9 +113,11 @@ public class TraitMethodGetterSetter extends Trait {
path = path + "." + getName(abc).getName(abc.constants, fullyQualifiedNames, false);
convertHeader(parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel);
int bodyIndex = abc.findBodyIndex(method_info);
if (!(classIndex != -1 && abc.instance_info.get(classIndex).isInterface() || bodyIndex == -1)) {
if (bodyIndex != -1) {
abc.bodies.get(bodyIndex).convert(convertData, path, exportMode, isStatic, method_info, scriptIndex, classIndex, abc, this, new ScopeStack(), 0, writer, fullyQualifiedNames, null, true);
if (exportMode != ScriptExportMode.AS_METHOD_STUBS) {
if (!(classIndex != -1 && abc.instance_info.get(classIndex).isInterface() || bodyIndex == -1)) {
if (bodyIndex != -1) {
abc.bodies.get(bodyIndex).convert(convertData, path, exportMode, isStatic, method_info, scriptIndex, classIndex, abc, this, new ScopeStack(), 0, writer, fullyQualifiedNames, null, true);
}
}
}
writer.endMethod();
@@ -133,8 +138,30 @@ public class TraitMethodGetterSetter extends Trait {
writer.appendNoHilight(";");
} else {
writer.startBlock();
if (bodyIndex != -1) {
abc.bodies.get(bodyIndex).toString(path, exportMode, abc, this, writer, fullyQualifiedNames);
if (exportMode != ScriptExportMode.AS_METHOD_STUBS) {
if (bodyIndex != -1) {
abc.bodies.get(bodyIndex).toString(path, exportMode, abc, this, writer, fullyQualifiedNames);
}
} else {
String retTypeRaw = abc.method_info.get(method_info).getReturnTypeRaw(abc.constants, fullyQualifiedNames);
switch (retTypeRaw) {
case "void":
break;
case "int":
case "uint":
writer.append("return 0; //autogenerated").newLine();
break;
case "double":
case "float":
writer.append("return 0.0; //autogenerated").newLine();
break;
case "String":
writer.append("return \"\"; //autogenerated").newLine();
break;
default:
writer.append("return null; //autogenerated").newLine();
break;
}
}
writer.endBlock();
}
@@ -26,6 +26,9 @@ import com.jpexs.decompiler.flash.abc.types.Namespace;
import com.jpexs.decompiler.flash.abc.types.ValueKind;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.exporters.script.Dependency;
import com.jpexs.decompiler.flash.exporters.script.DependencyParser;
import com.jpexs.decompiler.flash.exporters.script.DependencyType;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType;
@@ -103,7 +106,7 @@ public class TraitSlotConst extends Trait implements TraitWithSlot {
return writer;
}
public void getValueStr(Trait parent, ConvertData convertData, GraphTextWriter writer, ABC abc, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
public void getValueStr(ScriptExportMode exportMode, Trait parent, ConvertData convertData, GraphTextWriter writer, ABC abc, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
if (convertData.assignedValues.containsKey(this)) {
AssignedValue assignment = convertData.assignedValues.get(this);
@@ -116,8 +119,9 @@ public class TraitSlotConst extends Trait implements TraitWithSlot {
writer.appendNoHilight(assignment.method);
writer.newLine();
}
assignment.value.toString(writer, LocalData.create(abc.constants, new HashMap<>(), fullyQualifiedNames));
if (exportMode != ScriptExportMode.AS_METHOD_STUBS) {
assignment.value.toString(writer, LocalData.create(abc.constants, new HashMap<>(), fullyQualifiedNames));
}
writer.endMethod();
writer.endTrait();
return;
@@ -162,7 +166,7 @@ public class TraitSlotConst extends Trait implements TraitWithSlot {
getNameStr(writer, abc, fullyQualifiedNames);
if (value_kind != 0 || convertData.assignedValues.containsKey(this)) {
writer.appendNoHilight(" = ");
getValueStr(parent, convertData, writer, abc, fullyQualifiedNames);
getValueStr(exportMode, parent, convertData, writer, abc, fullyQualifiedNames);
}
return writer.appendNoHilight(";").newLine();
}
@@ -171,7 +175,7 @@ public class TraitSlotConst extends Trait implements TraitWithSlot {
public void convert(Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List<DottedChain> fullyQualifiedNames, boolean parallel) throws InterruptedException {
getNameStr(writer, abc, fullyQualifiedNames);
if (value_kind != 0 || convertData.assignedValues.containsKey(this)) {
getValueStr(parent, convertData, writer, abc, fullyQualifiedNames);
getValueStr(exportMode, parent, convertData, writer, abc, fullyQualifiedNames);
}
}
@@ -196,12 +200,12 @@ public class TraitSlotConst extends Trait implements TraitWithSlot {
}
@Override
public void getImportsUsages(String customNs, ABC abc, List<DottedChain> imports, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
public void getDependencies(String customNs, ABC abc, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
if (ignorePackage == null) {
ignorePackage = getPackage(abc);
}
super.getImportsUsages(customNs, abc, imports, uses, ignorePackage, fullyQualifiedNames);
parseImportsUsagesFromMultiname(customNs, abc, imports, uses, abc.constants.getMultiname(type_index), getPackage(abc), fullyQualifiedNames);
super.getDependencies(customNs, abc, dependencies, uses, ignorePackage, fullyQualifiedNames);
DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, uses, abc.constants.getMultiname(type_index), getPackage(abc), fullyQualifiedNames, DependencyType.SIGNATURE);
}
@Override
@@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.types.ConvertData;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.exporters.script.Dependency;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.graph.DottedChain;
@@ -244,9 +245,9 @@ public class Traits implements Cloneable, Serializable {
}
}
public void getImportsUsages(String customNs, ABC abc, List<DottedChain> imports, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
public void getDependencies(String customNs, ABC abc, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) {
for (Trait t : traits) {
t.getImportsUsages(customNs, abc, imports, uses, ignorePackage, fullyQualifiedNames);
t.getDependencies(customNs, abc, dependencies, uses, ignorePackage, fullyQualifiedNames);
}
}
}
@@ -568,7 +568,7 @@ public abstract class Action implements GraphSourceItem {
writer.appendNoHilight(Helper.byteToHex(fileData[(int) (fileOffset + i)]));
}
writer.appendNoHilight(")");
}
@@ -1114,7 +1114,7 @@ public abstract class Action implements GraphSourceItem {
}
/*ActionJump && ActionIf removed*/
/*if ((action instanceof ActionEnumerate2) || (action instanceof ActionEnumerate)) {
/*if ((action instanceof ActionEnumerate2) || (action instanceof ActionEnumerate)) {
loopStart = ip + 1;
isForIn = true;
ip += 4;
@@ -308,16 +308,12 @@ public class FunctionActionItem extends ActionItem {
} else {
v.setBoxedValue(new DirectValueActionItem(new RegisterNumber(registerNames.indexOf(varName), varName)));
}
} else if (v.isDefinition()) {
v.setBoxedValue(new DefineLocalActionItem(null, null, ((ActionSourceGenerator) generator).pushConstTargetItem(varName), stored));
} else if (stored != null) {
v.setBoxedValue(new SetVariableActionItem(null, null, ((ActionSourceGenerator) generator).pushConstTargetItem(varName), stored));
} else {
if (v.isDefinition()) {
v.setBoxedValue(new DefineLocalActionItem(null, null, ((ActionSourceGenerator) generator).pushConstTargetItem(varName), stored));
} else {
if (stored != null) {
v.setBoxedValue(new SetVariableActionItem(null, null, ((ActionSourceGenerator) generator).pushConstTargetItem(varName), stored));
} else {
v.setBoxedValue(new GetVariableActionItem(null, null, ((ActionSourceGenerator) generator).pushConstTargetItem(varName)));
}
}
v.setBoxedValue(new GetVariableActionItem(null, null, ((ActionSourceGenerator) generator).pushConstTargetItem(varName)));
}
}
@@ -1,6 +1,6 @@
/* The following code was generated by JFlex 1.6.0 */
/*
/*
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
@@ -16,7 +16,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
/* Flash assembler language lexer specification */
/* Flash assembler language lexer specification */
package com.jpexs.decompiler.flash.action.parser.pcode;
import com.jpexs.decompiler.flash.action.parser.ActionParseException;
@@ -27,8 +27,7 @@ import com.jpexs.decompiler.flash.ecma.Undefined;
/**
* This class is a scanner generated by
* <a href="http://www.jflex.de/">JFlex</a> 1.6.0
* from the specification file
* <a href="http://www.jflex.de/">JFlex</a> 1.6.0 from the specification file
* <tt>C:/Dropbox/Programovani/JavaSE/FFDec/libsrc/ffdec_lib/lexers/actionscript_pcode.flex</tt>
*/
public final class FlasmLexer {
@@ -54,9 +53,8 @@ public final class FlasmLexer {
/**
* ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
* ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l
* at the beginning of a line
* l is of the form l = 2*k, k a non negative integer
* ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l at the
* beginning of a line l is of the form l = 2*k, k a non negative integer
*/
private static final int ZZ_LEXSTATE[] = {
0, 0, 1, 1, 2, 2
@@ -238,9 +236,11 @@ public final class FlasmLexer {
}
private static int zzUnpackAction(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -282,9 +282,11 @@ public final class FlasmLexer {
}
private static int zzUnpackRowMap(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -458,9 +460,11 @@ public final class FlasmLexer {
}
private static int zzUnpackTrans(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -510,9 +514,11 @@ public final class FlasmLexer {
}
private static int zzUnpackAttribute(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -541,8 +547,8 @@ public final class FlasmLexer {
private int zzLexicalState = YYINITIAL;
/**
* this buffer contains the current text to be matched and is
* the source of the yytext() string
* this buffer contains the current text to be matched and is the source of
* the yytext() string
*/
private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
@@ -562,8 +568,8 @@ public final class FlasmLexer {
private int zzStartRead;
/**
* endRead marks the last character in the buffer, that has been read
* from input
* endRead marks the last character in the buffer, that has been read from
* input
*/
private int zzEndRead;
@@ -599,10 +605,10 @@ public final class FlasmLexer {
private boolean zzEOFDone;
/**
* The number of occupied positions in zzBuffer beyond zzEndRead.
* When a lead/high surrogate has been read from the input stream
* into the final zzBuffer position, this will have a value of 1;
* otherwise, it will have a value of 0.
* The number of occupied positions in zzBuffer beyond zzEndRead. When a
* lead/high surrogate has been read from the input stream into the final
* zzBuffer position, this will have a value of 1; otherwise, it will have a
* value of 0.
*/
private int zzFinalHighSurrogate = 0;
@@ -642,9 +648,11 @@ public final class FlasmLexer {
*/
private static char[] zzUnpackCMap(String packed) {
char[] map = new char[0x110000];
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = 0; /* index in unpacked array */
int j = 0;
/* index in unpacked array */
while (i < 2854) {
int count = packed.charAt(i++);
@@ -703,7 +711,8 @@ public final class FlasmLexer {
if (totalRead > 0) {
zzEndRead += totalRead;
if (totalRead == requested) { /* possibly more input available */
if (totalRead == requested) {
/* possibly more input available */
if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) {
--zzEndRead;
@@ -721,9 +730,11 @@ public final class FlasmLexer {
* Closes the input stream.
*/
public final void yyclose() throws java.io.IOException {
zzAtEOF = true; /* indicate end of file */
zzAtEOF = true;
/* indicate end of file */
zzEndRead = zzStartRead; /* invalidate buffer */
zzEndRead = zzStartRead;
/* invalidate buffer */
if (zzReader != null) {
zzReader.close();
@@ -731,12 +742,12 @@ public final class FlasmLexer {
}
/**
* Resets the scanner to read from a new input stream.
* Does not close the old reader.
* Resets the scanner to read from a new input stream. Does not close the
* old reader.
*
* All internal variables are reset, the old input stream
* <b>cannot</b> be reused (internal buffer is discarded and lost).
* Lexical state is set to <tt>ZZ_INITIAL</tt>.
* <b>cannot</b> be reused (internal buffer is discarded and lost). Lexical
* state is set to <tt>ZZ_INITIAL</tt>.
*
* Internal scan buffer is resized down to its initial length, if it has
* grown.
@@ -782,13 +793,12 @@ public final class FlasmLexer {
}
/**
* Returns the character at position <tt>pos</tt> from the
* matched text.
* Returns the character at position <tt>pos</tt> from the matched text.
*
* It is equivalent to yytext().charAt(pos), but faster
*
* @param pos the position of the character to fetch.
* A value from 0 to yylength()-1.
* @param pos the position of the character to fetch. A value from 0 to
* yylength()-1.
*
* @return the character at position pos
*/
@@ -806,14 +816,13 @@ public final class FlasmLexer {
/**
* Reports an error that occured while scanning.
*
* In a wellformed scanner (no or only correct usage of
* yypushback(int) and a match-all fallback rule) this method
* will only be called with things that "Can't Possibly Happen".
* If this method is called, something is seriously wrong
* (e.g. a JFlex bug producing a faulty scanner etc.).
* In a wellformed scanner (no or only correct usage of yypushback(int) and
* a match-all fallback rule) this method will only be called with things
* that "Can't Possibly Happen". If this method is called, something is
* seriously wrong (e.g. a JFlex bug producing a faulty scanner etc.).
*
* Usual syntax/scanner level error handling should be done
* in error fallback rules.
* Usual syntax/scanner level error handling should be done in error
* fallback rules.
*
* @param errorCode the code of the errormessage to display
*/
@@ -833,8 +842,8 @@ public final class FlasmLexer {
*
* They will be read again by then next call of the scanning method
*
* @param number the number of characters to be read again.
* This number must not be greater than yylength()!
* @param number the number of characters to be read again. This number must
* not be greater than yylength()!
*/
public void yypushback(int number) {
if (number > yylength()) {
@@ -845,8 +854,8 @@ public final class FlasmLexer {
}
/**
* Resumes scanning until the next regular expression is matched,
* the end of input is encountered or an I/O-Error occurs.
* Resumes scanning until the next regular expression is matched, the end of
* input is encountered or an I/O-Error occurs.
*
* @return the next token
* @exception java.io.IOException if any I/O-Error occurs
@@ -1,6 +1,6 @@
/* The following code was generated by JFlex 1.6.0 */
/*
/*
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
@@ -25,8 +25,7 @@ import java.util.Stack;
/**
* This class is a scanner generated by
* <a href="http://www.jflex.de/">JFlex</a> 1.6.0
* from the specification file
* <a href="http://www.jflex.de/">JFlex</a> 1.6.0 from the specification file
* <tt>D:/Dropbox/Programovani/JavaSE/FFDec/libsrc/ffdec_lib/lexers/actionscript_script.flex</tt>
*/
public final class ActionScriptLexer {
@@ -58,9 +57,8 @@ public final class ActionScriptLexer {
/**
* ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
* ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l
* at the beginning of a line
* l is of the form l = 2*k, k a non negative integer
* ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l at the
* beginning of a line l is of the form l = 2*k, k a non negative integer
*/
private static final int ZZ_LEXSTATE[] = {
0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5
@@ -278,9 +276,11 @@ public final class ActionScriptLexer {
}
private static int zzUnpackAction(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -395,9 +395,11 @@ public final class ActionScriptLexer {
}
private static int zzUnpackRowMap(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -1100,9 +1102,11 @@ public final class ActionScriptLexer {
}
private static int zzUnpackTrans(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -1157,9 +1161,11 @@ public final class ActionScriptLexer {
}
private static int zzUnpackAttribute(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -1188,8 +1194,8 @@ public final class ActionScriptLexer {
private int zzLexicalState = YYINITIAL;
/**
* this buffer contains the current text to be matched and is
* the source of the yytext() string
* this buffer contains the current text to be matched and is the source of
* the yytext() string
*/
private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
@@ -1209,8 +1215,8 @@ public final class ActionScriptLexer {
private int zzStartRead;
/**
* endRead marks the last character in the buffer, that has been read
* from input
* endRead marks the last character in the buffer, that has been read from
* input
*/
private int zzEndRead;
@@ -1246,10 +1252,10 @@ public final class ActionScriptLexer {
private boolean zzEOFDone;
/**
* The number of occupied positions in zzBuffer beyond zzEndRead.
* When a lead/high surrogate has been read from the input stream
* into the final zzBuffer position, this will have a value of 1;
* otherwise, it will have a value of 0.
* The number of occupied positions in zzBuffer beyond zzEndRead. When a
* lead/high surrogate has been read from the input stream into the final
* zzBuffer position, this will have a value of 1; otherwise, it will have a
* value of 0.
*/
private int zzFinalHighSurrogate = 0;
@@ -1326,9 +1332,11 @@ public final class ActionScriptLexer {
*/
private static char[] zzUnpackCMap(String packed) {
char[] map = new char[0x110000];
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = 0; /* index in unpacked array */
int j = 0;
/* index in unpacked array */
while (i < 2916) {
int count = packed.charAt(i++);
@@ -1387,7 +1395,8 @@ public final class ActionScriptLexer {
if (totalRead > 0) {
zzEndRead += totalRead;
if (totalRead == requested) { /* possibly more input available */
if (totalRead == requested) {
/* possibly more input available */
if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) {
--zzEndRead;
@@ -1405,9 +1414,11 @@ public final class ActionScriptLexer {
* Closes the input stream.
*/
public final void yyclose() throws java.io.IOException {
zzAtEOF = true; /* indicate end of file */
zzAtEOF = true;
/* indicate end of file */
zzEndRead = zzStartRead; /* invalidate buffer */
zzEndRead = zzStartRead;
/* invalidate buffer */
if (zzReader != null) {
zzReader.close();
@@ -1415,12 +1426,12 @@ public final class ActionScriptLexer {
}
/**
* Resets the scanner to read from a new input stream.
* Does not close the old reader.
* Resets the scanner to read from a new input stream. Does not close the
* old reader.
*
* All internal variables are reset, the old input stream
* <b>cannot</b> be reused (internal buffer is discarded and lost).
* Lexical state is set to <tt>ZZ_INITIAL</tt>.
* <b>cannot</b> be reused (internal buffer is discarded and lost). Lexical
* state is set to <tt>ZZ_INITIAL</tt>.
*
* Internal scan buffer is resized down to its initial length, if it has
* grown.
@@ -1466,13 +1477,12 @@ public final class ActionScriptLexer {
}
/**
* Returns the character at position <tt>pos</tt> from the
* matched text.
* Returns the character at position <tt>pos</tt> from the matched text.
*
* It is equivalent to yytext().charAt(pos), but faster
*
* @param pos the position of the character to fetch.
* A value from 0 to yylength()-1.
* @param pos the position of the character to fetch. A value from 0 to
* yylength()-1.
*
* @return the character at position pos
*/
@@ -1490,14 +1500,13 @@ public final class ActionScriptLexer {
/**
* Reports an error that occured while scanning.
*
* In a wellformed scanner (no or only correct usage of
* yypushback(int) and a match-all fallback rule) this method
* will only be called with things that "Can't Possibly Happen".
* If this method is called, something is seriously wrong
* (e.g. a JFlex bug producing a faulty scanner etc.).
* In a wellformed scanner (no or only correct usage of yypushback(int) and
* a match-all fallback rule) this method will only be called with things
* that "Can't Possibly Happen". If this method is called, something is
* seriously wrong (e.g. a JFlex bug producing a faulty scanner etc.).
*
* Usual syntax/scanner level error handling should be done
* in error fallback rules.
* Usual syntax/scanner level error handling should be done in error
* fallback rules.
*
* @param errorCode the code of the errormessage to display
*/
@@ -1517,8 +1526,8 @@ public final class ActionScriptLexer {
*
* They will be read again by then next call of the scanning method
*
* @param number the number of characters to be read again.
* This number must not be greater than yylength()!
* @param number the number of characters to be read again. This number must
* not be greater than yylength()!
*/
public void yypushback(int number) {
if (number > yylength()) {
@@ -1529,8 +1538,8 @@ public final class ActionScriptLexer {
}
/**
* Resumes scanning until the next regular expression is matched,
* the end of input is encountered or an I/O-Error occurs.
* Resumes scanning until the next regular expression is matched, the end of
* input is encountered or an I/O-Error occurs.
*
* @return the next token
* @exception java.io.IOException if any I/O-Error occurs
@@ -1626,7 +1635,8 @@ public final class ActionScriptLexer {
}
case 185:
break;
case 3: { /*ignore*/
case 3: {
/*ignore*/
}
case 186:
@@ -1963,7 +1973,8 @@ public final class ActionScriptLexer {
case 250:
break;
case 68: {
string.append('\\'); /*illegal escape sequence*/
string.append('\\');
/*illegal escape sequence*/
}
case 251:
@@ -539,6 +539,11 @@ public class Configuration {
@ConfigurationFile(".*\\.swc$")
public static final ConfigurationItem<String> playerLibLocation = null;
@ConfigurationDefaultString("")
@ConfigurationCategory("paths")
@ConfigurationDirectory
public static final ConfigurationItem<String> flexSdkLocation = null;
@ConfigurationDefaultDouble(0.7)
@ConfigurationName("gui.avm2.splitPane.vars.dividerLocationPercent")
@ConfigurationInternal
@@ -608,6 +613,10 @@ public class Configuration {
@ConfigurationInternal
public static final ConfigurationItem<Double> guiAvm2DocsSplitPaneDividerLocationPercent = null;
@ConfigurationDefaultBoolean(false)
@ConfigurationCategory("script")
public static final ConfigurationItem<Boolean> useFlexAs3Compiler = null;
private enum OSId {
WINDOWS, OSX, UNIX
@@ -1,152 +1,152 @@
function bind(el, evt, func) {
if (el.addEventListener){
if (el.addEventListener) {
el.addEventListener(evt, func, false);
} else if (el.attachEvent) {
el.attachEvent('on' + evt, func);
}
}
function showhide(e,show){
var cls = " "+e.className+" ";
if(show && cls.indexOf(" hidden ") > -1){
cls = cls.replace(" hidden "," ");
}else if(!show && cls.indexOf(" hidden ") == -1 ){
cls = cls + "hidden ";
}
cls = cls.trim();
e.className = cls;
}
function hideNoName(name){
var lis = document.getElementsByTagName("li");
loopi:for(var i=0;i<lis.length;i++) {
if(lis[i].className == "instruction-item"){
if ((typeof name) != "undefined" && name.trim()!="") {
var ss = lis[i].getElementsByTagName("strong");
for(var s=0;s<ss.length;s++){
if(ss[s].className=="instruction-name")
{
var insName = ss[s].innerHTML;
if(insName.toLowerCase().indexOf(name.toLowerCase())!=0){ //does not start with desired name
showhide(lis[i],false);
continue loopi;
}
}
}
}
function showhide(e, show) {
var cls = " " + e.className + " ";
if (show && cls.indexOf(" hidden ") > -1) {
cls = cls.replace(" hidden ", " ");
} else if (!show && cls.indexOf(" hidden ") == -1) {
cls = cls + "hidden ";
}
}
cls = cls.trim();
e.className = cls;
}
function showFlags(show,flagType){
function hideNoName(name) {
var lis = document.getElementsByTagName("li");
loopi:for (var i = 0; i < lis.length; i++) {
if (lis[i].className == "instruction-item") {
if ((typeof name) != "undefined" && name.trim() != "") {
var ss = lis[i].getElementsByTagName("strong");
for (var s = 0; s < ss.length; s++) {
if (ss[s].className == "instruction-name")
{
var insName = ss[s].innerHTML;
if (insName.toLowerCase().indexOf(name.toLowerCase()) != 0) { //does not start with desired name
showhide(lis[i], false);
continue loopi;
}
}
}
}
}
}
}
function showFlags(show, flagType) {
var lis = document.getElementsByTagName("div");
loopi:for(var i=0;i<lis.length;i++){
var cls = " "+lis[i].className+" ";
if ((typeof flagType) != "undefined"){
if(cls.indexOf("instruction-flag-"+flagType) == -1){
loopi:for (var i = 0; i < lis.length; i++) {
var cls = " " + lis[i].className + " ";
if ((typeof flagType) != "undefined") {
if (cls.indexOf("instruction-flag-" + flagType) == -1) {
continue;
}
}
showhide(lis[i].parentNode,show);
}
showhide(lis[i].parentNode, show);
}
}
function sortInstructions(order){
var newUl = document.createElement("ul");
newUl.className = "instruction-list";
var smallestItem = null;
var smallestVal = null;
var originalUl = null;
do {
smallestItem = null;
smallestVal = null;
var lis = document.getElementsByTagName("li");
loopi:for(var i=0;i<lis.length;i++) {
var cls = " "+lis[i].className+" ";
if(cls.indexOf(" instruction-item ") != -1) {
var ss = lis[i].getElementsByTagName(order == "code"?"span":"strong");
for(var s=0;s<ss.length;s++){
if(ss[s].className=="instruction-"+order)
function sortInstructions(order) {
var newUl = document.createElement("ul");
newUl.className = "instruction-list";
var smallestItem = null;
var smallestVal = null;
var originalUl = null;
do {
smallestItem = null;
smallestVal = null;
var lis = document.getElementsByTagName("li");
loopi:for (var i = 0; i < lis.length; i++) {
var cls = " " + lis[i].className + " ";
if (cls.indexOf(" instruction-item ") != -1) {
var ss = lis[i].getElementsByTagName(order == "code" ? "span" : "strong");
for (var s = 0; s < ss.length; s++) {
if (ss[s].className == "instruction-" + order)
{
var checkedVal = ss[s].innerHTML;
if(smallestVal == null || smallestVal > checkedVal)
if (smallestVal == null || smallestVal > checkedVal)
{
smallestItem = lis[i];
smallestVal = checkedVal;
}
break;
break;
}
}
}
}
}
}
if(smallestItem != null){
originalUl = smallestItem.parentNode;
originalUl.removeChild(smallestItem);
newUl.appendChild(smallestItem);
}
}while(smallestItem != null);
originalUl.parentNode.replaceChild(newUl,originalUl);
if (smallestItem != null) {
originalUl = smallestItem.parentNode;
originalUl.removeChild(smallestItem);
newUl.appendChild(smallestItem);
}
} while (smallestItem != null);
originalUl.parentNode.replaceChild(newUl, originalUl);
}
function applyFilter() {
var order_new = document.getElementById("filter_order").value;
if(order_set != order_new) {
order_set = order_new;
sortInstructions(order_new);
if (order_set != order_new) {
order_set = order_new;
sortInstructions(order_new);
}
showFlags(true);
hideNoName(document.getElementById("filter-byname").value);
var inputs = document.getElementsByTagName("input");
for(var i=0;i<inputs.length;i++){
if(inputs[i].type == "checkbox" && inputs[i].className == "filter" && inputs[i].hasAttribute("data-flag")){
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].type == "checkbox" && inputs[i].className == "filter" && inputs[i].hasAttribute("data-flag")) {
var flag = inputs[i].getAttribute("data-flag");
if(inputs[i].checked){
showFlags(false,flag);
}
if (inputs[i].checked) {
showFlags(false, flag);
}
}
}
}
}
function init(){
function init() {
var js_switcher = document.getElementById("js-switcher");
if(!js_switcher){
if (!js_switcher) {
return;
}
var t = "";
t += "<div class=\"filter\">";
t += "<div class=\"filter-item\">";
t += "<label for=\"filter-byname\"><strong class=\"filter-byname-title\">"+txt_filter_byname+"</strong></label>";
t += "<label for=\"filter-byname\"><strong class=\"filter-byname-title\">" + txt_filter_byname + "</strong></label>";
t += "<input onkeydown=\"applyFilter();\" onkeyup=\"applyFilter();\" onkeypress=\"applyFilter();\" type=\"text\" id=\"filter-byname\" size=\"15\" />";
t += "</div>";
t += "<div class=\"filter-item\">";
t += "<strong class=\"filter-hide-title\">"+txt_filter_hide+"</strong><br />";
for(var flag in flags){
t += "<strong class=\"filter-hide-title\">" + txt_filter_hide + "</strong><br />";
for (var flag in flags) {
var flagDesc = flags[flag];
var flagSet = flags_set[flag];
t+= '<input class="filter" data-flag="'+flag+'" onchange="applyFilter();" type="checkbox"'+(flagSet?' checked="checked"':'')+' id="flag-'+flag+'-switch"/><label for="flag-'+flag+'-switch">'+flagDesc+'</label><br />';
t += '<input class="filter" data-flag="' + flag + '" onchange="applyFilter();" type="checkbox"' + (flagSet ? ' checked="checked"' : '') + ' id="flag-' + flag + '-switch"/><label for="flag-' + flag + '-switch">' + flagDesc + '</label><br />';
}
t += "<div class=\"filter-item\">";
t += "<label for=\"filter-order\"><strong class=\"filter-order-title\">"+txt_filter_order+"</strong></label>";
t += "<label for=\"filter-order\"><strong class=\"filter-order-title\">" + txt_filter_order + "</strong></label>";
t += "<select id=\"filter_order\" onchange=\"applyFilter();\">";
t += "<option value=\"code\""+(order_set=="code"?' selected="selected"':'')+">"+txt_filter_order_code+"</option>";
t += "<option value=\"name\""+(order_set=="name"?' selected="selected"':'')+">"+txt_filter_order_name+"</option>";
t += "<option value=\"code\"" + (order_set == "code" ? ' selected="selected"' : '') + ">" + txt_filter_order_code + "</option>";
t += "<option value=\"name\"" + (order_set == "name" ? ' selected="selected"' : '') + ">" + txt_filter_order_name + "</option>";
t += "</select>";
t += "</div>";
t += "</div>";
t += "</div>";
t += "</div>";
t += "</div>"; //.filter
js_switcher.innerHTML = t;
applyFilter();
}
bind(window,"load",init);
bind(window, "load", init);
@@ -655,7 +655,7 @@ public class EcmaFloatingDecimal {
* We keep track of powers of 2 and powers of 5.
*/
/*
/*
* Estimate decimal exponent. (If it is small-ish,
* we could double-check.)
*
@@ -973,64 +973,60 @@ public class EcmaFloatingDecimal {
if (isExceptional) {
System.arraycopy(digits, 0, result, i, nDigits);
i += nDigits;
} else {
if (decExponent > 0 && decExponent < 22) {
// print digits.digits.
int charLength = Math.min(nDigits, decExponent);
System.arraycopy(digits, 0, result, i, charLength);
} else if (decExponent > 0 && decExponent < 22) {
// print digits.digits.
int charLength = Math.min(nDigits, decExponent);
System.arraycopy(digits, 0, result, i, charLength);
i += charLength;
if (charLength < decExponent) {
charLength = decExponent - charLength;
System.arraycopy(zero, 0, result, i, charLength);
i += charLength;
if (charLength < decExponent) {
charLength = decExponent - charLength;
System.arraycopy(zero, 0, result, i, charLength);
i += charLength;
} else {
if (charLength < nDigits) {
result[i++] = '.';
int t = nDigits - charLength;
System.arraycopy(digits, charLength, result, i, t);
i += t;
}
}
} else if (decExponent <= 0 && decExponent > -5) {
result[i++] = '0';
if (digits != zero) {
result[i++] = '.';
if (decExponent != 0) {
System.arraycopy(zero, 0, result, i, -decExponent);
i -= decExponent;
}
System.arraycopy(digits, 0, result, i, nDigits);
i += nDigits;
}
} else {
result[i++] = digits[0];
} else if (charLength < nDigits) {
result[i++] = '.';
if (nDigits > 1) {
System.arraycopy(digits, 1, result, i, nDigits - 1);
i += nDigits - 1;
} else {
result[i++] = '0';
}
result[i++] = 'e';
int e;
if (decExponent <= 0) {
result[i++] = '-';
e = -decExponent + 1;
} else {
e = decExponent - 1;
}
// decExponent has 1, 2, or 3, digits
if (e <= 9) {
result[i++] = (char) (e + '0');
} else if (e <= 99) {
result[i++] = (char) (e / 10 + '0');
result[i++] = (char) (e % 10 + '0');
} else {
result[i++] = (char) (e / 100 + '0');
e %= 100;
result[i++] = (char) (e / 10 + '0');
result[i++] = (char) (e % 10 + '0');
int t = nDigits - charLength;
System.arraycopy(digits, charLength, result, i, t);
i += t;
}
} else if (decExponent <= 0 && decExponent > -5) {
result[i++] = '0';
if (digits != zero) {
result[i++] = '.';
if (decExponent != 0) {
System.arraycopy(zero, 0, result, i, -decExponent);
i -= decExponent;
}
System.arraycopy(digits, 0, result, i, nDigits);
i += nDigits;
}
} else {
result[i++] = digits[0];
result[i++] = '.';
if (nDigits > 1) {
System.arraycopy(digits, 1, result, i, nDigits - 1);
i += nDigits - 1;
} else {
result[i++] = '0';
}
result[i++] = 'e';
int e;
if (decExponent <= 0) {
result[i++] = '-';
e = -decExponent + 1;
} else {
e = decExponent - 1;
}
// decExponent has 1, 2, or 3, digits
if (e <= 9) {
result[i++] = (char) (e + '0');
} else if (e <= 99) {
result[i++] = (char) (e / 10 + '0');
result[i++] = (char) (e % 10 + '0');
} else {
result[i++] = (char) (e / 100 + '0');
e %= 100;
result[i++] = (char) (e / 10 + '0');
result[i++] = (char) (e % 10 + '0');
}
}
return i;
@@ -1185,8 +1181,8 @@ public class EcmaFloatingDecimal {
}
/**
* Extract a hexadecimal digit from position <code>position</code>
* of string <code>s</code>.
* Extract a hexadecimal digit from position <code>position</code> of string
* <code>s</code>.
*/
static int getHexDigit(String s, int position) {
int value = Character.digit(s.charAt(position), 16);
@@ -1567,8 +1563,8 @@ class FDBigInt {
} else {
return 1; // b not big, answer is obvious;
}
} else {
// a is not really big
} else // a is not really big
{
if (b < 0) {
// but b is really big
return -1;
@@ -63,7 +63,7 @@ public class ShapeExporter {
return ret;
}
File foutdir = new File(outdir);
File foutdir = new File(outdir);
Path.createDirectorySafe(foutdir);
int count = 0;
@@ -22,5 +22,5 @@ package com.jpexs.decompiler.flash.exporters.modes;
*/
public enum ScriptExportMode {
AS, PCODE, PCODE_HEX, HEX, CONSTANTS;
AS, PCODE, PCODE_HEX, HEX, CONSTANTS, AS_METHOD_STUBS;
}
@@ -0,0 +1,58 @@
package com.jpexs.decompiler.flash.exporters.script;
import com.jpexs.decompiler.graph.DottedChain;
import java.util.Objects;
public class Dependency {
private DottedChain id;
private DependencyType type;
public Dependency(DottedChain id, DependencyType type) {
this.id = id;
this.type = type;
}
public DottedChain getId() {
return id;
}
public DependencyType getType() {
return type;
}
@Override
public String toString() {
return id.toString() + " (" + type + ")";
}
@Override
public int hashCode() {
int hash = 5;
hash = 79 * hash + Objects.hashCode(this.id);
hash = 79 * hash + Objects.hashCode(this.type);
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Dependency other = (Dependency) obj;
if (!Objects.equals(this.id, other.id)) {
return false;
}
if (this.type != other.type) {
return false;
}
return true;
}
}
@@ -0,0 +1,215 @@
/*
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.exporters.script;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Deobfuscation;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.AlchemyTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyStrictIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetLexIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.types.AsTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceIns;
import com.jpexs.decompiler.flash.abc.avm2.model.InitVectorAVM2Item;
import com.jpexs.decompiler.flash.abc.types.ABCException;
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.NamespaceSet;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.graph.DottedChain;
import java.util.List;
public class DependencyParser {
public static void parseDependenciesFromNS(String ignoredCustom, ABC abc, List<Dependency> dependencies, List<String> uses, int namespace_index, DottedChain ignorePackage, String name, DependencyType dependencyType) {
Namespace ns = abc.constants.getNamespace(namespace_index);
if (name.isEmpty()) {
name = "*";
}
DottedChain newimport = ns.getName(abc.constants);
if (parseUsagesFromNS(ignoredCustom, abc, dependencies, uses, namespace_index, ignorePackage, name)) {
return;
} else if ((ns.kind != Namespace.KIND_PACKAGE) && (ns.kind != Namespace.KIND_PACKAGE_INTERNAL)) {
return;
}
newimport = newimport.add(name);
Dependency dep = new Dependency(newimport, dependencyType);
if (!dependencies.contains(dep)) {
DottedChain pkg = newimport.getWithoutLast(); //.substring(0, newimport.lastIndexOf('.'));
if (pkg.equals(InitVectorAVM2Item.VECTOR_PACKAGE)) { //special case - is imported always
return;
}
if (!pkg.equals(ignorePackage)) {
dependencies.add(dep);
}
}
//}
}
public static void parseDependenciesFromMultiname(String ignoredCustom, ABC abc, List<Dependency> dependencies, List<String> uses, Multiname m, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames, DependencyType dependencyType) {
if (m != null) {
if (m.kind == Multiname.TYPENAME) {
if (m.qname_index != 0) {
parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames, dependencyType);
}
for (Integer i : m.params) {
if (i != 0) {
parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames, dependencyType);
}
}
return;
}
Namespace ns = m.getNamespace(abc.constants);
String name = m.getName(abc.constants, fullyQualifiedNames, true);
NamespaceSet nss = m.getNamespaceSet(abc.constants);
if (ns != null) {
parseDependenciesFromNS(ignoredCustom, abc, dependencies, uses, m.namespace_index, ignorePackage, name, dependencyType);
}
if (nss != null) {
for (int n : nss.namespaces) {
parseDependenciesFromNS(ignoredCustom, abc, dependencies, uses, n, ignorePackage, nss.namespaces.length > 1 ? "" : name, dependencyType);
}
}
}
}
public static void parseDependenciesFromMethodInfo(String ignoredCustom, ABC abc, int method_index, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames, List<Integer> visitedMethods) {
if ((method_index < 0) || (method_index >= abc.method_info.size())) {
return;
}
visitedMethods.add(method_index);
if (abc.method_info.get(method_index).ret_type != 0) {
parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(abc.method_info.get(method_index).ret_type), ignorePackage, fullyQualifiedNames, DependencyType.SIGNATURE);
}
for (int t : abc.method_info.get(method_index).param_types) {
if (t != 0) {
parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(t), ignorePackage, fullyQualifiedNames, DependencyType.SIGNATURE);
}
}
MethodBody body = abc.findBody(method_index);
if (body != null) {
body.traits.getDependencies(ignoredCustom, abc, dependencies, uses, ignorePackage, fullyQualifiedNames);
for (ABCException ex : body.exceptions) {
parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(ex.type_index), ignorePackage, fullyQualifiedNames, DependencyType.EXPRESSION /* or signature?*/);
}
for (AVM2Instruction ins : body.getCode().code) {
if (ins.definition instanceof AlchemyTypeIns) {
DottedChain nimport = AlchemyTypeIns.ALCHEMY_PACKAGE.add(ins.definition.instructionName);
Dependency depExp = new Dependency(nimport, DependencyType.EXPRESSION);
if (!dependencies.contains(depExp)) {
dependencies.add(depExp);
}
}
if (ins.definition instanceof NewFunctionIns) {
if (ins.operands[0] != method_index) {
if (!visitedMethods.contains(ins.operands[0])) {
parseDependenciesFromMethodInfo(ignoredCustom, abc, ins.operands[0], dependencies, uses, ignorePackage, fullyQualifiedNames, visitedMethods);
}
}
}
if ((ins.definition instanceof FindPropertyStrictIns)
|| (ins.definition instanceof FindPropertyIns)
|| (ins.definition instanceof GetLexIns)
|| (ins.definition instanceof CoerceIns)
|| (ins.definition instanceof AsTypeIns)) {
int m = ins.operands[0];
if (m != 0) {
if (m < abc.constants.getMultinameCount()) {
parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(m), ignorePackage, fullyQualifiedNames, DependencyType.EXPRESSION);
}
}
} else {
for (int k = 0; k < ins.definition.operands.length; k++) {
if (ins.definition.operands[k] == AVM2Code.DAT_MULTINAME_INDEX) {
int multinameIndex = ins.operands[k];
if (multinameIndex < abc.constants.getMultinameCount()) {
parseUsagesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(multinameIndex), ignorePackage, fullyQualifiedNames, DependencyType.EXPRESSION);
}
}
}
}
}
}
}
public static void parseUsagesFromMultiname(String ignoredCustom, ABC abc, List<Dependency> dependencies, List<String> uses, Multiname m, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames, DependencyType dependencyType) {
if (m != null) {
if (m.kind == Multiname.TYPENAME) {
if (m.qname_index != 0) {
parseUsagesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames, dependencyType);
}
for (Integer i : m.params) {
if (i != 0) {
parseUsagesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames, dependencyType);
}
}
return;
}
Namespace ns = m.getNamespace(abc.constants);
String name = m.getName(abc.constants, fullyQualifiedNames, false);
NamespaceSet nss = m.getNamespaceSet(abc.constants);
if (ns != null) {
parseUsagesFromNS(ignoredCustom, abc, dependencies, uses, m.namespace_index, ignorePackage, name);
}
if (nss != null) {
if (nss.namespaces.length == 1) {
parseUsagesFromNS(ignoredCustom, abc, dependencies, uses, nss.namespaces[0], ignorePackage, name);
} else {
for (int n : nss.namespaces) {
parseUsagesFromNS(ignoredCustom, abc, dependencies, uses, n, ignorePackage, "");
}
}
}
}
}
private static boolean parseUsagesFromNS(String ignoredCustom, ABC abc, List<Dependency> dependencies, List<String> uses, int namespace_index, DottedChain ignorePackage, String name) {
Namespace ns = abc.constants.getNamespace(namespace_index);
if (ns.kind == Namespace.KIND_NAMESPACE) {
String nsVal = ns.getName(abc.constants).toRawString();
for (ABCContainerTag abcTag : abc.getAbcTags()) {
DottedChain nsimport = abcTag.getABC().nsValueToName(nsVal);
if (nsimport.equals(AVM2Deobfuscation.BUILTIN)) {
return true; //handled, but import/use not added
}
if (!nsimport.isEmpty()) {
Dependency depNs = new Dependency(nsimport, DependencyType.NAMESPACE);
if (!nsimport.getWithoutLast().equals(ignorePackage) && !dependencies.contains(depNs)) {
dependencies.add(depNs);
}
if (ignoredCustom != null && nsVal.equals(ignoredCustom)) {
return true;
}
if (!uses.contains(nsimport.getLast())) {
uses.add(nsimport.getLast());
}
return true;
}
}
}
return false;
}
}
@@ -0,0 +1,5 @@
package com.jpexs.decompiler.flash.exporters.script;
public enum DependencyType {
INHERITANCE, NAMESPACE, SIGNATURE, EXPRESSION
}
@@ -0,0 +1,189 @@
/*
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.exporters.script;
import com.jpexs.decompiler.flash.EventListener;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.abc.types.ClassInfo;
import com.jpexs.decompiler.flash.abc.types.InstanceInfo;
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.graph.DottedChain;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Class LinkReportExporter - generates Linker reports similar to Flex
* -link-report, but for SWF files
*
* @author JPEXS
*/
public class LinkReportExporter {
private String newLineChar = "\n";
private String indentStr = " ";
/**
* Constructs reporter with LF as newline, two spaces as indent
*/
public LinkReportExporter() {
}
/**
* Constructs reporter with custom newline char, two spaces as indent
*
* @param newLineChar
*/
public LinkReportExporter(String newLineChar) {
this.newLineChar = newLineChar;
}
/**
* Constructs reporter with custom newline char and indent string
*
* @param newLineChar
* @param indentStr
*/
public LinkReportExporter(String newLineChar, String indentStr) {
this.newLineChar = newLineChar;
this.indentStr = indentStr;
}
private String indent(int cnt) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < cnt; i++) {
sb.append(indentStr);
}
return sb.toString();
}
public String generateReport(SWF swf, List<ScriptPack> as3scripts, EventListener evl) {
StringBuilder sb = new StringBuilder();
Set<String> extDeps = new HashSet<>();
sb.append("<report>").append(newLineChar);
sb.append(indent(1)).append("<scripts>").append(newLineChar);
List<ScriptPack> revList = new ArrayList<>(as3scripts);
Collections.reverse(revList);
List<DottedChain> existingObjects = new ArrayList<>();
for (ScriptPack sp : as3scripts) {
existingObjects.add(sp.getClassPath().packageStr.add(sp.getClassPath().className));
}
for (ScriptPack sp : revList) {
String scriptName = "script" + sp.scriptIndex;
sb.append(indent(2)).append("<script name=\"").append(scriptName).append("\">").append(newLineChar);
//TODO: additional atributes - mod="1469951734131" size="525" optimizedsize="508
ScriptInfo script = sp.abc.script_info.get(sp.scriptIndex);
for (int traitIndex : sp.traitIndices) {
Trait trait = script.traits.traits.get(traitIndex);
sb.append(reportTrait(extDeps, existingObjects, swf, sp.abc, trait));
}
//how about script_init method(?)
sb.append(indent(2)).append("</script>").append(newLineChar);
}
sb.append(indent(1)).append("</scripts>").append(newLineChar);
sb.append("</report>").append(newLineChar);
return sb.toString();
}
private String multiNameToId(ABC abc, Multiname multiName) {
Namespace ns = multiName.getNamespace(abc.constants);
NamespaceSet nss = multiName.getNamespaceSet(abc.constants);
if (nss != null && nss.namespaces.length == 1) {
ns = abc.constants.getNamespace(nss.namespaces[0]);
}
String pkgName = ns == null ? "" : ns.getName(abc.constants).toRawString();
String clsName = multiName.getName(abc.constants, new ArrayList<>(), true);
return pkgName.isEmpty() ? clsName : pkgName + ":" + clsName;
}
private String dottedChainToId(DottedChain dc) {
if (dc.getWithoutLast().isEmpty()) {
return dc.getLast();
}
return dc.getWithoutLast().toRawString() + ":" + dc.getLast();
}
private String reportTrait(Set<String> externalDefs, List<DottedChain> existingObjects, SWF swf, ABC abc, Trait t) {
//TODO: handle externalDefs - <external-defs> <ext id="..." /> </external-defs>
StringBuilder sb = new StringBuilder();
if (t instanceof TraitClass) {
TraitClass tc = (TraitClass) t;
sb.append(indent(3)).append("<def id=\"").append(multiNameToId(abc, tc.getName(abc))).append("\" />").append(newLineChar);
ClassInfo ci = abc.class_info.get(tc.class_info);
InstanceInfo ii = abc.instance_info.get(tc.class_info);
Set<String> allDeps = new HashSet<>();
String superPre;
if (ii.super_index != 0) {
superPre = multiNameToId(abc, abc.constants.getMultiname(ii.super_index));
} else {
superPre = "Object";
}
allDeps.add(superPre);
sb.append(indent(3)).append("<pre id=\"").append(superPre).append("\" />").append(newLineChar);
for (int iface : ii.interfaces) {
String ifacePre = multiNameToId(abc, abc.constants.getMultiname(iface));
allDeps.add(ifacePre);
sb.append(indent(3)).append("<pre id=\"").append(ifacePre).append("\" />").append(newLineChar);
}
for (Trait ct : ci.static_traits.traits) {
reportTrait(externalDefs, existingObjects, swf, abc, ct);
}
for (Trait it : ii.instance_traits.traits) {
reportTrait(externalDefs, existingObjects, swf, abc, it);
}
List<Dependency> dependencies = new ArrayList<>();
List<String> uses = new ArrayList<>();
sb.append(indent(3)).append("<dep id=\"AS3\" />").append(newLineChar); //Automatic
tc.getDependencies(null, abc, dependencies, uses, new DottedChain("FAKE!PACKAGE"), new ArrayList<>());
for (Dependency dependency : dependencies) {
DottedChain dc = dependency.getId();
if (!"*".equals(dc.getLast())) {
//some toplevel "imports" can be only method calls
if (dc.getWithoutLast().isEmpty() && !existingObjects.contains(dc)) {
continue;
}
String reportDepId = dottedChainToId(dc);
if (!allDeps.contains(reportDepId)) {
sb.append(indent(3)).append("<dep id=\"").append(reportDepId).append("\" />").append(newLineChar);
allDeps.add(reportDepId);
}
}
}
}
return sb.toString();
}
}
@@ -41,6 +41,7 @@ public class ScriptExportSettings {
public String getFileExtension() {
switch (mode) {
case AS:
case AS_METHOD_STUBS:
return ".as";
case PCODE:
case PCODE_HEX:
@@ -0,0 +1,308 @@
package com.jpexs.decompiler.flash.exporters.swf;
import com.jpexs.decompiler.flash.ReadOnlyTagList;
import com.jpexs.decompiler.flash.SWC;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.ClassPath;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.script.Dependency;
import com.jpexs.decompiler.flash.exporters.script.DependencyType;
import com.jpexs.decompiler.flash.importers.SwfXmlImporter;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.tags.DoABC2Tag;
import com.jpexs.decompiler.flash.tags.SymbolClassTag;
import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.helpers.Helper;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class SwfToSwcExporter {
private static final String DEPENDENCY_NAMESPACE = "n";
private static final String DEPENDENCY_INHERITANCE = "i";
private static final String DEPENDENCY_EXPRESSION = "e";
private static final String DEPENDENCY_SIGNATURE = "s";
private static String sha256(InputStream is) {
String output;
int read;
byte[] buffer = new byte[8192];
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
while ((read = is.read(buffer)) > 0) {
digest.update(buffer, 0, read);
}
byte[] hash = digest.digest();
BigInteger bigInt = new BigInteger(1, hash);
output = bigInt.toString(16);
while (output.length() < 32) {
output = "0" + output;
}
} catch (Exception e) {
return null;
}
return output;
}
public SwfToSwcExporter() {
}
private String dottedChainToId(DottedChain dc) {
if (dc.getWithoutLast().isEmpty()) {
return dc.getLast();
}
return dc.getWithoutLast().toRawString() + ":" + dc.getLast();
}
private String generateCatalog(SWF swf, byte[] swfBytes, boolean skipDependencies) {
StringBuilder sb = new StringBuilder();
final String libraryFileName = "library.swf";
final String SWC_VERSION = "1.2";
final String FLEX_VERSION = "4.6.0";
final String FLEX_BUILD = "23201";
final String MINIMUM_SUPPORTED_VERSION = "3.0.0";
sb.append("<?xml version=\"1.0\" encoding =\"utf-8\"?>\n")
.append("<swc xmlns=\"http://www.adobe.com/flash/swccatalog/9\">\n")
.append(" <versions>\n")
.append(" <swc version=\"").append(SWC_VERSION).append("\" />\n")
.append(" <flex version=\"").append(FLEX_VERSION).append("\" build=\"").append(FLEX_BUILD).append("\" minimumSupportedVersion=\"").append(MINIMUM_SUPPORTED_VERSION).append("\" />\n")
.append(" </versions>\n")
.append(" <features>\n")
.append(" <feature-script-deps />\n")
.append(" <feature-files />\n")
.append(" </features>\n")
.append(" <libraries>\n")
.append(" <library path=\"").append(libraryFileName).append("\">\n");
final long TIME_NOW = new Date().getTime();
Set<DottedChain> definedObjects = new HashSet<>();
List<ABCContainerTag> abcTagList = swf.getAbcList();
List<ScriptPack> packs = swf.getAS3Packs();
for (ScriptPack pack : packs) {
ClassPath cp = pack.getClassPath();
definedObjects.add(cp.packageStr.add(cp.className));
}
List<ABC> allAbcList = new ArrayList<>();
for (int i = 0; i < abcTagList.size(); i++) {
allAbcList.add(abcTagList.get(i).getABC());
}
for (ABCContainerTag abcContainer : abcTagList) {
if (!(abcContainer instanceof DoABC2Tag)) {
continue; //DoABCTag 1 does not have name
}
DoABC2Tag abcTag = (DoABC2Tag) abcContainer;
String scriptName = abcTag.name;
sb.append(" <script name=\"").append(scriptName).append("\" mod=\"").append(TIME_NOW).append("\">\n");
List<ScriptPack> tagPacks = abcTag.getABC().getScriptPacks(null, allAbcList);
for (ScriptPack pack : tagPacks) {
ClassPath cp = pack.getClassPath();
String defId = dottedChainToId(cp.packageStr.add(cp.className));
sb.append(" <def id=\"").append(defId).append("\" />\n");
Set<DottedChain> allDeps = new HashSet<>();
allDeps.add(new DottedChain("AS3"));
sb.append(" <dep id=\"AS3\" type=\"").append(DEPENDENCY_NAMESPACE).append("\" />\n");
if (!skipDependencies) {
List<Dependency> dependencies = new ArrayList<>();
List<String> uses = new ArrayList<>();
pack.abc.script_info.get(pack.scriptIndex).traits.getDependencies(null, pack.abc, dependencies, uses, new DottedChain("NO:PACKAGE"), new ArrayList<>());
for (Dependency d : dependencies) {
if ("*".equals(d.getId().getLast())) {
continue;
}
//some toplevel "imports" can be only method calls
if (d.getId().getWithoutLast().isEmpty() && !definedObjects.contains(d.getId())) {
continue;
}
if (allDeps.contains(d.getId())) {
continue;
}
sb.append(" <dep id=\"").append(dottedChainToId(d.getId())).append("\" type=\"").append(getDependencyStr(d.getType())).append("\" />\n");
allDeps.add(d.getId());
}
}
}
sb.append(" </script>\n");
}
String sha256Hash = sha256(new ByteArrayInputStream(swfBytes));
sb.append(" <digests>\n")
.append(" <digest type=\"SHA-256\" signed=\"false\" value=\"").append(sha256Hash).append("\" />\n")
.append(" </digests>\n")
.append(" </library>\n")
.append(" </libraries>\n")
.append(" <files>\n")
.append(" </files>\n")
.append("</swc>\n");
return sb.toString();
}
private static String getDependencyStr(DependencyType depType) {
switch (depType) {
case EXPRESSION:
return DEPENDENCY_EXPRESSION;
case INHERITANCE:
return DEPENDENCY_INHERITANCE;
case SIGNATURE:
return DEPENDENCY_SIGNATURE;
case NAMESPACE:
return DEPENDENCY_NAMESPACE;
default:
return null;
}
}
private SWF recompileSWF(SWF swf) throws IOException, InterruptedException {
ByteArrayOutputStream swfOrigBaos = new ByteArrayOutputStream();
swf.saveTo(swfOrigBaos);
return new SWF(new ByteArrayInputStream(swfOrigBaos.toByteArray()), Configuration.parallelSpeedUp.get(), false);
}
private static void printDelay(String title, long t1, long t2) {
//System.out.println("time " + title + ": " + (t2 - t1));
}
public void exportSwf(SWF swf, File outSwcFile, boolean skipDependencies) throws IOException {
long t4 = 0;
//Make local copy of SWF so we do not modify original
try {
long t1 = System.currentTimeMillis();
swf = recompileSWF(swf);
long t2 = System.currentTimeMillis();
printDelay("swc.recompile", t1, t2);
final String HASH = "myhash";
String abcTagXml = new String(Helper.readStream(SwfToSwcExporter.class.getResourceAsStream("/com/jpexs/decompiler/flash/exporters/swf/swc_main_abctag.xml")), "UTF-8");
abcTagXml = abcTagXml.replace("%hash%", HASH);
SwfXmlImporter xmlImporter = new SwfXmlImporter();
DoABC2Tag mainAbcTag = (DoABC2Tag) xmlImporter.importObject(abcTagXml, DoABC2Tag.class, swf);
ReadOnlyTagList list = swf.getTags();
final String documentClassStub = "_%hash%_flash_display_Sprite";
String documentClass = documentClassStub.replace("%hash%", HASH);
boolean documentClassSet = false;
for (int i = 0; i < list.size(); i++) {
if (list.get(i) instanceof ABCContainerTag) {
swf.addTag(i, mainAbcTag);
break;
}
}
for (int i = 0; i < list.size(); i++) {
if (list.get(i) instanceof SymbolClassTag) {
SymbolClassTag sct = (SymbolClassTag) list.get(i);
for (int j = 0; j < sct.tags.size(); j++) {
if (sct.tags.get(j) == 0) {
sct.names.set(j, documentClass);
documentClassSet = true;
break;
}
}
}
}
long t3 = System.currentTimeMillis();
printDelay("swc.documentTag", t2, t3);
if (!documentClassSet) {
throw new IOException("Original document class not found!");
}
swf = recompileSWF(swf);
t4 = System.currentTimeMillis();
printDelay("swc.recompile2", t3, t4);
} catch (Exception ex) {
ex.printStackTrace();
System.exit(0);
throw new RuntimeException(ex);
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
swf.saveTo(baos);
byte[] swfBytes = baos.toByteArray();
long t5 = System.currentTimeMillis();
printDelay("swc.getBytes", t4, t5);
String catalogStr = generateCatalog(swf, swfBytes, skipDependencies);
long t6 = System.currentTimeMillis();
printDelay("swc.generateCatalog", t5, t6);
File tempFile = new File((outSwcFile.getAbsolutePath()) + ".tmp");
FileOutputStream fos = null;
ZipOutputStream zos = null;
try {
fos = new FileOutputStream(tempFile);
zos = new ZipOutputStream(fos);
ZipEntry libraryEntry = new ZipEntry("library.swf");
zos.putNextEntry(libraryEntry);
zos.write(swfBytes);
zos.closeEntry();
ZipEntry catalogEntry = new ZipEntry("catalog.xml");
zos.putNextEntry(catalogEntry);
zos.write(catalogStr.getBytes("UTF-8"));
zos.closeEntry();
zos.close();
zos = null;
fos.close();
fos = null;
outSwcFile.delete();
tempFile.renameTo(outSwcFile);
} finally {
if (zos != null) {
try {
zos.close();
} catch (IOException ex) {
//ignore
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException ex) {
//ignore
}
}
if (tempFile.exists()) {
tempFile.delete();
}
}
long t7 = System.currentTimeMillis();
printDelay("swc.zip", t6, t7);
}
}
@@ -0,0 +1,216 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Stub for generating Main tag of SWC file -->
<item flags="1" name="_%hash%_flash_display_Sprite" type="DoABC2Tag">
<abc type="ABC">
<version major="46" minor="16" type="ABCVersion"/>
<constants type="AVM2ConstantPool">
<constant_int/>
<constant_uint/>
<constant_double/>
<constant_decimal/>
<constant_float/>
<constant_float4/>
<constant_string>
<item isNull="true"/>
<item>_%hash%_flash_display_Sprite</item>
<item/>
<item>_%hash%_flash_display_Sprite/_%hash%_flash_display_Sprite</item>
<item>Security</item>
<item>flash.system</item>
<item>allowDomain</item>
<item>apply</item>
<item>http://adobe.com/AS3/2006/builtin</item>
<item>_%hash%_flash_display_Sprite/allowDomainInRSL</item>
<item>void</item>
<item>domains</item>
<item>allowInsecureDomain</item>
<item>_%hash%_flash_display_Sprite/allowInsecureDomainInRSL</item>
<item>allowDomainInRSL</item>
<item>__go_to_definition_help</item>
<item>pos</item>
<item>602</item>
<item>allowInsecureDomainInRSL</item>
<item>922</item>
<item>flash.display</item>
<item>Sprite</item>
<item>Object</item>
<item>EventDispatcher</item>
<item>flash.events</item>
<item>DisplayObject</item>
<item>InteractiveObject</item>
<item>DisplayObjectContainer</item>
<item>ExcludeClass</item>
<item>__go_to_ctor_definition_help</item>
<item>275</item>
<item>130</item>
</constant_string>
<constant_namespace>
<item isNull="true"/>
<item kind="5" name_index="1" type="Namespace"/>
<item kind="22" name_index="5" type="Namespace"/>
<item kind="22" name_index="2" type="Namespace"/>
<item kind="8" name_index="8" type="Namespace"/>
<item kind="22" name_index="20" type="Namespace"/>
<item kind="24" name_index="1" type="Namespace"/>
<item kind="22" name_index="24" type="Namespace"/>
<item kind="22" name_index="2" type="Namespace"/>
</constant_namespace>
<constant_namespace_set/>
<constant_multiname>
<item isNull="true"/>
<item kind="7" name_index="4" namespace_index="2" namespace_set_index="0" qname_index="0" type="Multiname"/>
<item kind="7" name_index="6" namespace_index="3" namespace_set_index="0" qname_index="0" type="Multiname"/>
<item kind="7" name_index="7" namespace_index="4" namespace_set_index="0" qname_index="0" type="Multiname"/>
<item kind="7" name_index="10" namespace_index="3" namespace_set_index="0" qname_index="0" type="Multiname"/>
<item kind="7" name_index="12" namespace_index="3" namespace_set_index="0" qname_index="0" type="Multiname"/>
<item kind="7" name_index="14" namespace_index="3" namespace_set_index="0" qname_index="0" type="Multiname"/>
<item kind="7" name_index="18" namespace_index="3" namespace_set_index="0" qname_index="0" type="Multiname"/>
<item kind="7" name_index="1" namespace_index="3" namespace_set_index="0" qname_index="0" type="Multiname"/>
<item kind="7" name_index="21" namespace_index="5" namespace_set_index="0" qname_index="0" type="Multiname"/>
<item kind="7" name_index="22" namespace_index="3" namespace_set_index="0" qname_index="0" type="Multiname"/>
<item kind="7" name_index="23" namespace_index="7" namespace_set_index="0" qname_index="0" type="Multiname"/>
<item kind="7" name_index="25" namespace_index="5" namespace_set_index="0" qname_index="0" type="Multiname"/>
<item kind="7" name_index="26" namespace_index="5" namespace_set_index="0" qname_index="0" type="Multiname"/>
<item kind="7" name_index="27" namespace_index="5" namespace_set_index="0" qname_index="0" type="Multiname"/>
</constant_multiname>
</constants>
<method_info>
<item flags="0" name_index="2" ret_type="0" type="MethodInfo">
<param_types/>
<optional/>
<paramNames/>
</item>
<item flags="0" name_index="3" ret_type="0" type="MethodInfo">
<param_types/>
<optional/>
<paramNames/>
</item>
<item flags="132" name_index="9" ret_type="4" type="MethodInfo">
<param_types/>
<optional/>
<paramNames/>
</item>
<item flags="132" name_index="13" ret_type="4" type="MethodInfo">
<param_types/>
<optional/>
<paramNames/>
</item>
<item flags="0" name_index="2" ret_type="0" type="MethodInfo">
<param_types/>
<optional/>
<paramNames/>
</item>
</method_info>
<metadata_info>
<item name_index="15" type="MetadataInfo">
<keys>
<item>16</item>
</keys>
<values>
<item>17</item>
</values>
</item>
<item name_index="15" type="MetadataInfo">
<keys>
<item>16</item>
</keys>
<values>
<item>19</item>
</values>
</item>
<item name_index="28" type="MetadataInfo">
<keys/>
<values/>
</item>
<item name_index="29" type="MetadataInfo">
<keys>
<item>16</item>
</keys>
<values>
<item>30</item>
</values>
</item>
<item name_index="15" type="MetadataInfo">
<keys>
<item>16</item>
</keys>
<values>
<item>31</item>
</values>
</item>
</metadata_info>
<instance_info>
<item flags="9" iinit_index="1" name_index="8" protectedNS="6" super_index="9" type="InstanceInfo">
<interfaces/>
<instance_traits type="Traits">
<traits>
<item bytes="064100020100" disp_id="0" fileOffset="1994" kindFlags="4" kindType="1" method_info="2" name_index="6" type="TraitMethodGetterSetter">
<metadata>
<item>0</item>
</metadata>
</item>
<item bytes="074100030101" disp_id="0" fileOffset="2000" kindFlags="4" kindType="1" method_info="3" name_index="7" type="TraitMethodGetterSetter">
<metadata>
<item>1</item>
</metadata>
</item>
</traits>
</instance_traits>
</item>
</instance_info>
<class_info>
<item cinit_index="0" type="ClassInfo">
<static_traits type="Traits">
<traits/>
</static_traits>
</item>
</class_info>
<script_info>
<item init_index="4" type="ScriptInfo">
<traits type="Traits">
<traits>
<item bytes="0844010003020304" class_info="0" fileOffset="2011" kindFlags="4" kindType="4" name_index="8" slot_id="1" type="TraitClass">
<metadata>
<item>2</item>
<item>3</item>
<item>4</item>
</metadata>
</item>
</traits>
</traits>
</item>
</script_info>
<bodies>
<item codeBytes="d03047" init_scope_depth="8" max_regs="1" max_scope_depth="9" max_stack="1" method_info="0" type="MethodBody">
<exceptions/>
<traits type="Traits">
<traits/>
</traits>
</item>
<item codeBytes="d030d0490047" init_scope_depth="9" max_regs="1" max_scope_depth="10" max_stack="1" method_info="1" type="MethodBody">
<exceptions/>
<traits type="Traits">
<traits/>
</traits>
</item>
<item codeBytes="d0305d016601660220d14603022947" init_scope_depth="9" max_regs="2" max_scope_depth="10" max_stack="3" method_info="2" type="MethodBody">
<exceptions/>
<traits type="Traits">
<traits/>
</traits>
</item>
<item codeBytes="d0305d016601660520d14603022947" init_scope_depth="9" max_regs="2" max_scope_depth="10" max_stack="3" method_info="3" type="MethodBody">
<exceptions/>
<traits type="Traits">
<traits/>
</traits>
</item>
<item codeBytes="d03065005d0a660a305d0b660b305d0c660c305d0d660d305d0e660e305d096609305d09660958001d1d1d1d1d1d680847" init_scope_depth="1" max_regs="1" max_scope_depth="8" max_stack="2" method_info="4" type="MethodBody">
<exceptions/>
<traits type="Traits">
<traits/>
</traits>
</item>
</bodies>
</abc>
</item>
@@ -0,0 +1,311 @@
package com.jpexs.decompiler.flash.flexsdk;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException;
import com.jpexs.decompiler.flash.abc.types.InstanceInfo;
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.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.exporters.script.AS3ScriptExporter;
import com.jpexs.decompiler.flash.exporters.script.LinkReportExporter;
import com.jpexs.decompiler.flash.exporters.settings.ScriptExportSettings;
import com.jpexs.decompiler.flash.exporters.swf.SwfToSwcExporter;
import com.jpexs.decompiler.flash.importers.As3ScriptReplaceException;
import com.jpexs.decompiler.flash.importers.As3ScriptReplaceExceptionItem;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.graph.CompilationException;
import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.helpers.Helper;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.jpexs.decompiler.flash.importers.As3ScriptReplacerInterface;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MxmlcAs3ScriptReplacer extends MxmlcRunner implements As3ScriptReplacerInterface {
private ScriptPack initedPack;
private File tempDir;
private File pkgDir;
private File swcFile;
public MxmlcAs3ScriptReplacer(String flexSdkPath) {
super(flexSdkPath);
}
private synchronized boolean isInited(ScriptPack pack) {
return tempDir != null && initedPack == pack;
}
private static void deleteFolder(File folder) {
File[] files = folder.listFiles();
if (files != null) { //some JVMs return null for empty dirs
for (File f : files) {
if (f.isDirectory()) {
deleteFolder(f);
} else {
f.delete();
}
}
}
folder.delete();
}
private SWF recompileSWF(SWF swf) throws IOException, InterruptedException {
ByteArrayOutputStream swfOrigBaos = new ByteArrayOutputStream();
swf.saveTo(swfOrigBaos);
return new SWF(new ByteArrayInputStream(swfOrigBaos.toByteArray()), Configuration.parallelSpeedUp.get(), false);
}
private boolean isParentDeleted(ABC abc, List<ABC> allAbcs, DottedChain className) {
int class_index = abc.findClassByName(className);
if (class_index == -1) {
for (ABC a : allAbcs) {
class_index = abc.findClassByName(className);
if (class_index != -1) {
abc = a;
break;
}
}
if (class_index == -1) {
return false;
}
}
InstanceInfo ii = abc.instance_info.get(class_index);
if (ii.deleted) {
return true;
}
if (ii.super_index != 0 && isParentDeleted(abc, allAbcs, abc.constants.getMultiname(ii.super_index).getNameWithNamespace(abc.constants))) {
return true;
}
for (int iface : ii.interfaces) {
if (isParentDeleted(abc, allAbcs, abc.constants.getMultiname(iface).getNameWithNamespace(abc.constants))) {
return true;
}
}
return false;
}
@Override
public synchronized void replaceScript(ScriptPack pack, String text) throws As3ScriptReplaceException, IOException, InterruptedException {
if (!pack.isSimple) {
throw new IOException("Cannot compile such file"); //Alchemy, etc. TODO: handle better
}
if (!isInited(pack)) {
initReplacement(pack);
}
File scriptFileToCompile = new File(pkgDir, pack.getClassPath().className + ".as");
//Write new script
Helper.writeFile(scriptFileToCompile.getAbsolutePath(), text.getBytes("UTF-8"));
File compiledSwfFile = new File(pkgDir, "out.swf");
try {
//Compile it (and subclasses stubs)
mxmlc("-strict=false", "-include-inheritance-dependencies-only", "-warnings=false", "-library-path", swcFile.getAbsolutePath(), "-source-path", tempDir.getAbsolutePath(), "-output", compiledSwfFile.getAbsolutePath(), "-debug=true", scriptFileToCompile.getAbsolutePath());
} catch (MxmlcException ex1) {
//String compiledFilePath = scriptFileToCompile.getAbsolutePath();
Pattern errPattern = Pattern.compile("^" + Pattern.quote(tempDir.getAbsolutePath()) + "(?<file>.*)\\((?<line>[0-9]+)\\): col: (?<col>[0-9]+) (?<message>.*)$");
String err = ex1.getMxmlcErrorOutput();
String errLines[] = err.split("\r?\n");
List<As3ScriptReplaceExceptionItem> errorItems = new ArrayList<>();
for (int i = 0; i < errLines.length; i++) {
String line = errLines[i].trim();
Matcher m = errPattern.matcher(line);
if (m.matches()) {
String errFile = m.group("file");
int errLine = Integer.parseInt(m.group("line"));
int errCol = Integer.parseInt(m.group("col"));
String errMsg = m.group("message");
errorItems.add(new As3ScriptReplaceExceptionItem(errFile, errMsg, errLine, errCol));
}
}
throw new As3ScriptReplaceException(errorItems);
}
try (FileInputStream fis = new FileInputStream(compiledSwfFile)) {
SWF newSWF = new SWF(fis, false, false);
List<ABCContainerTag> newTags = newSWF.getAbcList();
int oldScriptIndex = pack.scriptIndex;
int oldClassIndex = -1;
ScriptInfo oldScriptInfo = pack.abc.script_info.get(pack.scriptIndex);
for (Trait t : oldScriptInfo.traits.traits) {
if (t instanceof TraitClass) {
int traitClassIndex = ((TraitClass) t).class_info;
if (oldClassIndex == -1 || traitClassIndex < oldClassIndex) {
oldClassIndex = traitClassIndex;
}
}
}
if (pack.isSimple) {
oldScriptInfo.delete(pack.abc, true);
} else {
//NOO
}
pack.abc.pack(); // removes old classes/methods/scripts
ABCContainerTag newTagsLast = newTags.get(newTags.size() - 1);
ABC newLastAbc = newTagsLast.getABC();
Map<Integer, Integer> classesMap = new HashMap<>();
Map<Integer, Integer> scriptsMap = new HashMap<>();
pack.abc.mergeABC(newLastAbc,
new HashMap<>(),
new HashMap<>(),
new HashMap<>(),
new HashMap<>(),
new HashMap<>(),
new HashMap<>(),
new HashMap<>(),
new HashMap<>(),
new HashMap<>(),
new HashMap<>(),
new HashMap<>(),
new HashMap<>(),
classesMap,
new HashMap<>(),
scriptsMap
);
//Reorder newly created scripts to be in place
//where old script was
List<Integer> addedScriptIndices = new ArrayList<>(scriptsMap.values());
Collections.sort(addedScriptIndices);
List<ScriptInfo> addedScripts = new ArrayList<>();
for (int i = addedScriptIndices.size() - 1; i >= 0; i--) {
int newScriptIndex = addedScriptIndices.get(i);
addedScripts.add(0, pack.abc.script_info.remove(newScriptIndex));
}
for (int i = 0; i < addedScripts.size(); i++) {
pack.abc.script_info.add(oldScriptIndex + i, addedScripts.get(i));
}
//IMPORTANT: Map newly created classes to their position as they
//were in original script because FlashPlayer needs
//parent class to be defined earlier
if (oldClassIndex > -1) {
List<Integer> addedClassIndices = new ArrayList<>(classesMap.values());
Collections.sort(addedClassIndices);
int totalClassCount = pack.abc.class_info.size();
Map<Integer, Integer> classesRemap = new HashMap<>();
for (int i = 0; i < addedClassIndices.size(); i++) {
classesRemap.put(addedClassIndices.get(i), oldClassIndex + i);
}
int mappingStart = oldClassIndex;
for (int i = oldClassIndex; i < totalClassCount; i++) {
if (!classesRemap.containsKey(i)) {
for (int j = mappingStart; j < totalClassCount; j++) {
if (!classesRemap.containsValue(j)) {
classesRemap.put(i, j);
mappingStart = j + 1;
break;
}
}
}
}
pack.abc.reorganizeClasses(classesRemap);
}
((Tag) pack.abc.parentTag).setModified(true);
deinitReplacement(pack);//successfull finish
}
}
@Override
public boolean isAvailable() {
String flexLocation = Configuration.flexSdkLocation.get();
return !(flexLocation.isEmpty() || (!new File(MxmlcRunner.getMxmlcPath(flexLocation)).exists()));
}
@Override
public synchronized void initReplacement(ScriptPack pack) {
if (tempDir != null) {
deinitReplacement(pack);
}
try {
tempDir = Files.createTempDirectory("ffdec-mxmlc-replace").toFile();
pkgDir = tempDir;
for (String pkgPart : pack.getClassPath().packageStr.toList()) {
if (!pkgPart.isEmpty()) {
pkgDir = new File(pkgDir, pkgPart);
}
}
pkgDir.mkdirs();
swcFile = new File(pkgDir, "out.swc");
//Make copy without the old script
SWF swfCopy = recompileSWF(pack.getSwf());
List<ABC> modAbcs = new ArrayList<>();
List<ScriptPack> copyPacks = swfCopy.getAS3Packs();
for (ScriptPack sp : copyPacks) {
if (sp.getClassPath().equals(pack.getClassPath())) {
sp.abc.script_info.get(sp.scriptIndex).delete(sp.abc, true);
((Tag) sp.abc.parentTag).setModified(true);
modAbcs.add(sp.abc);
break;
}
}
List<ScriptPack> removedPacks = new ArrayList<>();
//remove all subclasses from the SWC
for (ScriptPack sp : copyPacks) {
DottedChain dc = sp.getPathPackage().add(sp.getPathScriptName());
if (isParentDeleted(sp.abc, sp.allABCs, dc)) {
sp.abc.script_info.get(sp.scriptIndex).delete(sp.abc, true);
modAbcs.add(sp.abc);
removedPacks.add(sp);
}
}
//Export subclasses so they can be compiled by Flex, but ONLY STUBS.
//No method code to avoid code compilation problems.
//This compiled code won't be used at all in original SWF,
//it is used only by Flex to properly compile current script
AS3ScriptExporter ex = new AS3ScriptExporter();
ex.exportActionScript3(swfCopy, null, tempDir.getAbsolutePath(), removedPacks, new ScriptExportSettings(ScriptExportMode.AS_METHOD_STUBS, false), false, null);
//now really remove the classes from SWF copy
for (ABC a : modAbcs) {
a.pack();
}
//Generate SWC file from the modified SWF file.
//Flex then uses the code already present in the SWC, no need to decompile it (hurray!)
SwfToSwcExporter swcExport = new SwfToSwcExporter();
swcExport.exportSwf(swfCopy, swcFile, true);
} catch (IOException iex) {
//ignore
} catch (InterruptedException ex) {
//ignore
}
this.initedPack = pack;
}
@Override
public synchronized void deinitReplacement(ScriptPack pack) {
if (tempDir != null && tempDir.exists()) {
deleteFolder(tempDir);
}
tempDir = null;
}
}
@@ -0,0 +1,15 @@
package com.jpexs.decompiler.flash.flexsdk;
public class MxmlcException extends Exception {
private String mxmlcErrorOutput;
public MxmlcException(String mxmlcErrorOutput) {
this.mxmlcErrorOutput = mxmlcErrorOutput;
}
public String getMxmlcErrorOutput() {
return mxmlcErrorOutput;
}
}
@@ -0,0 +1,54 @@
package com.jpexs.decompiler.flash.flexsdk;
import com.jpexs.helpers.Helper;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.logging.Level;
import java.util.logging.Logger;
public class MxmlcRunner {
private String flexSdkPath;
public MxmlcRunner(String flexSdkPath) {
this.flexSdkPath = flexSdkPath;
}
public static String getMxmlcPath(String flexSdkPath) {
boolean isWin = System.getProperty("os.name").toLowerCase().contains("win");
return flexSdkPath + File.separator + "bin" + File.separator + "mxmlc" + (isWin ? ".exe" : "");
}
public void mxmlc(String... arguments) throws MxmlcException, InterruptedException, IOException {
String runArgs[] = new String[arguments.length + 1];
runArgs[0] = getMxmlcPath(flexSdkPath);
System.arraycopy(arguments, 0, runArgs, 1, arguments.length);
//System.out.println("" + String.join(" ", runArgs));
Process proc = null;
try {
proc = Runtime.getRuntime().exec(runArgs);
Helper.readStream(proc.getInputStream());
String errstring = "";
try {
errstring = new String(Helper.readStream(proc.getErrorStream()), "UTF-8");
} catch (UnsupportedEncodingException ex) {
//should not happen
}
proc.waitFor();
int exitValue = proc.exitValue();
if (exitValue > 0) {
throw new MxmlcException(errstring);
}
} finally {
if (proc != null) {
try {
proc.destroy();
} catch (Exception ex2) {
//ignore
}
}
}
}
}
@@ -92,6 +92,7 @@ public class BMPFile extends Component {
b.save(image, image.getWidth(null), image.getHeight(null));
}
}
/*
* The saveMethod is the main method of the process. This method
* will call the convertImage method to convert the memory image to
@@ -100,7 +101,6 @@ public class BMPFile extends Component {
* information header; and writeBitmap writes the image.
*
*/
private void save(Image parImage, int parWidth, int parHeight) throws IOException {
convertImage(parImage, parWidth, parHeight);
writeBitmapFileHeader();
@@ -108,12 +108,12 @@ public class BMPFile extends Component {
writeBitmap();
}
/*
* convertImage converts the memory image to the bitmap format (BRG).
* It also computes some information for the bitmap info header.
*
*/
private boolean convertImage(Image parImage, int parWidth, int parHeight) {
int pad;
bitmap = new int[parWidth * parHeight];
@@ -133,6 +133,7 @@ public class BMPFile extends Component {
biHeight = parHeight;
return (true);
}
/*
* writeBitmap converts the image returned from the pixel grabber to
* the format required. Remember: scan lines are inverted in
@@ -140,7 +141,6 @@ public class BMPFile extends Component {
*
* Each scan line must be padded to an even 4-byte boundary.
*/
private void writeBitmap() throws IOException {
byte[] rgb = new byte[3];
int width = biWidth;
@@ -165,11 +165,11 @@ public class BMPFile extends Component {
bfSize += padCount;
biSizeImage += padCount;
}
/*
* writeBitmapFileHeader writes the bitmap file header to the file.
*
*/
private void writeBitmapFileHeader() throws IOException {
fo.write(bfType);
@@ -178,13 +178,13 @@ public class BMPFile extends Component {
fo.write(intToWord(bfReserved2));
fo.write(intToDWord(bfOffBits));
}
/*
*
* writeBitmapInfoHeader writes the bitmap information header
* to the file.
*
*/
private void writeBitmapInfoHeader() throws IOException {
fo.write(intToDWord(biSize));
@@ -200,26 +200,26 @@ public class BMPFile extends Component {
fo.write(intToDWord(biClrImportant));
}
/*
*
* intToWord converts an int to a word, where the return
* value is stored in a 2-byte array.
*
*/
private byte[] intToWord(int parValue) {
byte[] retValue = new byte[2];
retValue[0] = (byte) (parValue & 0x00FF);
retValue[1] = (byte) ((parValue >> 8) & 0x00FF);
return (retValue);
}
/*
*
* intToDWord converts an int to a double word, where the return
* value is stored in a 4-byte array.
*
*/
private byte[] intToDWord(int parValue) {
byte[] retValue = new byte[4];
retValue[0] = (byte) (parValue & 0x00FF);
@@ -243,10 +243,8 @@ public abstract class GraphTextWriter {
if (formatting.spaceBeforeParenthesesMethodCallParentheses) {
space();
}
} else {
if (formatting.spaceBeforeParenthesesMethodCallEmptyParentheses) {
space();
}
} else if (formatting.spaceBeforeParenthesesMethodCallEmptyParentheses) {
space();
}
return this;
}
@@ -103,19 +103,17 @@ public class ImageHelper {
String formatName = getImageFormatString(format).toUpperCase(Locale.ENGLISH);
if (format == ImageFormat.JPEG) {
image = fixImageIOJpegBug(image);
} else {
if (image.getType() == BufferedImage.TYPE_INT_ARGB_PRE) {
BufferedImage image2 = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
divideAlpha(pixels);
} else if (image.getType() == BufferedImage.TYPE_INT_ARGB_PRE) {
BufferedImage image2 = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
divideAlpha(pixels);
int[] pixels2 = ((DataBufferInt) image2.getRaster().getDataBuffer()).getData();
for (int i = 0; i < pixels.length; i++) {
pixels2[i] = pixels[i];
}
image = image2;
int[] pixels2 = ((DataBufferInt) image2.getRaster().getDataBuffer()).getData();
for (int i = 0; i < pixels.length; i++) {
pixels2[i] = pixels[i];
}
image = image2;
}
try {
@@ -36,7 +36,7 @@ public class AS3ScriptImporter {
private static final Logger logger = Logger.getLogger(AS3ScriptImporter.class.getName());
public int importScripts(String scriptsFolder, List<ScriptPack> packs) {
public int importScripts(As3ScriptReplacerInterface scriptReplacer, String scriptsFolder, List<ScriptPack> packs) {
if (!scriptsFolder.endsWith(File.separator)) {
scriptsFolder += File.separator;
}
@@ -50,11 +50,11 @@ public class AS3ScriptImporter {
String txt = Helper.readTextFile(fileName);
try {
pack.abc.replaceScriptPack(pack, txt);
} catch (AVM2ParseException ex) {
logger.log(Level.SEVERE, "%error% on line %line%, file: %file%".replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)).replace("%file%", fileName));
} catch (CompilationException ex) {
logger.log(Level.SEVERE, "%error% on line %line%, file: %file%".replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)).replace("%file%", fileName));
pack.abc.replaceScriptPack(scriptReplacer, pack, txt);
} catch (As3ScriptReplaceException asre) {
for (As3ScriptReplaceExceptionItem item : asre.getExceptionItems()) {
logger.log(Level.SEVERE, "%error% on line %line%, column %col%, file: %file%".replace("%error%", item.getMessage()).replace("%line%", Long.toString(item.getLine())).replace("%file%", fileName).replace("%col%", "" + item.getCol()));
}
} catch (InterruptedException ex) {
logger.log(Level.SEVERE, "error during script import, file: %file%".replace("%file%", fileName), ex);
}
@@ -0,0 +1,27 @@
package com.jpexs.decompiler.flash.importers;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author JPEXS
*/
public class As3ScriptReplaceException extends Exception {
private List<As3ScriptReplaceExceptionItem> exceptionItems;
public As3ScriptReplaceException(List<As3ScriptReplaceExceptionItem> exceptionItems) {
this.exceptionItems = exceptionItems;
}
public As3ScriptReplaceException(As3ScriptReplaceExceptionItem exceptionItem) {
this.exceptionItems = new ArrayList<>();
this.exceptionItems.add(exceptionItem);
}
public List<As3ScriptReplaceExceptionItem> getExceptionItems() {
return exceptionItems;
}
}
@@ -0,0 +1,44 @@
package com.jpexs.decompiler.flash.importers;
public class As3ScriptReplaceExceptionItem {
private String file;
private int line;
private int col;
private String message;
public static final int COL_UNKNOWN = -1;
public static final int LINE_UNKNOWN = -1;
public As3ScriptReplaceExceptionItem(String file, String message, int line) {
this(file, message, line, COL_UNKNOWN);
}
public As3ScriptReplaceExceptionItem(String file, String message) {
this(file, message, LINE_UNKNOWN, COL_UNKNOWN);
}
public As3ScriptReplaceExceptionItem(String file, String message, int line, int col) {
this.file = file;
this.line = line;
this.col = col;
this.message = message;
}
public String getFile() {
return file;
}
public int getLine() {
return line;
}
public String getMessage() {
return message;
}
public int getCol() {
return col;
}
}
@@ -0,0 +1,23 @@
package com.jpexs.decompiler.flash.importers;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.flexsdk.MxmlcAs3ScriptReplacer;
public class As3ScriptReplacerFactory {
public static As3ScriptReplacerInterface createByConfig() {
if (Configuration.useFlexAs3Compiler.get()) {
return createFlex();
} else {
return createFFDec();
}
}
public static As3ScriptReplacerInterface createFlex() {
return new MxmlcAs3ScriptReplacer(Configuration.flexSdkLocation.get());
}
public static As3ScriptReplacerInterface createFFDec() {
return new FFDecAs3ScriptReplacer();
}
}
@@ -0,0 +1,15 @@
package com.jpexs.decompiler.flash.importers;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import java.io.IOException;
public interface As3ScriptReplacerInterface {
public boolean isAvailable();
public void initReplacement(ScriptPack pack);
public void replaceScript(ScriptPack pack, String text) throws As3ScriptReplaceException, IOException, InterruptedException;
public void deinitReplacement(ScriptPack pack);
}
@@ -0,0 +1,89 @@
package com.jpexs.decompiler.flash.importers;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.ActionScript3Parser;
import com.jpexs.decompiler.flash.abc.types.ScriptInfo;
import com.jpexs.decompiler.flash.abc.types.traits.TraitClass;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.graph.CompilationException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;
public class FFDecAs3ScriptReplacer implements As3ScriptReplacerInterface {
@Override
public void replaceScript(ScriptPack pack, String text) throws As3ScriptReplaceException, IOException, InterruptedException {
ABC abc = pack.abc;
SWF swf = pack.abc.getSwf();
String scriptName = pack.getPathScriptName() + ".as";
int oldIndex = pack.scriptIndex;
int newIndex = abc.script_info.size();
try {
String documentClass = swf.getDocumentClass();
boolean isDocumentClass = documentClass != null && documentClass.equals(pack.getClassPath().toString());
ScriptInfo si = abc.script_info.get(oldIndex);
if (pack.isSimple) {
si.delete(abc, true);
} else {
for (int t : pack.traitIndices) {
si.traits.traits.get(t).delete(abc, true);
}
}
int newClassIndex = abc.instance_info.size();
for (int t : pack.traitIndices) {
if (si.traits.traits.get(t) instanceof TraitClass) {
TraitClass tc = (TraitClass) si.traits.traits.get(t);
newClassIndex = tc.class_info + 1;
}
}
List<ABC> otherAbcs = new ArrayList<>(pack.allABCs);
otherAbcs.remove(abc);
abc.script_info.get(oldIndex).delete(abc, true);
ActionScript3Parser.compile(text, abc, otherAbcs, isDocumentClass, scriptName, newClassIndex, oldIndex);
if (pack.isSimple) {
// Move newly added script to its position
abc.script_info.set(oldIndex, abc.script_info.get(newIndex));
abc.script_info.remove(newIndex);
} else {
//???
}
abc.script_info.get(oldIndex).setModified(true);
abc.pack();//remove old deleted items
((Tag) abc.parentTag).setModified(true);
} catch (AVM2ParseException ex) {
abc.script_info.get(oldIndex).delete(abc, false);
throw new As3ScriptReplaceException(new As3ScriptReplaceExceptionItem(null, ex.text, (int) ex.line));
} catch (CompilationException ex) {
abc.script_info.get(oldIndex).delete(abc, false);
}
}
@Override
public boolean isAvailable() {
File swc = Configuration.getPlayerSWC();
return !(swc == null || !swc.exists());
}
@Override
public void initReplacement(ScriptPack pack) {
//empty
}
@Override
public void deinitReplacement(ScriptPack pack) {
//empty
}
}
@@ -151,6 +151,18 @@ public class SwfXmlImporter {
}
}
public Object importObject(String xml, Class requiredType, SWF swf) throws IOException {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(new InputSource(new StringReader(xml)));
return processObject(doc.getDocumentElement(), requiredType, swf, null);
} catch (ParserConfigurationException | SAXException | IllegalArgumentException | IllegalAccessException | NoSuchMethodException | InstantiationException | InvocationTargetException ex) {
Logger.getLogger(SwfXmlImporter.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
private Field getField(Class cls, String name) throws NoSuchFieldException {
Field field;
try {
@@ -243,7 +255,7 @@ public class SwfXmlImporter {
setFieldValue(field, obj, childObj);
}
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException | NoSuchMethodException | InstantiationException | InvocationTargetException ex) {
logger.log(Level.SEVERE, null, ex);
logger.log(Level.SEVERE, "Error while getting val from class " + cls + " field: " + name, ex);
}
}
}
@@ -60,10 +60,8 @@ public class TextImporter {
int id = Integer.parseInt(idLine.substring(3).trim());
String[] records = textArr[1].split(recordSeparator);
result.put(id, records);
} else {
if (errorHandler.handle(null)) {
return null;
}
} else if (errorHandler.handle(null)) {
return null;
}
}
return result;
@@ -142,11 +140,9 @@ public class TextImporter {
return false;
}
}
} else {
if (textTag != null) {
if (!saveText(textTag, newText, null)) {
return false;
}
} else if (textTag != null) {
if (!saveText(textTag, newText, null)) {
return false;
}
}
File diff suppressed because it is too large Load Diff
@@ -500,7 +500,7 @@ public class DefineFont2Tag extends FontTag {
pos = i;
break;
}
return false;
}
}
@@ -524,7 +524,7 @@ public class DefineFont2Tag extends FontTag {
getSwf().clearImageCache();
return true;
}
@Override
public void setAdvanceValues(Font font) {
boolean hasLayout = fontFlagsHasLayout;
@@ -485,7 +485,7 @@ public class DefineFont3Tag extends FontTag {
@Override
public boolean removeCharacter(char character) {
//Font Align Zones will be removed as removing character zones is not supported:-(
for (int i = 0; i < swf.getTags().size(); i++) {
Tag t = swf.getTags().get(i);
@@ -523,13 +523,13 @@ public class DefineFont3Tag extends FontTag {
}
shiftGlyphIndices(fontID, pos + 1, false);
checkWideParameters();
setModified(true);
getSwf().clearImageCache();
return true;
}
@Override
public void setAdvanceValues(Font font) {
boolean hasLayout = fontFlagsHasLayout;
@@ -312,7 +312,7 @@ public class DefineFontTag extends FontTag {
if (fontInfoTag == null) {
return false;
}
int code = (int) character;
int pos = -1;
List<Integer> codeTable = fontInfoTag.getCodeTable();
@@ -335,12 +335,12 @@ public class DefineFontTag extends FontTag {
fontInfoTag.removeFontCharacter(pos);
shiftGlyphIndices(fontId, pos + 1, false);
setModified(true);
getSwf().clearImageCache();
return true;
}
@Override
public void setAdvanceValues(Font font) {
throw new UnsupportedOperationException("Setting the advance values for DefineFontTag is not supported.");
@@ -1,6 +1,6 @@
/* The following code was generated by JFlex 1.6.0 */
/*
/*
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
@@ -20,8 +20,7 @@ package com.jpexs.decompiler.flash.tags.text;
/**
* This class is a scanner generated by
* <a href="http://www.jflex.de/">JFlex</a> 1.6.0
* from the specification file
* <a href="http://www.jflex.de/">JFlex</a> 1.6.0 from the specification file
* <tt>C:/Dropbox/Programovani/JavaSE/FFDec/libsrc/ffdec_lib/lexers/text.flex</tt>
*/
public final class TextLexer {
@@ -47,9 +46,8 @@ public final class TextLexer {
/**
* ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
* ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l
* at the beginning of a line
* l is of the form l = 2*k, k a non negative integer
* ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l at the
* beginning of a line l is of the form l = 2*k, k a non negative integer
*/
private static final int ZZ_LEXSTATE[] = {
0, 0, 1, 1, 2, 2
@@ -88,9 +86,11 @@ public final class TextLexer {
}
private static int zzUnpackAction(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -122,9 +122,11 @@ public final class TextLexer {
}
private static int zzUnpackRowMap(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -158,9 +160,11 @@ public final class TextLexer {
}
private static int zzUnpackTrans(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -206,9 +210,11 @@ public final class TextLexer {
}
private static int zzUnpackAttribute(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -237,8 +243,8 @@ public final class TextLexer {
private int zzLexicalState = YYINITIAL;
/**
* this buffer contains the current text to be matched and is
* the source of the yytext() string
* this buffer contains the current text to be matched and is the source of
* the yytext() string
*/
private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
@@ -258,8 +264,8 @@ public final class TextLexer {
private int zzStartRead;
/**
* endRead marks the last character in the buffer, that has been read
* from input
* endRead marks the last character in the buffer, that has been read from
* input
*/
private int zzEndRead;
@@ -295,10 +301,10 @@ public final class TextLexer {
private boolean zzEOFDone;
/**
* The number of occupied positions in zzBuffer beyond zzEndRead.
* When a lead/high surrogate has been read from the input stream
* into the final zzBuffer position, this will have a value of 1;
* otherwise, it will have a value of 0.
* The number of occupied positions in zzBuffer beyond zzEndRead. When a
* lead/high surrogate has been read from the input stream into the final
* zzBuffer position, this will have a value of 1; otherwise, it will have a
* value of 0.
*/
private int zzFinalHighSurrogate = 0;
@@ -344,9 +350,11 @@ public final class TextLexer {
*/
private static char[] zzUnpackCMap(String packed) {
char[] map = new char[0x110000];
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = 0; /* index in unpacked array */
int j = 0;
/* index in unpacked array */
while (i < 114) {
int count = packed.charAt(i++);
@@ -405,7 +413,8 @@ public final class TextLexer {
if (totalRead > 0) {
zzEndRead += totalRead;
if (totalRead == requested) { /* possibly more input available */
if (totalRead == requested) {
/* possibly more input available */
if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) {
--zzEndRead;
@@ -423,9 +432,11 @@ public final class TextLexer {
* Closes the input stream.
*/
public final void yyclose() throws java.io.IOException {
zzAtEOF = true; /* indicate end of file */
zzAtEOF = true;
/* indicate end of file */
zzEndRead = zzStartRead; /* invalidate buffer */
zzEndRead = zzStartRead;
/* invalidate buffer */
if (zzReader != null) {
zzReader.close();
@@ -433,12 +444,12 @@ public final class TextLexer {
}
/**
* Resets the scanner to read from a new input stream.
* Does not close the old reader.
* Resets the scanner to read from a new input stream. Does not close the
* old reader.
*
* All internal variables are reset, the old input stream
* <b>cannot</b> be reused (internal buffer is discarded and lost).
* Lexical state is set to <tt>ZZ_INITIAL</tt>.
* <b>cannot</b> be reused (internal buffer is discarded and lost). Lexical
* state is set to <tt>ZZ_INITIAL</tt>.
*
* Internal scan buffer is resized down to its initial length, if it has
* grown.
@@ -484,13 +495,12 @@ public final class TextLexer {
}
/**
* Returns the character at position <tt>pos</tt> from the
* matched text.
* Returns the character at position <tt>pos</tt> from the matched text.
*
* It is equivalent to yytext().charAt(pos), but faster
*
* @param pos the position of the character to fetch.
* A value from 0 to yylength()-1.
* @param pos the position of the character to fetch. A value from 0 to
* yylength()-1.
*
* @return the character at position pos
*/
@@ -508,14 +518,13 @@ public final class TextLexer {
/**
* Reports an error that occured while scanning.
*
* In a wellformed scanner (no or only correct usage of
* yypushback(int) and a match-all fallback rule) this method
* will only be called with things that "Can't Possibly Happen".
* If this method is called, something is seriously wrong
* (e.g. a JFlex bug producing a faulty scanner etc.).
* In a wellformed scanner (no or only correct usage of yypushback(int) and
* a match-all fallback rule) this method will only be called with things
* that "Can't Possibly Happen". If this method is called, something is
* seriously wrong (e.g. a JFlex bug producing a faulty scanner etc.).
*
* Usual syntax/scanner level error handling should be done
* in error fallback rules.
* Usual syntax/scanner level error handling should be done in error
* fallback rules.
*
* @param errorCode the code of the errormessage to display
*/
@@ -535,8 +544,8 @@ public final class TextLexer {
*
* They will be read again by then next call of the scanning method
*
* @param number the number of characters to be read again.
* This number must not be greater than yylength()!
* @param number the number of characters to be read again. This number must
* not be greater than yylength()!
*/
public void yypushback(int number) {
if (number > yylength()) {
@@ -547,8 +556,8 @@ public final class TextLexer {
}
/**
* Resumes scanning until the next regular expression is matched,
* the end of input is encountered or an I/O-Error occurs.
* Resumes scanning until the next regular expression is matched, the end of
* input is encountered or an I/O-Error occurs.
*
* @return the next token
* @exception java.io.IOException if any I/O-Error occurs
@@ -1,6 +1,6 @@
/* The following code was generated by JFlex 1.6.0 */
/*
/*
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
@@ -22,8 +22,7 @@ import java.util.Stack;
/**
* This class is a scanner generated by
* <a href="http://www.jflex.de/">JFlex</a> 1.6.0
* from the specification file
* <a href="http://www.jflex.de/">JFlex</a> 1.6.0 from the specification file
* <tt>C:/FFDec/jpexs-decompiler/libsrc/ffdec_lib/lexers/tag_conditions.flex</tt>
*/
public final class ConditionLexer {
@@ -45,9 +44,8 @@ public final class ConditionLexer {
/**
* ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
* ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l
* at the beginning of a line
* l is of the form l = 2*k, k a non negative integer
* ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l at the
* beginning of a line l is of the form l = 2*k, k a non negative integer
*/
private static final int ZZ_LEXSTATE[] = {
0, 0
@@ -84,9 +82,11 @@ public final class ConditionLexer {
}
private static int zzUnpackAction(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -116,9 +116,11 @@ public final class ConditionLexer {
}
private static int zzUnpackRowMap(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -145,9 +147,11 @@ public final class ConditionLexer {
}
private static int zzUnpackTrans(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -192,9 +196,11 @@ public final class ConditionLexer {
}
private static int zzUnpackAttribute(String packed, int offset, int[] result) {
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = offset; /* index in unpacked array */
int j = offset;
/* index in unpacked array */
int l = packed.length();
while (i < l) {
@@ -223,8 +229,8 @@ public final class ConditionLexer {
private int zzLexicalState = YYINITIAL;
/**
* this buffer contains the current text to be matched and is
* the source of the yytext() string
* this buffer contains the current text to be matched and is the source of
* the yytext() string
*/
private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
@@ -244,8 +250,8 @@ public final class ConditionLexer {
private int zzStartRead;
/**
* endRead marks the last character in the buffer, that has been read
* from input
* endRead marks the last character in the buffer, that has been read from
* input
*/
private int zzEndRead;
@@ -281,10 +287,10 @@ public final class ConditionLexer {
private boolean zzEOFDone;
/**
* The number of occupied positions in zzBuffer beyond zzEndRead.
* When a lead/high surrogate has been read from the input stream
* into the final zzBuffer position, this will have a value of 1;
* otherwise, it will have a value of 0.
* The number of occupied positions in zzBuffer beyond zzEndRead. When a
* lead/high surrogate has been read from the input stream into the final
* zzBuffer position, this will have a value of 1; otherwise, it will have a
* value of 0.
*/
private int zzFinalHighSurrogate = 0;
@@ -338,9 +344,11 @@ public final class ConditionLexer {
*/
private static char[] zzUnpackCMap(String packed) {
char[] map = new char[0x110000];
int i = 0; /* index in packed string */
int i = 0;
/* index in packed string */
int j = 0; /* index in unpacked array */
int j = 0;
/* index in unpacked array */
while (i < 96) {
int count = packed.charAt(i++);
@@ -399,7 +407,8 @@ public final class ConditionLexer {
if (totalRead > 0) {
zzEndRead += totalRead;
if (totalRead == requested) { /* possibly more input available */
if (totalRead == requested) {
/* possibly more input available */
if (Character.isHighSurrogate(zzBuffer[zzEndRead - 1])) {
--zzEndRead;
@@ -417,9 +426,11 @@ public final class ConditionLexer {
* Closes the input stream.
*/
public final void yyclose() throws java.io.IOException {
zzAtEOF = true; /* indicate end of file */
zzAtEOF = true;
/* indicate end of file */
zzEndRead = zzStartRead; /* invalidate buffer */
zzEndRead = zzStartRead;
/* invalidate buffer */
if (zzReader != null) {
zzReader.close();
@@ -427,12 +438,12 @@ public final class ConditionLexer {
}
/**
* Resets the scanner to read from a new input stream.
* Does not close the old reader.
* Resets the scanner to read from a new input stream. Does not close the
* old reader.
*
* All internal variables are reset, the old input stream
* <b>cannot</b> be reused (internal buffer is discarded and lost).
* Lexical state is set to <tt>ZZ_INITIAL</tt>.
* <b>cannot</b> be reused (internal buffer is discarded and lost). Lexical
* state is set to <tt>ZZ_INITIAL</tt>.
*
* Internal scan buffer is resized down to its initial length, if it has
* grown.
@@ -478,13 +489,12 @@ public final class ConditionLexer {
}
/**
* Returns the character at position <tt>pos</tt> from the
* matched text.
* Returns the character at position <tt>pos</tt> from the matched text.
*
* It is equivalent to yytext().charAt(pos), but faster
*
* @param pos the position of the character to fetch.
* A value from 0 to yylength()-1.
* @param pos the position of the character to fetch. A value from 0 to
* yylength()-1.
*
* @return the character at position pos
*/
@@ -502,14 +512,13 @@ public final class ConditionLexer {
/**
* Reports an error that occured while scanning.
*
* In a wellformed scanner (no or only correct usage of
* yypushback(int) and a match-all fallback rule) this method
* will only be called with things that "Can't Possibly Happen".
* If this method is called, something is seriously wrong
* (e.g. a JFlex bug producing a faulty scanner etc.).
* In a wellformed scanner (no or only correct usage of yypushback(int) and
* a match-all fallback rule) this method will only be called with things
* that "Can't Possibly Happen". If this method is called, something is
* seriously wrong (e.g. a JFlex bug producing a faulty scanner etc.).
*
* Usual syntax/scanner level error handling should be done
* in error fallback rules.
* Usual syntax/scanner level error handling should be done in error
* fallback rules.
*
* @param errorCode the code of the errormessage to display
*/
@@ -529,8 +538,8 @@ public final class ConditionLexer {
*
* They will be read again by then next call of the scanning method
*
* @param number the number of characters to be read again.
* This number must not be greater than yylength()!
* @param number the number of characters to be read again. This number must
* not be greater than yylength()!
*/
public void yypushback(int number) {
if (number > yylength()) {
@@ -541,8 +550,8 @@ public final class ConditionLexer {
}
/**
* Resumes scanning until the next regular expression is matched,
* the end of input is encountered or an I/O-Error occurs.
* Resumes scanning until the next regular expression is matched, the end of
* input is encountered or an I/O-Error occurs.
*
* @return the next token
* @exception java.io.IOException if any I/O-Error occurs
@@ -29,11 +29,11 @@ public enum FLAVersion {
CS5_5("CS5.5", "Flash CS 5.5", "2.1", 11),
CS6("CS6", "Flash CS 6", "2.2", 17),
CC("CC", "Flash CC", "2.4", Integer.MAX_VALUE) {
@Override
public int minASVersion() {
return 3; //AS 1/2 not supported anymore
}
};
@Override
public int minASVersion() {
return 3; //AS 1/2 not supported anymore
}
};
private final String xflVersion;
@@ -28,7 +28,7 @@ import java.util.List;
*
* @author JPEXS
*/
public class DottedChain implements Serializable {
public class DottedChain implements Serializable, Comparable<DottedChain> {
public static final DottedChain EMPTY = new DottedChain(true);
@@ -278,4 +278,9 @@ public class DottedChain implements Serializable {
return true;
}
@Override
public int compareTo(DottedChain o) {
return toRawString().compareTo(o.toRawString());
}
}
@@ -171,19 +171,15 @@ public class GraphPart implements Serializable {
for (GraphPart p : nextParts) {
if (p == part) {
return true;
} else {
if (p.leadsTo(localData, gr, code, part, visited, loops)) {
return true;
}
} else if (p.leadsTo(localData, gr, code, part, visited, loops)) {
return true;
}
}
for (GraphPart p : throwParts) {
if (p == part) {
return true;
} else {
if (p.leadsTo(localData, gr, code, part, visited, loops)) {
return true;
}
} else if (p.leadsTo(localData, gr, code, part, visited, loops)) {
return true;
}
}
return false;
@@ -957,8 +957,7 @@ function doDrag(e) {
if (dragWidth) {
canvas.width = (startWidth + e.clientX - startX);
canvas.height = canvas.width * originalHeight / originalWidth;
}
else if (dragHeight) {
} else if (dragHeight) {
canvas.height = (startHeight + e.clientY - startY);
canvas.width = canvas.height * originalWidth / originalHeight;
}
@@ -175,7 +175,8 @@ public class ActionScript2ModificationTest extends ActionScript2TestBase {
+ "Return\n"
+ "}\n"
+ "Push 2\n"
+ "Jump label_1\n" + // remove this action
+ "Jump label_1\n"
+ // remove this action
"label_1:Push 3";
String expectedResult
= "ConstantPool\n"
@@ -27,6 +27,7 @@ import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.helpers.CodeFormatting;
import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter;
import com.jpexs.decompiler.flash.importers.FFDecAs3ScriptReplacer;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.graph.CompilationException;
@@ -90,7 +91,7 @@ public class DirectEditingTest extends FileTestBase {
try {
en.toSource(htw, abc.script_info.get(s).traits.traits, new ConvertData(), ScriptExportMode.AS, false);
String original = htw.toString();
abc.replaceScriptPack(en, original);
abc.replaceScriptPack(new FFDecAs3ScriptReplacer() /*TODO: test the otherone*/, en, original);
} catch (Exception ex) {
fail("Exception during decompilation - file: " + filePath + " class: " + classPathString, ex);
throw ex;
@@ -0,0 +1,50 @@
package com.jpexs.decompiler.flash.flexsdk;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.helpers.Helper;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.testng.annotations.Test;
public class As3ScriptReplacerTest {
//Commented out yet... there's no Flex SDK on build server
//@Test
public void testReplace() throws IOException, InterruptedException, Exception {
MxmlcAs3ScriptReplacer replacer = new MxmlcAs3ScriptReplacer(Configuration.flexSdkLocation.get());
SWF swf = new SWF(new BufferedInputStream(new FileInputStream("testdata/as3/as3.swf")), false);
String replacement = "package classes\n"
+ "{\n"
+ "\n"
+ " public dynamic class TestClass1\n"
+ " {\n"
+ " public var attrib:int = 5;\n"
+ " public var sons:Array;\n"
+ "\n"
+ " public function testHello()\n"
+ " {\n"
+ " trace(\"helloA\");\n"
+ " }\n"
+ "\n"
+ " public function method(i:int):int\n"
+ " {\n"
+ " trace(\"methodB\");\n"
+ " return 7;\n"
+ " }\n"
+ " }\n"
+ "}";
List<String> classNames = new ArrayList<>();
classNames.add("classes.TestClass1");
List<ScriptPack> packs = swf.getScriptPacksByClassNames(classNames);
for (ScriptPack sp : packs) {
replacer.replaceScript(sp, replacement);
return;
}
}
}
Binary file not shown.
+24
View File
@@ -0,0 +1,24 @@
package {
import flash.display.MovieClip;
import flash.text.TextField;
import pkg.MyClass;
public class Main extends MovieClip {
private var mc:MyClass;
public function Main() {
this.mc = new MyClass(5);
var display_txt:TextField = new TextField();
display_txt.text = "Hello myclass: "+this.mc.getVal()+" char:"+this.mc.getAChar();
display_txt.width = 300;
addChild(display_txt);
}
}
}
Binary file not shown.
+49
View File
@@ -0,0 +1,49 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Main</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css" media="screen">
html, body { height:100%; background-color: #ffffff;}
body { margin:0; padding:0; overflow:hidden; }
#flashContent { width:100%; height:100%; }
</style>
</head>
<body>
<div id="flashContent">
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="550" height="400" id="Main" align="middle">
<param name="movie" value="Main.swf" />
<param name="quality" value="high" />
<param name="bgcolor" value="#ffffff" />
<param name="play" value="true" />
<param name="loop" value="true" />
<param name="wmode" value="window" />
<param name="scale" value="showall" />
<param name="menu" value="true" />
<param name="devicefont" value="false" />
<param name="salign" value="" />
<param name="allowScriptAccess" value="sameDomain" />
<!--[if !IE]>-->
<object type="application/x-shockwave-flash" data="Main.swf" width="550" height="400">
<param name="movie" value="Main.swf" />
<param name="quality" value="high" />
<param name="bgcolor" value="#ffffff" />
<param name="play" value="true" />
<param name="loop" value="true" />
<param name="wmode" value="window" />
<param name="scale" value="showall" />
<param name="menu" value="true" />
<param name="devicefont" value="false" />
<param name="salign" value="" />
<param name="allowScriptAccess" value="sameDomain" />
<!--<![endif]-->
<a href="http://www.adobe.com/go/getflash">
<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" />
</a>
<!--[if !IE]>-->
</object>
<!--<![endif]-->
</object>
</div>
</body>
</html>
Binary file not shown.
+17
View File
@@ -0,0 +1,17 @@
package pkg {
public class MyClass extends ParentClass {
private var val:int;
public function MyClass(val) {
this.val = val;
}
public function getVal():int{
return this.val;
}
}
}
+11
View File
@@ -0,0 +1,11 @@
package pkg {
public class ParentClass extends ParentParentClass {
public function ParentClass() {
// constructor code
}
}
}
@@ -0,0 +1,22 @@
package pkg {
public class ParentParentClass {
//Reference to subclass: (circular reference)
private var other:ParentClass;
public function ParentParentClass() {
// constructor code
}
public function setOther(other:ParentClass){
this.other = other;
}
public function getAChar():String{
return "A";
}
}
}
@@ -75,6 +75,7 @@ import com.jpexs.decompiler.flash.exporters.modes.ShapeExportMode;
import com.jpexs.decompiler.flash.exporters.modes.SoundExportMode;
import com.jpexs.decompiler.flash.exporters.modes.SpriteExportMode;
import com.jpexs.decompiler.flash.exporters.modes.TextExportMode;
import com.jpexs.decompiler.flash.exporters.script.LinkReportExporter;
import com.jpexs.decompiler.flash.exporters.settings.BinaryDataExportSettings;
import com.jpexs.decompiler.flash.exporters.settings.ButtonExportSettings;
import com.jpexs.decompiler.flash.exporters.settings.FontExportSettings;
@@ -87,18 +88,26 @@ import com.jpexs.decompiler.flash.exporters.settings.ShapeExportSettings;
import com.jpexs.decompiler.flash.exporters.settings.SoundExportSettings;
import com.jpexs.decompiler.flash.exporters.settings.SpriteExportSettings;
import com.jpexs.decompiler.flash.exporters.settings.TextExportSettings;
import com.jpexs.decompiler.flash.exporters.swf.SwfToSwcExporter;
import com.jpexs.decompiler.flash.exporters.swf.SwfXmlExporter;
import com.jpexs.decompiler.flash.flexsdk.MxmlcAs3ScriptReplacer;
import com.jpexs.decompiler.flash.gui.AppStrings;
import com.jpexs.decompiler.flash.gui.Main;
import com.jpexs.decompiler.flash.gui.SearchInMemory;
import com.jpexs.decompiler.flash.gui.SearchInMemoryListener;
import com.jpexs.decompiler.flash.gui.SwfInMemory;
import com.jpexs.decompiler.flash.gui.View;
import com.jpexs.decompiler.flash.gui.helpers.CheckResources;
import com.jpexs.decompiler.flash.helpers.FileTextWriter;
import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
import com.jpexs.decompiler.flash.importers.AS2ScriptImporter;
import com.jpexs.decompiler.flash.importers.AS3ScriptImporter;
import com.jpexs.decompiler.flash.importers.As3ScriptReplaceException;
import com.jpexs.decompiler.flash.importers.As3ScriptReplaceExceptionItem;
import com.jpexs.decompiler.flash.importers.As3ScriptReplacerFactory;
import com.jpexs.decompiler.flash.importers.As3ScriptReplacerInterface;
import com.jpexs.decompiler.flash.importers.BinaryDataImporter;
import com.jpexs.decompiler.flash.importers.FFDecAs3ScriptReplacer;
import com.jpexs.decompiler.flash.importers.FontImporter;
import com.jpexs.decompiler.flash.importers.ImageImporter;
import com.jpexs.decompiler.flash.importers.MorphShapeImporter;
@@ -107,6 +116,7 @@ import com.jpexs.decompiler.flash.importers.SwfXmlImporter;
import com.jpexs.decompiler.flash.importers.TextImporter;
import com.jpexs.decompiler.flash.importers.amf.amf3.Amf3Importer;
import com.jpexs.decompiler.flash.importers.amf.amf3.Amf3ParseException;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG2Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG3Tag;
@@ -192,6 +202,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
/**
*
@@ -577,6 +588,27 @@ public class CommandLineArgumentParser {
out.println(" ...<swffile>: SWF file to search instance in");
}
if (filter == null || filter.equals("linkreport")) {
out.println(" " + (cnt++) + ") -linkReport [-outfile <outfile>] <swffile>");
out.println(" ...generates linker report for the swffile");
out.println(" ...-outfile <outfile> (optional): Saves XML report to <outfile>. When ommited, the report is printed to stdout.");
out.println(" ...<swffile>: SWF file to search instance in");
}
if (filter == null || filter.equals("swf2swc")) {
out.println(" " + (cnt++) + ") -swf2swc <outfile> <swffile>");
out.println(" ...generates SWC file from SWF");
out.println(" ...<outfile>: Where to save SWC file");
out.println(" ...<swffile>: Input SWF file");
}
if (filter == null || filter.equals("abcmerge")) {
out.println(" " + (cnt++) + ") -abcmerge <outfile> <swffile>");
out.println(" ...merge all ABC tags in SWF file to one");
out.println(" ...<outfile>: Where to save merged file");
out.println(" ...<swffile>: Input SWF file");
}
printCmdLineUsageExamples(out, filter);
}
@@ -792,7 +824,13 @@ public class CommandLineArgumentParser {
command = nextParam.substring(1);
}
if (command.equals("getinstancemetadata")) {
if (command.equals("abcmerge")) {
parseAbcMerge(args);
} else if (command.equals("swf2swc")) {
parseSwf2Swc(args);
} else if (command.equals("linkreport")) {
parseLinkReport(selectionClasses, args);
} else if (command.equals("getinstancemetadata")) {
parseGetInstanceMetadata(args);
} else if (command.equals("setinstancemetadata")) {
parseSetInstanceMetadata(args);
@@ -987,6 +1025,83 @@ public class CommandLineArgumentParser {
setConfigurations(args.pop());
}
private static void parseAbcMerge(Stack<String> args) {
if (args.size() < 2) {
badArguments("abcmerge");
}
final File outFile = new File(args.pop());
final File swfFile = new File(args.pop());
processModifySWF(swfFile, outFile, null, (SWF swf, OutputStream stdout) -> {
List<ABCContainerTag> abcList = swf.getAbcList();
if (!abcList.isEmpty() && abcList.size() > 1) {
ABC firstAbc = abcList.get(0).getABC();
for (int i = 1; i < abcList.size(); i++) {
firstAbc.mergeABC(abcList.get(i).getABC());
}
for (int i = 1; i < abcList.size(); i++) {
swf.removeTag((Tag) abcList.get(i));
}
}
});
}
private static void parseSwf2Swc(Stack<String> args) {
if (args.size() < 2) {
badArguments("swf2swc");
}
final File outFile = new File(args.pop());
final File swfFile = new File(args.pop());
processReadSWF(swfFile, null, (SWF swf, OutputStream stdout) -> {
SwfToSwcExporter exporter = new SwfToSwcExporter();
exporter.exportSwf(swf, outFile, false);
});
}
private static void parseLinkReport(List<String> selectionClasses, Stack<String> args) {
if (args.isEmpty()) {
badArguments("linkreport");
}
File stdOutFile = null;
File swfFile = null;
while (!args.isEmpty()) {
String paramName = args.pop().toLowerCase();
switch (paramName) {
case "-outfile":
if (args.empty()) {
System.err.println("Missing output file");
badArguments("linkreport");
}
stdOutFile = new File(args.pop());
break;
default:
if (!args.isEmpty()) {
badArguments("linkreport");
}
swfFile = new File(paramName);
}
}
if (swfFile == null) {
System.err.println("No SWF file specified");
badArguments("getinstancemetadata");
}
processReadSWF(swfFile, stdOutFile, (SWF swf, OutputStream stdout) -> {
LinkReportExporter lre = new LinkReportExporter();
List<ScriptPack> reportPacks;
try {
reportPacks = selectionClasses != null ? swf.getScriptPacksByClassNames(selectionClasses) : swf.getAS3Packs();
} catch (Exception ex) {
System.err.println("Error while getting packs");
System.exit(1);
return;
}
String reportStr = lre.generateReport(swf, reportPacks, null);
stdout.write(reportStr.getBytes("UTF-8"));
});
}
private static void parseGetInstanceMetadata(Stack<String> args) {
if (args.size() < 3) {
badArguments("getinstancemetadata");
@@ -3294,6 +3409,13 @@ public class CommandLineArgumentParser {
}
private static void parseImportScript(Stack<String> args) {
String flexLocation = Configuration.flexSdkLocation.get();
if (flexLocation.isEmpty() || (!new File(flexLocation).exists())) {
System.err.println("Flex SDK path not set");
System.exit(1);
}
if (args.size() < 3) {
badArguments("importscript");
}
@@ -3305,7 +3427,7 @@ public class CommandLineArgumentParser {
SWF swf = new SWF(is, Configuration.parallelSpeedUp.get());
String scriptsFolder = Path.combine(args.pop(), ScriptExportSettings.EXPORT_FOLDER_NAME);
new AS2ScriptImporter().importScripts(scriptsFolder, swf.getASMs(true));
new AS3ScriptImporter().importScripts(scriptsFolder, swf.getAS3Packs());
new AS3ScriptImporter().importScripts(As3ScriptReplacerFactory.createByConfig(), scriptsFolder, swf.getAS3Packs());
try {
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(outFile))) {
@@ -3436,23 +3558,35 @@ public class CommandLineArgumentParser {
private static void replaceAS3(String as, ScriptPack pack) throws IOException, InterruptedException {
System.out.println("Replace AS3");
System.out.println("Warning: This feature is EXPERIMENTAL");
File swc = Configuration.getPlayerSWC();
if (swc == null) {
final String adobePage = "http://www.adobe.com/support/flashplayer/downloads.html";
System.err.println("For ActionScript 3 direct editation, a library called \"PlayerGlobal.swc\" needs to be downloaded from Adobe homepage:");
System.err.println(adobePage);
System.err.println("Download the library called PlayerGlobal(.swc), and place it to directory");
System.err.println(Configuration.getFlashLibPath().getAbsolutePath());
As3ScriptReplacerInterface scriptReplacer = As3ScriptReplacerFactory.createByConfig();
if (!scriptReplacer.isAvailable()) {
System.err.println("Current script replacer is not available.");
if (scriptReplacer instanceof FFDecAs3ScriptReplacer) {
System.err.println("Current replacer: FFDec");
final String adobePage = "http://www.adobe.com/support/flashplayer/downloads.html";
System.err.println("For ActionScript 3 direct editation, a library called \"PlayerGlobal.swc\" needs to be downloaded from Adobe homepage:");
System.err.println(adobePage);
System.err.println("Download the library called PlayerGlobal(.swc), and place it to directory");
System.err.println(Configuration.getFlashLibPath().getAbsolutePath());
} else if (scriptReplacer instanceof MxmlcAs3ScriptReplacer) {
System.err.println("Current replacer: Flex SDK");
final String flexPage = "http://www.adobe.com/devnet/flex/flex-sdk-download.html";
System.err.println("For ActionScript 3 direct editation, Flex SDK needs to be download");
System.err.println(flexPage);
System.err.println("Download FLEX Sdk, unzip it to some directory and set its directory path in the configuration");
} else {
}
System.exit(1);
}
try {
pack.abc.replaceScriptPack(pack, as);
} catch (AVM2ParseException ex) {
System.err.println("%error% on line %line%".replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)));
System.exit(1);
} catch (CompilationException ex) {
System.err.println("%error% on line %line%".replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)));
pack.abc.replaceScriptPack(scriptReplacer, pack, as);
} catch (As3ScriptReplaceException asre) {
for (As3ScriptReplaceExceptionItem item : asre.getExceptionItems()) {
logger.log(Level.SEVERE, "%error% on line %line%, column %col%, file: %file%".replace("%error%", item.getMessage()).replace("%line%", Long.toString(item.getLine())).replace("%file%", item.getFile()).replace("%col%", "" + item.getCol()));
}
System.exit(1);
}
}
@@ -57,6 +57,7 @@ import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JEditorPane;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
@@ -68,6 +69,8 @@ import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.SpringLayout;
import javax.swing.WindowConstants;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.table.DefaultTableModel;
import org.pushingpixels.substance.api.ColorSchemeAssociationKind;
@@ -479,24 +482,19 @@ public class AdvancedSettingsDialog extends AppDialog {
itemCount, 2, //rows, cols
6, 6, //initX, initY
6, 6); //xPad, yPad
//https://www.adobe.com/support/flashplayer/debug_downloads.html
if (resourceBundle.containsKey("config.group.tip." + cat)) {
String tip = resourceBundle.getString("config.group.tip." + cat);
String url = null;
String urls[] = new String[0];
if (resourceBundle.containsKey("config.group.link." + cat)) {
url = resourceBundle.getString("config.group.link." + cat);
urls = resourceBundle.getString("config.group.link." + cat).split(" ");
}
for (int i = 0; i < urls.length; i++) {
tip = tip.replace("%link" + (i + 1) + "%", urls[i]);
}
JPanel p = new JPanel(new BorderLayout());
p.add(configPanel, BorderLayout.CENTER);
JPanel tipPanel = new JPanel(new FlowLayout());
tipPanel.add(new JLabel("<html><b>" + resourceBundle.getString("tip") + "</b>" + tip + "</html>"));
if (url != null) {
String linkText = url;
if (resourceBundle.containsKey("config.group.linkText." + cat)) {
linkText = resourceBundle.getString("config.group.linkText." + cat);
}
tipPanel.add(new LinkLabel(linkText, url));
}
tipPanel.add(new HtmlLabel("<b>" + resourceBundle.getString("tip") + "</b>" + tip));
p.add(tipPanel, BorderLayout.SOUTH);
configPanel = p;
}
@@ -0,0 +1,63 @@
/*
* Copyright (C) 2016 Jindra
*
* 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.gui;
import java.awt.Color;
import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.event.HyperlinkEvent;
public class HtmlLabel extends JEditorPane {
private JLabel label = new JLabel();
private String rawText;
public HtmlLabel() {
this("");
}
public HtmlLabel(String text) {
super("text/html", "");
setText(text);
setEditable(false);
setFocusable(false);
setOpaque(false);
addHyperlinkListener((HyperlinkEvent hle) -> {
if (HyperlinkEvent.EventType.ACTIVATED.equals(hle.getEventType())) {
View.navigateUrl(hle.getURL().toString());
}
});
}
@Override
public void setText(String t) {
String modText = t;
if (!t.equals("")) {
Color fgColor = label.getForeground();
modText = "<body style=\"font-size:" + label.getFont().getSize() + "pt; font-family: " + label.getFont().getFamily() + "; color:rgb(" + fgColor.getRed() + "," + fgColor.getGreen() + "," + fgColor.getBlue() + ");\">" + t + "</body>";
}
this.rawText = t;
super.setText(modText);
}
@Override
public String getText() {
return rawText;
}
}
@@ -99,50 +99,48 @@ public class LicenseUpdater {
for (File f : files) {
if (f.isDirectory()) {
updateLicenseInDir(f, lgpl);
} else {
if (f.getName().endsWith(".java")) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintWriter pw = new Utf8PrintWriter(baos);
try {
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f), Utf8Helper.charset))) {
String s;
boolean packageFound = false;
String author = defaultAuthor;
String yearStr = defaultYearStr;
while ((s = br.readLine()) != null) {
if (!packageFound) {
if (s.trim().startsWith("package")) {
packageFound = true;
pw.println(license.replace("{year}", yearStr).replace("{author}", author));
} else {
Matcher mAuthor = Pattern.compile(lgpl ? "^.*Copyright \\(C\\) ([0-9]+)(-[0-9]+)? (.*), All rights reserved.*" : "^.*Copyright \\(C\\) ([0-9]+)(-[0-9]+)? (.*)$").matcher(s);
if (mAuthor.matches()) {
author = mAuthor.group(3).trim();
int startYear = Integer.parseInt(mAuthor.group(1).trim());
if (startYear == defaultFinalYear) {
yearStr = Integer.toString(startYear);
} else {
yearStr = Integer.toString(startYear) + "-" + defaultFinalYear;
}
if (!author.equals(defaultAuthor)) {
System.out.println("Detected nodefault author:" + author + " in " + f.getAbsolutePath());
}
} else if (f.getName().endsWith(".java")) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintWriter pw = new Utf8PrintWriter(baos);
try {
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f), Utf8Helper.charset))) {
String s;
boolean packageFound = false;
String author = defaultAuthor;
String yearStr = defaultYearStr;
while ((s = br.readLine()) != null) {
if (!packageFound) {
if (s.trim().startsWith("package")) {
packageFound = true;
pw.println(license.replace("{year}", yearStr).replace("{author}", author));
} else {
Matcher mAuthor = Pattern.compile(lgpl ? "^.*Copyright \\(C\\) ([0-9]+)(-[0-9]+)? (.*), All rights reserved.*" : "^.*Copyright \\(C\\) ([0-9]+)(-[0-9]+)? (.*)$").matcher(s);
if (mAuthor.matches()) {
author = mAuthor.group(3).trim();
int startYear = Integer.parseInt(mAuthor.group(1).trim());
if (startYear == defaultFinalYear) {
yearStr = Integer.toString(startYear);
} else {
yearStr = Integer.toString(startYear) + "-" + defaultFinalYear;
}
if (!author.equals(defaultAuthor)) {
System.out.println("Detected nodefault author:" + author + " in " + f.getAbsolutePath());
}
}
}
if (packageFound) {
pw.println(s);
}
}
if (packageFound) {
pw.println(s);
}
}
pw.close();
} catch (IOException ex) {
}
pw.close();
} catch (IOException ex) {
}
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(f))) {
fos.write(baos.toByteArray());
} catch (IOException ex) {
}
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(f))) {
fos.write(baos.toByteArray());
} catch (IOException ex) {
}
}
}
@@ -100,10 +100,8 @@ public class LoadingDialog extends AppDialog {
public void windowClosing(WindowEvent e) {
if (Main.shouldCloseWhenClosingLoadingDialog) {
System.exit(0);
} else {
if (worker != null) {
worker.cancel(true);
}
} else if (worker != null) {
worker.cancel(true);
}
}
});
@@ -73,6 +73,7 @@ import com.jpexs.decompiler.flash.exporters.settings.SpriteExportSettings;
import com.jpexs.decompiler.flash.exporters.settings.TextExportSettings;
import com.jpexs.decompiler.flash.exporters.swf.SwfJavaExporter;
import com.jpexs.decompiler.flash.exporters.swf.SwfXmlExporter;
import com.jpexs.decompiler.flash.flexsdk.MxmlcAs3ScriptReplacer;
import com.jpexs.decompiler.flash.gui.abc.ABCPanel;
import com.jpexs.decompiler.flash.gui.abc.ABCPanelSearchResult;
import com.jpexs.decompiler.flash.gui.abc.ClassesListTreeModel;
@@ -94,7 +95,10 @@ import com.jpexs.decompiler.flash.helpers.FileTextWriter;
import com.jpexs.decompiler.flash.helpers.Freed;
import com.jpexs.decompiler.flash.importers.AS2ScriptImporter;
import com.jpexs.decompiler.flash.importers.AS3ScriptImporter;
import com.jpexs.decompiler.flash.importers.As3ScriptReplacerFactory;
import com.jpexs.decompiler.flash.importers.As3ScriptReplacerInterface;
import com.jpexs.decompiler.flash.importers.BinaryDataImporter;
import com.jpexs.decompiler.flash.importers.FFDecAs3ScriptReplacer;
import com.jpexs.decompiler.flash.importers.ImageImporter;
import com.jpexs.decompiler.flash.importers.ShapeImporter;
import com.jpexs.decompiler.flash.importers.SwfXmlImporter;
@@ -861,11 +865,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
? translate("message.confirm.closeAll")
: translate("message.confirm.close").replace("{swfName}", swfList.toString());
if (View.showConfirmDialog(this, message, translate("message.warning"), JOptionPane.OK_CANCEL_OPTION, Configuration.showCloseConfirmation, JOptionPane.OK_OPTION) != JOptionPane.OK_OPTION) {
return false;
}
return true;
return View.showConfirmDialog(this, message, translate("message.warning"), JOptionPane.OK_CANCEL_OPTION, Configuration.showCloseConfirmation, JOptionPane.OK_OPTION) == JOptionPane.OK_OPTION;
}
public boolean isModified() {
@@ -2143,7 +2143,32 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
}
}
public As3ScriptReplacerInterface getAs3ScriptReplacer() {
As3ScriptReplacerInterface r = As3ScriptReplacerFactory.createByConfig();
if (!r.isAvailable()) {
if (r instanceof MxmlcAs3ScriptReplacer) {
if (View.showConfirmDialog(null, AppStrings.translate("message.flexpath.notset"), AppStrings.translate("error"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.OK_OPTION) {
Main.advancedSettings("paths");
}
} else if (r instanceof FFDecAs3ScriptReplacer) {
if (View.showConfirmDialog(this, AppStrings.translate("message.playerpath.lib.notset"), AppStrings.translate("message.action.playerglobal.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.OK_OPTION) {
Main.advancedSettings("paths");
}
} else {
//Not translated yet - just in case there are more Script replacers in the future. Unused now.
View.showConfirmDialog(this, "Current script replacer is not available", "Script replacer not available", JOptionPane.OK_OPTION, JOptionPane.ERROR_MESSAGE);
}
return null;
}
return r;
}
public void importScript(final SWF swf) {
As3ScriptReplacerInterface as3ScriptReplacer = getAs3ScriptReplacer();
if (as3ScriptReplacer == null) {
return;
}
String flexLocation = Configuration.flexSdkLocation.get();
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new File(Configuration.lastExportDir.get()));
chooser.setDialogTitle(translate("import.select.directory"));
@@ -2154,7 +2179,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
String scriptsFolder = Path.combine(selFile, ScriptExportSettings.EXPORT_FOLDER_NAME);
int countAs2 = new AS2ScriptImporter().importScripts(scriptsFolder, swf.getASMs(true));
int countAs3 = new AS3ScriptImporter().importScripts(scriptsFolder, swf.getAS3Packs());
int countAs3 = new AS3ScriptImporter().importScripts(as3ScriptReplacer, scriptsFolder, swf.getAS3Packs());
if (countAs3 > 0) {
updateClassesList();
@@ -55,65 +55,65 @@ public class MyRibbonApplicationMenuPopupPanelUI extends BasicRibbonApplicationM
super.installComponents();
Border newBorder = new CompoundBorder(new SubstanceBorder(new Insets(2,
2, 2, 2)), new Border() {
@Override
public boolean isBorderOpaque() {
return true;
}
@Override
public boolean isBorderOpaque() {
return true;
}
@Override
public Insets getBorderInsets(Component c) {
return new Insets(18, 0, 0, 0);
}
@Override
public Insets getBorderInsets(Component c) {
return new Insets(18, 0, 0, 0);
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y,
int width, int height) {
SubstanceColorScheme bgFillScheme = SubstanceColorSchemeUtilities
@Override
public void paintBorder(Component c, Graphics g, int x, int y,
int width, int height) {
SubstanceColorScheme bgFillScheme = SubstanceColorSchemeUtilities
.getColorScheme(c,
ColorSchemeAssociationKind.HIGHLIGHT,
ComponentState.ENABLED);
SubstanceColorScheme bgBorderScheme = SubstanceColorSchemeUtilities
SubstanceColorScheme bgBorderScheme = SubstanceColorSchemeUtilities
.getColorScheme(c,
ColorSchemeAssociationKind.HIGHLIGHT_BORDER,
ComponentState.ENABLED);
HighlightPainterUtils.paintHighlight(g, null, c, new Rectangle(
x, y, width, height), 0.0f, null, bgFillScheme,
bgBorderScheme);
HighlightPainterUtils.paintHighlight(g, null, c, new Rectangle(
x, y, width, height), 0.0f, null, bgFillScheme,
bgBorderScheme);
// draw the application menu button
JRibbonApplicationMenuButton rendererButton = new JRibbonApplicationMenuButton(
applicationMenuPopupPanel.getAppMenuButton()
.getRibbon());
// draw the application menu button
JRibbonApplicationMenuButton rendererButton = new JRibbonApplicationMenuButton(
applicationMenuPopupPanel.getAppMenuButton()
.getRibbon());
JRibbonApplicationMenuButton appMenuButton = applicationMenuPopupPanel
JRibbonApplicationMenuButton appMenuButton = applicationMenuPopupPanel
.getAppMenuButton();
rendererButton.applyComponentOrientation(appMenuButton
.getComponentOrientation());
rendererButton.applyComponentOrientation(appMenuButton
.getComponentOrientation());
rendererButton.setPopupKeyTip(appMenuButton.getPopupKeyTip());
rendererButton.getPopupModel().setPopupShowing(true);
rendererButton.setDisplayState(appMenuButton.getDisplayState());
rendererButton.setPopupKeyTip(appMenuButton.getPopupKeyTip());
rendererButton.getPopupModel().setPopupShowing(true);
rendererButton.setDisplayState(appMenuButton.getDisplayState());
rendererButton.getPopupModel().setRollover(false);
rendererButton.getPopupModel().setPressed(true);
rendererButton.getPopupModel().setArmed(true);
rendererButton.getPopupModel().setRollover(false);
rendererButton.getPopupModel().setPressed(true);
rendererButton.getPopupModel().setArmed(true);
CellRendererPane buttonRendererPane = new CellRendererPane();
Point buttonLoc = appMenuButton.getLocationOnScreen();
Point panelLoc = c.getLocationOnScreen();
CellRendererPane buttonRendererPane = new CellRendererPane();
Point buttonLoc = appMenuButton.getLocationOnScreen();
Point panelLoc = c.getLocationOnScreen();
buttonRendererPane.setBounds(panelLoc.x - buttonLoc.x,
panelLoc.y - buttonLoc.y, appMenuButton.getWidth(),
appMenuButton.getHeight());
buttonRendererPane.setBounds(panelLoc.x - buttonLoc.x,
panelLoc.y - buttonLoc.y, appMenuButton.getWidth(),
appMenuButton.getHeight());
buttonRendererPane.paintComponent(g, rendererButton,
(Container) c, -panelLoc.x + buttonLoc.x, -panelLoc.y
+ buttonLoc.y, appMenuButton.getWidth(),
appMenuButton.getHeight(), true);
/*g.setColor(Color.red);
buttonRendererPane.paintComponent(g, rendererButton,
(Container) c, -panelLoc.x + buttonLoc.x, -panelLoc.y
+ buttonLoc.y, appMenuButton.getWidth(),
appMenuButton.getHeight(), true);
/*g.setColor(Color.red);
g.fillRect(0, 0, width,height);*/
}
});
}
});
this.applicationMenuPopupPanel.setBorder(newBorder);
this.panelLevel2.setBorder(new Border() {
@@ -186,13 +186,13 @@ public class OceanicSkin extends SubstanceSkin {
this.addOverlayPainter(new BottomLineOverlayPainter(
new ColorSchemeSingleColorQuery() {
@Override
public Color query(SubstanceColorScheme scheme) {
Color fg = scheme.getForegroundColor();
return new Color(fg.getRed(), fg.getGreen(), fg
.getBlue(), 72);
}
}), DecorationAreaType.PRIMARY_TITLE_PANE,
@Override
public Color query(SubstanceColorScheme scheme) {
Color fg = scheme.getForegroundColor();
return new Color(fg.getRed(), fg.getGreen(), fg
.getBlue(), 72);
}
}), DecorationAreaType.PRIMARY_TITLE_PANE,
DecorationAreaType.SECONDARY_TITLE_PANE);
this.buttonShaper = new ClassicButtonShaper();
@@ -216,12 +216,12 @@ public class OceanicSkin extends SubstanceSkin {
"Oceanic Inner", outerBorderPainter, new int[]{
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
new ColorSchemeTransform() {
@Override
public SubstanceColorScheme transform(
SubstanceColorScheme scheme) {
return scheme.tint(0.8f);
}
});
@Override
public SubstanceColorScheme transform(
SubstanceColorScheme scheme) {
return scheme.tint(0.8f);
}
});
this.borderPainter = new CompositeBorderPainter("Oceanic",
outerBorderPainter, innerBorderPainter);
@@ -27,7 +27,6 @@ import com.jpexs.decompiler.flash.abc.ScriptPack;
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.AVM2Instructions;
import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference;
import com.jpexs.decompiler.flash.abc.types.ABCException;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
@@ -69,10 +68,12 @@ import com.jpexs.decompiler.flash.gui.abc.tablemodels.UIntTableModel;
import com.jpexs.decompiler.flash.gui.controls.JPersistentSplitPane;
import com.jpexs.decompiler.flash.gui.editor.LinkHandler;
import com.jpexs.decompiler.flash.gui.tagtree.TagTreeModel;
import com.jpexs.decompiler.flash.importers.As3ScriptReplaceException;
import com.jpexs.decompiler.flash.importers.As3ScriptReplaceExceptionItem;
import com.jpexs.decompiler.flash.importers.As3ScriptReplacerInterface;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
import com.jpexs.decompiler.graph.CompilationException;
import com.jpexs.helpers.CancellableWorker;
import com.jpexs.helpers.Helper;
import de.hameister.treetable.MyTreeTable;
@@ -116,6 +117,7 @@ import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JToggleButton;
import javax.swing.SwingConstants;
import javax.swing.SwingWorker;
import javax.swing.border.BevelBorder;
import javax.swing.event.EventListenerList;
import javax.swing.event.TableModelListener;
@@ -134,6 +136,9 @@ import jsyntaxpane.TokenType;
*/
public class ABCPanel extends JPanel implements ItemListener, SearchListener<ABCPanelSearchResult>, TagEditorPanel {
private As3ScriptReplacerInterface scriptReplacer = null;
private ScriptPack pack = null;
private final MainPanel mainPanel;
public final TraitsList navigator;
@@ -1150,36 +1155,40 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<ABC
}
private void editDecompiledButtonActionPerformed(ActionEvent evt) {
File swc = Configuration.getPlayerSWC();
if (swc == null || !swc.exists()) {
if (View.showConfirmDialog(this, AppStrings.translate("message.playerpath.lib.notset"), AppStrings.translate("message.action.playerglobal.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.INFORMATION_MESSAGE) == JOptionPane.OK_OPTION) {
Main.advancedSettings("paths");
return;
}
scriptReplacer = mainPanel.getAs3ScriptReplacer();
if (scriptReplacer == null) {
return;
}
if (View.showConfirmDialog(null, AppStrings.translate("message.confirm.experimental.function"), AppStrings.translate("message.warning"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, Configuration.warningExperimentalAS3Edit, JOptionPane.OK_OPTION) == JOptionPane.OK_OPTION) {
pack = decompiledTextArea.getScriptLeaf();
setDecompiledEditMode(true);
SwingWorker initReplaceWorker = new SwingWorker() {
@Override
protected Object doInBackground() throws Exception {
scriptReplacer.initReplacement(pack);
return null;
}
};
initReplaceWorker.execute();
}
}
private void cancelDecompiledButtonActionPerformed(ActionEvent evt) {
setDecompiledEditMode(false);
if (scriptReplacer != null) {
scriptReplacer.deinitReplacement(pack);
}
}
private void saveDecompiledButtonActionPerformed(ActionEvent evt) {
ScriptPack pack = decompiledTextArea.getScriptLeaf();
int oldIndex = pack.scriptIndex;
SWF.uncache(pack);
try {
String oldSp = pack.getClassPath().toRawString();
/*List<ScriptPack> packs = abc.script_info.get(oldIndex).getPacks(abc, oldIndex, null, pack.allABCs);
if (!packs.isEmpty()) {
}*/
String as = decompiledTextArea.getText();
abc.replaceScriptPack(pack, as);
abc.replaceScriptPack(scriptReplacer, pack, as);
scriptReplacer.deinitReplacement(pack);
lastDecompiled = as;
setDecompiledEditMode(false);
mainPanel.updateClassesList();
@@ -1190,20 +1199,35 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<ABC
reload();
View.showMessageDialog(this, AppStrings.translate("message.action.saved"), AppStrings.translate("dialog.message.title"), JOptionPane.INFORMATION_MESSAGE, Configuration.showCodeSavedMessage);
} catch (AVM2ParseException ex) {
} catch (As3ScriptReplaceException asre) {
StringBuilder sb = new StringBuilder();
int firstErrorLine = As3ScriptReplaceExceptionItem.LINE_UNKNOWN;
int firstErrorCol = As3ScriptReplaceExceptionItem.COL_UNKNOWN;
abc.script_info.get(oldIndex).delete(abc, false);
decompiledTextArea.gotoLine((int) ex.line);
decompiledTextArea.markError();
View.showMessageDialog(this, AppStrings.translate("error.action.save").replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
} catch (CompilationException ex) {
abc.script_info.get(oldIndex).delete(abc, false);
decompiledTextArea.gotoLine((int) ex.line);
decompiledTextArea.markError();
View.showMessageDialog(this, AppStrings.translate("error.action.save").replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
for (As3ScriptReplaceExceptionItem item : asre.getExceptionItems()) {
if (firstErrorLine == As3ScriptReplaceExceptionItem.LINE_UNKNOWN) {
firstErrorLine = item.getLine();
firstErrorCol = item.getCol();
}
sb.append(item.getFile()).append(":").append(item.getLine()).append(" (column ").append(item.getCol()).append(")").append(":").append("\n");
sb.append(" ").append(item.getMessage());
sb.append("\n");
sb.append("\n");
}
if (firstErrorLine != As3ScriptReplaceExceptionItem.LINE_UNKNOWN) {
if (firstErrorCol != As3ScriptReplaceExceptionItem.COL_UNKNOWN) {
decompiledTextArea.gotoLineCol(firstErrorLine, firstErrorCol);
} else {
decompiledTextArea.gotoLine(firstErrorLine);
}
decompiledTextArea.markError();
}
//View.showMessageDialog(this, AppStrings.translate("error.action.save").replace("%error%", ex.text).replace("%line%", Long.toString(ex.line)), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
View.showMessageDialog(this, sb.toString(), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
decompiledTextArea.requestFocus();
} catch (Throwable ex) {
Logger.getLogger(ABCPanel.class
.getName()).log(Level.SEVERE, null, ex);
Logger.getLogger(ABCPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
@@ -225,10 +225,8 @@ public class DetailPanel extends JPanel implements TagEditorPanel {
selectedLabel.setText(AppStrings.translate(name));
if (trait == null) {
traitNameLabel.setText("-");
} else {
if (abcPanel != null) {
traitNameLabel.setText(trait.getName(abcPanel.abc).getName(abcPanel.abc.constants, null, false));
}
} else if (abcPanel != null) {
traitNameLabel.setText(trait.getName(abcPanel.abc).getName(abcPanel.abc.constants, null, false));
}
});
@@ -218,6 +218,10 @@ public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHan
setCaretPosition(ActionUtils.getDocumentPosition(this, line, 0));
}
public void gotoLineCol(int line, int column) {
setCaretPosition(ActionUtils.getDocumentPosition(this, line, column));
}
public Point getLineLocation(int line) {
int pos = ActionUtils.getDocumentPosition(this, line + 1, 0);
if (pos < 0) {
@@ -114,11 +114,9 @@ public class UndoFixedEditorPane extends JEditorPane {
contentType = "text/plain";
originalContentType = getContentType();
changeContentType(contentType);
} else {
if (originalContentType != null) {
changeContentType(originalContentType);
originalContentType = null;
}
} else if (originalContentType != null) {
changeContentType(originalContentType);
originalContentType = null;
}
Stopwatch sw = Stopwatch.startNew();
@@ -379,9 +379,8 @@ config.description.lastSessionFileTitles = Contains the opened file titles from
config.group.name.paths = Paths
config.group.description.paths = Location of needed files
config.group.tip.paths = You can download these files on adobe webpage
config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html
config.group.linkText.paths = [visit]
config.group.tip.paths = Download projector and Playerglobal on <a href="%link1%">adobe webpage</a>. Flex SDK can be downloaded on <a href="%link2%">adobe devnet</a>.
config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html http://www.adobe.com/devnet/flex/flex-sdk-download.html
config.name.playerLocation = 1) Flash Player projector path
config.description.playerLocation = Location of standalone flash player executable. Used for Run action.
@@ -432,3 +431,9 @@ config.description.simplifyExpressions = Evaluate and simplify expressions to ma
config.name.resetLetterSpacingOnTextImport = Reset Letter Spacing on text import
config.description.resetLetterSpacingOnTextImport = Useful for cyrillic fonts, because they are wider
config.name.flexSdkLocation = 4) Flex SDK directory path
config.description.flexSdkLocation = Location of Adobe Flex SDK. It is used mostly for AS3 compilation.
config.name.useFlexAs3Compiler = Use Flex SDK AS3 compiler
config.description.useFlexAs3Compiler = Use AS3 compiler from Flex SDK while ActionScript direct editation (Flex SDK directory needs to be set)
@@ -363,9 +363,8 @@ config.description.lastSessionFileTitles = Obsahuje titulky souboru z naposledy
config.group.name.paths = Cesty
config.group.description.paths = Um\u00edst\u011bn\u00ed pot\u0159ebn\u00fdch soubor\u016f
config.group.tip.paths = Tyto soubory m\u016f\u017eete st\u00e1hnout na str\u00e1nk\u00e1ch adobe
config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html
config.group.linkText.paths = [nav\u0161t\u00edvit]
config.group.tip.paths = Stahn\u011bte si projector a Playerglobal na <a href="%link1%">str\u00e1nk\u00e1ch adobe</a>. Flex SDK lze stahnout na <a href="%link2%">webu adobe devnet</a>.
config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html http://www.adobe.com/devnet/flex/flex-sdk-download.html
config.name.playerLocation = 1) Cesta k Flash Player projectoru
config.description.playerLocation = Um\u00edst\u011bn\u00ed spustiteln\u00e9ho flash playeru. Pou\u017e\u00edvan\u00e9 pro akci Spustit.
@@ -379,9 +379,10 @@ config.description.lastSessionFileTitles = Contiene los t\u00edtulos de archivoa
config.group.name.paths = Rutas
config.group.description.paths = Ubicaci\u00f3n de los archivos necesarios
config.group.tip.paths = Usted puede bajar estos archivos desde la p\u00e1gina web de Adobe
config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html
config.group.linkText.paths = [visita]
#config.group.tip.paths = Usted puede bajar estos archivos desde la p\u00e1gina web de Adobe
#TODO: translate again:
config.group.tip.paths = Download projector and Playerglobal on <a href="%link1%">adobe webpage</a>. Flex SDK can be downloaded on <a href="%link2%">adobe devnet</a>.
config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html http://www.adobe.com/devnet/flex/flex-sdk-download.html
config.name.playerLocation = 1) Ruta de Flash Player projector
config.description.playerLocation = Ubicaci\u00f3n del ejecutable aut\u00f3nomo de Flash Player. Utilizado para la acci\u00f3n Correr.
@@ -379,9 +379,10 @@ config.description.lastSessionFileTitles = Comprend les titres des fichiers ouve
config.group.name.paths = Chemins
config.group.description.paths = Location des fichiers demand\u00e9s
config.group.tip.paths = Vous pouvez t\u00e9l\u00e9charger ces fichiers depuis le site web d'Adobe
config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html
config.group.linkText.paths = [visiter]
#config.group.tip.paths = Vous pouvez t\u00e9l\u00e9charger ces fichiers depuis le site web d'Adobe
#TODO: translate again:
config.group.tip.paths = Download projector and Playerglobal on <a href="%link1%">adobe webpage</a>. Flex SDK can be downloaded on <a href="%link2%">adobe devnet</a>.
config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html http://www.adobe.com/devnet/flex/flex-sdk-download.html
config.name.playerLocation = 1) Chemin du lecteur Flash
config.description.playerLocation = Location du lecteur autonome de fichier ex\u00e9cutable Flash. Used for Run action.
@@ -379,9 +379,10 @@ config.description.lastSessionFileTitles = Tartalmazza az utols\u00f3 munkamenet
config.group.name.paths = \u00datvonalak
config.group.description.paths = A sz\u00fcks\u00e9ges f\u00e1jlok el\u00e9rhet\u0151s\u00e9gei
config.group.tip.paths = Ezeket a f\u00e1jlokat az Adobe honlapj\u00e1r\u00f3l t\u00f6ltheti le
config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html
config.group.linkText.paths = [visit]
#config.group.tip.paths = Ezeket a f\u00e1jlokat az Adobe honlapj\u00e1r\u00f3l t\u00f6ltheti le
#TODO: translate again:
config.group.tip.paths = Download projector and Playerglobal on <a href="%link1%">adobe webpage</a>. Flex SDK can be downloaded on <a href="%link2%">adobe devnet</a>.
config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html http://www.adobe.com/devnet/flex/flex-sdk-download.html
config.name.playerLocation = 1) Flash Player projector \u00fatvonal
config.description.playerLocation = Standalone flash player helye. A Futtat\u00e1shoz sz\u00fcks\u00e9ges.
@@ -379,9 +379,10 @@ config.description.lastSessionFileTitles = Contiene i titoli dei file aperti nel
config.group.name.paths = Percorsi
config.group.description.paths = Ubicazione dei file richiesti
config.group.tip.paths = \ufffd possibile ottenere questi file dal sito Adobe
config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html
config.group.linkText.paths = [apri]
#config.group.tip.paths = possibile ottenere questi file dal sito Adobe
#TODO: translate again:
config.group.tip.paths = Download projector and Playerglobal on <a href="%link1%">adobe webpage</a>. Flex SDK can be downloaded on <a href="%link2%">adobe devnet</a>.
config.group.link.paths = https://www.adobe.com/support/flashplayer/debug_downloads.html http://www.adobe.com/devnet/flex/flex-sdk-download.html
config.name.playerLocation = 1) Percorso Flash Player
config.description.playerLocation = Posizione eseguibile Flash Player. Utilizzato per l'azione Esegui.
@@ -44,6 +44,7 @@ scripts.pcode = P-code
scripts.pcode_hex = P-code with Hex
scripts.hex = Hex
scripts.constants = Constants
scripts.as_method_stubs = ActionScript method stubs
binaryData = Binary data
binaryData.raw = Raw
@@ -735,4 +735,4 @@ generic.editor.amf3.help = AMF3 value syntax:\n\
%reference_sample%\n\
\ * Keys in Dictionary entries can be any type\n
contextmenu.showInResources = Show in Resources
message.flexpath.notset = Flex SDK not found. Please configure its path in Advanced Settings / Paths (4).
@@ -438,13 +438,11 @@ public class Win32ProcessTools extends ProcessTools {
bufSize = maxsize - pos;
}
} while (bufSize > 0);
} else {
if (hasGuard(mbi)) {
if (unsetGuard(hOtherProcess, mbi)) {
guardedPages.add(pg);
pg--;
continue;
}
} else if (hasGuard(mbi)) {
if (unsetGuard(hOtherProcess, mbi)) {
guardedPages.add(pg);
pg--;
continue;
}
}
actualPos += mbi.regionSize.longValue();
+8 -13
View File
@@ -966,12 +966,9 @@ public interface User32 extends StdCallLibrary, WinUser {
* process is idle.
*
* @return The following table shows the possible return values for this
* function.
* Return code: Description
* 0: The wait was satisfied successfully.
* WAIT_TIMEOUT: The wait was terminated because the time-out interval
* elapsed.
* WAIT_FAILED: An error occurred.
* function. Return code: Description 0: The wait was satisfied
* successfully. WAIT_TIMEOUT: The wait was terminated because the time-out
* interval elapsed. WAIT_FAILED: An error occurred.
*/
DWORD WaitForInputIdle(HANDLE hProcess, DWORD dwMilliseconds);
@@ -1099,8 +1096,7 @@ public interface User32 extends StdCallLibrary, WinUser {
* If the function fails, the return value is zero. To get extended error
* information, call {@link Kernel32#GetLastError}.
* {@link WinUser#WM_HOTKEY} messages generated by the hot key
* {@link WinUser#WM_HOTKEY} message.
* A combination of the following values
* {@link WinUser#WM_HOTKEY} message. A combination of the following values
* <ul>
* <li>{@link WinUser#MOD_ALT} Either ALT key must be held down.</li>
* <li>{@link WinUser#MOD_CONTROL} Either CTRL key must be held down.</li>
@@ -1317,11 +1313,10 @@ public interface User32 extends StdCallLibrary, WinUser {
*
* This function typically fails for one of the following reasons:
*
* - an invalid parameter value
* - the system class was registered by a different module
* - The WH_CBT hook is installed and returns a failure code
* - if one of the controls in the dialog template is not registered, or its
* window window procedure fails WM_CREATE or WM_NCCREATE
* - an invalid parameter value - the system class was registered by a
* different module - The WH_CBT hook is installed and returns a failure
* code - if one of the controls in the dialog template is not registered,
* or its window window procedure fails WM_CREATE or WM_NCCREATE
*/
public HWND CreateWindowEx(int dwExStyle, WString lpClassName,
String lpWindowName, int dwStyle, int x, int y, int nWidth,

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