using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Globalization; using System.IO; namespace Filter { public class SHNFile { public byte[] CryptHeader; public uint Header; public string Path; public DataTable table = new DataTable(); public Dictionary displayToReal = new Dictionary(); public List columns = new List(); private uint RecordCount; private uint DefaultRecordLength; private uint ColumnCount; private string[] ColumnNames; private uint[] ColumnTypes; private int[] ColumnLengths; public byte[] data; public bool isTextData; public SHNFile() { } public SHNFile(string path) { { try { this.columns.Clear(); this.Path = path; if (System.IO.Path.GetFileNameWithoutExtension(path).ToLower().Contains("textdata")) { this.isTextData = true; } BinaryReaderEx binaryReaderEx = new BinaryReaderEx(File.OpenRead(path)); BinaryReaderEx binaryReaderEx1 = binaryReaderEx; using (binaryReaderEx) { if (!path.EndsWith(".shn")) { this.data = binaryReaderEx1.ReadBytes((int)binaryReaderEx1.Length); } else { this.CryptHeader = binaryReaderEx1.ReadBytes(32); this.data = binaryReaderEx1.ReadBytes(binaryReaderEx1.ReadInt32() - 36); } } this.Decrypt(this.data, 0, (int)this.data.Length); binaryReaderEx1 = new BinaryReaderEx(new MemoryStream(this.data)); this.Header = binaryReaderEx1.ReadUInt32(); this.RecordCount = binaryReaderEx1.ReadUInt32(); this.DefaultRecordLength = binaryReaderEx1.ReadUInt32(); this.ColumnCount = binaryReaderEx1.ReadUInt32(); this.ColumnNames = new string[this.ColumnCount]; this.ColumnTypes = new uint[this.ColumnCount]; this.ColumnLengths = new int[this.ColumnCount]; int num = 2; int num1 = 0; for (uint i = 0; i < this.ColumnCount; i++) { string str = binaryReaderEx1.ReadString(48); uint num2 = binaryReaderEx1.ReadUInt32(); int num3 = binaryReaderEx1.ReadInt32(); SHNColumn sHNColumn = new SHNColumn(); if (str.Length == 0 || string.IsNullOrWhiteSpace(str)) { str = string.Concat("UnkCol", num1.ToString()); num1++; } sHNColumn.name = str; sHNColumn.Type = num2; sHNColumn.Lenght = num3; this.columns.Add(sHNColumn); this.ColumnNames[i] = str; this.ColumnTypes[i] = num2; this.ColumnLengths[i] = num3; num = num + num3; } //if (num != (ulong)DefaultRecordLength) { throw new Exception("Wrong record length!"); } this.GenerateColumns(this.table, this.columns); this.ReadRows(binaryReaderEx1, this.table); } catch (Exception exception1) { Exception exception = exception1; BinaryWriter binaryWriter = new BinaryWriter(new FileStream("unk.dat", FileMode.OpenOrCreate)); binaryWriter.Write(this.data, 0, (int)this.data.Length); binaryWriter.Close(); throw new Exception(string.Concat("An error occured trying to open the file: ", exception.Message)); } } } public void CreateColumn(string name, int len, uint type, string defaultval) { SHNColumn sHNColumn = new SHNColumn() { name = name, Lenght = len, Type = type }; this.columns.Add(sHNColumn); DataColumn dataColumn = new DataColumn() { ColumnName = name, DefaultValue = defaultval, DataType = this.GetType(sHNColumn) }; this.table.Columns.Add(dataColumn); } public void CreateDefaultLayout() { this.CryptHeader = new byte[32]; this.SetCryptHeader("3B 02 00 00 32 30 30 35 2D 30 38 2D 32 36 20 BF C0 C8 C4 20 32 3A 33 00 6A 7F 00 00 01 00 00 00"); this.Header = 0; this.CreateColumn("Empty Column", 255, 24, ""); this.Path = "New File.shn"; } private void Decrypt(byte[] data, int index, int length) { if (index < 0 | length < 1 | index + length > (int)data.Length) { throw new IndexOutOfRangeException(); } byte num = (byte)length; for (int i = length - 1; i >= 0; i--) { data[i] = (byte)(data[i] ^ num); byte num1 = (byte)((byte)((byte)i & 15) + 85); num1 = (byte)(num1 ^ (byte)((byte)i * 11)); num = (byte)((byte)(num1 ^ num) ^ 170); } } public void DeleteColumn(string name) { this.columns.Remove(this.GetColByName(name)); this.table.Columns.Remove(this.GetDataColByName(name)); } public void Dispose() { this.table = null; this.CryptHeader = null; } public void EditColumnName(string from, string to) { this.GetDataColByName(from).ColumnName = to; this.GetColByName(from).name = to; } private void GenerateColumns(DataTable table, List cols) { for (int i = 0; i < cols.Count; i++) { DataColumn dataColumn = new DataColumn() { ColumnName = cols[i].name, DataType = this.GetType(cols[i]) }; table.Columns.Add(dataColumn); } } public SHNColumn GetColByName(string name) { SHNColumn sHNColumn; List.Enumerator enumerator = this.columns.GetEnumerator(); try { while (enumerator.MoveNext()) { SHNColumn current = enumerator.Current; if (current.name.ToLower() != name.ToLower()) { continue; } sHNColumn = current; return sHNColumn; } return null; } finally { ((IDisposable)enumerator).Dispose(); } return sHNColumn; } public int getColIndex(string name) { for (int i = 0; i < this.table.Columns.Count; i++) { if (this.table.Columns[i].ColumnName == name) { return i; } } return -1; } public string GetCryptString() { string str = ""; for (int i = 0; i < (int)this.CryptHeader.Length; i++) { str = (i == (int)this.CryptHeader.Length - 1 ? string.Concat(str, this.CryptHeader[i].ToString("X2")) : string.Concat(str, this.CryptHeader[i].ToString("X2"), " ")); } return str; } public DataColumn GetDataColByName(string name) { for (int i = 0; i < this.table.Columns.Count; i++) { if (this.table.Columns[i].ColumnName == name) { return this.table.Columns[i]; } } return null; } public uint GetDefaultRecLen() { uint lenght = 2; foreach (DataColumn column in this.table.Columns) { SHNColumn colByName = this.GetColByName(column.ColumnName); //lenght = lenght + colByName.Lenght; } return lenght; } public int GetRowByIndex(int ColIndex, string RowInput) { for (int i = 0; i < this.table.Rows.Count; i++) { if (this.table.Rows[i][ColIndex].ToString().ToLower() == RowInput.ToLower()) { return i; } } return -1; } public Type GetType(SHNColumn col) { switch (col.Type) { case 1: case 12: { return typeof(byte); } case 2: { return typeof(ushort); } case 3: case 11: { return typeof(uint); } case 5: { return typeof(float); } case 9: case 24: case 26: { return typeof(string); } case 13: case 21: { return typeof(short); } case 16: { return typeof(byte); } case 18: case 27: { return typeof(uint); } case 20: { return typeof(sbyte); } case 22: { return typeof(int); } default: { return typeof(object); } } } public void LoadMe(string path) { BinaryReaderEx binaryReaderEx = new BinaryReaderEx(File.OpenRead(path)); if (!path.EndsWith(".shn")) { this.data = binaryReaderEx.ReadBytes((int)binaryReaderEx.Length); } else { this.CryptHeader = binaryReaderEx.ReadBytes(32); this.data = binaryReaderEx.ReadBytes(binaryReaderEx.ReadInt32() - 36); } binaryReaderEx.Close(); this.Decrypt(this.data, 0, (int)this.data.Length); } private void ReadRows(BinaryReaderEx r, DataTable table) { object[] objArray = new object[this.columns.Count]; for (uint i = 0; i < this.RecordCount; i++) { r.ReadUInt16(); int num = 0; while (num < this.columns.Count) { switch (this.columns[num].Type) { case 1: { objArray[num] = r.ReadByte(); goto case 25; } case 2: { objArray[num] = r.ReadUInt16(); goto case 25; } case 3: { objArray[num] = r.ReadUInt32(); goto case 25; } case 4: case 6: case 7: case 8: case 10: case 14: case 15: case 17: case 19: case 23: case 25: { num++; continue; } case 5: { objArray[num] = r.ReadSingle(); goto case 25; } case 9: { objArray[num] = r.ReadString(this.ColumnLengths[num]); goto case 25; } case 11: { objArray[num] = r.ReadUInt32(); goto case 25; } case 12: { objArray[num] = r.ReadByte(); goto case 25; } case 13: { objArray[num] = r.ReadInt16(); goto case 25; } case 16: { objArray[num] = r.ReadByte(); goto case 25; } case 18: { objArray[num] = r.ReadUInt32(); goto case 25; } case 20: { objArray[num] = r.ReadSByte(); goto case 25; } case 21: { objArray[num] = r.ReadInt16(); goto case 25; } case 22: { objArray[num] = r.ReadInt32(); goto case 25; } case 24: { objArray[num] = r.ReadString(this.ColumnLengths[num]); goto case 25; } case 26: { objArray[num] = r.ReadString(); goto case 25; } case 27: { objArray[num] = r.ReadUInt32(); goto case 25; } default: { goto case 25; } } } table.Rows.Add(objArray); } } public void SetCryptHeader(string hexString) { string[] strArrays = hexString.Split(new char[] { ' ' }); if ((int)strArrays.Length != 32) { throw new Exception("Incorrect header length!"); } for (int i = 0; i < (int)strArrays.Length; i++) { this.CryptHeader[i] = byte.Parse(strArrays[i], NumberStyles.HexNumber); } } } }