protected virtual void WriteHashData(BinaryWriter hashInput, ASClass asClass, bool isOutgoing) { if (isOutgoing) { string outgoingTypeName = asClass.Instance.Type.ObjName; if (outgoingTypeName.EndsWith("Composer")) { hashInput.Write(outgoingTypeName); return; } } else { ASClass parserClass = GetIncomingParser(asClass.Instance); if (parserClass != null) WriteClassHashData(hashInput, parserClass); } WriteClassHashData(hashInput, asClass); }
public string GetHash(ASClass asClass, bool referenceScan, bool isOutgoing) { using (var hashStream = new MemoryStream()) using (var hashInput = new BinaryWriter(hashStream)) { hashInput.Write(isOutgoing); WriteHashData(hashInput, asClass, isOutgoing); if (referenceScan) { ScanForMessageReferences(asClass.ABC); if (_messageReferencesCache.ContainsKey(asClass)) { List<Tuple<ASMethod, int>> messageReferences = _messageReferencesCache[asClass]; if (asClass.Instance.Type.ObjName == "RenderRoomMessageComposer") { } foreach (Tuple<ASMethod, int> messageReference in messageReferences) { ASMethod referencingMethod = messageReference.Item1; int referenceId = messageReference.Item2; WriteMethodHashData(hashInput, referencingMethod, false); hashInput.Write(referenceId); } } } return GetHash(hashStream.ToArray()); } }
protected virtual void WriteClassHashData(BinaryWriter hashInput, ASClass asClass) { ABCFile abc = asClass.ABC; WriteTraitsHashData(hashInput, asClass); WriteMethodHashData(hashInput, asClass.Constructor, true); WriteTraitsHashData(hashInput, asClass.Instance); WriteMethodHashData(hashInput, asClass.Instance.Constructor, true); string superClassObjName = asClass.Instance.SuperType?.ObjName; if (!string.IsNullOrWhiteSpace(superClassObjName) && superClassObjName != "Object") { ASClass superClass = abc .FindClassByName(superClassObjName); if (superClass != null) { WriteMultinameHashData(hashInput, asClass.Instance.SuperType); WriteClassHashData(hashInput, superClass); } } hashInput.Write((byte)asClass.Instance.ClassInfo); hashInput.Write((byte)asClass.Instance.Type.MultinameType); hashInput.Write((byte)asClass.Instance.ProtectedNamespace.NamespaceType); }
protected void ScanForMessageReference(Dictionary<string, ASClass> messageClasses, ASClass asClass, ASMethod method, int traitIndex, int messageRefCount = 0) { ABCFile abc = asClass.ABC; ASClass messageClass = null; using (var outCode = new FlashReader(method.Body.Bytecode)) { while (outCode.IsDataAvailable) { OPCode op = outCode.ReadOP(); object[] values = outCode.ReadValues(op); switch (op) { case OPCode.NewFunction: { var newFuncIndex = (int)values[0]; ASMethod newFuncMethod = abc.Methods[newFuncIndex]; ScanForMessageReference(messageClasses, asClass, newFuncMethod, traitIndex, messageRefCount); break; } case OPCode.ConstructProp: { var constructPropIndex = (int)values[0]; if (messageClass != null) { ASMultiname constructPropType = abc.Constants.Multinames[constructPropIndex]; if (constructPropType.ObjName == messageClass.Instance.Type.ObjName) { if (!_messageReferencesCache.ContainsKey(messageClass)) _messageReferencesCache[messageClass] = new List<Tuple<ASMethod, int>>(); _messageReferencesCache[messageClass].Add( new Tuple<ASMethod, int>(method, (traitIndex + (++messageRefCount)))); } messageClass = null; } break; } case OPCode.FindPropStrict: { var findPropStrictIndex = (int)values[0]; string findPropStrictObjName = abc.Constants .Multinames[findPropStrictIndex].ObjName; if (messageClasses.ContainsKey(findPropStrictObjName)) { messageClass = messageClasses[findPropStrictObjName]; // Incoming messages currently not supported. if (IncomingTypes.ContainsValue(messageClass)) messageClass = null; } break; } } } } }
public string GetHash(ASClass asClass) { using (var hashStream = new MemoryStream()) using (var hashInput = new BinaryWriter(hashStream)) { WriteClassHashData(hashInput, asClass); return GetHash(hashStream.ToArray()); } }