"""Pure resolution of stored media paths into browser-reachable upload URLs.""" from __future__ import annotations from pathlib import Path from urllib.parse import quote _ABSOLUTE_SCHEMES = ("http://", "https://", "data:") _UPLOAD_ROUTE_PREFIX = "/uploads/" _CANONICAL_PREFIXES = ("documents/", "persons/", "photos/") def absolute_upload_url(path: str, *, base_url: str) -> str: """Join an application-relative upload path onto the request base URL.""" base = base_url.rstrip("/") normalized_path = path if path.startswith("/") else f"/{path}" return f"{base}{normalized_path}" def resolve_media_url(path: str | None, *, upload_dir: Path, base_url: str) -> str | None: """Map a canonical stored relative media path onto a served upload URL.""" candidate = (path or "").strip() if not candidate: return None normalized = candidate.replace("\\", "/") lowered = normalized.casefold() if lowered.startswith(_ABSOLUTE_SCHEMES): return normalized if normalized.startswith(_UPLOAD_ROUTE_PREFIX): return _resolve_upload_relative(normalized.removeprefix(_UPLOAD_ROUTE_PREFIX), upload_dir=upload_dir, base_url=base_url) if lowered.startswith(_CANONICAL_PREFIXES): return _resolve_upload_relative(normalized, upload_dir=upload_dir, base_url=base_url) return None def _resolve_upload_relative(relative: str, *, upload_dir: Path, base_url: str) -> str | None: candidate = relative.strip().replace("\\", "/") if not candidate: return None resolved_upload_dir = upload_dir.resolve() try: normalized_relative = Path(candidate).as_posix() if not normalized_relative.casefold().startswith(_CANONICAL_PREFIXES): return None absolute_candidate = (resolved_upload_dir / Path(normalized_relative)).resolve() safe_relative = absolute_candidate.relative_to(resolved_upload_dir).as_posix() except ValueError: return None if not absolute_candidate.is_file(): return None return absolute_upload_url(f"/uploads/{quote(safe_relative)}", base_url=base_url) def public_media_path_label(path: str | None, *, upload_dir: Path) -> str: """Return a safe, non-local path label for UI metadata display.""" _ = upload_dir candidate = (path or "").strip() if not candidate: return "unknown" normalized = candidate.replace("\\", "/") lowered = normalized.casefold() if normalized.startswith(_UPLOAD_ROUTE_PREFIX): return normalized if lowered.startswith(_CANONICAL_PREFIXES): return f"/uploads/{normalized}" return Path(normalized).name or "unknown"