Files
2026-08-27 10:55:23 -06:00

458 lines
12 KiB
C#

using System;
using System.IO;
using System.Text;
namespace Intelix.Helper.Sql;
public class SqLite
{
private struct RecordHeaderField
{
public long Size;
public long Type;
}
private struct TableEntry
{
public string[] Content;
}
private struct SqliteMasterEntry
{
public string ItemName;
public long RootNum;
public string SqlStatement;
}
private readonly ulong _dbEncoding;
private readonly byte[] _fileBytes;
private readonly ulong _pageSize;
private readonly byte[] _sqlDataTypeSize = new byte[10] { 0, 1, 2, 3, 4, 6, 8, 8, 0, 0 };
private string[] _fieldNames;
private SqliteMasterEntry[] _masterTableEntries;
private TableEntry[] _tableEntries;
public SqLite(string fileName)
{
_fileBytes = File.ReadAllBytes(fileName);
_pageSize = ConvertToULong(16, 2);
_dbEncoding = ConvertToULong(56, 4);
ReadMasterTable(100L);
}
public SqLite(byte[] basedata)
{
_fileBytes = basedata;
_pageSize = ConvertToULong(16, 2);
_dbEncoding = ConvertToULong(56, 4);
ReadMasterTable(100L);
}
public string GetValue(int rowNum, int field)
{
try
{
if (rowNum >= _tableEntries.Length)
{
return null;
}
return (field >= _tableEntries[rowNum].Content.Length) ? null : _tableEntries[rowNum].Content[field];
}
catch
{
return "";
}
}
public int GetRowCount()
{
return _tableEntries.Length;
}
private bool ReadTableFromOffset(ulong offset)
{
try
{
switch (_fileBytes[offset])
{
case 13:
{
uint num4 = (uint)(ConvertToULong((int)offset + 3, 2) - 1);
int num5 = 0;
if (_tableEntries != null)
{
num5 = _tableEntries.Length;
Array.Resize(ref _tableEntries, _tableEntries.Length + (int)num4 + 1);
}
else
{
_tableEntries = new TableEntry[num4 + 1];
}
for (uint num6 = 0u; (int)num6 <= (int)num4; num6++)
{
ulong num7 = ConvertToULong((int)offset + 8 + (int)(num6 * 2), 2);
if (offset != 100)
{
num7 += offset;
}
int num8 = Gvl((int)num7);
Cvl((int)num7, num8);
int num9 = Gvl((int)((long)num7 + ((long)num8 - (long)num7) + 1));
Cvl((int)((long)num7 + ((long)num8 - (long)num7) + 1), num9);
ulong num10 = num7 + (ulong)((long)num9 - (long)num7 + 1);
int num11 = Gvl((int)num10);
int num12 = num11;
long num13 = Cvl((int)num10, num11);
RecordHeaderField[] array = null;
long num14 = (long)num10 - (long)num11 + 1;
int num15 = 0;
while (num14 < num13)
{
Array.Resize(ref array, num15 + 1);
int num16 = num12 + 1;
num12 = Gvl(num16);
array[num15].Type = Cvl(num16, num12);
array[num15].Size = ((array[num15].Type <= 9) ? _sqlDataTypeSize[array[num15].Type] : ((!IsOdd(array[num15].Type)) ? ((array[num15].Type - 12) / 2) : ((array[num15].Type - 13) / 2)));
num14 = num14 + (num12 - num16) + 1;
num15++;
}
if (array == null)
{
continue;
}
_tableEntries[num5 + (int)num6].Content = new string[array.Length];
int num17 = 0;
for (int i = 0; i <= array.Length - 1; i++)
{
if (array[i].Type > 9)
{
if (!IsOdd(array[i].Type))
{
long dbEncoding = (long)_dbEncoding;
long num18 = dbEncoding - 1;
if ((ulong)num18 <= 2uL)
{
switch (num18)
{
case 0L:
_tableEntries[num5 + (int)num6].Content[i] = Encoding.Default.GetString(_fileBytes, (int)((long)num10 + num13 + num17), (int)array[i].Size);
break;
case 1L:
_tableEntries[num5 + (int)num6].Content[i] = Encoding.Unicode.GetString(_fileBytes, (int)((long)num10 + num13 + num17), (int)array[i].Size);
break;
case 2L:
_tableEntries[num5 + (int)num6].Content[i] = Encoding.BigEndianUnicode.GetString(_fileBytes, (int)((long)num10 + num13 + num17), (int)array[i].Size);
break;
}
}
}
else
{
_tableEntries[num5 + (int)num6].Content[i] = Encoding.Default.GetString(_fileBytes, (int)((long)num10 + num13 + num17), (int)array[i].Size);
}
}
else
{
_tableEntries[num5 + (int)num6].Content[i] = Convert.ToString(ConvertToULong((int)((long)num10 + num13 + num17), (int)array[i].Size));
}
num17 += (int)array[i].Size;
}
}
break;
}
case 5:
{
uint num = (uint)(ConvertToULong((int)(offset + 3), 2) - 1);
for (uint num2 = 0u; (int)num2 <= (int)num; num2++)
{
uint num3 = (uint)ConvertToULong((int)offset + 12 + (int)(num2 * 2), 2);
ReadTableFromOffset((ConvertToULong((int)(offset + num3), 4) - 1) * _pageSize);
}
ReadTableFromOffset((ConvertToULong((int)(offset + 8), 4) - 1) * _pageSize);
break;
}
}
return true;
}
catch
{
return false;
}
}
private void ReadMasterTable(long offset)
{
while (true)
{
switch (_fileBytes[offset])
{
default:
return;
case 5:
{
uint num13 = (uint)(ConvertToULong((int)offset + 3, 2) - 1);
for (int j = 0; j <= (int)num13; j++)
{
uint num14 = (uint)ConvertToULong((int)offset + 12 + j * 2, 2);
if (offset == 100)
{
ReadMasterTable((long)((ConvertToULong((int)num14, 4) - 1) * _pageSize));
}
else
{
ReadMasterTable((long)((ConvertToULong((int)(offset + num14), 4) - 1) * _pageSize));
}
}
break;
}
case 13:
{
ulong num = ConvertToULong((int)offset + 3, 2) - 1;
int num2 = 0;
if (_masterTableEntries != null)
{
num2 = _masterTableEntries.Length;
Array.Resize(ref _masterTableEntries, _masterTableEntries.Length + (int)num + 1);
}
else
{
checked
{
_masterTableEntries = new SqliteMasterEntry[(ulong)unchecked((long)(num + 1))];
}
}
for (ulong num3 = 0uL; num3 <= num; num3++)
{
ulong num4 = ConvertToULong((int)offset + 8 + (int)num3 * 2, 2);
if (offset != 100)
{
num4 += (ulong)offset;
}
int num5 = Gvl((int)num4);
Cvl((int)num4, num5);
int num6 = Gvl((int)((long)num4 + ((long)num5 - (long)num4) + 1));
Cvl((int)((long)num4 + ((long)num5 - (long)num4) + 1), num6);
ulong num7 = num4 + (ulong)((long)num6 - (long)num4 + 1);
int num8 = Gvl((int)num7);
int num9 = num8;
long num10 = Cvl((int)num7, num8);
long[] array = new long[5];
for (int i = 0; i <= 4; i++)
{
int startIdx = num9 + 1;
num9 = Gvl(startIdx);
array[i] = Cvl(startIdx, num9);
array[i] = ((array[i] <= 9) ? _sqlDataTypeSize[array[i]] : ((!IsOdd(array[i])) ? ((array[i] - 12) / 2) : ((array[i] - 13) / 2)));
}
long dbEncoding;
if (_dbEncoding == 1 || _dbEncoding == 2)
{
dbEncoding = (long)_dbEncoding;
long num11 = dbEncoding - 1;
if ((ulong)num11 <= 2uL)
{
switch (num11)
{
case 0L:
_masterTableEntries[num2 + (int)num3].ItemName = Encoding.Default.GetString(_fileBytes, (int)((long)num7 + num10 + array[0]), (int)array[1]);
break;
case 1L:
_masterTableEntries[num2 + (int)num3].ItemName = Encoding.Unicode.GetString(_fileBytes, (int)((long)num7 + num10 + array[0]), (int)array[1]);
break;
case 2L:
_masterTableEntries[num2 + (int)num3].ItemName = Encoding.BigEndianUnicode.GetString(_fileBytes, (int)((long)num7 + num10 + array[0]), (int)array[1]);
break;
}
}
}
_masterTableEntries[num2 + (int)num3].RootNum = (long)ConvertToULong((int)((long)num7 + num10 + array[0] + array[1] + array[2]), (int)array[3]);
dbEncoding = (long)_dbEncoding;
long num12 = dbEncoding - 1;
if ((ulong)num12 <= 2uL)
{
switch (num12)
{
case 0L:
_masterTableEntries[num2 + (int)num3].SqlStatement = Encoding.Default.GetString(_fileBytes, (int)((long)num7 + num10 + array[0] + array[1] + array[2] + array[3]), (int)array[4]);
break;
case 1L:
_masterTableEntries[num2 + (int)num3].SqlStatement = Encoding.Unicode.GetString(_fileBytes, (int)((long)num7 + num10 + array[0] + array[1] + array[2] + array[3]), (int)array[4]);
break;
case 2L:
_masterTableEntries[num2 + (int)num3].SqlStatement = Encoding.BigEndianUnicode.GetString(_fileBytes, (int)((long)num7 + num10 + array[0] + array[1] + array[2] + array[3]), (int)array[4]);
break;
}
}
}
return;
}
}
offset = (long)((ConvertToULong((int)offset + 8, 4) - 1) * _pageSize);
}
}
public bool ReadTable(string tableName)
{
int num = -1;
for (int i = 0; i <= _masterTableEntries.Length; i++)
{
if (string.Compare(_masterTableEntries[i].ItemName.ToLower(), tableName.ToLower(), StringComparison.Ordinal) == 0)
{
num = i;
break;
}
}
if (num == -1)
{
return false;
}
string[] array = _masterTableEntries[num].SqlStatement.Substring(_masterTableEntries[num].SqlStatement.IndexOf("(", StringComparison.Ordinal) + 1).Split(',');
for (int j = 0; j <= array.Length - 1; j++)
{
array[j] = array[j].TrimStart();
int num2 = array[j].IndexOf(' ');
if (num2 > 0)
{
array[j] = array[j].Substring(0, num2);
}
if (array[j].IndexOf("UNIQUE", StringComparison.Ordinal) != 0)
{
Array.Resize(ref _fieldNames, j + 1);
_fieldNames[j] = array[j];
}
}
return ReadTableFromOffset((ulong)(_masterTableEntries[num].RootNum - 1) * _pageSize);
}
private ulong ConvertToULong(int startIndex, int size)
{
try
{
if (size > 8 || size == 0)
{
return 0uL;
}
ulong num = 0uL;
for (int i = 0; i <= size - 1; i++)
{
num = (num << 8) | _fileBytes[startIndex + i];
}
return num;
}
catch
{
return 0uL;
}
}
private int Gvl(int startIdx)
{
try
{
if (startIdx > _fileBytes.Length)
{
return 0;
}
for (int i = startIdx; i <= startIdx + 8; i++)
{
if (i > _fileBytes.Length - 1)
{
return 0;
}
if ((_fileBytes[i] & 0x80) != 128)
{
return i;
}
}
return startIdx + 8;
}
catch
{
return 0;
}
}
private long Cvl(int startIdx, int endIdx)
{
try
{
endIdx++;
byte[] array = new byte[8];
int num = endIdx - startIdx;
bool flag = false;
if (num == 0 || num > 9)
{
return 0L;
}
switch (num)
{
case 1:
array[0] = (byte)(_fileBytes[startIdx] & 0x7F);
return BitConverter.ToInt64(array, 0);
case 9:
flag = true;
break;
}
int num2 = 1;
int num3 = 7;
int num4 = 0;
if (flag)
{
array[0] = _fileBytes[endIdx - 1];
endIdx--;
num4 = 1;
}
for (int i = endIdx - 1; i >= startIdx; i += -1)
{
if (i - 1 >= startIdx)
{
array[num4] = (byte)(((_fileBytes[i] >> num2 - 1) & (255 >> num2)) | (_fileBytes[i - 1] << num3));
num2++;
num4++;
num3--;
}
else if (!flag)
{
array[num4] = (byte)((_fileBytes[i] >> num2 - 1) & (255 >> num2));
}
}
return BitConverter.ToInt64(array, 0);
}
catch
{
return 0L;
}
}
private static bool IsOdd(long value)
{
return (value & 1) == 1;
}
public static SqLite ReadTable(string database, string table)
{
try
{
string text = Path.GetTempFileName() + ".tmpdb";
File.Copy(database, text);
SqLite sqLite = new SqLite(text);
sqLite.ReadTable(table);
File.Delete(text);
return (sqLite.GetRowCount() == 65536) ? null : sqLite;
}
catch
{
return null;
}
}
}