//! Résolution des chemins miroir sous `data/dossiers-permanents/` (upload binaire, sync Git). use crate::config::Config; use hyper::header::HeaderMap; use std::path::PathBuf; use uuid::Uuid; use crate::dp_git_sync; pub fn sanitize_dp_mirror_filename(name: &str) -> String { let base: String = name .chars() .map(|c| match c { '/' | '\\' | ':' | '\0' => '-', c if c.is_control() => '-', c => c, }) .collect(); let t = base.trim(); if t.is_empty() { return "document".into(); } t.chars().take(240).collect() } pub fn header_dp_mirror_relative_path(hdr: &HeaderMap) -> Option { hdr.get("x-enso-dp-mirror-relative-path") .and_then(|v| v.to_str().ok()) .map(str::trim) .filter(|s| !s.is_empty()) .map(|s| s.to_string()) } /// Chemin relatif sous `DOCV_DP_GIT_DATA_SUBPATH`, si entête valide ou sync Git activé (défaut `_uploads/...`). pub fn resolve_dp_mirror_relative( cfg: &Config, hdr: &HeaderMap, folder_uid: Uuid, name: &str, ) -> Option { let safe = sanitize_dp_mirror_filename(name); if let Some(raw) = header_dp_mirror_relative_path(hdr) { let t = raw.trim(); if !t.is_empty() { let is_dir = t.ends_with('/'); let trimmed = t.trim_end_matches('/').trim(); if let Some(mut p) = dp_git_sync::safe_relative_under_repo(trimmed) { if is_dir { p.push(safe.clone()); } return Some(p); } } } if cfg.dp_git_sync.enabled { Some( PathBuf::from("_uploads") .join(folder_uid.to_string()) .join(safe), ) } else { None } }