mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-05-31 05:06:27 +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;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user