You've already forked DataMate
feat(data-management): 实现数据集文件版本管理和内部路径保护
- 将数据集文件查询方法替换为只查询可见文件的版本 - 引入文件状态管理(ACTIVE/ARCHIVED)和内部目录结构 - 实现文件重复处理策略,支持版本控制模式而非覆盖 - 添加内部数据目录保护,防止访问.datamate等系统目录 - 重构文件上传流程,引入暂存目录和事务后清理机制 - 实现文件版本归档功能,保留历史版本到专用存储位置 - 优化文件路径规范化和安全验证逻辑 - 修复文件删除逻辑,确保归档文件不会被错误移除 - 更新数据集压缩下载功能以排除内部系统文件
This commit is contained in:
@@ -143,7 +143,20 @@ public class ArchiveAnalyzer {
|
||||
private static Optional<FileUploadResult> extractEntity(ArchiveInputStream<?> archiveInputStream, ArchiveEntry archiveEntry, Path archivePath)
|
||||
throws IOException {
|
||||
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
|
||||
Path path = Paths.get(archivePath.getParent().toString(), archiveEntry.getName());
|
||||
Path archiveRoot = archivePath.getParent().toAbsolutePath().normalize();
|
||||
String entryName = archiveEntry.getName();
|
||||
if (entryName == null || entryName.isBlank()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
entryName = entryName.replace("\\", "/");
|
||||
while (entryName.startsWith("/")) {
|
||||
entryName = entryName.substring(1);
|
||||
}
|
||||
Path path = archiveRoot.resolve(entryName).normalize();
|
||||
if (!path.startsWith(archiveRoot)) {
|
||||
log.warn("Skip unsafe archive entry path traversal: {}", archiveEntry.getName());
|
||||
return Optional.empty();
|
||||
}
|
||||
File file = path.toFile();
|
||||
long fileSize = 0L;
|
||||
FileUtils.createParentDirectories(file);
|
||||
|
||||
@@ -13,7 +13,10 @@ public class CommonUtils {
|
||||
* @return 文件名(带后缀)
|
||||
*/
|
||||
public static String trimFilePath(String filePath) {
|
||||
int lastSlashIndex = filePath.lastIndexOf(File.separator);
|
||||
if (filePath == null || filePath.isBlank()) {
|
||||
return "";
|
||||
}
|
||||
int lastSlashIndex = Math.max(filePath.lastIndexOf('/'), filePath.lastIndexOf('\\'));
|
||||
|
||||
String filename = filePath;
|
||||
if (lastSlashIndex != -1) {
|
||||
|
||||
Reference in New Issue
Block a user