using System; using System.Collections.Generic; using System.IO; using System.Text; namespace SHARP { public class SQLiteHandler { private readonly byte[] db_bytes; private readonly ulong encoding; private string[] field_names = new string[1]; private SQLiteHandler.sqlite_master_entry[] master_table_entries; private readonly ushort page_size; private readonly byte[] SQLDataTypeSize = new byte[10] { (byte) 0, (byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 6, (byte) 8, (byte) 8, (byte) 0, (byte) 0 }; private SQLiteHandler.table_entry[] table_entries; public SQLiteHandler(string baseName) { if (!File.Exists(baseName)) return; this.db_bytes = File.ReadAllBytes(baseName); if (Encoding.Default.GetString(this.db_bytes, 0, 15).CompareTo("SQLite format 3") != 0) throw new Exception("Not a valid SQLite 3 Database File"); if (this.db_bytes[52] != (byte) 0) throw new Exception("Auto-vacuum capable database is not supported"); this.page_size = (ushort) this.ConvertToInteger(16 /*0x10*/, 2); this.encoding = this.ConvertToInteger(56, 4); if (Decimal.Compare(new Decimal(this.encoding), 0M) == 0) this.encoding = 1UL; this.ReadMasterTable(100UL); } private ulong ConvertToInteger(int startIndex, int Size) { if (Size > 8 | Size == 0) return 0; ulong integer = 0; int num = Size - 1; for (int index = 0; index <= num; ++index) integer = integer << 8 | (ulong) this.db_bytes[startIndex + index]; return integer; } private long CVL(int startIndex, int endIndex) { ++endIndex; byte[] numArray = new byte[8]; int num1 = endIndex - startIndex; bool flag = false; if (num1 == 0 | num1 > 9) return 0; switch (num1) { case 1: numArray[0] = (byte) ((uint) this.db_bytes[startIndex] & (uint) sbyte.MaxValue); return BitConverter.ToInt64(numArray, 0); case 9: flag = true; break; } int num2 = 1; int num3 = 7; int index1 = 0; if (flag) { numArray[0] = this.db_bytes[endIndex - 1]; --endIndex; index1 = 1; } int num4 = startIndex; for (int index2 = endIndex - 1; index2 >= num4; index2 += -1) { if (index2 - 1 >= startIndex) { numArray[index1] = (byte) ((uint) (byte) ((uint) this.db_bytes[index2] >> (num2 - 1 & 7)) & (uint) ((int) byte.MaxValue >> num2) | (uint) (byte) ((uint) this.db_bytes[index2 - 1] << (num3 & 7))); ++num2; ++index1; --num3; } else if (!flag) numArray[index1] = (byte) ((uint) (byte) ((uint) this.db_bytes[index2] >> (num2 - 1 & 7)) & (uint) ((int) byte.MaxValue >> num2)); } return BitConverter.ToInt64(numArray, 0); } public int GetRowCount() => this.table_entries.Length; public string[] GetTableNames() { List stringList = new List(); int num = this.master_table_entries.Length - 1; for (int index = 0; index <= num; ++index) { if (this.master_table_entries[index].item_type == "table") stringList.Add(this.master_table_entries[index].item_name); } return stringList.ToArray(); } public string GetValue(int row_num, int field) { if (row_num >= this.table_entries.Length) return (string) null; return field >= this.table_entries[row_num].content.Length ? (string) null : this.table_entries[row_num].content[field]; } public string GetValue(int row_num, string field) { int field1 = -1; int num = this.field_names.Length - 1; for (int index = 0; index <= num; ++index) { if (this.field_names[index].ToLower().CompareTo(field.ToLower()) == 0) { field1 = index; break; } } return field1 == -1 ? (string) null : this.GetValue(row_num, field1); } private int GVL(int startIndex) { if (startIndex > this.db_bytes.Length) return 0; int num = startIndex + 8; for (int index = startIndex; index <= num; ++index) { if (index > this.db_bytes.Length - 1) return 0; if (((int) this.db_bytes[index] & 128 /*0x80*/) != 128 /*0x80*/) return index; } return startIndex + 8; } private bool IsOdd(long value) => (value & 1L) == 1L; private void ReadMasterTable(ulong Offset) { if (this.db_bytes[(int) Offset] == (byte) 13) { ushort uint16 = Convert.ToUInt16(Decimal.Subtract(new Decimal(this.ConvertToInteger(Convert.ToInt32(Decimal.Add(new Decimal(Offset), 3M)), 2)), 1M)); int num1 = 0; if (this.master_table_entries != null) { num1 = this.master_table_entries.Length; Array.Resize(ref this.master_table_entries, this.master_table_entries.Length + (int) uint16 + 1); } else this.master_table_entries = new SQLiteHandler.sqlite_master_entry[(int) uint16 + 1]; int num2 = (int) uint16; for (int index1 = 0; index1 <= num2; ++index1) { ulong integer = this.ConvertToInteger(Convert.ToInt32(Decimal.Add(Decimal.Add(new Decimal(Offset), 8M), new Decimal(index1 * 2))), 2); if (Decimal.Compare(new Decimal(Offset), 100M) != 0) integer += Offset; int endIndex1 = this.GVL((int) integer); this.CVL((int) integer, endIndex1); int endIndex2 = this.GVL(Convert.ToInt32(Decimal.Add(Decimal.Add(new Decimal(integer), Decimal.Subtract(new Decimal(endIndex1), new Decimal(integer))), 1M))); this.master_table_entries[num1 + index1].row_id = this.CVL(Convert.ToInt32(Decimal.Add(Decimal.Add(new Decimal(integer), Decimal.Subtract(new Decimal(endIndex1), new Decimal(integer))), 1M)), endIndex2); ulong uint64 = Convert.ToUInt64(Decimal.Add(Decimal.Add(new Decimal(integer), Decimal.Subtract(new Decimal(endIndex2), new Decimal(integer))), 1M)); int endIndex3 = this.GVL((int) uint64); int endIndex4 = endIndex3; long num3 = this.CVL((int) uint64, endIndex3); long[] numArray = new long[5]; int index2 = 0; do { int startIndex = endIndex4 + 1; endIndex4 = this.GVL(startIndex); numArray[index2] = this.CVL(startIndex, endIndex4); numArray[index2] = numArray[index2] <= 9L ? (long) this.SQLDataTypeSize[(int) numArray[index2]] : (!this.IsOdd(numArray[index2]) ? (long) Math.Round((double) (numArray[index2] - 12L) / 2.0) : (long) Math.Round((double) (numArray[index2] - 13L) / 2.0)); ++index2; } while (index2 <= 4); if (Decimal.Compare(new Decimal(this.encoding), 1M) == 0) this.master_table_entries[num1 + index1].item_type = Encoding.Default.GetString(this.db_bytes, Convert.ToInt32(Decimal.Add(new Decimal(uint64), new Decimal(num3))), (int) numArray[0]); else if (Decimal.Compare(new Decimal(this.encoding), 2M) == 0) this.master_table_entries[num1 + index1].item_type = Encoding.Unicode.GetString(this.db_bytes, Convert.ToInt32(Decimal.Add(new Decimal(uint64), new Decimal(num3))), (int) numArray[0]); else if (Decimal.Compare(new Decimal(this.encoding), 3M) == 0) this.master_table_entries[num1 + index1].item_type = Encoding.BigEndianUnicode.GetString(this.db_bytes, Convert.ToInt32(Decimal.Add(new Decimal(uint64), new Decimal(num3))), (int) numArray[0]); if (Decimal.Compare(new Decimal(this.encoding), 1M) == 0) this.master_table_entries[num1 + index1].item_name = Encoding.Default.GetString(this.db_bytes, Convert.ToInt32(Decimal.Add(Decimal.Add(new Decimal(uint64), new Decimal(num3)), new Decimal(numArray[0]))), (int) numArray[1]); else if (Decimal.Compare(new Decimal(this.encoding), 2M) == 0) this.master_table_entries[num1 + index1].item_name = Encoding.Unicode.GetString(this.db_bytes, Convert.ToInt32(Decimal.Add(Decimal.Add(new Decimal(uint64), new Decimal(num3)), new Decimal(numArray[0]))), (int) numArray[1]); else if (Decimal.Compare(new Decimal(this.encoding), 3M) == 0) this.master_table_entries[num1 + index1].item_name = Encoding.BigEndianUnicode.GetString(this.db_bytes, Convert.ToInt32(Decimal.Add(Decimal.Add(new Decimal(uint64), new Decimal(num3)), new Decimal(numArray[0]))), (int) numArray[1]); this.master_table_entries[num1 + index1].root_num = (long) this.ConvertToInteger(Convert.ToInt32(Decimal.Add(Decimal.Add(Decimal.Add(Decimal.Add(new Decimal(uint64), new Decimal(num3)), new Decimal(numArray[0])), new Decimal(numArray[1])), new Decimal(numArray[2]))), (int) numArray[3]); if (Decimal.Compare(new Decimal(this.encoding), 1M) == 0) this.master_table_entries[num1 + index1].sql_statement = Encoding.Default.GetString(this.db_bytes, Convert.ToInt32(Decimal.Add(Decimal.Add(Decimal.Add(Decimal.Add(Decimal.Add(new Decimal(uint64), new Decimal(num3)), new Decimal(numArray[0])), new Decimal(numArray[1])), new Decimal(numArray[2])), new Decimal(numArray[3]))), (int) numArray[4]); else if (Decimal.Compare(new Decimal(this.encoding), 2M) == 0) this.master_table_entries[num1 + index1].sql_statement = Encoding.Unicode.GetString(this.db_bytes, Convert.ToInt32(Decimal.Add(Decimal.Add(Decimal.Add(Decimal.Add(Decimal.Add(new Decimal(uint64), new Decimal(num3)), new Decimal(numArray[0])), new Decimal(numArray[1])), new Decimal(numArray[2])), new Decimal(numArray[3]))), (int) numArray[4]); else if (Decimal.Compare(new Decimal(this.encoding), 3M) == 0) this.master_table_entries[num1 + index1].sql_statement = Encoding.BigEndianUnicode.GetString(this.db_bytes, Convert.ToInt32(Decimal.Add(Decimal.Add(Decimal.Add(Decimal.Add(Decimal.Add(new Decimal(uint64), new Decimal(num3)), new Decimal(numArray[0])), new Decimal(numArray[1])), new Decimal(numArray[2])), new Decimal(numArray[3]))), (int) numArray[4]); } } else { if (this.db_bytes[(int) Offset] != (byte) 5) return; int uint16 = (int) Convert.ToUInt16(Decimal.Subtract(new Decimal(this.ConvertToInteger(Convert.ToInt32(Decimal.Add(new Decimal(Offset), 3M)), 2)), 1M)); for (int index = 0; index <= uint16; ++index) { ushort integer = (ushort) this.ConvertToInteger(Convert.ToInt32(Decimal.Add(Decimal.Add(new Decimal(Offset), 12M), new Decimal(index * 2))), 2); if (Decimal.Compare(new Decimal(Offset), 100M) == 0) this.ReadMasterTable(Convert.ToUInt64(Decimal.Multiply(Decimal.Subtract(new Decimal(this.ConvertToInteger((int) integer, 4)), 1M), new Decimal((int) this.page_size)))); else this.ReadMasterTable(Convert.ToUInt64(Decimal.Multiply(Decimal.Subtract(new Decimal(this.ConvertToInteger((int) ((long) Offset + (long) integer), 4)), 1M), new Decimal((int) this.page_size)))); } this.ReadMasterTable(Convert.ToUInt64(Decimal.Multiply(Decimal.Subtract(new Decimal(this.ConvertToInteger(Convert.ToInt32(Decimal.Add(new Decimal(Offset), 8M)), 4)), 1M), new Decimal((int) this.page_size)))); } } public bool ReadTable(string TableName) { int index1 = -1; int num1 = this.master_table_entries.Length - 1; for (int index2 = 0; index2 <= num1; ++index2) { if (this.master_table_entries[index2].item_name.ToLower().CompareTo(TableName.ToLower()) == 0) { index1 = index2; break; } } if (index1 == -1) return false; string[] strArray = this.master_table_entries[index1].sql_statement.Substring(this.master_table_entries[index1].sql_statement.IndexOf("(") + 1).Split(','); int num2 = strArray.Length - 1; for (int index3 = 0; index3 <= num2; ++index3) { strArray[index3] = strArray[index3].TrimStart(); int length = strArray[index3].IndexOf(" "); if (length > 0) strArray[index3] = strArray[index3].Substring(0, length); if (strArray[index3].IndexOf("UNIQUE") != 0) { Array.Resize(ref this.field_names, index3 + 1); this.field_names[index3] = strArray[index3]; } else break; } return this.ReadTableFromOffset((ulong) (this.master_table_entries[index1].root_num - 1L) * (ulong) this.page_size); } private bool ReadTableFromOffset(ulong Offset) { if (this.db_bytes[(int) Offset] == (byte) 13) { int int32 = Convert.ToInt32(Decimal.Subtract(new Decimal(this.ConvertToInteger(Convert.ToInt32(Decimal.Add(new Decimal(Offset), 3M)), 2)), 1M)); int num1 = 0; if (this.table_entries != null) { num1 = this.table_entries.Length; Array.Resize(ref this.table_entries, this.table_entries.Length + int32 + 1); } else this.table_entries = new SQLiteHandler.table_entry[int32 + 1]; int num2 = int32; for (int index1 = 0; index1 <= num2; ++index1) { SQLiteHandler.record_header_field[] array = new SQLiteHandler.record_header_field[1]; ulong integer = this.ConvertToInteger(Convert.ToInt32(Decimal.Add(Decimal.Add(new Decimal(Offset), 8M), new Decimal(index1 * 2))), 2); if (Decimal.Compare(new Decimal(Offset), 100M) != 0) integer += Offset; int endIndex1 = this.GVL((int) integer); this.CVL((int) integer, endIndex1); int endIndex2 = this.GVL(Convert.ToInt32(Decimal.Add(Decimal.Add(new Decimal(integer), Decimal.Subtract(new Decimal(endIndex1), new Decimal(integer))), 1M))); this.table_entries[num1 + index1].row_id = this.CVL(Convert.ToInt32(Decimal.Add(Decimal.Add(new Decimal(integer), Decimal.Subtract(new Decimal(endIndex1), new Decimal(integer))), 1M)), endIndex2); ulong uint64 = Convert.ToUInt64(Decimal.Add(Decimal.Add(new Decimal(integer), Decimal.Subtract(new Decimal(endIndex2), new Decimal(integer))), 1M)); int endIndex3 = this.GVL((int) uint64); int endIndex4 = endIndex3; long num3 = this.CVL((int) uint64, endIndex3); long num4 = Convert.ToInt64(Decimal.Add(Decimal.Subtract(new Decimal(uint64), new Decimal(endIndex3)), 1M)); int index2 = 0; while (num4 < num3) { Array.Resize(ref array, index2 + 1); int startIndex = endIndex4 + 1; endIndex4 = this.GVL(startIndex); array[index2].type = this.CVL(startIndex, endIndex4); array[index2].size = array[index2].type <= 9L ? (long) this.SQLDataTypeSize[(int) array[index2].type] : (!this.IsOdd(array[index2].type) ? (long) Math.Round((double) (array[index2].type - 12L) / 2.0) : (long) Math.Round((double) (array[index2].type - 13L) / 2.0)); num4 = num4 + (long) (endIndex4 - startIndex) + 1L; ++index2; } this.table_entries[num1 + index1].content = new string[array.Length - 1 + 1]; int num5 = 0; int num6 = array.Length - 1; for (int index3 = 0; index3 <= num6; ++index3) { if (array[index3].type > 9L) { if (!this.IsOdd(array[index3].type)) { if (Decimal.Compare(new Decimal(this.encoding), 1M) == 0) this.table_entries[num1 + index1].content[index3] = Encoding.Default.GetString(this.db_bytes, Convert.ToInt32(Decimal.Add(Decimal.Add(new Decimal(uint64), new Decimal(num3)), new Decimal(num5))), (int) array[index3].size); else if (Decimal.Compare(new Decimal(this.encoding), 2M) == 0) this.table_entries[num1 + index1].content[index3] = Encoding.Unicode.GetString(this.db_bytes, Convert.ToInt32(Decimal.Add(Decimal.Add(new Decimal(uint64), new Decimal(num3)), new Decimal(num5))), (int) array[index3].size); else if (Decimal.Compare(new Decimal(this.encoding), 3M) == 0) this.table_entries[num1 + index1].content[index3] = Encoding.BigEndianUnicode.GetString(this.db_bytes, Convert.ToInt32(Decimal.Add(Decimal.Add(new Decimal(uint64), new Decimal(num3)), new Decimal(num5))), (int) array[index3].size); } else this.table_entries[num1 + index1].content[index3] = Encoding.Default.GetString(this.db_bytes, Convert.ToInt32(Decimal.Add(Decimal.Add(new Decimal(uint64), new Decimal(num3)), new Decimal(num5))), (int) array[index3].size); } else this.table_entries[num1 + index1].content[index3] = Convert.ToString(this.ConvertToInteger(Convert.ToInt32(Decimal.Add(Decimal.Add(new Decimal(uint64), new Decimal(num3)), new Decimal(num5))), (int) array[index3].size)); num5 += (int) array[index3].size; } } } else if (this.db_bytes[(int) Offset] == (byte) 5) { int uint16 = (int) Convert.ToUInt16(Decimal.Subtract(new Decimal(this.ConvertToInteger(Convert.ToInt32(Decimal.Add(new Decimal(Offset), 3M)), 2)), 1M)); for (int index = 0; index <= uint16; ++index) { ushort integer = (ushort) this.ConvertToInteger(Convert.ToInt32(Decimal.Add(Decimal.Add(new Decimal(Offset), 12M), new Decimal(index * 2))), 2); this.ReadTableFromOffset(Convert.ToUInt64(Decimal.Multiply(Decimal.Subtract(new Decimal(this.ConvertToInteger((int) ((long) Offset + (long) integer), 4)), 1M), new Decimal((int) this.page_size)))); } this.ReadTableFromOffset(Convert.ToUInt64(Decimal.Multiply(Decimal.Subtract(new Decimal(this.ConvertToInteger(Convert.ToInt32(Decimal.Add(new Decimal(Offset), 8M)), 4)), 1M), new Decimal((int) this.page_size)))); } return true; } private struct record_header_field { public long size; public long type; } private struct sqlite_master_entry { public long row_id; public string item_type; public string item_name; public readonly string astable_name; public long root_num; public string sql_statement; } private struct table_entry { public long row_id; public string[] content; } } }