Skip to content

Commit

Permalink
Merge pull request #1926 from liuliaozhong/master
Browse files Browse the repository at this point in the history
fast_transfer_file API 分发文件,如果源文件中的文件名包含空格,会报错 #812
  • Loading branch information
wangyu096 authored Apr 7, 2023
2 parents 64a5b5f + 16ef356 commit 8d15ef3
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 60 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.tencent.bk.job.common.util;

import org.apache.commons.lang3.StringUtils;

import java.util.regex.Pattern;

/**
* 文件路径合法性校验工具类
*/
public class FilePathValidateUtil {
// 传统DOS正则表达式
private static final String CONVENTIONAL_DOS_PATH_REGEX = "(^[A-Za-z]:\\\\([^\\\\])(([^\\\\/:*?\"<>|])*\\\\?)*)|" +
"(^[A-Za-z]:[\\\\])";
// Linux路径正则表达式
private static final String LINUX_PATH_REGEX = "^/(((../)*|(./)*)|(\\.?[^.].*/{0,1}))+";

// 传统DOS Pattern
private static final Pattern CONVENTIONAL_DOS_PATH_PATTERN = Pattern.compile(CONVENTIONAL_DOS_PATH_REGEX);
// Linux路径Pattern
private static final Pattern LINUX_PATH_PATTERN = Pattern.compile(LINUX_PATH_REGEX);

/**
* 验证文件系统绝对路径的合法性
* @param path 绝对路径
* @return boolean true合法,false非法
*/
public static boolean validateFileSystemAbsolutePath(String path) {
if (StringUtils.isBlank(path)) {
return false;
}
if (isLinuxAbsolutePath(path)) {
return validateLinuxFileSystemAbsolutePath(path);
} else {
return validateWindowsFileSystemAbsolutePath(path);
}
}

/**
* 判断是否Linux绝对路径
*
* @param path 文件路径
* @return boolean
*/
private static boolean isLinuxAbsolutePath(String path) {
if (path.startsWith("/")) {
return true;
}
return false;
}

/**
* 1 传统DOS路径
* 标准的DOS路径可由以下三部分组成:
* 1)卷号或驱动器号,后跟卷分隔符(:)。
* 2)目录名称。目录分隔符用来分隔嵌套目录层次结构中的子目录。
* 3)文件名。目录分隔符用来分隔文件路径和文件名。
* @param path
* @return boolean
*/
private static boolean validateWindowsFileSystemAbsolutePath(String path) {
// 传统DOS
if (CONVENTIONAL_DOS_PATH_PATTERN.matcher(path).matches()) {
return true;
}
return false;
}

/**
* 文件或目录名,除了/以外,所有的字符都合法
*
* @param path
* @return boolean
*/
private static boolean validateLinuxFileSystemAbsolutePath(String path) {
if (LINUX_PATH_PATTERN.matcher(path).matches()) {
return true;
}
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.tencent.bk.job.common.util;

import org.junit.jupiter.api.Test;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

public class FilePathValidateUtilTest {
@Test
void testFileSystemAbsolutePath(){
// 传统DOS路径
assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\Documents\\abc.txt")).isTrue();
assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("c:\\Documents\\abc.txt")).isTrue();
assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\Documents\\嘉 abc.txt")).isTrue();
assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath(":\\abc.txt")).isFalse();
assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:")).isFalse();
assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\\\")).isFalse();
assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\")).isTrue();
assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\logs\\..\\access.log")).isTrue();
assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\.config\\conf")).isTrue();
assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("C:\\user\\abc>a")).isFalse();

// linux路径
assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("/data/test_2022-04-12.apk")).isTrue();
assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("/data/test_2022 04 12.apk")).isTrue();
assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("/")).isTrue();
assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("/tmp/")).isTrue();
assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("/tmp/.conf/abc")).isTrue();
assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("/tmp/test/../test.log")).isTrue();
assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("data/test_2022-04-12.apk")).isFalse();
assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("///")).isTrue(); // 根目录
assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("/tmp////")).isTrue(); // /tmp/
assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("/tmp//test/")).isTrue();// /tmp/test/
assertThat(FilePathValidateUtil.validateFileSystemAbsolutePath("///")).isTrue();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import com.tencent.bk.job.common.model.ValidateResult;
import com.tencent.bk.job.common.service.AppScopeMappingService;
import com.tencent.bk.job.common.util.ArrayUtil;
import com.tencent.bk.job.common.util.FilePathValidateUtil;
import com.tencent.bk.job.common.util.date.DateUtils;
import com.tencent.bk.job.common.web.metrics.CustomTimed;
import com.tencent.bk.job.execute.api.esb.v2.EsbFastPushFileResource;
Expand Down Expand Up @@ -67,8 +68,6 @@
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@RestController
@Slf4j
Expand Down Expand Up @@ -126,7 +125,7 @@ public EsbResp<EsbJobExecuteDTO> fastPushFile(EsbFastPushFileRequest request) {
}

private ValidateResult checkFastPushFileRequest(EsbFastPushFileRequest request) {
if (!validateFileSystemPath(request.getTargetPath())) {
if (!FilePathValidateUtil.validateFileSystemAbsolutePath(request.getTargetPath())) {
log.warn("Fast transfer file, target path is invalid!path={}", request.getTargetPath());
return ValidateResult.fail(ErrorCode.MISSING_OR_ILLEGAL_PARAM_WITH_PARAM_NAME, "file_target_path");
}
Expand Down Expand Up @@ -164,7 +163,7 @@ private ValidateResult validateFileSource(EsbFastPushFileRequest request) {
return ValidateResult.fail(ErrorCode.MISSING_PARAM_WITH_PARAM_NAME, "file_source.files");
}
for (String file : files) {
if (!validateFileSystemPath(file)) {
if (!FilePathValidateUtil.validateFileSystemAbsolutePath(file)) {
log.warn("Invalid path:{}", file);
return ValidateResult.fail(ErrorCode.ILLEGAL_PARAM_WITH_PARAM_NAME, "file_source.files");
}
Expand All @@ -185,32 +184,6 @@ private ValidateResult validateFileSource(EsbFastPushFileRequest request) {
return ValidateResult.pass();
}

private boolean validateFileSystemPath(String path) {
if (StringUtils.isBlank(path)) {
return false;
}
if (path.indexOf(' ') != -1) {
return false;
}
Pattern p1 = Pattern.compile("(//|\\\\)+");
Matcher m1 = p1.matcher(path);
if (m1.matches()) {
return false;
}

Pattern p2 = Pattern.compile("^[a-zA-Z]:(/|\\\\).*");//windows
Matcher m2 = p2.matcher(path);

if (!m2.matches()) { //非windows
if (path.charAt(0) == '/') {
return !path.contains("\\\\");
} else {
return false;
}
}
return true;
}

private TaskInstanceDTO buildFastFileTaskInstance(EsbFastPushFileRequest request) {
TaskInstanceDTO taskInstance = new TaskInstanceDTO();
taskInstance.setType(TaskTypeEnum.FILE.getValue());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import com.tencent.bk.job.common.model.InternalResponse;
import com.tencent.bk.job.common.model.ValidateResult;
import com.tencent.bk.job.common.service.AppScopeMappingService;
import com.tencent.bk.job.common.util.FilePathValidateUtil;
import com.tencent.bk.job.common.util.date.DateUtils;
import com.tencent.bk.job.common.web.metrics.CustomTimed;
import com.tencent.bk.job.execute.client.FileSourceResourceClient;
Expand Down Expand Up @@ -68,8 +69,6 @@
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@RestController
@Slf4j
Expand Down Expand Up @@ -155,7 +154,7 @@ private ValidateResult checkFileSource(EsbFileSourceV3DTO fileSource) {
for (String file : files) {
if ((fileType == null
|| TaskFileTypeEnum.SERVER.getType() == fileType)
&& !validateFileSystemPath(file)) {
&& !FilePathValidateUtil.validateFileSystemAbsolutePath(file)) {
log.warn("Invalid path:{}", file);
return ValidateResult.fail(ErrorCode.ILLEGAL_PARAM_WITH_PARAM_NAME, "file_source.file_list");
}
Expand Down Expand Up @@ -189,7 +188,7 @@ private ValidateResult checkFileSource(EsbFileSourceV3DTO fileSource) {
}

private ValidateResult checkFastTransferFileRequest(EsbFastTransferFileV3Request request) {
if (!validateFileSystemPath(request.getTargetPath())) {
if (!FilePathValidateUtil.validateFileSystemAbsolutePath(request.getTargetPath())) {
log.warn("Fast transfer file, target path is invalid!path={}", request.getTargetPath());
return ValidateResult.fail(ErrorCode.MISSING_OR_ILLEGAL_PARAM_WITH_PARAM_NAME, "file_target_path");
}
Expand All @@ -216,32 +215,6 @@ private ValidateResult checkFastTransferFileRequest(EsbFastTransferFileV3Request
return ValidateResult.pass();
}

private boolean validateFileSystemPath(String path) {
if (StringUtils.isBlank(path)) {
return false;
}
if (path.indexOf(' ') != -1) {
return false;
}
Pattern p1 = Pattern.compile("(//|\\\\)+");
Matcher m1 = p1.matcher(path);
if (m1.matches()) {
return false;
}

Pattern p2 = Pattern.compile("^[a-zA-Z]:(/|\\\\).*");//windows
Matcher m2 = p2.matcher(path);

if (!m2.matches()) { //非windows
if (path.charAt(0) == '/') {
return !path.contains("\\\\");
} else {
return false;
}
}
return true;
}

private TaskInstanceDTO buildFastFileTaskInstance(EsbFastTransferFileV3Request request) {
TaskInstanceDTO taskInstance = new TaskInstanceDTO();
taskInstance.setType(TaskTypeEnum.FILE.getValue());
Expand Down

0 comments on commit 8d15ef3

Please sign in to comment.