The code is currently only sufficient to read data from SOL of the software I’m working on, it’s not really mature enough to share and use for anything else, but I’m thinking of contributing to Haxe formats library once it’s fully done.
Although there are a few documentations available on AMF3, I couldn’t find anything useful for reading SOL files. And while the data is similar to AMF3, it’s not exactly the same, so it cannot be read with ByteArray.readObject() or with the aforementioned Haxe formats library (it gave inconsistent results on complex objects).
The docs I found are misleading in a few aspects, and the source code of FlashDevelop wasn’t helpful either, because while it has a perfect SOL reader (by ALESSANDRO CRUGNOLA), it’s only included as a DLL library. So I had to come up with my own parser.
Anyway here’s the idea for future reference, maybe someone will find it useful.
Note the method is not fail-safe, some aspects are totally unknown or only guessed, and there are probably better and easier techniques out there. Also it’s only for AMF3 object encoding!
The basic concept of parsing SOL byte data is this:
- The first 17 bytes (header) can be completely ignored. An integer at byte index 2 stores the length of the data (file size minus header size), and there’s a “TCSO” string at byte index 6 which can be used to verify it really is a SharedObject file
- The next data to parse is the name of the shared object starting with the length of the string which is stored on a single byte. So you have to read 1 byte as the length, then read length bytes as string (UTF8)
- Then there’s an integer (4 bytes) which looks to be 3 in all of my test files. I believe it stores whether the data is AMF3 or AMF0 but I can’t say for sure. Who’s using AMF0 nowadays anyway
- The next byte is the length of the property name. It’s a bit tricky, because it has to be shifted right bitwise (byteData >> 1) to get the real length. So a 0x0F byte data actually means that the name of the property is 0x07 bytes long
- The next is to read length bytes as a string, which is the name of the property (as in so.data.myproperty)
- Then comes the type of the data value (1 byte) called marker. Here’s a good read on the subject. Undefined, null, true and false are all stored only as markers, there’s no need to read anything further.
- Then you have to read the actual value. This part is very complex because different types have to be read differently. I.e. Numbers are always 64 bit, Strings always start with the length and so on. More advanced types are a bit difficult to read. Object, ByteArray, Dictionary all have their unique aspects.
- Each and every value ends with 0x0 byte. I believe it is a marker for “data end” in AMF.
- There’s no footer whatsoever in the file, it just ends with the last 0x0 byte for the last property
I hope this all can be helpful to someone. I also recommend to create a basic Flash/AIR application and store all the possible types in a sharedobject to see how the SOL file looks. And yes, a good Hex editor/viewer can come in very handy
Maybe there’s an easier open-source SOL reader somewhere for parsing reference, I just didn’t have much time to look, and gave up searching for it.