sile / amf Goto Github PK
View Code? Open in Web Editor NEWA Rust Implementation of AMF (Action Media Format)
License: Apache License 2.0
A Rust Implementation of AMF (Action Media Format)
License: Apache License 2.0
Hey I implemented serialization and deserialization of AMF packets
It's my first time writing something like that in Rust so correct me if I did something horrible in code.
Feel free to do whatever you want with it, include in amf crate maybe as optional feature or if you wish I can create amf_packet crate.
I tested it and it seems to work fine
// amf_packet.rs
use std::{io};
use std::convert::{TryFrom, TryInto};
use amf::{Version, Amf0Value};
use amf::amf0::{Value, array, string, number};
extern crate byteorder;
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian, LittleEndian};
use std::fs::File;
use std::io::Read;
use std::string::FromUtf8Error;
use std::borrow::BorrowMut;
pub struct AmfHeader {
pub name: String,
pub must_understand: bool,
pub content: Value,
}
pub struct AmfMessage {
pub target: String,
pub response: String,
pub content: Value,
}
pub struct AmfPacket {
pub version: Version,
pub headers: Vec<AmfHeader>,
pub messages: Vec<AmfMessage>,
}
trait ReadBytesExt2: io::Read {
#[inline]
fn read_bytes(&mut self, size: usize) -> Vec<u8> {
let mut buf = vec![0; size];
self.read_exact(&mut buf).unwrap();
buf
}
#[inline]
fn read_utf8_string(&mut self, length: usize) -> io::Result<String> {
Ok(String::from_utf8(self.read_bytes(length)).unwrap())
}
}
impl<R: io::Read + ?Sized> ReadBytesExt2 for R {}
impl AmfPacket {
pub fn new(version: Version) -> Self {
AmfPacket {version, headers: Vec::new(), messages: Vec::new()}
}
pub fn read_from<R>(mut reader: R) -> io::Result<Self>
where
R: io::Read,
{
let version = reader.read_u16::<BigEndian>()?;
let mut headers = Vec::new();
let header_count = reader.read_u16::<BigEndian>()?;
for _ in 0..header_count {
let header_name_length = reader.read_u16::<BigEndian>()?;
let header_name = reader.read_utf8_string(header_name_length as usize)?;
let must_understand = reader.read_u8()? != 0;
let _header_length = reader.read_i32::<BigEndian>()?;
let content = Value::read_from(&mut reader).unwrap();
headers.push(AmfHeader {name: header_name, must_understand, content });
}
let mut messages = Vec::new();
let message_count = reader.read_u16::<BigEndian>()?;
for _ in 0..message_count {
let target_length = reader.read_u16::<BigEndian>()?;
let target = reader.read_utf8_string(target_length as usize)?;
let response_length = reader.read_u16::<BigEndian>()?;
let response = reader.read_utf8_string(response_length as usize)?;
let _message_length = reader.read_i32::<BigEndian>()?;
let content = Value::read_from(&mut reader).unwrap();
messages.push(AmfMessage {target, response, content});
}
Ok(AmfPacket { version: match version {
0 => Version::Amf0,
3 => Version::Amf3,
_ => panic!("Unknown version! Probably not AMF packet: {}", version),
}, headers, messages })
}
pub fn write_to<W>(&self, mut writer: W) -> io::Result<()>
where
W: io::Write,
{
writer.write_u16::<BigEndian>(match self.version {
Version::Amf0 => 0,
Version::Amf3 => 3
})?;
writer.write_u16::<BigEndian>(self.headers.len() as u16)?;
for header in &self.headers {
writer.write_u16::<BigEndian>(header.name.len() as u16)?;
writer.write_all(header.name.as_bytes())?;
writer.write_u8(header.must_understand as u8)?;
writer.write_i32::<BigEndian>(-1)?; // https://www.adobe.com/content/dam/acom/en/devnet/pdf/amf0-file-format-specification.pdf -1 can be specified
header.content.write_to(&mut writer)?;
}
writer.write_u16::<BigEndian>(self.messages.len() as u16)?;
for message in &self.messages {
writer.write_u16::<BigEndian>(message.target.len() as u16)?;
writer.write_all(message.target.as_bytes())?;
writer.write_u16::<BigEndian>(message.response.len() as u16)?;
writer.write_all(message.response.as_bytes())?;
writer.write_i32::<BigEndian>(-1)?;
message.content.write_to(&mut writer)?;
}
Ok(())
}
}
While developing my .sol editor, I encountered a few .sol files where decoding an AMF3 object
resulted in an OutOfRangeReference
error. While trying to debug, I eventually had the idea that
these AMF objects might be referring to previously read traits/strings/complexes, which are discarded when you call decode()
.
I made a new function which omits the discard code.
/// Decodes a AMF3 value. Keeps traits/strings/complexes.
pub fn decode_keep_state(&mut self) -> DecodeResult<Value> {
self.decode_value()
}
If I call it instead of decode()
, these files seem to read just fine.
The question is, am I assuming this correctly, or could something else cause this OutOfRangeReference
error? Before I submit a pull request, I thought I would ask your expert opinion, as I don't fully understand the AMF3 format.
Here is one such file, which seems to be a cookie for an online flash game:
00000000 00 bf 00 00 01 c4 54 43 53 4f 00 04 00 00 00 00 |......TCSO......|
00000010 00 09 61 6e 61 6c 79 74 69 63 73 00 00 00 03 09 |..analytics.....|
00000020 75 74 6d 61 0a 0b 01 17 63 75 72 72 65 6e 74 54 |utma....currentT|
00000030 69 6d 65 05 41 d7 63 3f 6d 00 00 00 19 73 65 73 |ime.A.c?m....ses|
00000040 73 69 6f 6e 43 6f 75 6e 74 04 02 15 65 78 70 69 |sionCount...expi|
00000050 72 61 74 69 6f 6e 08 01 42 77 c1 e2 15 f0 c0 00 |ration..Bw......|
00000060 11 63 72 65 61 74 69 6f 6e 08 01 42 76 d6 eb f0 |.creation..Bv...|
00000070 70 c0 00 13 66 69 72 73 74 54 69 6d 65 05 41 d7 |p...firstTime.A.|
00000080 63 3d e2 c0 00 00 11 6c 61 73 74 54 69 6d 65 05 |c=.....lastTime.|
00000090 41 d7 63 3d e2 c0 00 00 15 64 6f 6d 61 69 6e 48 |A.c=.....domainH|
000000a0 61 73 68 04 b6 8a e4 8f 13 73 65 73 73 69 6f 6e |ash......session|
000000b0 49 64 05 43 cb e2 a7 3a 88 3a b2 01 00 09 75 74 |Id.C...:.:....ut|
000000c0 6d 7a 0a 01 21 63 61 6d 70 61 69 67 6e 54 72 61 |mz..!campaignTra|
000000d0 63 6b 69 6e 67 06 81 27 75 74 6d 63 73 72 3d 63 |cking..'utmcsr=c|
000000e0 6f 6f 6c 6d 61 74 68 67 61 6d 65 73 2e 63 6f 6d |oolmathgames.com|
000000f0 7c 75 74 6d 63 63 6e 3d 28 72 65 66 65 72 72 61 ||utmccn=(referra|
00000100 6c 29 7c 75 74 6d 63 6d 64 3d 72 65 66 65 72 72 |l)|utmcmd=referr|
00000110 61 6c 7c 75 74 6d 63 63 74 3d 2f 30 2d 63 6c 69 |al|utmcct=/0-cli|
00000120 63 6b 65 72 2d 68 65 72 6f 65 73 21 63 61 6d 70 |cker-heroes!camp|
00000130 61 69 67 6e 53 65 73 73 69 6f 6e 73 04 02 1b 72 |aignSessions...r|
00000140 65 73 70 6f 6e 73 65 43 6f 75 6e 74 04 02 08 08 |esponseCount....|
00000150 01 42 76 d6 eb f0 71 20 00 21 63 61 6d 70 61 69 |.Bv...q .!campai|
00000160 67 6e 43 72 65 61 74 69 6f 6e 05 41 d7 63 3f 6d |gnCreation.A.c?m|
00000170 00 00 00 0e 04 b6 8a e4 8f 06 08 01 42 77 11 a9 |............Bw..|
00000180 79 d1 20 00 01 00 09 75 74 6d 62 0a 01 06 08 01 |y. ....utmb.....|
00000190 42 76 d6 ed a7 e5 a0 00 08 08 01 42 76 d6 eb f0 |Bv.........Bv...|
000001a0 71 a0 00 0c 05 41 d7 63 3d e2 c0 00 00 15 74 72 |q....A.c=.....tr|
000001b0 61 63 6b 43 6f 75 6e 74 04 02 0e 04 b6 8a e4 8f |ackCount........|
000001c0 0b 74 6f 6b 65 6e 04 0a 01 00 |.token....|
000001ca
If needed, I can send you the raw file in email, which you can read with my program: https://github.com/crumblingstatue/soledit
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.