first implementations of database and logging utilities.
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -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
7
config.json
Normal 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"
|
||||||
|
}
|
||||||
@@ -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
6
run.py
@@ -1,4 +1,4 @@
|
|||||||
import forensic_trails
|
from src.forensictrails.__main__ import main
|
||||||
|
|
||||||
def run():
|
if __name__ == "__main__":
|
||||||
forensic_trails.main()
|
main()
|
||||||
@@ -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())
|
||||||
45
src/forensictrails/db/database.py
Normal file
45
src/forensictrails/db/database.py
Normal 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()
|
||||||
20
src/forensictrails/utils/config.py
Normal file
20
src/forensictrails/utils/config.py
Normal 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()
|
||||||
31
src/forensictrails/utils/logging.py
Normal file
31
src/forensictrails/utils/logging.py
Normal 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)
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user