mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-18 17:41:56 +00:00
Fixed: #2586 AS3 direct editation + decompilation - XML escape sequences and other XML problems
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.abc.avm2.model;
|
||||
|
||||
import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.parser.script.ActionScript3Parser;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
@@ -23,8 +25,17 @@ import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetVisitorInterface;
|
||||
import com.jpexs.decompiler.graph.TypeItem;
|
||||
import com.jpexs.decompiler.graph.model.LocalData;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.Reference;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* XML.
|
||||
@@ -40,6 +51,7 @@ public class XMLAVM2Item extends AVM2Item {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param instruction Instruction
|
||||
* @param lineStartIns Line start instruction
|
||||
* @param parts Parts
|
||||
@@ -54,14 +66,104 @@ public class XMLAVM2Item extends AVM2Item {
|
||||
visitor.visitAll(parts);
|
||||
}
|
||||
|
||||
private String handleSingleXml(String s, Reference<Boolean> inAttributeRef, Reference<Boolean> inOpeningTagRef) {
|
||||
|
||||
String identRegexp = "[:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][\\-\\.0-9:A-Z_a-z\\u00B7\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0300-\\u036F\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u203F-\\u2040\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD]*";
|
||||
|
||||
StringBuilder writer = new StringBuilder();
|
||||
|
||||
for (int j = 0; j < s.length(); j++) {
|
||||
char c = s.charAt(j);
|
||||
switch (c) {
|
||||
case '"':
|
||||
if (inOpeningTagRef.getVal()) {
|
||||
inAttributeRef.setVal(!inAttributeRef.getVal());
|
||||
}
|
||||
writer.append(c);
|
||||
break;
|
||||
case '<':
|
||||
Pattern p = Pattern.compile("^(" + identRegexp + ").*", Pattern.MULTILINE | Pattern.DOTALL);
|
||||
String sub = s.substring(j + 1);
|
||||
Matcher m = p.matcher(sub);
|
||||
writer.append(c);
|
||||
if (m.matches()) {
|
||||
inOpeningTagRef.setVal(true);
|
||||
String tag = m.group(1);
|
||||
writer.append(tag);
|
||||
j += tag.length();
|
||||
}
|
||||
break;
|
||||
case '>':
|
||||
if (inOpeningTagRef.getVal()) {
|
||||
inOpeningTagRef.setVal(false);
|
||||
}
|
||||
writer.append(c);
|
||||
break;
|
||||
default:
|
||||
if (inAttributeRef.getVal()) {
|
||||
switch (c) {
|
||||
case '\r':
|
||||
writer.append(" ");
|
||||
break;
|
||||
case '\n':
|
||||
writer.append(" ");
|
||||
break;
|
||||
case '\t':
|
||||
writer.append("	");
|
||||
break;
|
||||
default:
|
||||
writer.append(c);
|
||||
}
|
||||
} else {
|
||||
writer.append(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
|
||||
Reference<Boolean> inAttributeRef = new Reference<>(false);
|
||||
Reference<Boolean> inOpeningTagRef = new Reference<>(false);
|
||||
|
||||
if (parts.size() == 1 && parts.get(0) instanceof StringAVM2Item) {
|
||||
String s = ((StringAVM2Item) parts.get(0)).getValue();
|
||||
s = handleSingleXml(s, inAttributeRef, inOpeningTagRef);
|
||||
boolean validXml = true;
|
||||
try {
|
||||
ActionScript3Parser par = new ActionScript3Parser(new AbcIndexing());
|
||||
if (!par.checkBasicXmlOnly(s)) {
|
||||
validXml = false;
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
validXml = false;
|
||||
}
|
||||
|
||||
if (!validXml) {
|
||||
writer.append("new XML");
|
||||
writer.spaceBeforeCallParenthesis(1);
|
||||
writer.append("(\"").append(Helper.escapeActionScriptString(s)).append("\")");
|
||||
return writer;
|
||||
}
|
||||
writer.spaceBeforeCallParenthesis(precedence);
|
||||
writer.append(s);
|
||||
return writer;
|
||||
}
|
||||
|
||||
for (int i = 0; i < parts.size(); i++) {
|
||||
GraphTargetItem part = parts.get(i);
|
||||
GraphTargetItem partBefore = i > 0 ? parts.get(i - 1) : null;
|
||||
GraphTargetItem partAfter = i < parts.size() - 1 ? parts.get(i + 1) : null;
|
||||
|
||||
/*
|
||||
Older versions of Flex allow inserting escape sequences like \r, \n, \t
|
||||
into attributes. Air does not allow this. We handle this by converting it into XML entities.
|
||||
*/
|
||||
if (part instanceof StringAVM2Item) {
|
||||
String s = ((StringAVM2Item) part).getValue();
|
||||
|
||||
if (partAfter instanceof EscapeXAttrAVM2Item) {
|
||||
if (s.endsWith("\"")) {
|
||||
s = s.substring(0, s.length() - 1);
|
||||
@@ -72,7 +174,8 @@ public class XMLAVM2Item extends AVM2Item {
|
||||
s = s.substring(1);
|
||||
}
|
||||
}
|
||||
writer.append(s);
|
||||
|
||||
writer.append(handleSingleXml(s, inAttributeRef, inOpeningTagRef));
|
||||
} else if ((part instanceof EscapeXElemAVM2Item) || (part instanceof EscapeXAttrAVM2Item)) {
|
||||
part.toString(writer, localData);
|
||||
} else {
|
||||
|
||||
@@ -1572,6 +1572,21 @@ public class ActionScript3Parser {
|
||||
//TODO: Order of additions as in official compiler
|
||||
return ret;
|
||||
}
|
||||
|
||||
public boolean checkBasicXmlOnly(String txt) {
|
||||
lexer = new ActionScriptLexer(txt);
|
||||
try {
|
||||
xml(new ArrayList<>(), null, null, new Reference<>(false), new ArrayList<>(), new ArrayList<>(), new HashMap<>(), false, false, new ArrayList<>(), null);
|
||||
|
||||
ParsedSymbol s = lexer.lex();
|
||||
if (s.type != SymbolType.EOF) {
|
||||
return false;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private GraphTargetItem command(List<List<NamespaceItem>> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference<Boolean> needsActivation, List<DottedChain> importedClasses, List<NamespaceItem> openedNamespaces, Stack<Loop> loops, Map<Loop, String> loopLabels, HashMap<String, Integer> registerVars, boolean inFunction, boolean inMethod, int forinlevel, boolean mustBeCommand, List<AssignableAVM2Item> variables, ABC abc) throws IOException, AVM2ParseException, InterruptedException {
|
||||
LexBufferer buf = new LexBufferer();
|
||||
|
||||
Reference in New Issue
Block a user