"""Utility functions for Ohm Stream Downloader""" import re import os import logging from typing import Optional from pathlib import Path logger = logging.getLogger(__name__) def sanitize_filename(filename: str, max_length: int = 255) -> str: """ Safely sanitize filenames to prevent path traversal and invalid characters Args: filename: The original filename max_length: Maximum length for filename (default 255 for most filesystems) Returns: Sanitized safe filename Examples: >>> sanitize_filename("../../../etc/passwd") '______etc_passwd' >>> sanitize_filename("video:file?.mp4") 'video_file_.mp4' """ if not filename: return "download" # Remove path separators and dangerous characters # Remove: \ / : * ? " < > | and control characters filename = re.sub(r'[\\/*?:"<>|]', '_', filename) # Remove any path components (prevent path traversal) filename = Path(filename).name # Remove leading dots and dashes filename = filename.lstrip('.-') # Limit length if len(filename) > max_length: # Keep extension name, ext = os.path.splitext(filename) max_name_length = max_length - len(ext) filename = name[:max_name_length] + ext # If empty after sanitization, use default if not filename: filename = "download" logger.debug(f"Sanitized filename: {filename}") return filename def is_safe_filename(filename: str) -> bool: """ Check if a filename is safe (no path traversal attempts) Args: filename: The filename to check Returns: True if filename is safe, False otherwise """ if not filename: return False # Check for path traversal patterns if ".." in filename or "/" in filename or "\\" in filename: return False # Check for absolute paths if filename.startswith("/") or filename.startswith("\\"): return False # Check for drive letters (Windows) if re.match(r'^[A-Za-z]:', filename): return False return True