├── 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 | }
--------------------------------------------------------------------------------