"""File operation utilities with validation and safety checks."""
from pathlib import Path
import os
MAX_FILE_SIZE = 5 * 1024 * 1024 # 5MB
def validate_path(file_path: str) -> Path:
"""Validate and resolve file path to prevent directory traversal.
Args:
file_path: Path to validate
Returns:
Resolved Path object
Raises:
ValueError: If path is invalid or unsafe
"""
try:
path = Path(file_path).resolve()
# Ensure path exists
if not path.exists():
raise ValueError(f"File not found: {file_path}")
# Ensure it's a file, not a directory
if not path.is_file():
raise ValueError(f"Path is not a file: {file_path}")
return path
except Exception as e:
raise ValueError(f"Invalid file path: {str(e)}")
def read_file(file_path: str) -> str:
"""Read content from a local file with safety checks.
Args:
file_path: Path to the file to read
Returns:
File content as string
Raises:
ValueError: If file is too large or path is invalid
"""
path = validate_path(file_path)
# Check file size
file_size = path.stat().st_size
if file_size > MAX_FILE_SIZE:
raise ValueError(
f"File too large ({file_size / 1024 / 1024:.2f}MB). "
f"Maximum allowed size is {MAX_FILE_SIZE / 1024 / 1024}MB"
)
# Read file content
try:
with open(path, 'r', encoding='utf-8') as f:
return f.read()
except UnicodeDecodeError:
# Try with a different encoding if UTF-8 fails
with open(path, 'r', encoding='latin-1') as f:
return f.read()
def write_file(file_path: str, content: str) -> None:
"""Write content to a file.
Args:
file_path: Path to write to
content: Content to write
Raises:
ValueError: If path is invalid
"""
path = Path(file_path).resolve()
# Ensure parent directory exists
path.parent.mkdir(parents=True, exist_ok=True)
with open(path, 'w', encoding='utf-8') as f:
f.write(content)