mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-27 08:16:26 +00:00
AMF3 tests, exceptions
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
package com.jpexs.decompiler.flash.amf.amf3;
|
||||
|
||||
import com.jpexs.decompiler.flash.amf.amf3.types.ArrayType;
|
||||
import com.jpexs.decompiler.flash.amf.amf3.types.DictionaryType;
|
||||
import com.jpexs.decompiler.flash.amf.amf3.types.ObjectType;
|
||||
import com.jpexs.decompiler.flash.amf.amf3.types.VectorObjectType;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import static org.testng.Assert.*;
|
||||
import org.testng.annotations.AfterTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class Amf3InputStreamTest {
|
||||
|
||||
private FileInputStream fis;
|
||||
private AMF3InputStream is;
|
||||
|
||||
@AfterTest
|
||||
public void deinitStream() {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException ex) {
|
||||
//ignore
|
||||
}
|
||||
is = null;
|
||||
}
|
||||
if (fis != null) {
|
||||
try {
|
||||
fis.close();
|
||||
} catch (IOException ex) {
|
||||
//ignore
|
||||
}
|
||||
fis = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void initStream(String fileName) throws FileNotFoundException {
|
||||
fis = new FileInputStream("testdata/amf3/generated/" + fileName);
|
||||
is = new AMF3InputStream(fis);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadObject() throws IOException, NoSerializerExistsException {
|
||||
initStream("all.bin");
|
||||
is.readValue();
|
||||
}
|
||||
|
||||
private Map<String, ObjectTypeSerializeHandler> getSerializers() {
|
||||
Map<String, ObjectTypeSerializeHandler> serializers = new HashMap<>();
|
||||
serializers.put("CustomClass", new ObjectTypeSerializeHandler() {
|
||||
@Override
|
||||
public List<Pair<String, Object>> readObject(String className, InputStream is) throws IOException {
|
||||
List<Pair<String, Object>> members = new ArrayList<>();
|
||||
members.add(new Pair<>("val8", (long) is.read()));
|
||||
members.add(new Pair<>("val32", (long) ((is.read() << 24) + (is.read() << 16) + (is.read() << 8) + (is.read()))));
|
||||
return members;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeObject(List<Pair<String, Object>> members, OutputStream os) throws IOException {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
});
|
||||
return serializers;
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NoSerializerExistsException.class)
|
||||
public void testReadCustomSerializedNeedsSerializer() throws IOException, NoSerializerExistsException {
|
||||
initStream("custom.bin");
|
||||
is.readValue(); //needs deserializer for CustomClass
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCustomSerialized() throws IOException, NoSerializerExistsException {
|
||||
initStream("custom.bin");
|
||||
is.readValue(getSerializers());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoSerializerHandlingInObjectDynamicProp() throws IOException {
|
||||
initStream("noserializer_object_dynamic.bin");
|
||||
try {
|
||||
is.readValue();
|
||||
} catch (NoSerializerExistsException ex) {
|
||||
assertTrue(ex.getIncompleteData() instanceof ObjectType, "Expected datatype: ObjectType, Actual datatype: " + ex.getIncompleteData().getClass());
|
||||
//TODO: examinate the data more
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoSerializerHandlingInObjectSealedProp() throws IOException {
|
||||
initStream("noserializer_object_sealed.bin");
|
||||
try {
|
||||
is.readValue();
|
||||
} catch (NoSerializerExistsException ex) {
|
||||
assertTrue(ex.getIncompleteData() instanceof ObjectType, "Expected datatype: ObjectType, Actual datatype: " + ex.getIncompleteData().getClass());
|
||||
//TODO: examinate the data more
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoSerializerHandlingInArrayDense() throws IOException {
|
||||
initStream("noserializer_array_dense.bin");
|
||||
try {
|
||||
is.readValue();
|
||||
} catch (NoSerializerExistsException ex) {
|
||||
assertTrue(ex.getIncompleteData() instanceof ArrayType, "Expected datatype: ArrayType, Actual datatype: " + ex.getIncompleteData().getClass());
|
||||
//TODO: examinate the data more
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoSerializerHandlingInArrayAssociative() throws IOException {
|
||||
initStream("noserializer_array_associative.bin");
|
||||
try {
|
||||
is.readValue();
|
||||
} catch (NoSerializerExistsException ex) {
|
||||
assertTrue(ex.getIncompleteData() instanceof ArrayType, "Expected datatype: ArrayType, Actual datatype: " + ex.getIncompleteData().getClass());
|
||||
//TODO: examinate the data more
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoSerializerHandlingInVector() throws IOException {
|
||||
initStream("noserializer_vector.bin");
|
||||
try {
|
||||
is.readValue();
|
||||
} catch (NoSerializerExistsException ex) {
|
||||
assertTrue(ex.getIncompleteData() instanceof VectorObjectType, "Expected datatype: VectorObjectType, Actual datatype: " + ex.getIncompleteData().getClass());
|
||||
//TODO: examinate the data more
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoSerializerHandlingInDictionaryValues() throws IOException {
|
||||
initStream("noserializer_dictionary_value.bin");
|
||||
try {
|
||||
is.readValue();
|
||||
} catch (NoSerializerExistsException ex) {
|
||||
assertTrue(ex.getIncompleteData() instanceof DictionaryType, "Expected datatype: DictionaryType, Actual datatype: " + ex.getIncompleteData().getClass());
|
||||
//TODO: examinate the data more
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoSerializerHandlingInDictionaryKeys() throws IOException {
|
||||
initStream("noserializer_dictionary_key.bin");
|
||||
try {
|
||||
is.readValue();
|
||||
} catch (NoSerializerExistsException ex) {
|
||||
assertTrue(ex.getIncompleteData() instanceof DictionaryType, "Expected datatype: DictionaryType, Actual datatype: " + ex.getIncompleteData().getClass());
|
||||
//TODO: examinate the data more
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = UnsupportedValueType.class)
|
||||
public void testUnsupportedMarker() throws IOException, NoSerializerExistsException {
|
||||
final int UNSUPPORTED_MARKER = 100;
|
||||
is = new AMF3InputStream(new ByteArrayInputStream(new byte[]{UNSUPPORTED_MARKER}));
|
||||
is.readValue();
|
||||
}
|
||||
}
|
||||
169
libsrc/ffdec_lib/testdata/amf3/AmfTest.as
vendored
Normal file
169
libsrc/ffdec_lib/testdata/amf3/AmfTest.as
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
package
|
||||
{
|
||||
import flash.display.Sprite;
|
||||
import flash.utils.ByteArray;
|
||||
import flash.filesystem.File;
|
||||
import flash.filesystem.FileStream;
|
||||
import flash.filesystem.FileMode;
|
||||
|
||||
import flash.utils.Dictionary;
|
||||
import flash.geom.Point;
|
||||
import flash.xml.XMLDocument;
|
||||
|
||||
import flash.net.registerClassAlias;
|
||||
|
||||
/**
|
||||
* Generating test data file
|
||||
*/
|
||||
public class AmfTest extends Sprite
|
||||
{
|
||||
|
||||
private function writeToFile(filename:String,data)
|
||||
{
|
||||
var urlStr:String = "file:///"+File.applicationDirectory.nativePath+"/generated/"+filename;
|
||||
var file:File = new File() ;
|
||||
file.url = urlStr;
|
||||
var fileStream:FileStream = new FileStream();
|
||||
fileStream.open(file, FileMode.WRITE);
|
||||
var bytes:ByteArray = new ByteArray();
|
||||
bytes.writeObject(data);
|
||||
fileStream.writeBytes(bytes, 0, bytes.length);
|
||||
fileStream.close();
|
||||
|
||||
}
|
||||
|
||||
public function AmfTest() {
|
||||
|
||||
|
||||
|
||||
var ar = ["a","b","c"];
|
||||
|
||||
var asoc_array = [1,2,3];
|
||||
asoc_array["key1"] = 5;
|
||||
asoc_array["key2"] = 6;
|
||||
|
||||
var ba:ByteArray = new ByteArray();
|
||||
ba.writeByte(65);
|
||||
ba.writeByte(66);
|
||||
ba.writeByte(67);
|
||||
|
||||
|
||||
var vector_int:Vector.<int> = new <int>[-10,20,-30,40];
|
||||
var vector_uint:Vector.<uint> = new <uint>[10,20,30,40];
|
||||
var vector_double:Vector.<Number> = new <Number>[-10.1,20.2,-30.3,40.4];
|
||||
var vector_string:Vector.<String> = new <String>["x","y","z"];
|
||||
var vector_point:Vector.<Point> = new <Point>[new Point(10,20),new Point(30,40),new Point(50,60)];
|
||||
|
||||
var dict = new Dictionary();
|
||||
dict["dkey1"] = "TestOne";
|
||||
dict["dkey2"] = "TestTwo";
|
||||
|
||||
var txmldoc:XMLDocument = new XMLDocument("<foo><bar>aa</bar></foo>");
|
||||
|
||||
var txml:XML = <foo>
|
||||
<bar>Hello</bar>
|
||||
<bar>Hi</bar>
|
||||
</foo>;
|
||||
|
||||
var date = new Date();
|
||||
|
||||
var me = {
|
||||
"01_int":5,
|
||||
"02_negative-int":-5,
|
||||
"03_string":"String",
|
||||
"04_true":true,
|
||||
"05_false":false,
|
||||
"06_undefined":undefined,
|
||||
"07_null":null,
|
||||
"08_double":5.6,
|
||||
"09_negative-double":-5.6,
|
||||
"10_array":ar,
|
||||
"11_asoc_array": asoc_array,
|
||||
"12_date":date,
|
||||
"13_xml":txml,
|
||||
"14_byteArray":ba,
|
||||
"15_vectorInt":vector_int,
|
||||
"16_vectorUInt":vector_uint,
|
||||
"17_vectorDouble":vector_double,
|
||||
"18_vectorString":vector_string,
|
||||
"19_vectorPoint":vector_point,
|
||||
"20_dictionary":dict,
|
||||
"21_xmldoc":txmldoc,
|
||||
"22_ref_string":"String",
|
||||
"23_ref_array":ar,
|
||||
"24_ref_date":date,
|
||||
"25_ref_byteArray":ba,
|
||||
"26_ref_vectorInt":vector_int,
|
||||
"27_ref_vectorUInt":vector_uint,
|
||||
"28_ref_vectorDouble":vector_double,
|
||||
"29_ref_vectorString":vector_string,
|
||||
"30_ref_dictionary":dict,
|
||||
"31_ref_xml":txml,
|
||||
"32_ref_xmldoc":txmldoc
|
||||
};
|
||||
me["33_me"] = me;
|
||||
|
||||
writeToFile("all.bin",me);
|
||||
|
||||
var custom = new CustomClass();
|
||||
custom.setVal8(127);
|
||||
custom.setVal32(-2500);
|
||||
registerClassAlias("CustomClass", CustomClass);
|
||||
|
||||
var cust_obj = {
|
||||
"member1":5,
|
||||
"member2":custom,
|
||||
"member3":27
|
||||
};
|
||||
|
||||
writeToFile("custom.bin",cust_obj);
|
||||
|
||||
writeToFile("noserializer_object_dynamic.bin",{
|
||||
"a":5,
|
||||
"b":8,
|
||||
"c":custom,
|
||||
"d":6,
|
||||
"e":7,
|
||||
"f":26
|
||||
});
|
||||
writeToFile("noserializer_array_dense.bin",
|
||||
["a","b",custom,"d","e","f"]
|
||||
);
|
||||
|
||||
var arx = [];
|
||||
arx["a"] = 1;
|
||||
arx["b"] = 2;
|
||||
arx["c"] = custom;
|
||||
arx["d"] = 4;
|
||||
arx["e"] = 5;
|
||||
arx["f"] = 6;
|
||||
writeToFile("noserializer_array_associative.bin", arx);
|
||||
|
||||
|
||||
writeToFile("noserializer_vector.bin", new <Object>["a","b",custom,"d","e","f"]);
|
||||
|
||||
var nsdict = new Dictionary();
|
||||
nsdict["a"] = "One";
|
||||
nsdict["b"] = "Two";
|
||||
nsdict["c"] = custom;
|
||||
nsdict["d"] = "Three";
|
||||
nsdict["e"] = "Four";
|
||||
nsdict["f"] = "Five";
|
||||
|
||||
writeToFile("noserializer_dictionary_value.bin", nsdict);
|
||||
|
||||
var nsdict2 = new Dictionary();
|
||||
nsdict2["a"] = "One";
|
||||
nsdict2["b"] = "Two";
|
||||
nsdict2[custom] = "Three";
|
||||
nsdict2["d"] = "Three";
|
||||
nsdict2["e"] = "Four";
|
||||
nsdict2["f"] = "Five";
|
||||
|
||||
writeToFile("noserializer_dictionary_key.bin", nsdict2);
|
||||
|
||||
var objWithCustom:ObjectWithCustom = new ObjectWithCustom("1","2",custom,"4","5","6");
|
||||
writeToFile("noserializer_object_sealed.bin", objWithCustom);
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
libsrc/ffdec_lib/testdata/amf3/AmfTest.swf
vendored
Normal file
BIN
libsrc/ffdec_lib/testdata/amf3/AmfTest.swf
vendored
Normal file
Binary file not shown.
32
libsrc/ffdec_lib/testdata/amf3/CustomClass.as
vendored
Normal file
32
libsrc/ffdec_lib/testdata/amf3/CustomClass.as
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
package
|
||||
{
|
||||
import flash.utils.IExternalizable;
|
||||
import flash.utils.IDataOutput;
|
||||
import flash.utils.IDataInput;
|
||||
|
||||
public class CustomClass implements IExternalizable
|
||||
{
|
||||
|
||||
private var val8:int;
|
||||
private var val32:int;
|
||||
public function CustomClass() { //No constructor parameters allowed
|
||||
}
|
||||
|
||||
public function setVal8(v:int){
|
||||
this.val8 = v;
|
||||
}
|
||||
public function setVal32(v:int){
|
||||
this.val32 = v;
|
||||
}
|
||||
|
||||
public function writeExternal(output:IDataOutput):void {
|
||||
output.writeByte(val8);
|
||||
output.writeInt(val32);
|
||||
}
|
||||
|
||||
public function readExternal(input:IDataInput):void {
|
||||
this.val8 = input.readByte();
|
||||
this.val32 = input.readInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
24
libsrc/ffdec_lib/testdata/amf3/ObjectWithCustom.as
vendored
Normal file
24
libsrc/ffdec_lib/testdata/amf3/ObjectWithCustom.as
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
package
|
||||
{
|
||||
public class ObjectWithCustom
|
||||
{
|
||||
|
||||
public var a:String;
|
||||
public var b:String;
|
||||
public var c:CustomClass;
|
||||
public var d:String;
|
||||
public var e:String;
|
||||
public var f:String;
|
||||
|
||||
|
||||
public function ObjectWithCustom(a:String,b:String,c:CustomClass,d:String,e:String,f:String) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.c = c;
|
||||
this.d = d;
|
||||
this.e = e;
|
||||
this.f = f;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
14
libsrc/ffdec_lib/testdata/amf3/app.xml
vendored
Normal file
14
libsrc/ffdec_lib/testdata/amf3/app.xml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<application xmlns="http://ns.adobe.com/air/application/3.1">
|
||||
<id>samples.flex.HelloWorld</id>
|
||||
<versionNumber>1</versionNumber>
|
||||
<filename>HelloWorld</filename>
|
||||
<initialWindow>
|
||||
<content>AmfTest.swf</content>
|
||||
<visible>true</visible>
|
||||
<systemChrome>none</systemChrome>
|
||||
<transparent>true</transparent>
|
||||
<width>400</width>
|
||||
<height>200</height>
|
||||
</initialWindow>
|
||||
</application>
|
||||
BIN
libsrc/ffdec_lib/testdata/amf3/generated/all.bin
vendored
Normal file
BIN
libsrc/ffdec_lib/testdata/amf3/generated/all.bin
vendored
Normal file
Binary file not shown.
3
libsrc/ffdec_lib/testdata/amf3/generated/custom.bin
vendored
Normal file
3
libsrc/ffdec_lib/testdata/amf3/generated/custom.bin
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
member3member1member2
|
||||
CustomClass<73><7F><EFBFBD><
|
||||
2
libsrc/ffdec_lib/testdata/amf3/generated/noserializer_array_associative.bin
vendored
Normal file
2
libsrc/ffdec_lib/testdata/amf3/generated/noserializer_array_associative.bin
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
fabc
|
||||
CustomClass<73><7F><EFBFBD><de
|
||||
2
libsrc/ffdec_lib/testdata/amf3/generated/noserializer_array_dense.bin
vendored
Normal file
2
libsrc/ffdec_lib/testdata/amf3/generated/noserializer_array_dense.bin
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
ab
|
||||
BIN
libsrc/ffdec_lib/testdata/amf3/generated/noserializer_dictionary_key.bin
vendored
Normal file
BIN
libsrc/ffdec_lib/testdata/amf3/generated/noserializer_dictionary_key.bin
vendored
Normal file
Binary file not shown.
BIN
libsrc/ffdec_lib/testdata/amf3/generated/noserializer_dictionary_value.bin
vendored
Normal file
BIN
libsrc/ffdec_lib/testdata/amf3/generated/noserializer_dictionary_value.bin
vendored
Normal file
Binary file not shown.
3
libsrc/ffdec_lib/testdata/amf3/generated/noserializer_object_dynamic.bin
vendored
Normal file
3
libsrc/ffdec_lib/testdata/amf3/generated/noserializer_object_dynamic.bin
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
fabc
|
||||
CustomClass<73><7F><EFBFBD><de
|
||||
3
libsrc/ffdec_lib/testdata/amf3/generated/noserializer_object_sealed.bin
vendored
Normal file
3
libsrc/ffdec_lib/testdata/amf3/generated/noserializer_object_sealed.bin
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
ccfadbe
|
||||
CustomClass<73><7F><EFBFBD><61425
|
||||
BIN
libsrc/ffdec_lib/testdata/amf3/generated/noserializer_vector.bin
vendored
Normal file
BIN
libsrc/ffdec_lib/testdata/amf3/generated/noserializer_vector.bin
vendored
Normal file
Binary file not shown.
20
libsrc/ffdec_lib/testdata/amf3/run.bat
vendored
Normal file
20
libsrc/ffdec_lib/testdata/amf3/run.bat
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
@echo off
|
||||
set ISDEBUG=false
|
||||
if "%1" == "debug" goto blockset
|
||||
goto block2
|
||||
:blockset
|
||||
set ISDEBUG=true
|
||||
:block2
|
||||
set AIRPATH=c:\air
|
||||
set COMPILERPATH=%AIRPATH%\bin\amxmlc.bat
|
||||
if not exist %COMPILERPATH% goto notex
|
||||
call %COMPILERPATH% -warnings=false -debug=%ISDEBUG% AmfTest.as>NUL
|
||||
if errorlevel==1 goto failed
|
||||
goto end
|
||||
:notex
|
||||
echo AIR SDK not found. Download and unpack Flex SDK into C:\air directory, then run build again
|
||||
goto end
|
||||
:failed
|
||||
pause
|
||||
:end
|
||||
%AIRPATH%\bin\adl.exe app.xml
|
||||
34
libsrc/ffdec_lib/testdata/as3/CustomClass.as
vendored
Normal file
34
libsrc/ffdec_lib/testdata/as3/CustomClass.as
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
package
|
||||
{
|
||||
import flash.utils.IExternalizable;
|
||||
import flash.utils.IDataOutput;
|
||||
import flash.utils.IDataInput;
|
||||
|
||||
public class CustomClass implements IExternalizable
|
||||
{
|
||||
|
||||
private var val8:int;
|
||||
private var val32:int;
|
||||
public function CustomClass()
|
||||
{
|
||||
}
|
||||
|
||||
public function setVal8(v:int){
|
||||
this.val8 = v;
|
||||
}
|
||||
public function setVal32(v:int){
|
||||
this.val32 = v;
|
||||
}
|
||||
|
||||
public function writeExternal(output:IDataOutput):void {
|
||||
output.writeByte(val8);
|
||||
output.writeInt(val32);
|
||||
|
||||
}
|
||||
|
||||
public function readExternal(input:IDataInput):void {
|
||||
this.val8 = input.readByte();
|
||||
this.val32 = input.readInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user