mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-05 11:14:50 +00:00
Parsing Flex SDK errors
init swf to flex before editig
This commit is contained in:
@@ -2502,6 +2502,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
|
||||
public void clearImageCache() {
|
||||
jtt = null;
|
||||
frameCache.clear();
|
||||
rectCache.clear();
|
||||
for (Tag tag : getTags()) {
|
||||
@@ -2898,8 +2899,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
timelined.setModified(true);
|
||||
timelined.resetTimeline();
|
||||
} else // timeline should be always the swf here
|
||||
{
|
||||
if (removeDependencies) {
|
||||
if (removeDependencies) {
|
||||
removeTagWithDependenciesFromTimeline(tag, timelined.getTimeline());
|
||||
timelined.setModified(true);
|
||||
} else {
|
||||
@@ -2908,7 +2908,6 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
timelined.setModified(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -56,19 +56,15 @@ import com.jpexs.decompiler.flash.abc.usages.MethodParamsMultinameUsage;
|
||||
import com.jpexs.decompiler.flash.abc.usages.MethodReturnTypeMultinameUsage;
|
||||
import com.jpexs.decompiler.flash.abc.usages.MultinameUsage;
|
||||
import com.jpexs.decompiler.flash.abc.usages.TypeNameMultinameUsage;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.dumpview.DumpInfo;
|
||||
import com.jpexs.decompiler.flash.dumpview.DumpInfoSpecial;
|
||||
import com.jpexs.decompiler.flash.dumpview.DumpInfoSpecialType;
|
||||
import com.jpexs.decompiler.flash.exporters.script.LinkReportExporter;
|
||||
import com.jpexs.decompiler.flash.flexsdk.MxmlcAs3ScriptReplacer;
|
||||
import com.jpexs.decompiler.flash.flexsdk.MxmlcException;
|
||||
import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
|
||||
import com.jpexs.decompiler.flash.importers.As3ScriptReplaceException;
|
||||
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.types.annotations.Internal;
|
||||
import com.jpexs.decompiler.graph.CompilationException;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
import com.jpexs.helpers.utf8.Utf8PrintWriter;
|
||||
import java.io.IOException;
|
||||
@@ -1405,7 +1401,7 @@ public class ABC {
|
||||
method_info.remove(index);
|
||||
}
|
||||
|
||||
public boolean replaceScriptPack(As3ScriptReplacerInterface replacer, ScriptPack pack, String as) throws AVM2ParseException, CompilationException, IOException, InterruptedException {
|
||||
public boolean replaceScriptPack(As3ScriptReplacerInterface replacer, ScriptPack pack, String as) throws As3ScriptReplaceException, IOException, InterruptedException {
|
||||
replacer.replaceScript(pack, as);
|
||||
((Tag) parentTag).setModified(true);
|
||||
return pack.isSimple;
|
||||
|
||||
@@ -6,6 +6,7 @@ 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;
|
||||
@@ -127,14 +128,15 @@ public class SwfToSwcExporter {
|
||||
String defId = dottedChainToId(cp.packageStr.add(cp.className));
|
||||
|
||||
sb.append(" <def id=\"").append(defId).append("\" />\n");
|
||||
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<>());
|
||||
|
||||
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;
|
||||
@@ -185,14 +187,22 @@ public class SwfToSwcExporter {
|
||||
private SWF recompileSWF(SWF swf) throws IOException, InterruptedException {
|
||||
ByteArrayOutputStream swfOrigBaos = new ByteArrayOutputStream();
|
||||
swf.saveTo(swfOrigBaos);
|
||||
return new SWF(new ByteArrayInputStream(swfOrigBaos.toByteArray()), false, false);
|
||||
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);
|
||||
@@ -208,6 +218,7 @@ public class SwfToSwcExporter {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (list.get(i) instanceof SymbolClassTag) {
|
||||
SymbolClassTag sct = (SymbolClassTag) list.get(i);
|
||||
@@ -220,20 +231,33 @@ public class SwfToSwcExporter {
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
@@ -277,6 +301,8 @@ public class SwfToSwcExporter {
|
||||
tempFile.delete();
|
||||
}
|
||||
}
|
||||
long t7 = System.currentTimeMillis();
|
||||
printDelay("swc.zip", t6, t7);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ 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;
|
||||
@@ -31,14 +33,22 @@ 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 LinkReportExporter linkReporter;
|
||||
private ScriptPack initedPack;
|
||||
private File tempDir;
|
||||
private File pkgDir;
|
||||
private File swcFile;
|
||||
|
||||
public MxmlcAs3ScriptReplacer(String flexSdkPath, LinkReportExporter linkReporter) {
|
||||
public MxmlcAs3ScriptReplacer(String flexSdkPath) {
|
||||
super(flexSdkPath);
|
||||
this.linkReporter = linkReporter;
|
||||
}
|
||||
|
||||
private synchronized boolean isInited(ScriptPack pack) {
|
||||
return tempDir != null && initedPack == pack;
|
||||
}
|
||||
|
||||
private static void deleteFolder(File folder) {
|
||||
@@ -58,7 +68,7 @@ public class MxmlcAs3ScriptReplacer extends MxmlcRunner implements As3ScriptRepl
|
||||
private SWF recompileSWF(SWF swf) throws IOException, InterruptedException {
|
||||
ByteArrayOutputStream swfOrigBaos = new ByteArrayOutputStream();
|
||||
swf.saveTo(swfOrigBaos);
|
||||
return new SWF(new ByteArrayInputStream(swfOrigBaos.toByteArray()), false, false);
|
||||
return new SWF(new ByteArrayInputStream(swfOrigBaos.toByteArray()), Configuration.parallelSpeedUp.get(), false);
|
||||
}
|
||||
|
||||
private boolean isParentDeleted(ABC abc, List<ABC> allAbcs, DottedChain className) {
|
||||
@@ -91,27 +101,157 @@ public class MxmlcAs3ScriptReplacer extends MxmlcRunner implements As3ScriptRepl
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceScript(ScriptPack pack, String text) throws AVM2ParseException, CompilationException, IOException, InterruptedException {
|
||||
public synchronized void replaceScript(ScriptPack pack, String text) throws As3ScriptReplaceException, IOException, InterruptedException {
|
||||
if (!pack.isSimple) {
|
||||
throw new IOException("Cannot compile such file"); //Alchemy, etc.
|
||||
throw new IOException("Cannot compile such file"); //Alchemy, etc. TODO: handle better
|
||||
}
|
||||
|
||||
File tempDir = null;
|
||||
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();
|
||||
File pkgDir = tempDir;
|
||||
pkgDir = tempDir;
|
||||
for (String pkgPart : pack.getClassPath().packageStr.toList()) {
|
||||
if (!pkgPart.isEmpty()) {
|
||||
pkgDir = new File(pkgDir, pkgPart);
|
||||
}
|
||||
}
|
||||
pkgDir.mkdirs();
|
||||
File scriptFileToCompile = new File(pkgDir, pack.getClassPath().className + ".as");
|
||||
File compiledSwfFile = new File(pkgDir, "out.swf");
|
||||
File swcFile = new File(pkgDir, "out.swc");
|
||||
|
||||
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();
|
||||
@@ -135,6 +275,7 @@ public class MxmlcAs3ScriptReplacer extends MxmlcRunner implements As3ScriptRepl
|
||||
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,
|
||||
@@ -146,115 +287,25 @@ public class MxmlcAs3ScriptReplacer extends MxmlcRunner implements As3ScriptRepl
|
||||
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);
|
||||
|
||||
//Write new script
|
||||
Helper.writeFile(scriptFileToCompile.getAbsolutePath(), text.getBytes("UTF-8"));
|
||||
|
||||
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) {
|
||||
throw new AVM2ParseException(ex1.getMxmlcErrorOutput(), 0);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
} finally {
|
||||
if (tempDir != null && tempDir.exists()) {
|
||||
deleteFolder(tempDir);
|
||||
}
|
||||
} catch (IOException iex) {
|
||||
//ignore
|
||||
} catch (InterruptedException ex) {
|
||||
//ignore
|
||||
}
|
||||
this.initedPack = pack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
String flexLocation = Configuration.flexSdkLocation.get();
|
||||
return !(flexLocation.isEmpty() || (!new File(MxmlcRunner.getMxmlcPath(flexLocation)).exists()));
|
||||
public synchronized void deinitReplacement(ScriptPack pack) {
|
||||
if (tempDir != null && tempDir.exists()) {
|
||||
deleteFolder(tempDir);
|
||||
}
|
||||
tempDir = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,10 +51,10 @@ public class AS3ScriptImporter {
|
||||
|
||||
try {
|
||||
pack.abc.replaceScriptPack(scriptReplacer, 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));
|
||||
} 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.jpexs.decompiler.flash.importers;
|
||||
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.exporters.script.LinkReportExporter;
|
||||
import com.jpexs.decompiler.flash.flexsdk.MxmlcAs3ScriptReplacer;
|
||||
|
||||
public class As3ScriptReplacerFactory {
|
||||
@@ -15,7 +14,7 @@ public class As3ScriptReplacerFactory {
|
||||
}
|
||||
|
||||
public static As3ScriptReplacerInterface createFlex() {
|
||||
return new MxmlcAs3ScriptReplacer(Configuration.flexSdkLocation.get(), new LinkReportExporter());
|
||||
return new MxmlcAs3ScriptReplacer(Configuration.flexSdkLocation.get());
|
||||
}
|
||||
|
||||
public static As3ScriptReplacerInterface createFFDec() {
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
package com.jpexs.decompiler.flash.importers;
|
||||
|
||||
import com.jpexs.decompiler.flash.abc.ScriptPack;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException;
|
||||
import com.jpexs.decompiler.graph.CompilationException;
|
||||
import java.io.IOException;
|
||||
|
||||
public interface As3ScriptReplacerInterface {
|
||||
|
||||
public boolean isAvailable();
|
||||
|
||||
public void replaceScript(ScriptPack pack, String text) throws AVM2ParseException, CompilationException, IOException, InterruptedException;
|
||||
public void initReplacement(ScriptPack pack);
|
||||
|
||||
public void replaceScript(ScriptPack pack, String text) throws As3ScriptReplaceException, IOException, InterruptedException;
|
||||
|
||||
public void deinitReplacement(ScriptPack pack);
|
||||
}
|
||||
|
||||
@@ -14,53 +14,62 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
public class FFDecAs3ScriptReplacer implements As3ScriptReplacerInterface {
|
||||
|
||||
@Override
|
||||
public void replaceScript(ScriptPack pack, String text) throws AVM2ParseException, CompilationException, 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();
|
||||
String documentClass = swf.getDocumentClass();
|
||||
boolean isDocumentClass = documentClass != null && documentClass.equals(pack.getClassPath().toString());
|
||||
public void replaceScript(ScriptPack pack, String text) throws As3ScriptReplaceException, IOException, InterruptedException {
|
||||
try {
|
||||
ABC abc = pack.abc;
|
||||
SWF swf = pack.abc.getSwf();
|
||||
String scriptName = pack.getPathScriptName() + ".as";
|
||||
int oldIndex = pack.scriptIndex;
|
||||
int newIndex = abc.script_info.size();
|
||||
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 {
|
||||
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) {
|
||||
si.traits.traits.get(t).delete(abc, true);
|
||||
}
|
||||
}
|
||||
if (si.traits.traits.get(t) instanceof TraitClass) {
|
||||
TraitClass tc = (TraitClass) si.traits.traits.get(t);
|
||||
newClassIndex = tc.class_info + 1;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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(newIndex).setModified(true);
|
||||
//Note: Is deleting traits safe?
|
||||
List<Integer> todel = new ArrayList<>(new TreeSet<>(pack.traitIndices));
|
||||
for (int i = todel.size() - 1; i >= 0; i--) {
|
||||
si.traits.traits.remove((int) todel.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
abc.script_info.get(oldIndex)
|
||||
.setModified(true);
|
||||
} catch (AVM2ParseException ex) {
|
||||
throw new As3ScriptReplaceException(new As3ScriptReplaceExceptionItem(null, ex.text, (int) ex.line));
|
||||
} catch (CompilationException ex) {
|
||||
throw new As3ScriptReplaceException(new As3ScriptReplaceExceptionItem(null, ex.text, ex.line));
|
||||
}
|
||||
List<ABC> otherAbcs = new ArrayList<>(pack.allABCs);
|
||||
otherAbcs.remove(abc);
|
||||
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(newIndex).setModified(true);
|
||||
//Note: Is deleting traits safe?
|
||||
List<Integer> todel = new ArrayList<>(new TreeSet<>(pack.traitIndices));
|
||||
for (int i = todel.size() - 1; i >= 0; i--) {
|
||||
si.traits.traits.remove((int) todel.get(i));
|
||||
}
|
||||
}
|
||||
abc.script_info.get(oldIndex).setModified(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,4 +78,14 @@ public class FFDecAs3ScriptReplacer implements As3ScriptReplacerInterface {
|
||||
return !(swc == null || !swc.exists());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initReplacement(ScriptPack pack) {
|
||||
//empty
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deinitReplacement(ScriptPack pack) {
|
||||
//empty
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user