from filetypes.base import *
import malcat




class Header(Struct):

    def parse(self):
        yield String(16, zero_terminated=True, name="Magic")
        yield UInt16BE(name="PageSize")
        yield UInt8(name="FormatWriteVersion", values=[("Legacy", 1), ("WAL", 2)])
        yield UInt8(name="FormatReadVersion", values=[("Legacy", 1), ("WAL", 2)])
        yield UInt8(name="UnusedSpace", comment="bytes of unused reserved space at the end of each page. Usually 0.")
        yield UInt8(name="MaximumEmbeddedPayload", comment="Maximum embedded payload fraction. Must be 64.")
        yield UInt8(name="MinimumEmbeddedPayload", comment="Maximum embedded payload fraction. Must be 32.")
        yield UInt8(name="LeafPayloadFraction", comment="Leaf payload fraction")
        yield UInt32BE(name="ChangeCounter", comment="File change counter")
        yield UInt32BE(name="PageCount", comment="Size of the database file in pages")
        yield UInt32BE(name="FreeListPage", comment="Page number of the first freelist trunk page")
        yield UInt32BE(name="FreeListCount", comment="Total number of freelist page")
        yield UInt32BE(name="Cookie", comment="Schema cookie")
        yield UInt32BE(name="Schema format number", comment="")
        yield UInt32BE(name="PageCacheSize", comment="Default page cache size")
        yield UInt32BE(name="VacuumPage", comment="page number of the largest root b-tree page when in auto-vacuum or incremental-vacuum modes, or zero otherwise")
        yield UInt32BE(name="Encoding", values = [
            ("UTF-8", 1),
            ("UTF-16le", 2),
            ("UTF-16be", 3),
        ])
        yield UInt32BE(name="UserVersion", comment="User version as read and set by the user_version pragma")
        yield UInt32BE(name="VacuumMode", comment="True iff non-zero")
        yield UInt32BE(name="ApplicationId", comment="Set by PRAGMA application_id")
        yield Unused(20)
        yield UInt32BE(name="VersionValidForNumber", comment="")
        yield UInt32BE(name="SqliteVersionNumber", comment="")


class SqliteAnalyzer(FileTypeAnalyzer):
    category = malcat.FileType.DATABASE
    name = "SQLITE"
    regexp = r"SQLite format 3\x00[^\x00\x01]\x00[\x01\x02][\x01\x02].\x40\x20\x20"


    def parse(self, hint):
        hdr = yield Header()
        sz = self["Header"]["PageCount"] * self["Header"]["PageSize"]
        self.set_eof(sz)
        self.confirm()
        for i in range(0, self["Header"]["PageCount"]):
            self.add_section(f"Page{i+1}", i * self["Header"]["PageSize"], self["Header"]["PageSize"])
            
