first implementations of database and logging utilities.

This commit is contained in:
overcuriousity 2025-10-08 14:57:54 +02:00
parent 4e6dff930d
commit 172de21f55
8 changed files with 129 additions and 14 deletions

2
.gitignore vendored
View File

@ -167,3 +167,5 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear # and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder. # option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/ #.idea/
forensic_trails.db

7
config.json Normal file
View File

@ -0,0 +1,7 @@
{
"database_path": "forensic_trails.db",
"database_schema_version": 1,
"database_template": "schema.sql",
"log_path": "forensic_trails.log",
"log_level": "DEBUG"
}

View File

@ -8,9 +8,9 @@ version = "0.1.0"
description = "Forensic Investigation Documentation System" description = "Forensic Investigation Documentation System"
readme = "README.md" readme = "README.md"
requires-python = ">=3.12" requires-python = ">=3.12"
license = {text = "MIT"} # Change as needed license = {text = "BSD 3-Clause"}
authors = [ authors = [
{name = "Your Name", email = "your.email@example.com"} {name = "Overcuriousity", email = "overcuriousity@posteo.org"}
] ]
classifiers = [ classifiers = [
"Development Status :: 3 - Alpha", "Development Status :: 3 - Alpha",
@ -26,6 +26,7 @@ dependencies = [
"Pillow>=10.0.0", "Pillow>=10.0.0",
"cryptography>=41.0.0", "cryptography>=41.0.0",
"pyinstaller>=6.0.0", "pyinstaller>=6.0.0",
"logging>=0.4.9.6",
] ]
[project.optional-dependencies] [project.optional-dependencies]

6
run.py
View File

@ -1,4 +1,4 @@
import forensic_trails from src.forensictrails.__main__ import main
def run(): if __name__ == "__main__":
forensic_trails.main() main()

View File

@ -1,24 +1,33 @@
"""Entry point for ForensicTrails application.""" """Entry point for ForensicTrails application."""
import sys import sys
import logging
from PyQt6.QtWidgets import QApplication from PyQt6.QtWidgets import QApplication
from .db.database import initialize_database
from .utils.logging import setup_logging
def main(): def main():
"""Main entry point for the application.""" """Main entry point for the application."""
setup_logging()
logging.info("Starting ForensicTrails application")
initialize_database()
# Create Qt application
app = QApplication(sys.argv) app = QApplication(sys.argv)
app.setApplicationName("ForensicTrails") app.setApplicationName("ForensicTrails")
app.setOrganizationName("Your Organization") app.setOrganizationName("ForensicTrails")
app.setApplicationVersion("0.1.0")
# TODO: Create and show main window # TODO: Create and show main window
# from forensictrails.gui.main_window import MainWindow # from .gui.main_window import MainWindow
# window = MainWindow() # window = MainWindow()
# window.show() # window.show()
print("ForensicTrails - Forensic Investigation Documentation System") # For now, just exit immediately since we have no GUI yet
print("Application starting...") logging.debug("No GUI yet - exiting...")
return 0
sys.exit(app.exec()) # sys.exit(app.exec())
if __name__ == "__main__": if __name__ == "__main__":
main() sys.exit(main())

View File

@ -0,0 +1,45 @@
import sqlite3
import logging
from pathlib import Path
from ..utils.config import config
def get_db_connection(db_path=None):
if db_path is None:
db_path = create_db_if_not_exists()
conn = sqlite3.connect(db_path)
conn.row_factory = sqlite3.Row
return conn
def create_db_if_not_exists(db_path=None, schema_path=None):
if db_path is None:
db_path = config.database_path
if schema_path is None:
schema_path = Path(__file__).parent / config.database_template
conn = get_db_connection(db_path)
cursor = conn.cursor()
with open(schema_path, 'r') as f:
schema = f.read()
cursor.executescript(schema)
conn.commit()
conn.close()
def initialize_database(db_path=None):
if db_path is None:
db_path = config.database_path
get_db_connection(db_path)
if config.log_level == 'DEBUG':
show_db_schema(db_path)
logging.info(f"Database initialized at {db_path}")
def show_db_schema(db_path):
conn = get_db_connection(db_path)
cursor = conn.cursor()
logging.debug("Displaying database schema:")
for row in cursor.execute("SELECT name, sql FROM sqlite_master WHERE type='table';"):
logging.debug(f"Table: {row['name']}\nSQL: {row['sql']}\n")
conn.close()

View File

@ -0,0 +1,20 @@
import json
import os
class Config:
def __init__(self, config_filepath='config.json'):
config_data = self._load_config(config_filepath)
self.database_template = config_data.get('database_template', 'schema.sql')
self.database_path = config_data.get('database_path', 'forensic_trails.db')
self.database_schema_version = config_data.get('database_schema_version', 1)
self.log_path = config_data.get('log_path', 'forensic_trails.log')
self.log_level = config_data.get('log_level', 'DEBUG')
def _load_config(self, config_filepath):
if os.path.exists(config_filepath):
with open(config_filepath, 'r') as f:
return json.load(f)
else:
return {}
config = Config()

View File

@ -0,0 +1,31 @@
import logging
from pathlib import Path
from ..utils.config import config
import sys
def setup_logging(log_path=None):
if log_path is None:
log_path = config.log_path
log_file = Path(log_path)
log_file.parent.mkdir(parents=True, exist_ok=True)
logger = logging.getLogger()
logger.setLevel(config.log_level)
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
file_handler = logging.FileHandler(log_file)
file_handler.setLevel(config.log_level)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
stream_handler = logging.StreamHandler(sys.stdout)
stream_handler.setLevel(config.log_level)
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)