From 64b6df7dfa9bd05fa8c1ff448425a1705ae32cd9 Mon Sep 17 00:00:00 2001 From: Ray Greenwell Date: Thu, 26 Feb 2009 00:24:23 +0000 Subject: [PATCH] It's another "Jesus, really Adobe?" commit message! Apparently they enhanced AMF3 encoding in flash 10. Dictionaries seem to be encoded differently. I'm sure they thought that they could sneak this in because it's backwards-compatible, but they thought wrong. If a Flash 10 client encodes a Dictionary, it can't be read by a flash 9 client because it's not forwards-compatible. If you change the spec, you gotta change the version number, because this shit might be persistent. So: work around it. Might be sketchy. Let's keep an eye on it. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5673 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../com/threerings/util/ObjectMarshaller.as | 44 ++++++++++++++++--- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/src/as/com/threerings/util/ObjectMarshaller.as b/src/as/com/threerings/util/ObjectMarshaller.as index 620017e4e..455e42da3 100644 --- a/src/as/com/threerings/util/ObjectMarshaller.as +++ b/src/as/com/threerings/util/ObjectMarshaller.as @@ -66,11 +66,26 @@ public class ObjectMarshaller return dest; } - // TODO: Our own encoding, that takes into account - // the ApplicationDomain.. ACK + var bytes :ByteArray = new ByteArray(); bytes.endian = Endian.BIG_ENDIAN; bytes.objectEncoding = ObjectEncoding.AMF3; + // FIX, Because adobe is FUCKING IT UP as usual. + // It seems that with flash 10, they "enhanced" AMF3 encoding. That's great and all, + // except when we try to send this data back to a flash 9 player, which can't read it. + // Guess what, asshats? If you change the encoding spec, IT'S NOT THE SAME VERSION ANYMORE. + // Thanks for breaking all our code where we explicitly set AMF3, even though + // it's currently the default. + if (obj is Dictionary) { + var asArray :Array = []; + for (var key :* in obj) { + asArray.push(key); + asArray.push(obj[key]); + } + obj = asArray; + // then insert our special marker byte before writing this array + bytes.writeByte(DICTIONARY_MARKER); + } bytes.writeObject(obj); return bytes; } @@ -114,11 +129,24 @@ public class ObjectMarshaller // array used to encode (and not a network reconstruction) bytes.position = 0; - // TODO: Our own decoding, that takes into account - // the ApplicationDomain.. ACK + // Work around dictionary idiocy. Holy shit. See note in encode(). + const isDict :Boolean = (bytes[0] === DICTIONARY_MARKER); + if (isDict) { + bytes.position = 1; // advance past our special marker + } + bytes.endian = Endian.BIG_ENDIAN; bytes.objectEncoding = ObjectEncoding.AMF3; - return bytes.readObject(); + var decoded :Object = bytes.readObject(); + if (isDict) { + var decodedArray :Array = decoded as Array; + var asDict :Dictionary = new Dictionary(); + for (var jj :int = 0; jj < decodedArray.length; jj += 2) { + asDict[decodedArray[jj]] = decodedArray[jj + 1]; + } + decoded = asDict; + } + return decoded; } /** @@ -193,6 +221,9 @@ public class ObjectMarshaller return null; // it all checks out! } + // hope and pray that they don't revamp amf3 again and start using this byte. Assholes. + public static const DICTIONARY_MARKER :int = 99; + /** * Our static initializer. */ @@ -205,6 +236,7 @@ public class ObjectMarshaller staticInit(); /** Non-simple classes that we allow, as long as they are not subclassed. */ - protected static const VALID_CLASSES :Array = [ "flash.utils.ByteArray", "flash.geom.Point", "flash.geom.Rectangle" ]; + protected static const VALID_CLASSES :Array = [ + "flash.utils.ByteArray", "flash.geom.Point", "flash.geom.Rectangle" ]; } }