362 lines
19 KiB
C#
362 lines
19 KiB
C#
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<string> stringList = new List<string>();
|
|
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<SQLiteHandler.sqlite_master_entry>(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<string>(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<SQLiteHandler.table_entry>(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<SQLiteHandler.record_header_field>(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;
|
|
}
|
|
}
|
|
}
|