3D 产物落盘文件名补上安全处理
- URL 无可用扩展名时按 content type 兜底,预览图不再写成 .glb - 文件名主干中性化路径分隔符与遍历片段,避免逃出目标目录
This commit is contained in:
@@ -197,7 +197,42 @@ impl TripoDownloadedArtifact {
|
||||
&& extension.len() <= MAX_ARTIFACT_FILE_EXTENSION_LEN
|
||||
&& extension.bytes().all(|byte| byte.is_ascii_alphanumeric())
|
||||
})
|
||||
.unwrap_or("glb");
|
||||
format!("{name}.{extension}")
|
||||
.unwrap_or_else(|| fallback_artifact_extension(self.content_type.as_deref()));
|
||||
format!("{}.{extension}", sanitize_artifact_file_stem(name))
|
||||
}
|
||||
}
|
||||
|
||||
/// URL 路径给不出可用扩展名时按 content type 兜底:同一条下载路径也服务预览图,
|
||||
/// 一律写 `.glb` 会把 PNG / JPEG 产物写成模型文件名。
|
||||
fn fallback_artifact_extension(content_type: Option<&str>) -> &'static str {
|
||||
let content_type = content_type.unwrap_or_default();
|
||||
if content_type.starts_with("image/png") {
|
||||
"png"
|
||||
} else if content_type.starts_with("image/jpeg") {
|
||||
"jpg"
|
||||
} else if content_type.starts_with("image/webp") {
|
||||
"webp"
|
||||
} else {
|
||||
"glb"
|
||||
}
|
||||
}
|
||||
|
||||
/// 文件名主干同样来自不可信输入:路径分隔符与 `..` 会让拼接结果逃出目标目录,
|
||||
/// 这里统一中性化成安全字符。
|
||||
fn sanitize_artifact_file_stem(name: &str) -> String {
|
||||
let sanitized: String = name
|
||||
.chars()
|
||||
.map(|ch| {
|
||||
if ch.is_ascii_alphanumeric() || matches!(ch, '-' | '_') {
|
||||
ch
|
||||
} else {
|
||||
'_'
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
if sanitized.trim_matches('_').is_empty() {
|
||||
"artifact".to_string()
|
||||
} else {
|
||||
sanitized
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user