This commit is contained in:
Exund
2022-04-19 22:09:03 +02:00
committed by Jindra Petřík
parent ae2ba584e5
commit 9a8d16311e
2 changed files with 69 additions and 77 deletions

View File

@@ -67,11 +67,15 @@ public class SwfXmlExporter {
private final Map<Class, List<Field>> cachedFields = new HashMap<>();
public List<File> exportXml(SWF swf, File outFile) throws IOException {
public List<File> exportXml(SWF swf, File outFile) throws IOException {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document xmlDoc = docBuilder.newDocument();
xmlDoc.appendChild(xmlDoc.createComment("WARNING: The structure of this XML is not final. In later versions of FFDec it can be changed."));
xmlDoc.appendChild(xmlDoc.createComment(ApplicationInfo.applicationVerName));
exportXml(swf, xmlDoc, xmlDoc);
try (Writer writer = new Utf8OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(outFile)))) {
writer.append(getXml(xmlDoc));
@@ -102,7 +106,7 @@ public class SwfXmlExporter {
}
public void exportXml(SWF swf, Document doc, Node node) throws IOException {
generateXml(doc, node, "swf", swf, false, 0, false);
generateXml(doc, node, "swf", swf, false, false);
}
public List<Field> getSwfFieldsCached(Class cls) {
@@ -115,7 +119,7 @@ public class SwfXmlExporter {
return result;
}
private void generateXml(Document doc, Node node, String name, Object obj, boolean isListItem, int level, boolean needsCData) {
private void generateXml(Document doc, Node node, String name, Object obj, boolean isListItem, boolean needsCData) {
Class cls = obj != null ? obj.getClass() : null;
if (obj != null && needsCData && cls == String.class) {
@@ -156,20 +160,16 @@ public class SwfXmlExporter {
} else if (obj instanceof byte[]) {
byte[] data = (byte[]) obj;
((Element) node).setAttribute(name, Helper.byteArrayToHex(data));
} else if (cls != null && obj != null && List.class.isAssignableFrom(cls)) {
List list = (List) obj;
Element listNode = doc.createElement(name);
node.appendChild(listNode);
for (int i = 0; i < list.size(); i++) {
generateXml(doc, listNode, "item", list.get(i), true, level + 1, false);
} else if (cls != null && (cls.isArray() || List.class.isAssignableFrom(cls))) {
if(List.class.isAssignableFrom(cls)) {
obj = ((List)obj).toArray();
}
} else if (cls != null && cls.isArray()) {
Class arrayType = cls.getComponentType();
Element arrayNode = doc.createElement(name);
node.appendChild(arrayNode);
int length = Array.getLength(obj);
for (int i = 0; i < length; i++) {
generateXml(doc, arrayNode, "item", Array.get(obj, i), true, level + 1, false);
generateXml(doc, arrayNode, "item", Array.get(obj, i), true, false);
}
} else if (obj != null) {
if (obj instanceof LazyObject) {
@@ -186,15 +186,10 @@ public class SwfXmlExporter {
Element objNode = doc.createElement(name);
objNode.setAttribute("type", className);
if (obj instanceof UnknownTag) {
objNode.setAttribute("tagId", "" + ((Tag) obj).getId());
objNode.setAttribute("tagId", String.valueOf(((Tag) obj).getId()));
}
node.appendChild(objNode);
if (level == 0) {
objNode.appendChild(doc.createComment("WARNING: The structure of this XML is not final. In later versions of FFDec it can be changed."));
objNode.appendChild(doc.createComment(ApplicationInfo.applicationVerName));
}
for (Field f : fields) {
if (Modifier.isStatic(f.getModifiers())) {
continue;
@@ -208,7 +203,7 @@ public class SwfXmlExporter {
try {
f.setAccessible(true);
generateXml(doc, objNode, f.getName(), f.get(obj), false, level + 1, multilineA != null);
generateXml(doc, objNode, f.getName(), f.get(obj), false, multilineA != null);
} catch (IllegalArgumentException | IllegalAccessException ex) {
logger.log(Level.SEVERE, null, ex);
}

View File

@@ -133,11 +133,63 @@ public class SwfXmlImporter {
private static final Logger logger = Logger.getLogger(SwfXmlImporter.class.getName());
private Map<String, Class> swfTags;
private static final Map<String, Class> swfTags;
private Map<String, Class> swfObjects;
private static final Map<String, Class> swfObjects;
private Map<String, Class> swfObjectsParam;
private static final Map<String, Class> swfObjectsParam;
static {
Map<String, Class> tags = new HashMap<>();
Map<Integer, TagTypeInfo> knownTags = Tag.getKnownClasses();
for (Integer key : knownTags.keySet()) {
Class cls = knownTags.get(key).getCls();
if (!ReflectionTools.canInstantiate(cls)) {
System.err.println("Can't instantiate: " + cls.getName());
}
tags.put(cls.getSimpleName(), cls);
}
swfTags = tags;
Map<String, Class> objects = new HashMap<>();
Class[] knownObjects = new Class[]{ALPHABITMAPDATA.class, ALPHACOLORMAPDATA.class, ARGB.class, BITMAPDATA.class,
BUTTONCONDACTION.class, BUTTONRECORD.class, CLIPACTIONRECORD.class, CLIPACTIONS.class, CLIPEVENTFLAGS.class,
COLORMAPDATA.class, ColorTransform.class, CXFORM.class, CXFORMWITHALPHA.class,
FILLSTYLE.class, FILLSTYLEARRAY.class, FOCALGRADIENT.class, GLYPHENTRY.class, GRADIENT.class, GRADRECORD.class,
KERNINGRECORD.class, LANGCODE.class, LINESTYLE.class, LINESTYLE2.class, LINESTYLEARRAY.class, MATRIX.class,
MORPHFILLSTYLE.class, MORPHFILLSTYLEARRAY.class, MORPHFOCALGRADIENT.class, MORPHGRADIENT.class,
MORPHGRADRECORD.class, MORPHLINESTYLE.class, MORPHLINESTYLE2.class, MORPHLINESTYLEARRAY.class, PIX15.class,
PIX24.class, RECT.class, RGB.class, RGBA.class, SHAPE.class, SHAPEWITHSTYLE.class, SOUNDENVELOPE.class,
SOUNDINFO.class, TEXTRECORD.class, ZONEDATA.class, ZONERECORD.class,
CurvedEdgeRecord.class, EndShapeRecord.class, StraightEdgeRecord.class, StyleChangeRecord.class,
BEVELFILTER.class, BLURFILTER.class, COLORMATRIXFILTER.class, CONVOLUTIONFILTER.class,
DROPSHADOWFILTER.class, GLOWFILTER.class, GRADIENTBEVELFILTER.class, GRADIENTGLOWFILTER.class,
AVM2ConstantPool.class, Decimal.class, Namespace.class, NamespaceSet.class, Multiname.class, MethodInfo.class, MetadataInfo.class,
ValueKind.class, InstanceInfo.class, Traits.class, TraitClass.class, TraitFunction.class,
TraitMethodGetterSetter.class, TraitSlotConst.class, ClassInfo.class, ScriptInfo.class, MethodBody.class,
ABCException.class, ABCVersion.class, Amf3Value.class};
for (Class cls2 : knownObjects) {
if (!ReflectionTools.canInstantiateDefaultConstructor(cls2)) {
System.err.println("Can't instantiate: " + cls2.getName());
}
objects.put(cls2.getSimpleName(), cls2);
}
swfObjects = objects;
Map<String, Class> objectsParam = new HashMap<>();
Class[] knownObjectsParam = new Class[]{ABC.class};
for (Class cls2 : knownObjectsParam) {
if (!ReflectionTools.canInstantiate(cls2)) {
System.err.println("Can't instantiate: " + cls2.getName());
}
objectsParam.put(cls2.getSimpleName(), cls2);
}
swfObjectsParam = objectsParam;
}
public void importSwf(SWF swf, String xml) throws IOException {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
@@ -309,20 +361,6 @@ public class SwfXmlImporter {
}
private Object createObject(String type, int tagTypeId, SWF swf, Tag tag) throws NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
if (swfTags == null) {
Map<String, Class> tags = new HashMap<>();
Map<Integer, TagTypeInfo> knownTags = Tag.getKnownClasses();
for (Integer key : knownTags.keySet()) {
Class cls = knownTags.get(key).getCls();
if (!ReflectionTools.canInstantiate(cls)) {
System.err.println("Can't instantiate: " + cls.getName());
}
tags.put(cls.getSimpleName(), cls);
}
swfTags = tags;
}
if ("UnknownTag".equals(type)) {
return new UnknownTag(swf, tagTypeId);
}
@@ -332,52 +370,11 @@ public class SwfXmlImporter {
return cls.getConstructor(SWF.class).newInstance(swf);
}
if (swfObjects == null) {
Map<String, Class> objects = new HashMap<>();
Class[] knownObjects = new Class[]{ALPHABITMAPDATA.class, ALPHACOLORMAPDATA.class, ARGB.class, BITMAPDATA.class,
BUTTONCONDACTION.class, BUTTONRECORD.class, CLIPACTIONRECORD.class, CLIPACTIONS.class, CLIPEVENTFLAGS.class,
COLORMAPDATA.class, ColorTransform.class, CXFORM.class, CXFORMWITHALPHA.class,
FILLSTYLE.class, FILLSTYLEARRAY.class, FOCALGRADIENT.class, GLYPHENTRY.class, GRADIENT.class, GRADRECORD.class,
KERNINGRECORD.class, LANGCODE.class, LINESTYLE.class, LINESTYLE2.class, LINESTYLEARRAY.class, MATRIX.class,
MORPHFILLSTYLE.class, MORPHFILLSTYLEARRAY.class, MORPHFOCALGRADIENT.class, MORPHGRADIENT.class,
MORPHGRADRECORD.class, MORPHLINESTYLE.class, MORPHLINESTYLE2.class, MORPHLINESTYLEARRAY.class, PIX15.class,
PIX24.class, RECT.class, RGB.class, RGBA.class, SHAPE.class, SHAPEWITHSTYLE.class, SOUNDENVELOPE.class,
SOUNDINFO.class, TEXTRECORD.class, ZONEDATA.class, ZONERECORD.class,
CurvedEdgeRecord.class, EndShapeRecord.class, StraightEdgeRecord.class, StyleChangeRecord.class,
BEVELFILTER.class, BLURFILTER.class, COLORMATRIXFILTER.class, CONVOLUTIONFILTER.class,
DROPSHADOWFILTER.class, GLOWFILTER.class, GRADIENTBEVELFILTER.class, GRADIENTGLOWFILTER.class,
AVM2ConstantPool.class, Decimal.class, Namespace.class, NamespaceSet.class, Multiname.class, MethodInfo.class, MetadataInfo.class,
ValueKind.class, InstanceInfo.class, Traits.class, TraitClass.class, TraitFunction.class,
TraitMethodGetterSetter.class, TraitSlotConst.class, ClassInfo.class, ScriptInfo.class, MethodBody.class,
ABCException.class, ABCVersion.class, Amf3Value.class};
for (Class cls2 : knownObjects) {
if (!ReflectionTools.canInstantiateDefaultConstructor(cls2)) {
System.err.println("Can't instantiate: " + cls2.getName());
}
objects.put(cls2.getSimpleName(), cls2);
}
swfObjects = objects;
}
cls = swfObjects.get(type);
if (cls != null) {
return cls.getConstructor().newInstance();
}
if (swfObjectsParam == null) {
Map<String, Class> objects = new HashMap<>();
Class[] knownObjects = new Class[]{ABC.class};
for (Class cls2 : knownObjects) {
if (!ReflectionTools.canInstantiate(cls2)) {
System.err.println("Can't instantiate: " + cls2.getName());
}
objects.put(cls2.getSimpleName(), cls2);
}
swfObjectsParam = objects;
}
cls = swfObjectsParam.get(type);
if (cls != null) {
for (Constructor<?> constructor : cls.getConstructors()) {