├── Extensions.cs ├── Database ├── Column.cs └── FieldType.cs ├── MarshalAttribute.cs ├── PyNone.cs ├── PyObjectType.cs ├── ZeroCompressOpcode.cs ├── PySubStruct.cs ├── PyRawData.cs ├── PyLongLong.cs ├── MarshalOpcode.cs ├── PyFloat.cs ├── PyChecksumedStream.cs ├── PyBuffer.cs ├── PyObjectData.cs ├── PyBool.cs ├── PyToken.cs ├── Properties └── AssemblyInfo.cs ├── Marshal.cs ├── PySubStream.cs ├── PyInt.cs ├── PyObjectEx.cs ├── PyIntegerVar.cs ├── PyList.cs ├── PyTuple.cs ├── PyDict.cs ├── eveMarshal.csproj ├── PyObject.cs ├── PyString.cs ├── MarshalData.cs ├── PyPackedRow.cs ├── Unmarshal.cs ├── PrettyPrinter.cs ├── Utility.cs └── StringTable.cs /Extensions.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace eveMarshal 4 | { 5 | 6 | internal static class Extensions 7 | { 8 | public static void WriteOpcode(this BinaryWriter w, MarshalOpcode op) 9 | { 10 | w.Write((byte) op); 11 | } 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /Database/Column.cs: -------------------------------------------------------------------------------- 1 | namespace eveMarshal.Database 2 | { 3 | 4 | public class Column 5 | { 6 | public string Name { get; private set; } 7 | public FieldType Type { get; private set; } 8 | public PyObject Value { get; set; } 9 | 10 | public Column(string name, FieldType type) 11 | { 12 | Name = name; 13 | Type = type; 14 | } 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /MarshalAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace eveMarshal 4 | { 5 | 6 | [AttributeUsage(AttributeTargets.Class)] 7 | public class MarshalOptions : Attribute 8 | { 9 | public bool Checksum { get; set; } 10 | } 11 | 12 | [AttributeUsage(AttributeTargets.Field)] 13 | public class MarshalAs : Attribute 14 | { 15 | public MarshalOpcode Opcode { get; private set; } 16 | 17 | public MarshalAs(MarshalOpcode opcode) 18 | { 19 | Opcode = opcode; 20 | } 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /PyNone.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace eveMarshal 4 | { 5 | 6 | public class PyNone : PyObject 7 | { 8 | 9 | public PyNone() 10 | : base(PyObjectType.None) 11 | { 12 | 13 | } 14 | 15 | public override void Decode(Unmarshal context, MarshalOpcode op, BinaryReader source) 16 | { 17 | } 18 | 19 | protected override void EncodeInternal(BinaryWriter output) 20 | { 21 | output.WriteOpcode(MarshalOpcode.None); 22 | } 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /PyObjectType.cs: -------------------------------------------------------------------------------- 1 | namespace eveMarshal 2 | { 3 | 4 | public enum PyObjectType 5 | { 6 | Tuple, 7 | String, 8 | Bool, 9 | None, 10 | Token, 11 | Float, 12 | LongLong, 13 | Long, 14 | SignedShort, 15 | Byte, 16 | Buffer, 17 | List, 18 | Dict, 19 | ObjectData, 20 | SubStream, 21 | ChecksumedStream, 22 | IntegerVar, 23 | ObjectEx, 24 | PackedRow, 25 | SubStruct, 26 | RawData, 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /ZeroCompressOpcode.cs: -------------------------------------------------------------------------------- 1 | namespace eveMarshal 2 | { 3 | 4 | public class ZeroCompressOpcode 5 | { 6 | public byte FirstLength; 7 | public bool FirstIsZero; 8 | public byte SecondLength; 9 | public bool SecondIsZero; 10 | 11 | public ZeroCompressOpcode(byte source) 12 | { 13 | FirstLength = (byte)(source & 0x07); 14 | FirstIsZero = (source & 0x08) > 0; 15 | SecondLength = (byte) ((source & 0x70) >> 4); 16 | SecondIsZero = (source & 0x80) > 0; 17 | } 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /PySubStruct.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace eveMarshal 4 | { 5 | 6 | public class PySubStruct : PyObject 7 | { 8 | public PyObject Definition { get; set; } 9 | 10 | public PySubStruct() 11 | : base(PyObjectType.SubStruct) 12 | { 13 | 14 | } 15 | 16 | public override void Decode(Unmarshal context, MarshalOpcode op, BinaryReader source) 17 | { 18 | Definition = context.ReadObject(source); 19 | } 20 | 21 | protected override void EncodeInternal(BinaryWriter output) 22 | { 23 | output.WriteOpcode(MarshalOpcode.SubStruct); 24 | Definition.Encode(output); 25 | } 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /PyRawData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace eveMarshal 5 | { 6 | 7 | /// 8 | /// Used to insert raw data into the marshal stream; not an actual blue marshal opcode 9 | /// 10 | public class PyRawData : PyObject 11 | { 12 | public byte[] Data { get; set; } 13 | 14 | public PyRawData() 15 | : base(PyObjectType.RawData) 16 | { 17 | 18 | } 19 | 20 | public PyRawData(byte[] data) 21 | : this() 22 | { 23 | Data = data; 24 | } 25 | 26 | public override void Decode(Unmarshal context, MarshalOpcode op, BinaryReader source) 27 | { 28 | throw new NotImplementedException(); 29 | } 30 | 31 | protected override void EncodeInternal(BinaryWriter output) 32 | { 33 | output.Write(Data); 34 | } 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /PyLongLong.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace eveMarshal 4 | { 5 | 6 | public class PyLongLong : PyObject 7 | { 8 | public long Value { get; private set; } 9 | 10 | public PyLongLong() 11 | : base(PyObjectType.LongLong) 12 | { 13 | 14 | } 15 | 16 | public PyLongLong(long val) 17 | : base(PyObjectType.LongLong) 18 | { 19 | Value = val; 20 | } 21 | 22 | public override void Decode(Unmarshal context, MarshalOpcode op, BinaryReader source) 23 | { 24 | Value = source.ReadInt64(); 25 | } 26 | 27 | protected override void EncodeInternal(BinaryWriter output) 28 | { 29 | output.WriteOpcode(MarshalOpcode.IntegerLongLong); 30 | output.Write(Value); 31 | } 32 | 33 | public override string ToString() 34 | { 35 | return "<" + Value + ">"; 36 | } 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /MarshalOpcode.cs: -------------------------------------------------------------------------------- 1 | namespace eveMarshal 2 | { 3 | 4 | public enum MarshalOpcode 5 | { 6 | Error, 7 | None, 8 | Token, 9 | IntegerLongLong, 10 | IntegerLong, 11 | IntegerSignedShort, 12 | IntegerByte, 13 | IntegerMinusOne, 14 | IntegerZero, 15 | IntegerOne, 16 | Real, 17 | RealZero, 18 | Buffer = 13, 19 | StringEmpty, 20 | StringChar, 21 | StringShort, 22 | StringTable, 23 | WStringUCS2, 24 | StringLong, 25 | Tuple, 26 | List, 27 | Dict, 28 | Object = 23, 29 | SubStruct = 25, 30 | SavedStreamElement = 27, 31 | ChecksumedStream, 32 | BoolTrue = 31, 33 | BoolFalse, 34 | ObjectEx1 = 34, 35 | ObjectEx2, 36 | TupleEmpty, 37 | TupleOne, 38 | ListEmpty, 39 | ListOne, 40 | WStringEmpty, 41 | WStringUCS2Char, 42 | PackedRow, 43 | SubStream, 44 | TupleTwo, 45 | WStringUTF8 = 46, 46 | IntegerVar 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /PyFloat.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace eveMarshal 4 | { 5 | 6 | public class PyFloat : PyObject 7 | { 8 | public double Value { get; private set; } 9 | 10 | public PyFloat() 11 | : base(PyObjectType.Float) 12 | { 13 | 14 | } 15 | 16 | public PyFloat(double value) 17 | : base(PyObjectType.Float) 18 | { 19 | Value = value; 20 | } 21 | 22 | public override void Decode(Unmarshal context, MarshalOpcode op, BinaryReader source) 23 | { 24 | if (op == MarshalOpcode.RealZero) 25 | Value = 0.0d; 26 | else 27 | Value = source.ReadDouble(); 28 | } 29 | 30 | protected override void EncodeInternal(BinaryWriter output) 31 | { 32 | if (Value == 0.0d) 33 | output.WriteOpcode(MarshalOpcode.RealZero); 34 | else 35 | { 36 | output.WriteOpcode(MarshalOpcode.Real); 37 | output.Write(Value); 38 | } 39 | } 40 | 41 | public override string ToString() 42 | { 43 | return "<" + Value + ">"; 44 | } 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /PyChecksumedStream.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace eveMarshal 4 | { 5 | 6 | public class PyChecksumedStream : PyObject 7 | { 8 | public uint Checksum { get; private set; } 9 | public PyObject Data { get; private set; } 10 | 11 | public PyChecksumedStream(PyObject data) 12 | : base(PyObjectType.ChecksumedStream) 13 | { 14 | Data = data; 15 | } 16 | 17 | public PyChecksumedStream() 18 | : base(PyObjectType.ChecksumedStream) 19 | { 20 | 21 | } 22 | 23 | public override void Decode(Unmarshal context, MarshalOpcode op, BinaryReader source) 24 | { 25 | Checksum = source.ReadUInt32(); 26 | Data = context.ReadObject(source); 27 | } 28 | 29 | protected override void EncodeInternal(BinaryWriter output) 30 | { 31 | output.WriteOpcode(MarshalOpcode.ChecksumedStream); 32 | var ms = new MemoryStream(); 33 | var tmp = new BinaryWriter(ms); 34 | Data.Encode(tmp); 35 | var data = ms.ToArray(); 36 | Checksum = Adler32.Checksum(data); 37 | output.Write(Checksum); 38 | output.Write(data); 39 | } 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /PyBuffer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Text; 4 | 5 | namespace eveMarshal 6 | { 7 | 8 | public class PyBuffer : PyObject 9 | { 10 | public byte[] Data { get; private set; } 11 | 12 | public PyBuffer() 13 | : base(PyObjectType.Buffer) 14 | { 15 | 16 | } 17 | 18 | public PyBuffer(byte[] data) 19 | : base(PyObjectType.Buffer) 20 | { 21 | Data = data; 22 | } 23 | 24 | public PyBuffer(string data) 25 | : base(PyObjectType.Buffer) 26 | { 27 | Data = Encoding.ASCII.GetBytes(data); 28 | } 29 | 30 | public override void Decode(Unmarshal context, MarshalOpcode op, BinaryReader source) 31 | { 32 | var size = source.ReadSizeEx(); 33 | Data = source.ReadBytes((int)size); 34 | } 35 | 36 | protected override void EncodeInternal(BinaryWriter output) 37 | { 38 | output.WriteOpcode(MarshalOpcode.Buffer); 39 | output.WriteSizeEx(Data.Length); 40 | output.Write(Data); 41 | } 42 | 43 | public override string ToString() 44 | { 45 | return "<" + BitConverter.ToString(Data) + ">"; 46 | } 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /PyObjectData.cs: -------------------------------------------------------------------------------- 1 | using System.Data; 2 | using System.IO; 3 | 4 | namespace eveMarshal 5 | { 6 | 7 | public class PyObjectData : PyObject 8 | { 9 | public PyObjectData() 10 | : base(PyObjectType.ObjectData) 11 | { 12 | 13 | } 14 | 15 | public PyObjectData(string objectName, PyObject arguments) 16 | : base(PyObjectType.ObjectData) 17 | { 18 | Name = objectName; 19 | Arguments = arguments; 20 | } 21 | 22 | public string Name { get; set; } 23 | public PyObject Arguments { get; set; } 24 | 25 | public override void Decode(Unmarshal context, MarshalOpcode op, BinaryReader source) 26 | { 27 | var nameObject = context.ReadObject(source); 28 | if (nameObject.Type != PyObjectType.String) 29 | throw new DataException("Expected PyString"); 30 | Name = (nameObject as PyString).Value; 31 | 32 | Arguments = context.ReadObject(source); 33 | } 34 | 35 | protected override void EncodeInternal(BinaryWriter output) 36 | { 37 | output.WriteOpcode(MarshalOpcode.Object); 38 | new PyString(Name).Encode(output); 39 | Arguments.Encode(output); 40 | } 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /PyBool.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace eveMarshal 4 | { 5 | 6 | public class PyBool : PyObject 7 | { 8 | public bool Value { get; set; } 9 | 10 | public PyBool() : base(PyObjectType.Bool) 11 | { 12 | } 13 | 14 | public PyBool(bool val) : this() 15 | { 16 | Value = val; 17 | } 18 | 19 | public override void Decode(Unmarshal context, MarshalOpcode op, BinaryReader source) 20 | { 21 | switch (op) 22 | { 23 | case MarshalOpcode.BoolTrue: 24 | Value = true; 25 | break; 26 | 27 | case MarshalOpcode.BoolFalse: 28 | Value = false; 29 | break; 30 | } 31 | } 32 | 33 | protected override void EncodeInternal(BinaryWriter output) 34 | { 35 | switch (Value) 36 | { 37 | case true: 38 | output.WriteOpcode(MarshalOpcode.BoolTrue); 39 | break; 40 | 41 | case false: 42 | output.WriteOpcode(MarshalOpcode.BoolFalse); 43 | break; 44 | } 45 | } 46 | 47 | public override string ToString() 48 | { 49 | return "<" + Value + ">"; 50 | } 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /PyToken.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Text; 3 | 4 | namespace eveMarshal 5 | { 6 | 7 | public class PyToken : PyObject 8 | { 9 | public byte[] RawToken { get; set; } 10 | public string Token { get; set; } 11 | 12 | public PyToken() 13 | : base(PyObjectType.Token) 14 | { 15 | 16 | } 17 | 18 | public PyToken(string token) 19 | : base(PyObjectType.Token) 20 | { 21 | Token = token; 22 | } 23 | 24 | public override void Decode(Unmarshal context, MarshalOpcode op, BinaryReader source) 25 | { 26 | byte len = source.ReadByte(); 27 | RawToken = source.ReadBytes(len); 28 | Token = Encoding.ASCII.GetString(RawToken); 29 | } 30 | 31 | protected override void EncodeInternal(BinaryWriter output) 32 | { 33 | output.WriteOpcode(MarshalOpcode.Token); 34 | if (RawToken != null) 35 | { 36 | output.Write((byte)RawToken.Length); 37 | output.Write(RawToken); 38 | } 39 | else if (Token != null) 40 | { 41 | output.Write((byte)Token.Length); 42 | output.Write(Encoding.ASCII.GetBytes(Token)); 43 | } 44 | else 45 | throw new InvalidDataException("Fill either RawToken or Token with data for encoding"); 46 | } 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("eveMarshal")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("eveMarshal")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2011")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("aea94c49-b86a-4af7-a8b6-63ea6ee23de0")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Marshal.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | 5 | namespace eveMarshal 6 | { 7 | 8 | public static class Marshal 9 | { 10 | public static byte[] Process(PyObject obj) 11 | { 12 | var ret = new MemoryStream(100); 13 | ret.WriteByte(Unmarshal.HeaderByte); 14 | // we have no support for save lists right now 15 | ret.WriteByte(0x00); 16 | ret.WriteByte(0x00); 17 | ret.WriteByte(0x00); 18 | ret.WriteByte(0x00); 19 | obj.Encode(new BinaryWriter(ret)); 20 | return ret.ToArray(); 21 | } 22 | 23 | public static PyTuple Tuple(params PyObject[] objs) 24 | { 25 | return new PyTuple(new List(objs)); 26 | } 27 | 28 | public static PyDict Dict(params object[] objs) 29 | { 30 | if (objs.Length % 2 == 1) 31 | throw new ArgumentException("Expected pair arguments"); 32 | 33 | var ret = new PyDict(new Dictionary(objs.Length / 2)); 34 | for (int i = 0; i < (objs.Length/2); i++) 35 | { 36 | var key = objs[i]; 37 | var val = objs[i + 1]; 38 | if (!(key is string)) 39 | throw new ArgumentException("Expected string"); 40 | if (!(val is PyObject)) 41 | throw new ArgumentException("Expected PyObject"); 42 | ret.Dictionary.Add(new PyString(key as string), val as PyObject); 43 | } 44 | return ret; 45 | } 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /PySubStream.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace eveMarshal 4 | { 5 | 6 | public class PySubStream : PyObject 7 | { 8 | public byte[] RawData { get; set; } 9 | public PyObject Data { get; set; } 10 | public Unmarshal DataUnmarshal { get; set; } 11 | 12 | public PySubStream() 13 | : base(PyObjectType.SubStream) 14 | { 15 | 16 | } 17 | 18 | public PySubStream(byte[] data) 19 | : base(PyObjectType.SubStream) 20 | { 21 | RawData = data; 22 | DataUnmarshal = new Unmarshal(); 23 | Data = DataUnmarshal.Process(data); 24 | } 25 | 26 | public PySubStream(PyObject data) 27 | : base(PyObjectType.SubStream) 28 | { 29 | Data = data; 30 | } 31 | 32 | public override void Decode(Unmarshal context, MarshalOpcode op, BinaryReader source) 33 | { 34 | uint len = source.ReadSizeEx(); 35 | RawData = source.ReadBytes((int) len); 36 | DataUnmarshal = new Unmarshal(); 37 | Data = DataUnmarshal.Process(RawData); 38 | } 39 | 40 | protected override void EncodeInternal(BinaryWriter output) 41 | { 42 | output.WriteOpcode(MarshalOpcode.SubStream); 43 | var tempMs = new MemoryStream(); 44 | var temp = new BinaryWriter(tempMs); 45 | temp.Write((byte)0x7E); 46 | temp.Write((uint)0); 47 | Data.Encode(temp); 48 | output.WriteSizeEx((uint)tempMs.Length); 49 | output.Write(tempMs.ToArray()); 50 | } 51 | 52 | public override string ToString() 53 | { 54 | return ""; 55 | } 56 | 57 | } 58 | 59 | } -------------------------------------------------------------------------------- /Database/FieldType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace eveMarshal.Database 4 | { 5 | 6 | public enum FieldType 7 | { 8 | Empty = 0x00, 9 | Null = 0x01, 10 | I2 = 0x02, 11 | I4 = 0x03, 12 | R4 = 0x04, 13 | R8 = 0x05, 14 | 15 | /// 16 | /// Currency 17 | /// 18 | CY = 0x06, 19 | 20 | Error = 0x0A, 21 | Bool = 0x0B, 22 | I1 = 0x10, 23 | UI1 = 0x11, 24 | UI2 = 0x12, 25 | UI4 = 0x13, 26 | I8 = 0x14, 27 | UI8 = 0x15, 28 | 29 | /// 30 | /// Win32 FILETIME 64 bit timestamp 31 | /// 32 | FileTime = 0x40, 33 | 34 | Bytes = 0x80, 35 | Str = 0x81, 36 | WStr = 0x82, 37 | } 38 | 39 | public static class FieldTypeHelper 40 | { 41 | public static int GetTypeBytes(FieldType type) 42 | { 43 | return ((GetTypeBits(type) + 7) >> 3); 44 | } 45 | 46 | public static int GetTypeBits(FieldType type) 47 | { 48 | switch (type) 49 | { 50 | case FieldType.I8: 51 | case FieldType.UI8: 52 | case FieldType.R8: 53 | case FieldType.CY: 54 | case FieldType.FileTime: 55 | return 64; 56 | 57 | case FieldType.I4: 58 | case FieldType.UI4: 59 | case FieldType.R4: 60 | return 32; 61 | 62 | case FieldType.I2: 63 | case FieldType.UI2: 64 | return 16; 65 | 66 | case FieldType.I1: 67 | case FieldType.UI1: 68 | return 8; 69 | 70 | case FieldType.Bool: 71 | return 1; 72 | 73 | case FieldType.Bytes: 74 | case FieldType.Str: 75 | case FieldType.WStr: 76 | // handled differently 77 | return 0; 78 | 79 | default: 80 | throw new Exception("Invalid FieldType"); 81 | } 82 | } 83 | } 84 | 85 | } -------------------------------------------------------------------------------- /PyInt.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | 3 | namespace eveMarshal 4 | { 5 | 6 | public class PyInt : PyObject 7 | { 8 | public int Value { get; private set; } 9 | 10 | public PyInt() 11 | : base(PyObjectType.Long) 12 | { 13 | 14 | } 15 | 16 | public PyInt(int val) 17 | : base(PyObjectType.Long) 18 | { 19 | Value = val; 20 | } 21 | 22 | public override void Decode(Unmarshal context, MarshalOpcode op, BinaryReader source) 23 | { 24 | if (op == MarshalOpcode.IntegerOne) 25 | Value = 1; 26 | else if (op == MarshalOpcode.IntegerZero) 27 | Value = 0; 28 | else if (op == MarshalOpcode.IntegerMinusOne) 29 | Value = -1; 30 | else if (op == MarshalOpcode.IntegerByte) 31 | Value = source.ReadByte(); 32 | else if (op == MarshalOpcode.IntegerSignedShort) 33 | Value = source.ReadInt16(); 34 | else if (op == MarshalOpcode.IntegerLong) 35 | Value = source.ReadInt32(); 36 | } 37 | 38 | protected override void EncodeInternal(BinaryWriter output) 39 | { 40 | if (Value == 1) 41 | output.WriteOpcode(MarshalOpcode.IntegerOne); 42 | else if (Value == 0) 43 | output.WriteOpcode(MarshalOpcode.IntegerZero); 44 | else if (Value == -1) 45 | output.WriteOpcode(MarshalOpcode.IntegerMinusOne); 46 | else if (Value < 127) 47 | { 48 | output.WriteOpcode(MarshalOpcode.IntegerByte); 49 | output.Write((byte)Value); 50 | } 51 | else if (Value < 32768) 52 | { 53 | output.WriteOpcode(MarshalOpcode.IntegerSignedShort); 54 | output.Write((short)Value); 55 | } 56 | else 57 | { 58 | output.WriteOpcode(MarshalOpcode.IntegerLong); 59 | output.Write(Value); 60 | } 61 | } 62 | 63 | public override string ToString() 64 | { 65 | return "<" + Value + ">"; 66 | } 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /PyObjectEx.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | 4 | namespace eveMarshal 5 | { 6 | 7 | public class PyObjectEx : PyObject 8 | { 9 | private const byte PackedTerminator = 0x2D; 10 | 11 | public bool IsType2 { get; private set; } 12 | public PyObject Header { get; private set; } 13 | public Dictionary Dictionary { get; private set; } 14 | public List List { get; private set; } 15 | 16 | public PyObjectEx(bool isType2, PyObject header) 17 | : base(PyObjectType.ObjectEx) 18 | { 19 | IsType2 = isType2; 20 | Header = header; 21 | Dictionary = new Dictionary(); 22 | } 23 | 24 | public PyObjectEx() 25 | : base(PyObjectType.ObjectEx) 26 | { 27 | 28 | } 29 | 30 | public override void Decode(Unmarshal context, MarshalOpcode op, BinaryReader source) 31 | { 32 | if (op == MarshalOpcode.ObjectEx2) 33 | IsType2 = true; 34 | 35 | Dictionary = new Dictionary(); 36 | List = new List(); 37 | Header = context.ReadObject(source); 38 | 39 | while (source.BaseStream.Position < source.BaseStream.Length) 40 | { 41 | var b = source.ReadByte(); 42 | if (b == PackedTerminator) 43 | break; 44 | source.BaseStream.Seek(-1, SeekOrigin.Current); 45 | List.Add(context.ReadObject(source)); 46 | } 47 | 48 | while (source.BaseStream.Position < source.BaseStream.Length) 49 | { 50 | var b = source.ReadByte(); 51 | if (b == PackedTerminator) 52 | break; 53 | source.BaseStream.Seek(-1, SeekOrigin.Current); 54 | var key = context.ReadObject(source); 55 | var value = context.ReadObject(source); 56 | Dictionary.Add(key, value); 57 | } 58 | } 59 | 60 | protected override void EncodeInternal(BinaryWriter output) 61 | { 62 | output.WriteOpcode(IsType2 ? MarshalOpcode.ObjectEx2 : MarshalOpcode.ObjectEx1); 63 | Header.Encode(output); 64 | // list 65 | output.Write(PackedTerminator); 66 | // dict 67 | output.Write(PackedTerminator); 68 | } 69 | } 70 | 71 | } -------------------------------------------------------------------------------- /PyIntegerVar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace eveMarshal 5 | { 6 | 7 | public class PyIntegerVar : PyObject 8 | { 9 | public byte[] Raw { get; private set; } 10 | 11 | public PyIntegerVar() 12 | : base (PyObjectType.IntegerVar) 13 | { 14 | 15 | } 16 | 17 | public PyIntegerVar(byte[] data) 18 | : base(PyObjectType.IntegerVar) 19 | { 20 | Raw = data; 21 | } 22 | 23 | public PyIntegerVar(int data) 24 | : base(PyObjectType.IntegerVar) 25 | { 26 | Raw = GetData(data); 27 | } 28 | 29 | public PyIntegerVar(long data) 30 | : base(PyObjectType.IntegerVar) 31 | { 32 | Raw = GetData(data); 33 | } 34 | 35 | public PyIntegerVar(short data) 36 | : base(PyObjectType.IntegerVar) 37 | { 38 | Raw = GetData(data); 39 | } 40 | 41 | public PyIntegerVar(byte data) 42 | : base(PyObjectType.IntegerVar) 43 | { 44 | Raw = new []{data}; 45 | } 46 | 47 | private static byte[] GetData(long value) 48 | { 49 | if (value < 128) 50 | return new[]{(byte)value}; 51 | if (value < Math.Pow(2, 15)) 52 | return BitConverter.GetBytes((short)value); 53 | if (value < Math.Pow(2, 31)) 54 | return BitConverter.GetBytes((int)value); 55 | return BitConverter.GetBytes(value); 56 | } 57 | 58 | public int Value 59 | { 60 | get 61 | { 62 | if (Raw.Length == 1) 63 | return Raw[0]; 64 | if (Raw.Length == 2) 65 | return BitConverter.ToInt16(Raw, 0); 66 | if (Raw.Length == 4) 67 | return BitConverter.ToInt32(Raw, 0); 68 | return -1; 69 | } 70 | } 71 | 72 | public override void Decode(Unmarshal context, MarshalOpcode op, BinaryReader source) 73 | { 74 | var len = source.ReadSizeEx(); 75 | Raw = source.ReadBytes((int) len); 76 | } 77 | 78 | protected override void EncodeInternal(BinaryWriter output) 79 | { 80 | output.WriteOpcode(MarshalOpcode.IntegerVar); 81 | output.WriteSizeEx(Raw.Length); 82 | output.Write(Raw); 83 | } 84 | } 85 | 86 | } -------------------------------------------------------------------------------- /PyList.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | 6 | namespace eveMarshal 7 | { 8 | 9 | public class PyList : PyObject, IEnumerable 10 | { 11 | public List Items { get; private set; } 12 | 13 | public PyList() 14 | : base(PyObjectType.List) 15 | { 16 | Items = new List(); 17 | } 18 | 19 | public PyList(List items) 20 | : base(PyObjectType.List) 21 | { 22 | Items = items; 23 | } 24 | 25 | public override void Decode(Unmarshal context, MarshalOpcode op, BinaryReader source) 26 | { 27 | int count = -1; 28 | switch (op) 29 | { 30 | case MarshalOpcode.ListEmpty: 31 | count = 0; 32 | break; 33 | case MarshalOpcode.ListOne: 34 | count = 1; 35 | break; 36 | case MarshalOpcode.List: 37 | count = (int)source.ReadSizeEx(); 38 | break; 39 | } 40 | 41 | if (count >= 0) 42 | { 43 | Items = new List(count); 44 | for (int i = 0; i < count; i++) 45 | Items.Add(context.ReadObject(source)); 46 | } 47 | } 48 | 49 | protected override void EncodeInternal(BinaryWriter output) 50 | { 51 | if (Items.Count == 0) 52 | output.WriteOpcode(MarshalOpcode.ListEmpty); 53 | else 54 | { 55 | if (Items.Count == 1) 56 | output.WriteOpcode(MarshalOpcode.ListOne); 57 | else 58 | { 59 | output.WriteOpcode(MarshalOpcode.List); 60 | output.WriteSizeEx(Items.Count); 61 | } 62 | 63 | foreach (var item in Items) 64 | item.Encode(output); 65 | } 66 | } 67 | 68 | public IEnumerator GetEnumerator() 69 | { 70 | return Items.GetEnumerator(); 71 | } 72 | 73 | public override string ToString() 74 | { 75 | var sb = new StringBuilder("<\n"); 76 | foreach (var obj in Items) 77 | sb.AppendLine("\t" + obj); 78 | sb.Append(">"); 79 | return sb.ToString(); 80 | } 81 | 82 | IEnumerator IEnumerable.GetEnumerator() 83 | { 84 | return GetEnumerator(); 85 | } 86 | } 87 | 88 | } -------------------------------------------------------------------------------- /PyTuple.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | 6 | namespace eveMarshal 7 | { 8 | 9 | public class PyTuple : PyObject, IEnumerable 10 | { 11 | public List Items { get; private set; } 12 | 13 | public PyTuple() 14 | : base(PyObjectType.Tuple) 15 | { 16 | Items = new List(); 17 | } 18 | 19 | public PyTuple(List items) 20 | : base(PyObjectType.Tuple) 21 | { 22 | Items = items; 23 | } 24 | 25 | public override void Decode(Unmarshal context, MarshalOpcode op, BinaryReader source) 26 | { 27 | int count = -1; 28 | switch (op) 29 | { 30 | case MarshalOpcode.TupleEmpty: 31 | count = 0; 32 | break; 33 | case MarshalOpcode.TupleOne: 34 | count = 1; 35 | break; 36 | case MarshalOpcode.TupleTwo: 37 | count = 2; 38 | break; 39 | case MarshalOpcode.Tuple: 40 | count = (int)source.ReadSizeEx(); 41 | break; 42 | } 43 | 44 | if (count >= 0) 45 | { 46 | Items = new List(count); 47 | for (int i = 0; i < count; i++) 48 | Items.Add(context.ReadObject(source)); 49 | } 50 | } 51 | 52 | protected override void EncodeInternal(BinaryWriter output) 53 | { 54 | if (Items.Count == 0) 55 | output.WriteOpcode(MarshalOpcode.TupleEmpty); 56 | else 57 | { 58 | if (Items.Count == 1) 59 | output.WriteOpcode(MarshalOpcode.TupleOne); 60 | else if (Items.Count == 2) 61 | output.WriteOpcode(MarshalOpcode.TupleTwo); 62 | else 63 | { 64 | output.WriteOpcode(MarshalOpcode.Tuple); 65 | output.WriteSizeEx(Items.Count); 66 | } 67 | 68 | foreach (var item in Items) 69 | item.Encode(output); 70 | } 71 | } 72 | 73 | public override PyObject this[int index] 74 | { 75 | get 76 | { 77 | return Items[index]; 78 | } 79 | set 80 | { 81 | Items[index] = value; 82 | } 83 | } 84 | 85 | public IEnumerator GetEnumerator() 86 | { 87 | return Items.GetEnumerator(); 88 | } 89 | 90 | public override string ToString() 91 | { 92 | var sb = new StringBuilder("<\n"); 93 | foreach (var obj in Items) 94 | sb.AppendLine("\t" + obj); 95 | sb.Append(">"); 96 | return sb.ToString(); 97 | } 98 | 99 | IEnumerator IEnumerable.GetEnumerator() 100 | { 101 | return GetEnumerator(); 102 | } 103 | } 104 | 105 | } -------------------------------------------------------------------------------- /PyDict.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Text; 4 | using System.Linq; 5 | 6 | namespace eveMarshal 7 | { 8 | 9 | public class PyDict : PyObject 10 | { 11 | public Dictionary Dictionary { get; private set; } 12 | 13 | public PyDict() 14 | : base(PyObjectType.Dict) 15 | { 16 | Dictionary = new Dictionary(); 17 | } 18 | 19 | public PyDict(Dictionary dict) 20 | : base(PyObjectType.Dict) 21 | { 22 | Dictionary = dict; 23 | } 24 | 25 | public PyObject Get(string key) 26 | { 27 | var keyObject = 28 | Dictionary.Keys.Where(k => k.Type == PyObjectType.String && (k as PyString).Value == key).FirstOrDefault(); 29 | return keyObject == null ? null : Dictionary[keyObject]; 30 | } 31 | 32 | public void Set(string key, PyObject value) 33 | { 34 | var keyObject = Dictionary.Count > 0 ? Dictionary.Keys.Where(k => k.Type == PyObjectType.String && (k as PyString).Value == key).FirstOrDefault() : null; 35 | if (keyObject != null) 36 | Dictionary[keyObject] = value; 37 | else 38 | Dictionary.Add(new PyString(key), value); 39 | } 40 | 41 | public bool Contains(string key) 42 | { 43 | return Dictionary.Keys.Any(k => k.Type == PyObjectType.String && (k as PyString).Value == key); 44 | } 45 | 46 | public override void Decode(Unmarshal context, MarshalOpcode op, BinaryReader source) 47 | { 48 | var entries = source.ReadSizeEx(); 49 | Dictionary = new Dictionary((int)entries); 50 | for (uint i = 0; i < entries; i++) 51 | { 52 | var value = context.ReadObject(source); 53 | var key = context.ReadObject(source); 54 | Dictionary.Add(key, value); 55 | } 56 | } 57 | 58 | protected override void EncodeInternal(BinaryWriter output) 59 | { 60 | output.WriteOpcode(MarshalOpcode.Dict); 61 | output.WriteSizeEx(Dictionary.Count); 62 | foreach (var pair in Dictionary) 63 | { 64 | pair.Value.Encode(output); 65 | pair.Key.Encode(output); 66 | } 67 | } 68 | 69 | public PyObject this[PyObject key] 70 | { 71 | get 72 | { 73 | return Dictionary[key]; 74 | } 75 | set 76 | { 77 | Dictionary[key] = value; 78 | } 79 | } 80 | 81 | public override PyObject this[string key] 82 | { 83 | get 84 | { 85 | return Get(key); 86 | } 87 | set 88 | { 89 | Set(key, value); 90 | } 91 | } 92 | 93 | public override string ToString() 94 | { 95 | var sb = new StringBuilder("<\n"); 96 | foreach (var pair in Dictionary) 97 | sb.AppendLine("\t" + pair.Key + " " + pair.Value); 98 | sb.Append(">"); 99 | return sb.ToString(); 100 | } 101 | 102 | } 103 | 104 | } -------------------------------------------------------------------------------- /eveMarshal.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {B68DB35D-A125-4EB5-97B6-076823514B23} 9 | Library 10 | Properties 11 | eveMarshal 12 | eveMarshal 13 | v4.0 14 | 512 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 86 | -------------------------------------------------------------------------------- /PyObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace eveMarshal 5 | { 6 | 7 | public abstract class PyObject 8 | { 9 | /// 10 | /// Enables recording RawSource and RawOffset data. More than doubles memory footprint of eveMarshal. 11 | /// 12 | public static bool EnableInspection; 13 | 14 | public byte[] RawSource { get; set; } 15 | public long RawOffset { get; set; } 16 | 17 | public PyObjectType Type 18 | { 19 | get; private set; 20 | } 21 | 22 | protected PyObject(PyObjectType type) 23 | { 24 | Type = type; 25 | } 26 | 27 | public abstract void Decode(Unmarshal context, MarshalOpcode op, BinaryReader source); 28 | 29 | public void Encode(BinaryWriter output) 30 | { 31 | RawOffset = output.BaseStream.Position; 32 | 33 | EncodeInternal(output); 34 | 35 | if (EnableInspection) 36 | { 37 | var postOffset = output.BaseStream.Position; 38 | output.BaseStream.Seek(RawOffset, SeekOrigin.Begin); 39 | RawSource = new byte[postOffset - RawOffset]; 40 | output.BaseStream.Read(RawSource, 0, (int)(postOffset - RawOffset)); 41 | } 42 | } 43 | 44 | protected abstract void EncodeInternal(BinaryWriter output); 45 | 46 | public T As() where T : PyObject 47 | { 48 | return this as T; 49 | } 50 | 51 | public virtual PyObject this[int index] 52 | { 53 | get 54 | { 55 | throw new NotSupportedException("Can't subscript a PyObject"); 56 | } 57 | set 58 | { 59 | throw new NotSupportedException("Can't subscript a PyObject"); 60 | } 61 | } 62 | 63 | public virtual PyObject this[string key] 64 | { 65 | get 66 | { 67 | throw new NotSupportedException("Can't subscript a PyObject"); 68 | } 69 | set 70 | { 71 | throw new NotSupportedException("Can't subscript a PyObject"); 72 | } 73 | } 74 | 75 | public double FloatValue 76 | { 77 | get 78 | { 79 | if (this is PyFloat) 80 | return (this as PyFloat).Value; 81 | return IntValue; 82 | } 83 | } 84 | 85 | public string StringValue 86 | { 87 | get 88 | { 89 | if (this is PyString) 90 | return (this as PyString).Value; 91 | if (this is PyToken) 92 | return (this as PyToken).Token; 93 | return null; 94 | } 95 | } 96 | 97 | public long IntValue 98 | { 99 | get 100 | { 101 | if (this is PyNone) 102 | return 0; 103 | 104 | if (this is PyFloat) 105 | return (long)As().Value; 106 | 107 | if (this is PyBool) 108 | return As().Value ? 1 : 0; 109 | 110 | if (this is PyInt) 111 | return As().Value; 112 | 113 | if (this is PyLongLong) 114 | return As().Value; 115 | 116 | if (this is PyIntegerVar) 117 | { 118 | var iv = this as PyIntegerVar; 119 | if (iv.Raw.Length <= 8) 120 | { 121 | var copy = new byte[8]; 122 | iv.Raw.CopyTo(copy, 0); 123 | return BitConverter.ToInt64(copy, 0); 124 | } 125 | } 126 | 127 | throw new InvalidDataException("Not an integer"); 128 | } 129 | } 130 | 131 | public override string ToString() 132 | { 133 | return "<" + Type + ">"; 134 | } 135 | } 136 | 137 | } -------------------------------------------------------------------------------- /PyString.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Text; 4 | 5 | namespace eveMarshal 6 | { 7 | 8 | public class PyString : PyObject 9 | { 10 | public string Value { get; private set; } 11 | public byte[] Raw { get; private set; } 12 | public bool ForceUTF8 { get; private set; } 13 | 14 | public PyString() 15 | : base(PyObjectType.String) 16 | { 17 | 18 | } 19 | 20 | public PyString(string data) 21 | : base(PyObjectType.String) 22 | { 23 | Raw = Encoding.ASCII.GetBytes(data); 24 | Value = data; 25 | } 26 | 27 | public PyString(string data, bool forceUTF8) 28 | : base(PyObjectType.String) 29 | { 30 | Raw = Encoding.UTF8.GetBytes(data); 31 | Value = data; 32 | ForceUTF8 = forceUTF8; 33 | } 34 | 35 | public PyString(byte[] raw) 36 | : base(PyObjectType.String) 37 | { 38 | Raw = raw; 39 | Value = Encoding.ASCII.GetString(raw); 40 | } 41 | 42 | private void Update(string data) 43 | { 44 | Raw = Encoding.ASCII.GetBytes(data); 45 | Value = data; 46 | } 47 | 48 | private void Update(byte[] data, bool isUnicode = false) 49 | { 50 | Raw = data; 51 | Value = isUnicode ? Encoding.Unicode.GetString(Raw) : Encoding.ASCII.GetString(Raw); 52 | } 53 | 54 | private void UpdateUTF8(byte[] data) 55 | { 56 | Raw = data; 57 | Value = Encoding.UTF8.GetString(Raw); 58 | } 59 | 60 | public override void Decode(Unmarshal context, MarshalOpcode op, BinaryReader source) 61 | { 62 | if (op == MarshalOpcode.StringEmpty) 63 | Update(new byte[0]); 64 | else if (op == MarshalOpcode.StringChar) 65 | Update(new[]{source.ReadByte()}); 66 | else if (op == MarshalOpcode.WStringUTF8) 67 | UpdateUTF8(source.ReadBytes((int)source.ReadSizeEx())); 68 | else if (op == MarshalOpcode.WStringUCS2Char) 69 | Update(new[]{source.ReadByte(), source.ReadByte()}, true); 70 | else if (op == MarshalOpcode.WStringEmpty) 71 | Update(new byte[0]); 72 | else if (op == MarshalOpcode.WStringUCS2) 73 | Update(source.ReadBytes((int)source.ReadSizeEx()), true); 74 | else if (op == MarshalOpcode.StringShort) 75 | Update(source.ReadBytes(source.ReadByte())); 76 | else if (op == MarshalOpcode.StringLong) 77 | Update(source.ReadBytes((int)source.ReadSizeEx())); 78 | else if (op == MarshalOpcode.StringTable) 79 | { 80 | byte index = source.ReadByte(); 81 | Update(StringTable.Entries[index-1]); 82 | } 83 | } 84 | 85 | protected override void EncodeInternal(BinaryWriter output) 86 | { 87 | if (ForceUTF8) 88 | { 89 | output.WriteOpcode(MarshalOpcode.WStringUTF8); 90 | output.WriteSizeEx(Raw.Length); 91 | output.Write(Raw); 92 | return; 93 | } 94 | 95 | int idx; 96 | if (Raw.Length == 0) 97 | output.WriteOpcode(MarshalOpcode.StringEmpty); 98 | else if (Raw.Length == 1) 99 | { 100 | output.WriteOpcode(MarshalOpcode.StringChar); 101 | output.Write(Raw[0]); 102 | } 103 | else if ((idx = StringTable.Entries.IndexOf(Value)) >= 0) 104 | { 105 | output.WriteOpcode(MarshalOpcode.StringTable); 106 | output.Write((byte)(idx+1)); 107 | } 108 | else 109 | { 110 | /*if (Raw.Length < 0xFF) 111 | { 112 | output.WriteOpcode(MarshalOpcode.StringShort); 113 | output.Write((byte)Raw.Length); 114 | output.Write(Raw); 115 | } 116 | else*/ 117 | { 118 | output.WriteOpcode(MarshalOpcode.StringLong); 119 | output.WriteSizeEx(Raw.Length); 120 | output.Write(Raw); 121 | } 122 | } 123 | } 124 | 125 | public override string ToString() 126 | { 127 | if (Value.Length <= 0) 128 | return ""; 129 | if (char.IsLetterOrDigit(Value[0])) 130 | return "<" + Value + ">"; 131 | return "<" + BitConverter.ToString(Raw) + ">"; 132 | } 133 | } 134 | 135 | } -------------------------------------------------------------------------------- /MarshalData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Text; 4 | 5 | namespace eveMarshal 6 | { 7 | 8 | public class MarshalData 9 | { 10 | private readonly MemoryStream _stream = new MemoryStream(); 11 | private readonly BinaryWriter _writer; 12 | 13 | public MarshalData() 14 | { 15 | _writer = new BinaryWriter(_stream); 16 | } 17 | 18 | public void PutHeader() 19 | { 20 | _writer.Write(Unmarshal.HeaderByte); 21 | _writer.Write((uint)0); 22 | } 23 | 24 | public byte[] GetData() 25 | { 26 | _writer.Flush(); 27 | return _stream.ToArray(); 28 | } 29 | 30 | private void WriteOpcode(MarshalOpcode op) 31 | { 32 | _writer.Write((byte)op); 33 | } 34 | 35 | private void WriteLength(int len) 36 | { 37 | if ((byte)len == 0xFF) 38 | { 39 | _writer.Write(0xFF); 40 | _writer.Write((uint)len); 41 | } 42 | else 43 | _writer.Write((byte)len); 44 | } 45 | 46 | private bool HandleSpecialInteger(long num) 47 | { 48 | if (num == -1) 49 | WriteOpcode(MarshalOpcode.IntegerMinusOne); 50 | else if (num == 1) 51 | WriteOpcode(MarshalOpcode.IntegerOne); 52 | else if (num == 0) 53 | WriteOpcode(MarshalOpcode.IntegerZero); 54 | return num == -1 || num == 1 || num == 0; 55 | } 56 | 57 | public void PutTuple(int count) 58 | { 59 | if (count == 0) 60 | WriteOpcode(MarshalOpcode.TupleEmpty); 61 | else if (count == 1) 62 | WriteOpcode(MarshalOpcode.TupleOne); 63 | else if (count == 2) 64 | WriteOpcode(MarshalOpcode.TupleTwo); 65 | else 66 | { 67 | WriteOpcode(MarshalOpcode.Tuple); 68 | WriteLength(count); 69 | } 70 | } 71 | 72 | public void PutList(int count) 73 | { 74 | if (count == 0) 75 | WriteOpcode(MarshalOpcode.ListEmpty); 76 | else if (count == 1) 77 | WriteOpcode(MarshalOpcode.ListOne); 78 | else 79 | { 80 | WriteOpcode(MarshalOpcode.List); 81 | WriteLength(count); 82 | } 83 | } 84 | 85 | public void PutDictionary(int count) 86 | { 87 | WriteOpcode(MarshalOpcode.Dict); 88 | WriteLength(count); 89 | } 90 | 91 | public void PutPair(T key, U value) 92 | { 93 | Put(value); 94 | Put(key); 95 | } 96 | 97 | public void Put(T data) 98 | { 99 | throw new ArgumentException("Unable to marshal " + data.GetType()); 100 | } 101 | 102 | public void PutNone() 103 | { 104 | WriteOpcode(MarshalOpcode.None); 105 | } 106 | 107 | public void Put(float num) 108 | { 109 | Put((double)num); 110 | } 111 | 112 | public void Put(double num) 113 | { 114 | if (num == 0.0d) 115 | WriteOpcode(MarshalOpcode.RealZero); 116 | else 117 | { 118 | WriteOpcode(MarshalOpcode.Real); 119 | _writer.Write(num); 120 | } 121 | } 122 | 123 | public void Put(byte num) 124 | { 125 | if (!HandleSpecialInteger(num)) 126 | { 127 | WriteOpcode(MarshalOpcode.IntegerByte); 128 | _writer.Write(num); 129 | } 130 | } 131 | 132 | public void Put(long num) 133 | { 134 | if (!HandleSpecialInteger(num)) 135 | { 136 | WriteOpcode(MarshalOpcode.IntegerLongLong); 137 | _writer.Write(num); 138 | } 139 | } 140 | 141 | public void Put(short num) 142 | { 143 | if (!HandleSpecialInteger(num)) 144 | { 145 | WriteOpcode(MarshalOpcode.IntegerSignedShort); 146 | _writer.Write(num); 147 | } 148 | } 149 | 150 | public void Put(uint num) 151 | { 152 | Put((int) num); 153 | } 154 | 155 | public void Put(int num) 156 | { 157 | if (!HandleSpecialInteger(num)) 158 | { 159 | WriteOpcode(MarshalOpcode.IntegerLong); 160 | _writer.Write(num); 161 | } 162 | } 163 | 164 | public void Put(string str) 165 | { 166 | Put(Encoding.ASCII.GetBytes(str)); 167 | } 168 | 169 | public void Put(byte[] str) 170 | { 171 | if (str.Length == 0) 172 | WriteOpcode(MarshalOpcode.StringEmpty); 173 | else 174 | { 175 | WriteOpcode(MarshalOpcode.StringLong); 176 | WriteLength(str.Length); 177 | _writer.Write(str); 178 | } 179 | } 180 | } 181 | 182 | } -------------------------------------------------------------------------------- /PyPackedRow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using eveMarshal.Database; 5 | using System.Linq; 6 | 7 | namespace eveMarshal 8 | { 9 | 10 | public class PyPackedRow : PyObject 11 | { 12 | public PyObject Header { get; private set; } 13 | public byte[] RawData { get; private set; } 14 | 15 | public List Columns { get; private set; } 16 | 17 | public PyPackedRow() 18 | : base(PyObjectType.PackedRow) 19 | { 20 | 21 | } 22 | 23 | public PyObject Get(string key) 24 | { 25 | var col = Columns.Where(c => c.Name == key).FirstOrDefault(); 26 | return col == null ? null : col.Value; 27 | } 28 | 29 | public override void Decode(Unmarshal context, MarshalOpcode op, BinaryReader source) 30 | { 31 | context.NeedObjectEx = true; 32 | Header = context.ReadObject(source); 33 | context.NeedObjectEx = false; 34 | RawData = LoadZeroCompressed(source); 35 | 36 | if (!ParseRowData(context, source)) 37 | throw new InvalidDataException("Could not fully unpack PackedRow, stream integrity is broken"); 38 | } 39 | 40 | private bool ParseRowData(Unmarshal context, BinaryReader source) 41 | { 42 | var objex = Header as PyObjectEx; 43 | if (objex == null) 44 | return false; 45 | 46 | var header = objex.Header as PyTuple; 47 | if (header == null || header.Items.Count < 2) 48 | return false; 49 | 50 | var columns = header.Items[1] as PyTuple; 51 | if (columns == null) 52 | return false; 53 | 54 | columns = columns.Items[0] as PyTuple; 55 | if (columns == null) 56 | return false; 57 | 58 | Columns = new List(columns.Items.Count); 59 | 60 | foreach (var obj in columns.Items) 61 | { 62 | var fieldData = obj as PyTuple; 63 | if (fieldData == null || fieldData.Items.Count < 2) 64 | continue; 65 | 66 | var name = fieldData.Items[0] as PyString; 67 | if (name == null) 68 | continue; 69 | 70 | Columns.Add(new Column(name.Value, (FieldType) fieldData.Items[1].IntValue)); 71 | } 72 | 73 | var sizeList = Columns.OrderByDescending(c => FieldTypeHelper.GetTypeBits(c.Type)); 74 | var sizeSum = sizeList.Sum(c => FieldTypeHelper.GetTypeBits(c.Type)); 75 | // align 76 | sizeSum = (sizeSum + 7) >> 3; 77 | var rawStream = new MemoryStream(); 78 | // fill up 79 | rawStream.Write(RawData, 0, RawData.Length); 80 | for (int i = 0; i < (sizeSum - RawData.Length); i++) 81 | rawStream.WriteByte(0); 82 | rawStream.Seek(0, SeekOrigin.Begin); 83 | var reader = new BinaryReader(rawStream); 84 | 85 | int bitOffset = 0; 86 | foreach (var column in sizeList) 87 | { 88 | switch (column.Type) 89 | { 90 | case FieldType.I8: 91 | case FieldType.UI8: 92 | case FieldType.CY: 93 | case FieldType.FileTime: 94 | column.Value = new PyLongLong(reader.ReadInt64()); 95 | break; 96 | 97 | case FieldType.I4: 98 | case FieldType.UI4: 99 | column.Value = new PyInt(reader.ReadInt32()); 100 | break; 101 | 102 | case FieldType.I2: 103 | case FieldType.UI2: 104 | column.Value = new PyInt(reader.ReadInt16()); 105 | break; 106 | 107 | case FieldType.I1: 108 | case FieldType.UI1: 109 | column.Value = new PyInt(reader.ReadByte()); 110 | break; 111 | 112 | case FieldType.R8: 113 | column.Value = new PyFloat(reader.ReadDouble()); 114 | break; 115 | 116 | case FieldType.R4: 117 | column.Value = new PyFloat(reader.ReadSingle()); 118 | break; 119 | 120 | case FieldType.Bytes: 121 | case FieldType.Str: 122 | case FieldType.WStr: 123 | column.Value = context.ReadObject(source); 124 | break; 125 | 126 | case FieldType.Bool: 127 | { 128 | if (7 < bitOffset) 129 | { 130 | bitOffset = 0; 131 | reader.ReadByte(); 132 | } 133 | 134 | var b = reader.ReadByte(); 135 | reader.BaseStream.Seek(-1, SeekOrigin.Current); 136 | column.Value = new PyInt((b >> bitOffset++) & 0x01); 137 | break; 138 | } 139 | 140 | default: 141 | throw new Exception("No support for " + column.Type); 142 | } 143 | } 144 | 145 | return true; 146 | } 147 | 148 | private static byte[] LoadZeroCompressed(BinaryReader reader) 149 | { 150 | var ret = new List(); 151 | uint packedLen = reader.ReadSizeEx(); 152 | long max = reader.BaseStream.Position + packedLen; 153 | while (reader.BaseStream.Position < max) 154 | { 155 | var opcode = new ZeroCompressOpcode(reader.ReadByte()); 156 | 157 | if (opcode.FirstIsZero) 158 | { 159 | for (int n = 0; n < (opcode.FirstLength+1); n++) 160 | ret.Add(0x00); 161 | } 162 | else 163 | { 164 | int bytes = (int)Math.Min(8 - opcode.FirstLength, max - reader.BaseStream.Position); 165 | for (int n = 0; n < bytes; n++) 166 | ret.Add(reader.ReadByte()); 167 | } 168 | 169 | if (opcode.SecondIsZero) 170 | { 171 | for (int n = 0; n < (opcode.SecondLength+1); n++) 172 | ret.Add(0x00); 173 | } 174 | else 175 | { 176 | int bytes = (int)Math.Min(8 - opcode.SecondLength, max - reader.BaseStream.Position); 177 | for (int n = 0; n < bytes; n++) 178 | ret.Add(reader.ReadByte()); 179 | } 180 | } 181 | return ret.ToArray(); 182 | } 183 | 184 | protected override void EncodeInternal(BinaryWriter output) 185 | { 186 | throw new NotImplementedException(); 187 | } 188 | } 189 | 190 | } -------------------------------------------------------------------------------- /Unmarshal.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | 6 | namespace eveMarshal 7 | { 8 | 9 | public class Unmarshal 10 | { 11 | public const byte SaveMask = 0x40; 12 | public const byte UnknownMask = 0x80; 13 | public const byte HeaderByte = 0x7E; 14 | 15 | // not a real magic since zlib just doesn't include one.. 16 | public const byte ZlibMarker = 0x78; 17 | public const byte OpcodeMask = 0x3F; 18 | 19 | public bool DebugMode { get; set; } 20 | 21 | // used to fix SavedStreamElement fuckups 22 | public bool NeedObjectEx { get; set; } 23 | 24 | public Dictionary SavedElementsMap { get; private set; } 25 | public PyObject[] SavedElements { get; private set; } 26 | 27 | private int _currentSaveIndex; 28 | 29 | public PyObject Process(byte[] data) 30 | { 31 | if (data == null) 32 | return null; 33 | if (data[0] == ZlibMarker) 34 | data = Zlib.Decompress(data); 35 | return Process(new BinaryReader(new MemoryStream(data), Encoding.ASCII)); 36 | } 37 | 38 | private PyObject Process(BinaryReader reader) 39 | { 40 | var magic = reader.ReadByte(); 41 | if (magic != HeaderByte) 42 | throw new InvalidDataException("Invalid magic, expected: " + HeaderByte + " read: " + magic); 43 | var saveCount = reader.ReadUInt32(); 44 | 45 | if (saveCount > 0) 46 | { 47 | var currentPos = reader.BaseStream.Position; 48 | reader.BaseStream.Seek(-saveCount * 4, SeekOrigin.End); 49 | SavedElementsMap = new Dictionary((int)saveCount); 50 | for (int i = 0; i < saveCount; i++) 51 | { 52 | var index = reader.ReadInt32(); 53 | if (index < 0) 54 | throw new InvalidDataException("Bogus map data in marshal stream"); 55 | SavedElementsMap.Add(i, index); 56 | } 57 | SavedElements = new PyObject[saveCount]; 58 | reader.BaseStream.Seek(currentPos, SeekOrigin.Begin); 59 | } 60 | 61 | return ReadObject(reader); 62 | } 63 | 64 | private PyObject CreateAndDecode(BinaryReader reader, MarshalOpcode op) where T : PyObject, new() 65 | { 66 | // -1 for the opcode 67 | var ret = new T {RawOffset = reader.BaseStream.Position - 1}; 68 | ret.Decode(this, op, reader); 69 | if (PyObject.EnableInspection) 70 | { 71 | var postOffset = reader.BaseStream.Position; 72 | reader.BaseStream.Seek(ret.RawOffset, SeekOrigin.Begin); 73 | ret.RawSource = reader.ReadBytes((int)(postOffset - ret.RawOffset)); 74 | } 75 | 76 | // lets just get rid of those here and now 77 | if (ret is PySubStream) 78 | return (ret as PySubStream).Data; 79 | 80 | return ret; 81 | } 82 | 83 | public PyObject ReadObject(BinaryReader reader) 84 | { 85 | var header = reader.ReadByte(); 86 | //bool flagUnknown = (header & UnknownMask) > 0; 87 | bool flagSave = (header & SaveMask) > 0; 88 | var opcode = (MarshalOpcode)(header & OpcodeMask); 89 | PyObject ret; 90 | 91 | switch (opcode) 92 | { 93 | case MarshalOpcode.SubStruct: 94 | ret = CreateAndDecode(reader, opcode); 95 | break; 96 | 97 | case MarshalOpcode.BoolFalse: 98 | case MarshalOpcode.BoolTrue: 99 | ret = CreateAndDecode(reader, opcode); 100 | break; 101 | 102 | case MarshalOpcode.None: 103 | ret = CreateAndDecode(reader, opcode); 104 | break; 105 | case MarshalOpcode.Token: 106 | ret = CreateAndDecode(reader, opcode); 107 | break; 108 | case MarshalOpcode.Real: 109 | case MarshalOpcode.RealZero: 110 | ret = CreateAndDecode(reader, opcode); 111 | break; 112 | case MarshalOpcode.IntegerLongLong: 113 | ret = CreateAndDecode(reader, opcode); 114 | break; 115 | case MarshalOpcode.IntegerSignedShort: 116 | case MarshalOpcode.IntegerByte: 117 | case MarshalOpcode.IntegerMinusOne: 118 | case MarshalOpcode.IntegerOne: 119 | case MarshalOpcode.IntegerZero: 120 | case MarshalOpcode.IntegerLong: 121 | ret = CreateAndDecode(reader, opcode); 122 | break; 123 | case MarshalOpcode.IntegerVar: 124 | ret = CreateAndDecode(reader, opcode); 125 | break; 126 | case MarshalOpcode.Buffer: 127 | ret = CreateAndDecode(reader, opcode); 128 | break; 129 | case MarshalOpcode.StringEmpty: 130 | case MarshalOpcode.StringChar: 131 | case MarshalOpcode.StringShort: 132 | case MarshalOpcode.StringTable: 133 | case MarshalOpcode.StringLong: 134 | case MarshalOpcode.WStringEmpty: 135 | case MarshalOpcode.WStringUCS2: 136 | case MarshalOpcode.WStringUCS2Char: 137 | case MarshalOpcode.WStringUTF8: 138 | ret = CreateAndDecode(reader, opcode); 139 | break; 140 | case MarshalOpcode.Tuple: 141 | case MarshalOpcode.TupleOne: 142 | case MarshalOpcode.TupleTwo: 143 | case MarshalOpcode.TupleEmpty: 144 | ret = CreateAndDecode(reader, opcode); 145 | break; 146 | case MarshalOpcode.List: 147 | case MarshalOpcode.ListOne: 148 | case MarshalOpcode.ListEmpty: 149 | ret = CreateAndDecode(reader, opcode); 150 | break; 151 | case MarshalOpcode.Dict: 152 | ret = CreateAndDecode(reader, opcode); 153 | break; 154 | case MarshalOpcode.Object: 155 | ret = CreateAndDecode(reader, opcode); 156 | break; 157 | case MarshalOpcode.ChecksumedStream: 158 | ret = CreateAndDecode(reader, opcode); 159 | break; 160 | case MarshalOpcode.SubStream: 161 | ret = CreateAndDecode(reader, opcode); 162 | break; 163 | case MarshalOpcode.SavedStreamElement: 164 | uint index = reader.ReadSizeEx(); 165 | ret = SavedElements[index - 1]; 166 | if (NeedObjectEx && !(ret is PyObjectEx)) 167 | { 168 | ret = SavedElements[SavedElementsMap[(int)index]]; 169 | if (!(ret is PyObjectEx)) 170 | { 171 | // ok, this is seriously bad. our last way out is to search for an ObjectEx 172 | foreach (var savedObj in SavedElements) 173 | { 174 | if (savedObj is PyObjectEx) 175 | { 176 | ret = savedObj; 177 | break; 178 | } 179 | } 180 | } 181 | } 182 | NeedObjectEx = false; 183 | break; 184 | case MarshalOpcode.ObjectEx1: 185 | case MarshalOpcode.ObjectEx2: 186 | ret = CreateAndDecode(reader, opcode); 187 | break; 188 | case MarshalOpcode.PackedRow: 189 | ret = CreateAndDecode(reader, opcode); 190 | break; 191 | default: 192 | throw new InvalidDataException("Failed to marshal " + opcode); 193 | } 194 | 195 | if (flagSave) 196 | { 197 | var nth = _currentSaveIndex++; 198 | var saveIndex = SavedElementsMap[nth]; 199 | SavedElements[saveIndex - 1] = ret; 200 | } 201 | 202 | if (DebugMode) 203 | { 204 | Console.WriteLine("Offset: " + ret.RawOffset + " Length: " + ret.RawSource.Length + " Opcode: " + opcode + " Type: " + ret.Type + " Result: " + ret); 205 | Console.WriteLine(Utility.HexDump(ret.RawSource)); 206 | Console.ReadLine(); 207 | } 208 | 209 | return ret; 210 | } 211 | 212 | public static T Process(byte[] data) where T : class 213 | { 214 | var un = new Unmarshal(); 215 | return un.Process(data) as T; 216 | } 217 | } 218 | 219 | } -------------------------------------------------------------------------------- /PrettyPrinter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace eveMarshal 5 | { 6 | 7 | public static class PrettyPrinter 8 | { 9 | public const string Indention = " "; 10 | 11 | public static string Print(PyObject obj) 12 | { 13 | var ret = new StringBuilder(); 14 | Print(ret, 0, obj); 15 | return ret.ToString(); 16 | } 17 | 18 | private static void Print(StringBuilder builder, int indention, PyObject obj) 19 | { 20 | var indent = ""; 21 | for (int i = 0; i < indention; i++) 22 | indent += Indention; 23 | 24 | if (obj is PyString) 25 | builder.AppendLine(PrintString(obj as PyString, indent) + PrintRawData(obj)); 26 | else if (obj is PyNone) 27 | builder.AppendLine(indent + PrintNone(obj as PyNone) + PrintRawData(obj)); 28 | else if (obj is PyFloat) 29 | builder.AppendLine(indent + PrintFloat(obj as PyFloat) + PrintRawData(obj)); 30 | else if (obj is PyInt) 31 | builder.AppendLine(indent + PrintInt(obj as PyInt) + PrintRawData(obj)); 32 | else if (obj is PyIntegerVar) 33 | builder.AppendLine(indent + PrintIntegerVar(obj as PyIntegerVar) + PrintRawData(obj)); 34 | else if (obj is PyTuple) 35 | { 36 | var tuple = obj as PyTuple; 37 | builder.AppendLine(indent + PrintTuple(tuple) + PrintRawData(obj)); 38 | foreach (var item in tuple.Items) 39 | Print(builder, indention + 1, item); 40 | } 41 | else if (obj is PyList) 42 | { 43 | var list = obj as PyList; 44 | builder.AppendLine(indent + PrintList(list) + PrintRawData(obj)); 45 | foreach (var item in list.Items) 46 | Print(builder, indention + 1, item); 47 | } 48 | else if (obj is PyLongLong) 49 | builder.AppendLine(indent + PrintLongLong(obj as PyLongLong) + PrintRawData(obj)); 50 | else if (obj is PyBuffer) 51 | builder.AppendLine(indent + PrintBuffer(obj as PyBuffer) + PrintRawData(obj)); 52 | else if (obj is PyObjectData) 53 | { 54 | var objdata = obj as PyObjectData; 55 | builder.AppendLine(indent + PrintObjectData(objdata) + PrintRawData(obj)); 56 | Print(builder, indention + 1, objdata.Arguments); 57 | } 58 | else if (obj is PySubStream) 59 | { 60 | var sub = obj as PySubStream; 61 | builder.AppendLine(indent + PrintSubStream(sub) + PrintRawData(obj)); 62 | Print(builder, indention + 1, sub.Data); 63 | } 64 | else if (obj is PyDict) 65 | { 66 | var dict = obj as PyDict; 67 | builder.AppendLine(indent + PrintDict(dict) + PrintRawData(obj)); 68 | foreach (var kvp in dict.Dictionary) 69 | { 70 | Print(builder, indention + 1, kvp.Key); 71 | Print(builder, indention + 1, kvp.Value); 72 | } 73 | } 74 | else if (obj is PyObjectEx) 75 | { 76 | var objex = obj as PyObjectEx; 77 | builder.AppendLine(indent + PrintObjectEx(objex) + PrintRawData(obj)); 78 | Print(builder, indention + 1, objex.Header); 79 | foreach (var item in objex.List) 80 | Print(builder, indention + 1, item); 81 | foreach (var kvp in objex.Dictionary) 82 | { 83 | Print(builder, indention + 1, kvp.Key); 84 | Print(builder, indention + 1, kvp.Value); 85 | } 86 | } 87 | else if (obj is PyToken) 88 | { 89 | builder.AppendLine(indent + PrintToken(obj as PyToken) + PrintRawData(obj)); 90 | } 91 | else if (obj is PyPackedRow) 92 | { 93 | var packedRow = obj as PyPackedRow; 94 | builder.AppendLine(indent + PrintPackedRow(packedRow)); 95 | if (packedRow.Columns != null) 96 | { 97 | foreach (var column in packedRow.Columns) 98 | { 99 | builder.AppendLine(indent + Indention + "[\"" + column.Name + "\" => " + column.Value + 100 | " [" + column.Type + "]]"); 101 | } 102 | } 103 | else 104 | builder.AppendLine(indent + Indention + "[Columns parsing failed!]"); 105 | } 106 | else if (obj is PyBool) 107 | { 108 | builder.AppendLine(indent + PrintBool(obj as PyBool) + PrintRawData(obj)); 109 | } 110 | else if (obj is PySubStruct) 111 | { 112 | var subs = obj as PySubStruct; 113 | builder.AppendLine(indent + PrintSubStruct(subs) + PrintRawData(obj)); 114 | Print(builder, indention + 1, subs.Definition); 115 | } 116 | else if (obj is PyChecksumedStream) 117 | { 118 | var chk = obj as PyChecksumedStream; 119 | builder.AppendLine(indent + PrintChecksumedStream(chk)); 120 | Print(builder, indention + 1, chk.Data); 121 | } 122 | else 123 | builder.AppendLine(indent + "[Warning: unable to print " + obj.Type + "]"); 124 | } 125 | 126 | private static string PrintChecksumedStream(PyChecksumedStream obj) 127 | { 128 | return "[PyChecksumedStream Checksum: " + obj.Checksum + "]"; 129 | } 130 | 131 | private static string PrintRawData(PyObject obj) 132 | { 133 | if (obj.RawSource == null) 134 | return ""; 135 | return " [" + BitConverter.ToString(obj.RawSource, 0, obj.RawSource.Length > 8 ? 8 : obj.RawSource.Length) + "]"; 136 | } 137 | 138 | private static string PrintSubStruct(PySubStruct substruct) 139 | { 140 | return "[PySubStruct]"; 141 | } 142 | 143 | private static string PrintBool(PyBool boolean) 144 | { 145 | return "[PyBool " + boolean.Value + "]"; 146 | } 147 | 148 | private static string PrintPackedRow(PyPackedRow packedRow) 149 | { 150 | return "[PyPackedRow " + packedRow.RawData.Length + " bytes]"; 151 | } 152 | 153 | private static string PrintToken(PyToken token) 154 | { 155 | return "[PyToken " + token.Token + "]"; 156 | } 157 | 158 | private static string PrintObjectEx(PyObjectEx obj) 159 | { 160 | return "[PyObjectEx " + (obj.IsType2 ? "Type2" : "Normal") + "]"; 161 | } 162 | 163 | private static string PrintDict(PyDict dict) 164 | { 165 | return "[PyDict " + dict.Dictionary.Count + " kvp]"; 166 | } 167 | 168 | private static string PrintSubStream(PySubStream sub) 169 | { 170 | if (sub.RawData != null) 171 | return "[PySubStream " + sub.RawData.Length + " bytes]"; 172 | return "[PySubStream]"; 173 | } 174 | 175 | private static string PrintIntegerVar(PyIntegerVar intvar) 176 | { 177 | return "[PyIntegerVar " + intvar.IntValue + "]"; 178 | } 179 | 180 | private static string PrintList(PyList list) 181 | { 182 | return "[PyList " + list.Items.Count + " items]"; 183 | } 184 | 185 | private static string PrintObjectData(PyObjectData data) 186 | { 187 | return "[PyObjectData Name: " + data.Name + "]"; 188 | } 189 | 190 | private static string PrintBuffer(PyBuffer buf) 191 | { 192 | return "[PyBuffer " + buf.Data.Length + " bytes]"; 193 | } 194 | 195 | private static string PrintLongLong(PyLongLong ll) 196 | { 197 | return "[PyLongLong " + ll.Value + "]"; 198 | } 199 | 200 | private static string PrintTuple(PyTuple tuple) 201 | { 202 | return "[PyTuple " + tuple.Items.Count + " items]"; 203 | } 204 | 205 | private static string PrintInt(PyInt integer) 206 | { 207 | return "[PyInt " + integer.Value + "]"; 208 | } 209 | 210 | private static string PrintFloat(PyFloat fl) 211 | { 212 | return "[PyFloat " + fl.Value + "]"; 213 | } 214 | 215 | private static string PrintString(PyString str, string indention) 216 | { 217 | // aggressive destiny update pretty printing 218 | #if false 219 | UpdateReader reader; 220 | try 221 | { 222 | reader = new UpdateReader(); 223 | reader.Read(new MemoryStream(str.Raw)); 224 | } 225 | catch (Exception) 226 | { 227 | reader = null; 228 | } 229 | 230 | if (reader == null) 231 | return indention + "[PyString \"" + str.Value + "\"]"; 232 | 233 | return eveDestiny.PrettyPrinter.Print(reader, indention); 234 | #endif 235 | return indention + "[PyString \"" + str.Value + "\"]"; 236 | } 237 | 238 | private static string PrintNone(PyNone none) 239 | { 240 | return "[PyNone]"; 241 | } 242 | } 243 | 244 | } -------------------------------------------------------------------------------- /Utility.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.IO.Compression; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace eveMarshal 8 | { 9 | 10 | public static class Utility 11 | { 12 | 13 | public static uint ToBigEndian(uint source) 14 | { 15 | return source >> 24 | 16 | ((source << 8) & 0x00FF0000) | 17 | ((source >> 8) & 0x0000FF00) | 18 | (source << 24); 19 | } 20 | 21 | public static ushort ToBigEndian(ushort source) 22 | { 23 | return (ushort)(source >> 8 | source << 8); 24 | } 25 | 26 | public static byte[] StringToByteArray(string hex) 27 | { 28 | var ret = new byte[hex.Length / 2]; 29 | for (int i = 0; i < hex.Length / 2; i++) 30 | { 31 | ret[i] = Convert.ToByte(hex.Substring((i * 2), 2), 16); 32 | } 33 | return ret; 34 | } 35 | 36 | public static string ByteArrayToString(byte[] data) 37 | { 38 | var r = new StringBuilder(data.Length * 2); 39 | foreach (var b in data) 40 | r.Append(b.ToString("X2")); 41 | return r.ToString(); 42 | } 43 | 44 | public static void ReadFully(this Stream stream, byte[] buffer, int index, int length) 45 | { 46 | var left = length; 47 | while (left > 0) 48 | { 49 | int read = stream.Read(buffer, index, left); 50 | left -= read; 51 | index += read; 52 | } 53 | } 54 | 55 | public static void ReadFully(this Stream stream, byte[] buffer) 56 | { 57 | ReadFully(stream, buffer, 0, buffer.Length); 58 | } 59 | 60 | public static uint ReadSizeEx(this BinaryReader reader) 61 | { 62 | var len = reader.ReadByte(); 63 | if (len == 0xFF) 64 | return reader.ReadUInt32(); 65 | return len; 66 | } 67 | 68 | public static void WriteSizeEx(this BinaryWriter writer, uint len) 69 | { 70 | if (len < 0xFF) 71 | writer.Write((byte)len); 72 | else 73 | { 74 | writer.Write((byte)0xFF); 75 | writer.Write(len); 76 | } 77 | } 78 | 79 | public static void WriteSizeEx(this BinaryWriter writer, int len) 80 | { 81 | WriteSizeEx(writer, (uint)len); 82 | } 83 | 84 | public static string HexDump(byte[] bytes) 85 | { 86 | if (bytes == null) return ""; 87 | int len = bytes.Length; 88 | var result = new StringBuilder(((len + 15) / 16) * 78); 89 | var chars = new char[78]; 90 | // fill all with blanks 91 | for (int i = 0; i < 75; i++) 92 | chars[i] = ' '; 93 | chars[76] = '\r'; 94 | chars[77] = '\n'; 95 | 96 | for (int i1 = 0; i1 < len; i1 += 16) 97 | { 98 | chars[0] = HexChar(i1 >> 28); 99 | chars[1] = HexChar(i1 >> 24); 100 | chars[2] = HexChar(i1 >> 20); 101 | chars[3] = HexChar(i1 >> 16); 102 | chars[4] = HexChar(i1 >> 12); 103 | chars[5] = HexChar(i1 >> 8); 104 | chars[6] = HexChar(i1 >> 4); 105 | chars[7] = HexChar(i1 >> 0); 106 | 107 | int offset1 = 11; 108 | int offset2 = 60; 109 | 110 | for (int i2 = 0; i2 < 16; i2++) 111 | { 112 | if (i1 + i2 >= len) 113 | { 114 | chars[offset1] = ' '; 115 | chars[offset1 + 1] = ' '; 116 | chars[offset2] = ' '; 117 | } 118 | else 119 | { 120 | byte b = bytes[i1 + i2]; 121 | chars[offset1] = HexChar(b >> 4); 122 | chars[offset1 + 1] = HexChar(b); 123 | chars[offset2] = (b < 32 ? '·' : (char)b); 124 | } 125 | offset1 += (i2 == 7 ? 4 : 3); 126 | offset2++; 127 | } 128 | result.Append(chars); 129 | } 130 | return result.ToString(); 131 | } 132 | 133 | private static char HexChar(int value) 134 | { 135 | value &= 0xF; 136 | if (value >= 0 && value <= 9) 137 | return (char)('0' + value); 138 | return (char)('A' + (value - 10)); 139 | } 140 | 141 | /// 142 | /// Reads the contents of the stream into a byte array. 143 | /// data is returned as a byte array. An IOException is 144 | /// thrown if any of the underlying IO calls fail. 145 | /// 146 | /// The stream to read. 147 | /// A byte array containing the contents of the stream. 148 | /// The stream does not support reading. 149 | /// Methods were called after the stream was closed. 150 | /// An I/O error occurs. 151 | public static byte[] ReadAllBytes(this Stream source) 152 | { 153 | var readBuffer = new byte[4096]; 154 | 155 | int totalBytesRead = 0; 156 | int bytesRead; 157 | 158 | while ((bytesRead = source.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0) 159 | { 160 | totalBytesRead += bytesRead; 161 | 162 | if (totalBytesRead == readBuffer.Length) 163 | { 164 | int nextByte = source.ReadByte(); 165 | if (nextByte != -1) 166 | { 167 | var temp = new byte[readBuffer.Length * 2]; 168 | Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length); 169 | Buffer.SetByte(temp, totalBytesRead, (byte)nextByte); 170 | readBuffer = temp; 171 | totalBytesRead++; 172 | } 173 | } 174 | } 175 | 176 | byte[] buffer = readBuffer; 177 | if (readBuffer.Length != totalBytesRead) 178 | { 179 | buffer = new byte[totalBytesRead]; 180 | Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead); 181 | } 182 | return buffer; 183 | } 184 | 185 | } 186 | 187 | public static class Zlib 188 | { 189 | public static byte[] Decompress(byte[] input) 190 | { 191 | // two bytes shaved off (zlib header) 192 | var sourceStream = new MemoryStream(input, 2, input.Length - 2); 193 | var stream = new DeflateStream(sourceStream, CompressionMode.Decompress); 194 | return stream.ReadAllBytes(); 195 | } 196 | } 197 | 198 | public static class Adler32 199 | { 200 | private const int ModuloPrime = 65521; 201 | 202 | public static uint Checksum(byte[] data) 203 | { 204 | uint checksum = 1; 205 | uint s1 = checksum & 0xFFFF; 206 | uint s2 = checksum >> 16; 207 | 208 | int len = data.Length; 209 | int i = 0; 210 | while (len > 0) 211 | { 212 | int maxDefer = 3800; 213 | if (maxDefer > len) 214 | maxDefer = len; 215 | len -= maxDefer; 216 | while (--maxDefer >= 0) 217 | { 218 | s1 = s1 + (uint)(data[i++] & 0xFF); 219 | s2 = s2 + s1; 220 | } 221 | s1 %= ModuloPrime; 222 | s2 %= ModuloPrime; 223 | } 224 | 225 | checksum = (s2 << 16) | s1; 226 | return checksum; 227 | } 228 | } 229 | 230 | public static class Crc32 231 | { 232 | private static readonly uint[] _crc32Tab = new uint[] 233 | { 234 | 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 235 | 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 236 | 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 237 | 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 238 | 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 239 | 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 240 | 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 241 | 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 242 | 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 243 | 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 244 | 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 245 | 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 246 | 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 247 | 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 248 | 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 249 | 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 250 | 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 251 | 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 252 | 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 253 | 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 254 | 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 255 | 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 256 | 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 257 | 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 258 | 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 259 | 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 260 | 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 261 | 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 262 | 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 263 | 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 264 | 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 265 | 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 266 | 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 267 | 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 268 | 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 269 | 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 270 | 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 271 | 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 272 | 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 273 | 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 274 | 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 275 | 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 276 | 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 277 | 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 278 | 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 279 | 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 280 | 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 281 | 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 282 | 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 283 | 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 284 | 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 285 | 0x2d02ef8d 286 | }; 287 | 288 | public static uint Checksum(byte[] data) 289 | { 290 | uint crc = data.Aggregate(0xFFFFFFFF, (current, b) => (current >> 8) ^ _crc32Tab[b ^ (current & 0x000000FF)]); 291 | return ~crc; 292 | } 293 | } 294 | 295 | } -------------------------------------------------------------------------------- /StringTable.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace eveMarshal 4 | { 5 | 6 | public static class StringTable 7 | { 8 | public static List Entries = new List 9 | { 10 | "*corpid", 11 | "*locationid", 12 | "age", 13 | "Asteroid", 14 | "authentication", 15 | "ballID", 16 | "beyonce", 17 | "bloodlineID", 18 | "capacity", 19 | "categoryID", 20 | "character", 21 | "characterID", 22 | "characterName", 23 | "characterType", 24 | "charID", 25 | "chatx", 26 | "clientID", 27 | "config", 28 | "contraband", 29 | "corporationDateTime", 30 | "corporationID", 31 | "createDateTime", 32 | "customInfo", 33 | "description", 34 | "divisionID", 35 | "DoDestinyUpdate", 36 | "dogmaIM", 37 | "EVE System", 38 | "flag", 39 | "foo.SlimItem", 40 | "gangID", 41 | "Gemini", 42 | "gender", 43 | "graphicID", 44 | "groupID", 45 | "header", 46 | "idName", 47 | "invbroker", 48 | "itemID", 49 | "items", 50 | "jumps", 51 | "line", 52 | "lines", 53 | "locationID", 54 | "locationName", 55 | "macho.CallReq", 56 | "macho.CallRsp", 57 | "macho.MachoAddress", 58 | "macho.Notification", 59 | "macho.SessionChangeNotification", 60 | "modules", 61 | "name", 62 | "objectCaching", 63 | "objectCaching.CachedObject", 64 | "OnChatJoin", 65 | "OnChatLeave", 66 | "OnChatSpeak", 67 | "OnGodmaShipEffect", 68 | "OnItemChange", 69 | "OnModuleAttributeChange", 70 | "OnMultiEvent", 71 | "orbitID", 72 | "ownerID", 73 | "ownerName", 74 | "quantity", 75 | "raceID", 76 | "RowClass", 77 | "securityStatus", 78 | "Sentry Gun", 79 | "sessionchange", 80 | "singleton", 81 | "skillEffect", 82 | "squadronID", 83 | "typeID", 84 | "used", 85 | "userID", 86 | "util.CachedObject", 87 | "util.IndexRowset", 88 | "util.Moniker", 89 | "util.Row", 90 | "util.Rowset", 91 | "*multicastID", 92 | "AddBalls", 93 | "AttackHit3", 94 | "AttackHit3R", 95 | "AttackHit4R", 96 | "DoDestinyUpdates", 97 | "GetLocationsEx", 98 | "InvalidateCachedObjects", 99 | "JoinChannel", 100 | "LSC", 101 | "LaunchMissile", 102 | "LeaveChannel", 103 | "OID+", 104 | "OID-", 105 | "OnAggressionChange", 106 | "OnCharGangChange", 107 | "OnCharNoLongerInStation", 108 | "OnCharNowInStation", 109 | "OnDamageMessage", 110 | "OnDamageStateChange", 111 | "OnEffectHit", 112 | "OnGangDamageStateChange", 113 | "OnLSC", 114 | "OnSpecialFX", 115 | "OnTarget", 116 | "RemoveBalls", 117 | "SendMessage", 118 | "SetMaxSpeed", 119 | "SetSpeedFraction", 120 | "TerminalExplosion", 121 | "address", 122 | "alert", 123 | "allianceID", 124 | "allianceid", 125 | "bid", 126 | "bookmark", 127 | "bounty", 128 | "channel", 129 | "charid", 130 | "constellationid", 131 | "corpID", 132 | "corpid", 133 | "corprole", 134 | "damage", 135 | "duration", 136 | "effects.Laser", 137 | "gangid", 138 | "gangrole", 139 | "hqID", 140 | "issued", 141 | "jit", 142 | "languageID", 143 | "locationid", 144 | "machoVersion", 145 | "marketProxy", 146 | "minVolume", 147 | "orderID", 148 | "price", 149 | "range", 150 | "regionID", 151 | "regionid", 152 | "role", 153 | "rolesAtAll", 154 | "rolesAtBase", 155 | "rolesAtHQ", 156 | "rolesAtOther", 157 | "shipid", 158 | "sn", 159 | "solarSystemID", 160 | "solarsystemid", 161 | "solarsystemid2", 162 | "source", 163 | "splash", 164 | "stationID", 165 | "stationid", 166 | "target", 167 | "userType", 168 | "userid", 169 | "volEntered", 170 | "volRemaining", 171 | "weapon", 172 | "agent.missionTemplatizedContent_BasicKillMission", 173 | "agent.missionTemplatizedContent_ResearchKillMission", 174 | "agent.missionTemplatizedContent_StorylineKillMission", 175 | "agent.missionTemplatizedContent_GenericStorylineKillMission", 176 | "agent.missionTemplatizedContent_BasicCourierMission", 177 | "agent.missionTemplatizedContent_ResearchCourierMission", 178 | "agent.missionTemplatizedContent_StorylineCourierMission", 179 | "agent.missionTemplatizedContent_GenericStorylineCourierMission", 180 | "agent.missionTemplatizedContent_BasicTradeMission", 181 | "agent.missionTemplatizedContent_ResearchTradeMission", 182 | "agent.missionTemplatizedContent_StorylineTradeMission", 183 | "agent.missionTemplatizedContent_GenericStorylineTradeMission", 184 | "agent.offerTemplatizedContent_BasicExchangeOffer", 185 | "agent.offerTemplatizedContent_BasicExchangeOffer_ContrabandDemand", 186 | "agent.offerTemplatizedContent_BasicExchangeOffer_Crafting", 187 | "agent.LoyaltyPoints", 188 | "agent.ResearchPoints", 189 | "agent.Credits", 190 | "agent.Item", 191 | "agent.Entity", 192 | "agent.Objective", 193 | "agent.FetchObjective", 194 | "agent.EncounterObjective", 195 | "agent.DungeonObjective", 196 | "agent.TransportObjective", 197 | "agent.Reward", 198 | "agent.TimeBonusReward", 199 | "agent.MissionReferral", 200 | "agent.Location", 201 | "agent.StandardMissionDetails", 202 | "agent.OfferDetails", 203 | "agent.ResearchMissionDetails", 204 | "agent.StorylineMissionDetails", 205 | }; 206 | } 207 | 208 | } --------------------------------------------------------------------------------