Closed LucBerge closed 1 year ago
The events argument cannot be parsed from the constructor. The int, uint, and Number types (in action script) could be multiple types on the socket binary stream.
Example:
In the file ChatAbstractServerMessage.as, channel
and timestamp
are both of type uint
. But channel
is deserialized using readByte
while timestamp
is deserialized using readInt
.
The expented result should be:
channel
: byte
,timestamp
: int
What matters is the variable types on the sockets, not the action script type.
int
-> See in deserialization methoduint
-> See in deserialization methodNumber
-> Double
String
-> String
Object
-> Object
Vector.<x>
-> Vector.<x>
The algorithm should be the following:
public class ...
INetworkMessage
(see #25 )protocolId
READER_REGEX
matchuint
or int
output.write(\w+)\(this.myvariable\)
matchimport re
class ActionScriptReader:
types_to_fix = ["uint", "int"]
class_pattern = re.compile(r"public\sclass\s(\w+)\s(?:extends\s(\w+)\s)?(?:implements\s([\w,\s]+))?")
protocolId_pattern = re.compile(r"public\sstatic\sconst\sprotocolId:\w+\s=\s(\d+);")
attribute_pattern = re.compile(r"public\svar\s(\w+):([\w.<>]+)(?:\s=\s(.*))?;")
def __init__(self, file_name):
self.file_name = file_name
self.class_name = ""
self.superclass = ""
self.interfaces = []
self.protocolId = ""
self.attributes = {}
def parse(self):
with open(self.file_name, "r") as f:
first_function_reached = False
attributs_to_fix = []
lines = f.readlines()
for line in lines:
class_match = self.class_pattern.search(line)
if class_match:
self.class_name = class_match.group(1)
self.superclass = class_match.group(2)
self.interfaces = class_match.group(3)
if self.interfaces:
self.interfaces = self.interfaces.split(',')
self.interfaces = [x.strip() for x in self.interfaces]
else:
self.interfaces = []
continue
protocolId_match = self.protocolId_pattern.search(line)
if protocolId_match:
self.protocolId = protocolId_match.group(1)
continue
attribute_match = self.attribute_pattern.search(line)
if attribute_match:
self.attributes[attribute_match.group(1)] = attribute_match.group(2)
continue
if "function" in line and not first_function_reached:
first_function_reached = True
attributs_to_fix = [key for key, value in self.attributes.items() if value in self.types_to_fix]
if len(attributs_to_fix) == 0:
break
if len(attributs_to_fix):
write_method_pattern = re.compile(rf"output.write(\w+)\(this.{attributs_to_fix[0]}\);")
write_method_match = write_method_pattern.search(line)
if write_method_match:
self.attributes[attributs_to_fix[0]] = write_method_match.group(1)
attributs_to_fix.pop(0)
if len(attributs_to_fix) == 0:
break
return {
'file': self.file_name,
'class_name': self.class_name,
'superclass': self.superclass,
'interfaces': self.interfaces,
'protocolId': self.protocolId,
'attributes': self.attributes
}
def main():
reader = ActionScriptReader("action_script_file.as")
result = reader.parse()
print(result)
if __name__ == "__main__":
main()
Small script to do it.