Files
litterbox/app/__init__.py
T
BlackSnufkin ce9a926246 Refactor backend into blueprints/services/utils package and frontend into ES6 modules
Backend (Python):
- Split app/routes.py (1,389 lines) into 6 Flask blueprints (upload, analysis,
  results, doppelganger, management, api) under app/blueprints/, plus
  service modules (rendering, summary, tool_check, error_handling) under
  app/services/, and the shared RouteHelpers class in app/helpers.py.
  app/__init__.py wires shared deps via app.extensions['litterbox'].
- Split app/utils.py (1,400 lines) into the app/utils/ package with
  single-concern modules: file_io, validators, path_manager, risk_analyzer,
  forensics, json_helpers, reporting. No facade — every caller migrated.
- Extracted BaseSubprocessAnalyzer in app/analyzers/base.py; refactored 9
  subprocess analyzers (yara/checkplz/stringnalyzer static; yara/pe_sieve/
  moneta/patriot/hsb/hollows_hunter dynamic) as thin subclasses that only
  declare config + implement _parse_output.

Frontend (JS):
- Split results.js (2,060), holygrail.js (1,025), byovd_info.js (1,069),
  and upload.js (974) into per-concern ES6 modules under
  app/static/js/{results,holygrail,byovd,upload}/.
- Added app/static/js/utils/ with shared helpers: escape, formatters,
  severity, fetch, modals, dom (single source of truth for escapeHtml,
  formatBytes, severity-color mapping, etc.).
- Converted base.js, summary.js, blender.js, fuzzy.js to ES6 modules;
  every <script> tag now uses type="module". window.X assignments preserved
  so inline onclick handlers in templates keep resolving.
- Targeted XSS hardening at user-data interpolation sites in results
  renderers (str.data, hex_dump, scan_info.target, list items).

Templates:
- New app/templates/partials/_macros.html with reusable scanner-table
  macros + 3-card status grid; static_info.html and dynamic_info.html
  migrated to use them, eliminating identical-HTML duplication.

CSS:
- Fixed broken @apply in .drag-over (no Tailwind build pipeline → @apply
  was silently ignored, leaving drag-and-drop visual feedback broken).
  Replaced with raw CSS equivalent.
- Dedented stray 8-space-indented block (lines 127-end) for consistency.
- Added header comment documenting the no-build-pipeline constraint.

Gitignore:
- Anchored Results/, Uploads/, DoppelgangerDB/Blender/, and Scanners/*
  patterns to repo root with leading slash so they don't shadow same-
  named directories elsewhere (notably the new app/static/js/results/
  module directory and app/blueprints/results.py).
- Added /Scanners/PE-Sieve/process_*/ for runtime scan artifacts.
2026-04-27 06:41:19 -07:00

111 lines
3.4 KiB
Python

import logging
import os
from types import SimpleNamespace
import yaml
from colorama import Fore, Style, init
from flask import Flask, render_template, request
# Initialize colorama for Windows compatibility
init(autoreset=True)
def load_config():
config_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'config', 'config.yaml')
with open(config_path, 'r') as config_file:
return yaml.safe_load(config_file)
def create_app():
app = Flask(__name__)
# Load configuration from YAML
config = load_config()
app.config.update(config)
app.name = config['application']['name']
# Create all necessary directories
paths_to_create = {
config['utils']['upload_folder'],
config['utils']['result_folder'],
config['analysis']['doppelganger']['db']['path'],
os.path.join(
config['analysis']['doppelganger']['db']['path'],
config['analysis']['doppelganger']['db']['blender'],
),
os.path.join(
config['analysis']['doppelganger']['db']['path'],
config['analysis']['doppelganger']['db']['fuzzyhash'],
),
}
for path in paths_to_create:
os.makedirs(path, exist_ok=True)
# Wire shared dependencies once; blueprints read them via current_app.extensions
from .analyzers.manager import AnalysisManager
from .helpers import RouteHelpers
app.extensions['litterbox'] = SimpleNamespace(
manager=AnalysisManager(app.config, logger=app.logger),
helpers=RouteHelpers(app.config, app.logger),
config=app.config,
)
# Register blueprints
from .blueprints import (
analysis_bp,
api_bp,
doppelganger_bp,
management_bp,
results_bp,
upload_bp,
)
app.register_blueprint(upload_bp)
app.register_blueprint(analysis_bp)
app.register_blueprint(results_bp)
app.register_blueprint(doppelganger_bp)
app.register_blueprint(management_bp)
app.register_blueprint(api_bp)
@app.errorhandler(404)
def page_not_found(error):
app.logger.debug(f"Page not found: {request.path}")
return render_template('error.html', error=f"Page not found: {request.path}"), 404
return app
def setup_logging(app):
"""Configure logging with selective colors and avoid duplicate logs."""
if os.environ.get('WERKZEUG_RUN_MAIN') != 'true':
return
if app.config['DEBUG']:
log_level = logging.DEBUG
from flask.logging import default_handler
app.logger.setLevel(log_level)
class ColoredFormatter(logging.Formatter):
LOG_COLORS = {
"DEBUG": Fore.CYAN,
"INFO": Fore.GREEN,
"WARNING": Fore.YELLOW,
"ERROR": Fore.RED,
"CRITICAL": Fore.MAGENTA + Style.BRIGHT,
}
def format(self, record):
log_color = self.LOG_COLORS.get(record.levelname, "")
levelname_color = f"{log_color}{record.levelname}{Style.RESET_ALL}"
message = f"{Style.RESET_ALL}{record.msg}"
record.levelname = levelname_color
record.msg = message
return super().format(record)
formatter = ColoredFormatter('[%(asctime)s - %(name)s] [%(levelname)s] - %(message)s')
default_handler.setFormatter(formatter)
app.logger.debug("Debug logging is enabled.")