AMF3 tests, exceptions

This commit is contained in:
Jindra Petřík
2016-07-17 15:48:56 +02:00
parent ec5ca5c3f1
commit f7b3d502cb
39 changed files with 2639 additions and 1545 deletions

View File

@@ -12,8 +12,10 @@ import com.jpexs.decompiler.flash.amf.amf3.types.VectorDoubleType;
import com.jpexs.decompiler.flash.amf.amf3.types.DictionaryType;
import com.jpexs.decompiler.flash.amf.amf3.types.VectorUIntType;
import com.jpexs.decompiler.flash.amf.amf3.types.BasicType;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.NoSuchFileException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -103,7 +105,7 @@ public class AMF3InputStream extends InputStream {
byte buf[] = new byte[(int) byteLength]; //how about long strings(?), will the int length be enough?
int cnt = is.read(buf);
if (cnt < buf.length) {
throw new IOException("EOF");
throw new PrematureEndOfTheStreamException();
}
String retString = new String(buf, "UTF-8");
return retString;
@@ -131,7 +133,7 @@ public class AMF3InputStream extends InputStream {
private int safeRead() throws IOException {
int ret = read();
if (ret == -1) {
throw new IOException("EOF");
throw new PrematureEndOfTheStreamException();
}
return ret;
}
@@ -141,11 +143,11 @@ public class AMF3InputStream extends InputStream {
return is.read();
}
public Object readValue() throws IOException {
public Object readValue() throws IOException, NoSerializerExistsException {
return readValue(new HashMap<>());
}
public Object readValue(Map<String, ObjectTypeSerializeHandler> serializers) throws IOException {
public Object readValue(Map<String, ObjectTypeSerializeHandler> serializers) throws IOException, NoSerializerExistsException {
return readValue(serializers, new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
}
@@ -153,7 +155,7 @@ public class AMF3InputStream extends InputStream {
List<Object> objectTable,
List<Traits> traitsTable,
List<String> stringTable
) throws IOException {
) throws IOException, NoSerializerExistsException {
int marker = readU8();
switch (marker) {
@@ -197,7 +199,7 @@ public class AMF3InputStream extends InputStream {
byte buf[] = new byte[(int) byteLength]; //TODO: long strings, int is not enough for them
int cnt = is.read(buf);
if (cnt < buf.length) {
throw new IOException("EOF");
throw new PrematureEndOfTheStreamException();
}
xval = new String(buf, "UTF-8");
}
@@ -243,14 +245,27 @@ public class AMF3InputStream extends InputStream {
if (key.isEmpty()) {
break;
} else {
Object val = readValue(serializers, objectTable, traitsTable, stringTable);
assocPart.add(new Pair<>(key, val));
try {
Object val = readValue(serializers, objectTable, traitsTable, stringTable);
assocPart.add(new Pair<>(key, val));
} catch (NoSerializerExistsException nse) {
assocPart.add(new Pair<>(key, nse.getIncompleteData()));
throw new NoSerializerExistsException(nse.getClassName(), retArray, nse);
}
}
}
LOGGER.log(Level.FINEST, "Array value: assocSize={0}", new Object[]{assocPart.size()});
for (int i = 0; i < denseCount; i++) {
densePart.add(readValue(serializers, objectTable, traitsTable, stringTable));
try {
densePart.add(readValue(serializers, objectTable, traitsTable, stringTable));
} catch (NoSerializerExistsException nse) {
densePart.add(nse.getIncompleteData());
for (int j = i + 1; j < denseCount; j++) {
densePart.add(BasicType.UNKNOWN);
}
throw new NoSerializerExistsException(nse.getClassName(), retArray, nse);
}
}
LOGGER.log(Level.FINER, "Array value: dense_size={0},assocSize={1}", new Object[]{densePart.size(), assocPart.size()});
return retArray;
@@ -274,13 +289,17 @@ public class AMF3InputStream extends InputStream {
if (objectTraitsExtFlag == 1) {
String className = readUtf8Vr(stringTable);
if (!serializers.containsKey(className)) {
throw new IOException("No (de)serializer for class " + className + " found");
throw new NoSerializerExistsException(className, new ObjectType(className, null, new ArrayList<>()), null);
}
retObjectType = serializers.get(className).readObject(className, is);
MonitoredInputStream mis = new MonitoredInputStream(is);
List<Pair<String, Object>> serMembers = serializers.get(className).readObject(className, mis);
byte serData[] = mis.getReadData();
retObjectType = new ObjectType(className, serData, serMembers);
LOGGER.log(Level.FINER, "Object/Traits value: customSerialized");
traits = new Traits(className, true, new ArrayList<>());// FIXME???
traitsTable.add(traits);
//TODO: verify this
objectTable.add(retObjectType);
return retObjectType;
} else {
int dynamicFlag = (int) ((objectU29 >> 3) & 1);
int numSealed = (int) (objectU29 >> 4);
@@ -310,8 +329,19 @@ public class AMF3InputStream extends InputStream {
Object retObjectType = new ObjectType(traits.isDynamic(), sealedMembers, dynamicMembers, traits.getClassName());
objectTable.add(retObjectType); //add it before any subvalue can reference it
List<Object> sealedMemberValues = new ArrayList<>();
NoSerializerExistsException error = null;
for (int i = 0; i < traits.getSealedMemberNames().size(); i++) {
sealedMemberValues.add(readValue(serializers, objectTable, traitsTable, stringTable));
try {
sealedMemberValues.add(readValue(serializers, objectTable, traitsTable, stringTable));
} catch (NoSerializerExistsException nse) {
sealedMemberValues.add(nse.getIncompleteData());
for (int j = i + 1; j < traits.getSealedMemberNames().size(); j++) {
sealedMemberValues.add(BasicType.UNKNOWN);
}
error = nse;
break;
}
}
for (int i = 0; i < traits.getSealedMemberNames().size(); i++) {
@@ -320,8 +350,13 @@ public class AMF3InputStream extends InputStream {
if (traits.isDynamic()) {
String dynamicMemberName;
while (!(dynamicMemberName = readUtf8Vr(stringTable)).isEmpty()) {
Object dynamicMemberValue = readValue(serializers, objectTable, traitsTable, stringTable);
dynamicMembers.add(new Pair<>(dynamicMemberName, dynamicMemberValue));
try {
Object dynamicMemberValue = readValue(serializers, objectTable, traitsTable, stringTable);
dynamicMembers.add(new Pair<>(dynamicMemberName, dynamicMemberValue));
} catch (NoSerializerExistsException nse) {
dynamicMembers.add(new Pair<>(dynamicMemberName, nse.getIncompleteData()));
throw new NoSerializerExistsException(nse.getClassName(), retObjectType, nse);
}
}
}
@@ -356,7 +391,7 @@ public class AMF3InputStream extends InputStream {
int byteArrayLength = (int) (byteArrayU29 >> 1);
byte byteArrayBuf[] = new byte[byteArrayLength];
if (is.read(byteArrayBuf) != byteArrayLength) {
throw new IOException("EOF");
throw new PrematureEndOfTheStreamException();
}
LOGGER.log(Level.FINER, "ByteArray value: bytes[{0}]", byteArrayLength);
@@ -437,12 +472,25 @@ public class AMF3InputStream extends InputStream {
int fixed = readU8();
String objectTypeName = readUtf8Vr(stringTable); //uses "*" for any type
List<Object> vals = new ArrayList<>();
NoSerializerExistsException error = null;
for (int i = 0; i < vectorObjectCountItems; i++) {
vals.add(readValue(serializers, objectTable, traitsTable, stringTable));
try {
vals.add(readValue(serializers, objectTable, traitsTable, stringTable));
} catch (NoSerializerExistsException nse) {
vals.add(nse.getIncompleteData());
for (int j = i + 1; j < vectorObjectCountItems; j++) {
vals.add(BasicType.UNKNOWN);
}
error = nse;
break;
}
}
VectorObjectType retVectorObject = new VectorObjectType(fixed == 1, objectTypeName, vals);
LOGGER.log(Level.FINER, "Vector<Object> value: fixed={0}, size={1}, typeName:{2}]", new Object[]{fixed, vectorObjectCountItems, objectTypeName});
objectTable.add(retVectorObject);
if (error != null) {
throw new NoSerializerExistsException(error.getClassName(), retVectorObject, error);
}
return retVectorObject;
} else {
int refIndexVectorObject = (int) (vectorObjectU29 >> 1);
@@ -456,13 +504,37 @@ public class AMF3InputStream extends InputStream {
int numEntries = (int) (dictionaryObjectU29 >> 1);
int weakKeys = readU8();
List<Pair<Object, Object>> data = new ArrayList<>();
NoSerializerExistsException error = null;
for (int i = 0; i < numEntries; i++) {
Object key = readValue(serializers, objectTable, traitsTable, stringTable);
Object val = readValue(serializers, objectTable, traitsTable, stringTable);
Object key;
Object val;
try {
key = readValue(serializers, objectTable, traitsTable, stringTable);
try {
val = readValue(serializers, objectTable, traitsTable, stringTable);
} catch (NoSerializerExistsException nse) {
error = nse;
val = BasicType.UNKNOWN;
}
} catch (NoSerializerExistsException nse) {
error = nse;
key = BasicType.UNKNOWN;
val = BasicType.UNKNOWN;
}
data.add(new Pair<>(key, val));
if (error != null) {
for (int j = i + 1; j < numEntries; j++) {
data.add(new Pair<>(BasicType.UNKNOWN, BasicType.UNKNOWN));
}
break;
}
}
DictionaryType retDictionary = new DictionaryType(weakKeys == 1, data);
objectTable.add(retDictionary);
if (error != null) {
throw new NoSerializerExistsException(error.getClassName(), retDictionary, error);
}
return retDictionary;
} else {
int refIndexDictionary = (int) (dictionaryObjectU29 >> 1);
@@ -470,8 +542,31 @@ public class AMF3InputStream extends InputStream {
return objectTable.get(refIndexDictionary);
}
default:
return null;
throw new UnsupportedValueType(marker);
}
}
private class MonitoredInputStream extends InputStream {
private final InputStream is;
private ByteArrayOutputStream baos;
public MonitoredInputStream(InputStream is) {
this.is = is;
this.baos = new ByteArrayOutputStream();
}
@Override
public int read() throws IOException {
int ret = is.read();
if (ret > -1) {
baos.write(ret);
}
return ret;
}
public byte[] getReadData() {
return baos.toByteArray();
}
}
}

View File

@@ -46,6 +46,9 @@ public class AMF3Tools {
if (((List<? extends Class>) Arrays.asList(String.class, Long.class, Double.class, BasicType.class, Boolean.class)).contains(object.getClass())) {
return;
}
if (object instanceof BasicType) {
return;
}
int prevRef = 0;
if (referenceCount.containsKey(object)) {
prevRef = referenceCount.get(object);
@@ -85,7 +88,11 @@ public class AMF3Tools {
if (object instanceof String) {
return "\"" + Helper.escapeActionScriptString((String) object) + "\"";
}
if (((List<? extends Class>) Arrays.asList(Long.class, Double.class, BasicType.class, Boolean.class)).contains(object.getClass())) {
if (((List<? extends Class>) Arrays.asList(Long.class, Double.class, Boolean.class)).contains(object.getClass())) {
return object.toString();
}
if (object instanceof BasicType) {
return object.toString();
}
@@ -122,35 +129,58 @@ public class AMF3Tools {
ret.append(indent(level + 1)).append("\"type\": \"Object\",\r\n");
ret.append(addId);
ret.append(indent(level + 1)).append("\"className\": ").append(amfToString(processedObjects, level, ot.getClassName(), referenceCount, objectAlias)).append(",\r\n");
ret.append(indent(level + 1)).append("\"dynamic\": ").append(ot.isDynamic()).append(",\r\n");
if (!ot.getSealedMembers().isEmpty()) {
ret.append(indent(level + 1)).append("\"sealedMembers\": {\r\n");
for (int i = 0; i < ot.getSealedMembers().size(); i++) {
Pair<String, Object> member = ot.getSealedMembers().get(i);
ret.append(indent(level + 2)).append(amfToString(processedObjects, level + 2, member.getFirst(), referenceCount, objectAlias)).append(":").append(amfToString(processedObjects, level + 1, member.getSecond(), referenceCount, objectAlias));
if (i < ot.getSealedMembers().size() - 1) {
ret.append(",\r\n");
} else {
if (ot.isSerialized()) {
byte[] serData = ot.getSerializedData();
if (serData == null) {
ret.append(indent(level + 1)).append("\"serialized\": unknown\r\n");
} else {
ret.append(indent(level + 1)).append("\"serialized\": 0x").append(javax.xml.bind.DatatypeConverter.printHexBinary(serData)).append(",\r\n");
if (!ot.getSerializedMembers().isEmpty()) {
ret.append(indent(level + 1)).append("\"unserializedMembers\": {\r\n");
for (int i = 0; i < ot.getSerializedMembers().size(); i++) {
Pair<String, Object> member = ot.getSerializedMembers().get(i);
ret.append(indent(level + 2)).append(amfToString(processedObjects, level + 2, member.getFirst(), referenceCount, objectAlias)).append(":").append(amfToString(processedObjects, level + 1, member.getSecond(), referenceCount, objectAlias));
if (i < ot.getSerializedMembers().size() - 1) {
ret.append(",\r\n");
} else {
ret.append("\r\n");
}
}
ret.append(indent(level + 1)).append("}");
ret.append("\r\n");
}
}
ret.append(indent(level + 1)).append("}");
if (!ot.getDynamicMembers().isEmpty()) {
ret.append(",");
}
ret.append("\r\n");
}
if (!ot.getDynamicMembers().isEmpty()) {
ret.append(indent(level + 1)).append("\"dynamicMembers\": {\r\n");
for (int i = 0; i < ot.getDynamicMembers().size(); i++) {
Pair<String, Object> member = ot.getDynamicMembers().get(i);
ret.append(indent(level + 2)).append(amfToString(processedObjects, level + 2, member.getFirst(), referenceCount, objectAlias)).append(":").append(amfToString(processedObjects, level + 2, member.getSecond(), referenceCount, objectAlias));
if (i < ot.getDynamicMembers().size() - 1) {
} else {
ret.append(indent(level + 1)).append("\"dynamic\": ").append(ot.isDynamic()).append(",\r\n");
if (!ot.getSealedMembers().isEmpty()) {
ret.append(indent(level + 1)).append("\"sealedMembers\": {\r\n");
for (int i = 0; i < ot.getSealedMembers().size(); i++) {
Pair<String, Object> member = ot.getSealedMembers().get(i);
ret.append(indent(level + 2)).append(amfToString(processedObjects, level + 2, member.getFirst(), referenceCount, objectAlias)).append(":").append(amfToString(processedObjects, level + 1, member.getSecond(), referenceCount, objectAlias));
if (i < ot.getSealedMembers().size() - 1) {
ret.append(",\r\n");
} else {
ret.append("\r\n");
}
}
ret.append(indent(level + 1)).append("}");
if (!ot.getDynamicMembers().isEmpty()) {
ret.append(",");
}
ret.append("\r\n");
}
ret.append(indent(level + 1)).append("}\r\n");
if (!ot.getDynamicMembers().isEmpty()) {
ret.append(indent(level + 1)).append("\"dynamicMembers\": {\r\n");
for (int i = 0; i < ot.getDynamicMembers().size(); i++) {
Pair<String, Object> member = ot.getDynamicMembers().get(i);
ret.append(indent(level + 2)).append(amfToString(processedObjects, level + 2, member.getFirst(), referenceCount, objectAlias)).append(":").append(amfToString(processedObjects, level + 2, member.getSecond(), referenceCount, objectAlias));
if (i < ot.getDynamicMembers().size() - 1) {
ret.append(",");
}
ret.append("\r\n");
}
ret.append(indent(level + 1)).append("}\r\n");
}
}
ret.append(indent(level)).append("}");
} else if (object instanceof ArrayType) {
@@ -198,7 +228,7 @@ public class AMF3Tools {
ret.append("\r\n");
}
ret.append(indent(level + 1)).append("}\r\n");
ret.append(indent(level)).append("}");
ret.append(indent(level) + "}");
} else if (object instanceof ByteArrayType) {
ByteArrayType ba = (ByteArrayType) object;
byte data[] = ba.getData();
@@ -228,10 +258,6 @@ public class AMF3Tools {
+ addId
+ indent(level + 1) + "\"value\": " + amfToString(processedObjects, level, ((XmlType) object).getData(), referenceCount, objectAlias) + "\r\n"
+ indent(level) + "}";
} else if (object == BasicType.NULL) {
return "null";
} else if (object == BasicType.UNDEFINED) {
return "undefined";
} else {
throw new IllegalArgumentException("Unsupported type: " + object.getClass());
}

View File

@@ -0,0 +1,25 @@
package com.jpexs.decompiler.flash.amf.amf3;
public class NoSerializerExistsException extends Exception {
private final String className;
private final Object incompleteData;
/*public NoSerializerExistsException(String className, Object incompleteData) {
this(className, incompleteData, null);
}*/
public NoSerializerExistsException(String className, Object incompleteData, Throwable cause) {
super("Cannot read AMF - no deserializer defined for class \"" + className + "\".", cause);
this.className = className;
this.incompleteData = incompleteData;
}
public String getClassName() {
return className;
}
public Object getIncompleteData() {
return incompleteData;
}
}

View File

@@ -1,12 +1,13 @@
package com.jpexs.decompiler.flash.amf.amf3;
import com.jpexs.decompiler.flash.amf.amf3.types.ObjectType;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
public interface ObjectTypeSerializeHandler {
public ObjectType readObject(String className, InputStream is);
public List<Pair<String, Object>> readObject(String className, InputStream is) throws IOException;
public void writeObject(ObjectType val, OutputStream os);
public void writeObject(List<Pair<String, Object>> members, OutputStream os) throws IOException;
}

View File

@@ -0,0 +1,11 @@
package com.jpexs.decompiler.flash.amf.amf3;
import java.io.IOException;
public class PrematureEndOfTheStreamException extends IOException {
public PrematureEndOfTheStreamException() {
super("Premature end of the stream reached");
}
}

View File

@@ -0,0 +1,16 @@
package com.jpexs.decompiler.flash.amf.amf3;
public class UnsupportedValueType extends RuntimeException {
private int marker;
public UnsupportedValueType(int marker) {
super("Unsupported type of value - marker: 0x" + Integer.toHexString(marker));
this.marker = marker;
}
public int getMarker() {
return marker;
}
}

View File

@@ -0,0 +1,40 @@
package com.jpexs.decompiler.flash.amf.amf3.types;
import com.jpexs.decompiler.flash.amf.amf3.AMF3Tools;
import java.util.ArrayList;
import java.util.List;
import com.jpexs.decompiler.flash.amf.amf3.WithSubValues;
public abstract class AbstractVectorType<T> implements WithSubValues {
private boolean fixed;
private List<T> values;
public boolean isFixed() {
return fixed;
}
public AbstractVectorType(boolean fixed, List<T> values) {
this.values = values;
this.fixed = fixed;
}
public List<T> getValues() {
return values;
}
@Override
public List<Object> getSubValues() {
List<Object> ret = new ArrayList<>();
ret.addAll(values);
return ret;
}
public abstract String getTypeName();
@Override
public String toString() {
return AMF3Tools.amfToString(this);
}
}

View File

@@ -0,0 +1,46 @@
package com.jpexs.decompiler.flash.amf.amf3.types;
import com.jpexs.decompiler.flash.amf.amf3.AMF3Tools;
import com.jpexs.decompiler.flash.amf.amf3.Pair;
import com.jpexs.helpers.Helper;
import java.util.ArrayList;
import java.util.List;
import com.jpexs.decompiler.flash.amf.amf3.WithSubValues;
public class ArrayType implements WithSubValues {
private List<Object> denseValues;
private List<Pair<String, Object>> associativeValues;
public ArrayType(List<Object> denseValues, List<Pair<String, Object>> associativeValues) {
this.denseValues = denseValues;
this.associativeValues = associativeValues;
}
public List<Object> getDenseValues() {
return denseValues;
}
public List<Pair<String, Object>> getAssociativeValues() {
return associativeValues;
}
@Override
public String toString() {
return AMF3Tools.amfToString(this);
}
@Override
public List<Object> getSubValues() {
List<Object> ret = new ArrayList<>();
for (Pair<String, Object> p : associativeValues) {
ret.add(p.getFirst());
ret.add(p.getSecond());
}
for (Object v : denseValues) {
ret.add(v);
}
return ret;
}
}

View File

@@ -0,0 +1,26 @@
package com.jpexs.decompiler.flash.amf.amf3.types;
public enum BasicType {
NULL {
@Override
public String toString() {
return "null";
}
},
UNDEFINED {
@Override
public String toString() {
return "undefined";
}
},
//Special types for errors while reading
UNKNOWN {
@Override
public String toString() {
return "unknown";
}
}
}

View File

@@ -0,0 +1,22 @@
package com.jpexs.decompiler.flash.amf.amf3.types;
import com.jpexs.decompiler.flash.amf.amf3.AMF3Tools;
public class ByteArrayType {
private byte[] data;
public ByteArrayType(byte[] data) {
this.data = data;
}
public byte[] getData() {
return data;
}
@Override
public String toString() {
return AMF3Tools.amfToString(this);
}
}

View File

@@ -0,0 +1,30 @@
package com.jpexs.decompiler.flash.amf.amf3.types;
import com.jpexs.decompiler.flash.amf.amf3.AMF3Tools;
import java.util.Date;
public class DateType {
private double val;
public DateType(double val) {
this.val = val;
}
public double getVal() {
return val;
}
public void setVal(double val) {
this.val = val;
}
@Override
public String toString() {
return AMF3Tools.amfToString(this);
}
public Date toDate() {
return new Date((long) val);
}
}

View File

@@ -0,0 +1,38 @@
package com.jpexs.decompiler.flash.amf.amf3.types;
import com.jpexs.decompiler.flash.amf.amf3.AMF3Tools;
import com.jpexs.decompiler.flash.amf.amf3.Pair;
import java.util.ArrayList;
import java.util.List;
import com.jpexs.decompiler.flash.amf.amf3.WithSubValues;
public class DictionaryType implements WithSubValues {
private boolean weakKeys;
private List<Pair<Object, Object>> pairs;
public DictionaryType(boolean weakKeys, List<Pair<Object, Object>> pairs) {
this.weakKeys = weakKeys;
this.pairs = pairs;
}
public List<Pair<Object, Object>> getPairs() {
return pairs;
}
@Override
public List<Object> getSubValues() {
List<Object> ret = new ArrayList<>();
for (Pair<Object, Object> p : pairs) {
ret.add(p.getFirst());
ret.add(p.getSecond());
}
return ret;
}
@Override
public String toString() {
return AMF3Tools.amfToString(this);
}
}

View File

@@ -0,0 +1,116 @@
package com.jpexs.decompiler.flash.amf.amf3.types;
import com.jpexs.decompiler.flash.amf.amf3.AMF3Tools;
import com.jpexs.decompiler.flash.amf.amf3.Pair;
import com.jpexs.helpers.Helper;
import java.util.ArrayList;
import java.util.List;
import com.jpexs.decompiler.flash.amf.amf3.WithSubValues;
public class ObjectType implements WithSubValues {
private boolean dynamic;
private List<Pair<String, Object>> sealedMembers;
private List<Pair<String, Object>> dynamicMembers;
private List<Pair<String, Object>> serializedMembers;
private String className;
//null = not serialized or unknown
private byte[] serializedData = null;
private boolean serialized;
public boolean isSerialized() {
return serialized;
}
public ObjectType(String className, byte[] serializedData, List<Pair<String, Object>> serializedMembers) {
this.className = className;
this.serializedData = serializedData;
this.serializedMembers = serializedMembers;
this.dynamicMembers = new ArrayList<>();
this.sealedMembers = new ArrayList<>();
this.serialized = true;
}
public ObjectType(boolean dynamic, List<Pair<String, Object>> sealedMembers, List<Pair<String, Object>> dynamicMembers, String className) {
this.dynamic = dynamic;
this.sealedMembers = sealedMembers;
this.dynamicMembers = dynamicMembers;
this.className = className;
this.serializedMembers = new ArrayList<>();
this.serialized = false;
}
public boolean isDynamic() {
return dynamic;
}
public List<Pair<String, Object>> getDynamicMembers() {
return dynamicMembers;
}
public List<Pair<String, Object>> getSealedMembers() {
return sealedMembers;
}
public String getClassName() {
return className;
}
public void setDynamic(boolean dynamic) {
this.dynamic = dynamic;
}
public void setDynamicMembers(List<Pair<String, Object>> dynamicMembers) {
this.dynamicMembers = dynamicMembers;
}
public void setSealedMembers(List<Pair<String, Object>> sealedMembers) {
this.sealedMembers = sealedMembers;
}
public void setClassName(String className) {
this.className = className;
}
@Override
public List<Object> getSubValues() {
List<Object> ret = new ArrayList<>();
for (Pair<String, Object> p : dynamicMembers) {
ret.add(p.getFirst());
ret.add(p.getSecond());
}
for (Pair<String, Object> p : sealedMembers) {
ret.add(p.getFirst());
ret.add(p.getSecond());
}
for (Pair<String, Object> p : serializedMembers) {
ret.add(p.getFirst());
ret.add(p.getSecond());
}
return ret;
}
@Override
public String toString() {
return AMF3Tools.amfToString(this);
}
public void setSerializedData(byte[] serializedData) {
this.serializedData = serializedData;
}
public byte[] getSerializedData() {
return serializedData;
}
public void setSerializedMembers(List<Pair<String, Object>> serializedMembers) {
this.serializedMembers = serializedMembers;
}
public List<Pair<String, Object>> getSerializedMembers() {
return serializedMembers;
}
}

View File

@@ -0,0 +1,16 @@
package com.jpexs.decompiler.flash.amf.amf3.types;
import java.util.List;
public class VectorDoubleType extends AbstractVectorType<Double> {
public VectorDoubleType(boolean fixed, List<Double> values) {
super(fixed, values);
}
@Override
public String getTypeName() {
return "Number";
}
}

View File

@@ -0,0 +1,16 @@
package com.jpexs.decompiler.flash.amf.amf3.types;
import java.util.List;
public class VectorIntType extends AbstractVectorType<Long> {
public VectorIntType(boolean fixed, List<Long> values) {
super(fixed, values);
}
@Override
public String getTypeName() {
return "int";
}
}

View File

@@ -0,0 +1,21 @@
package com.jpexs.decompiler.flash.amf.amf3.types;
import com.jpexs.helpers.Helper;
import java.util.ArrayList;
import java.util.List;
public class VectorObjectType extends AbstractVectorType<Object> {
private String typeName;
public VectorObjectType(boolean fixed, String typeName, List<Object> values) {
super(fixed, values);
this.typeName = typeName;
}
@Override
public String getTypeName() {
return typeName;
}
}

View File

@@ -0,0 +1,17 @@
package com.jpexs.decompiler.flash.amf.amf3.types;
import java.util.ArrayList;
import java.util.List;
public class VectorUIntType extends AbstractVectorType<Long> {
public VectorUIntType(boolean fixed, List<Long> values) {
super(fixed, values);
}
@Override
public String getTypeName() {
return "uint";
}
}

View File

@@ -0,0 +1,24 @@
package com.jpexs.decompiler.flash.amf.amf3.types;
public class XmlDocType {
private String data;
public XmlDocType(String data) {
this.data = data;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
@Override
public String toString() {
return data;
}
}

View File

@@ -0,0 +1,24 @@
package com.jpexs.decompiler.flash.amf.amf3.types;
public class XmlType {
private String data;
public XmlType(String data) {
this.data = data;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
@Override
public String toString() {
return data;
}
}