From 7bc70ced4798e9df1613e5b2761cb30e5817b344 Mon Sep 17 00:00:00 2001 From: gkchp Date: Thu, 28 Jul 2022 15:13:19 +0800 Subject: [PATCH 1/2] =?UTF-8?q?Windows=20=E5=85=BC=E5=AE=B9=20file:path=20?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E7=9A=84url?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/controller/OnlinePreviewController.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/server/src/main/java/cn/keking/web/controller/OnlinePreviewController.java b/server/src/main/java/cn/keking/web/controller/OnlinePreviewController.java index 0855dca05..d79498c1d 100644 --- a/server/src/main/java/cn/keking/web/controller/OnlinePreviewController.java +++ b/server/src/main/java/cn/keking/web/controller/OnlinePreviewController.java @@ -11,6 +11,7 @@ import io.mola.galimatias.GalimatiasParseException; import jodd.io.NetUtil; import org.apache.commons.codec.binary.Base64; +import org.artofsolving.jodconverter.util.PlatformUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; @@ -38,6 +39,8 @@ public class OnlinePreviewController { public static final String BASE64_DECODE_ERROR_MSG = "Base64解码失败,请检查你的 %s 是否采用 Base64 + urlEncode 双重编码了!"; + public static final String FILE_SCHEME = "file:"; + public static final String FILE_SCHEME_FULL = "file:///"; private final Logger logger = LoggerFactory.getLogger(OnlinePreviewController.class); private final FilePreviewFactory previewFactory; @@ -61,6 +64,11 @@ public String onlinePreview(String url, Model model, HttpServletRequest req) { String errorMsg = String.format(BASE64_DECODE_ERROR_MSG, "url"); return otherFilePreview.notSupportedFile(model, errorMsg); } + if (PlatformUtils.isWindows()) { + if (fileUrl.startsWith(FILE_SCHEME) && !fileUrl.startsWith(FILE_SCHEME + "/")) { + fileUrl = FILE_SCHEME_FULL + fileUrl.substring(FILE_SCHEME.length()); + } + } FileAttribute fileAttribute = fileHandlerService.getFileAttribute(fileUrl, req); model.addAttribute("file", fileAttribute); FilePreview filePreview = previewFactory.get(fileAttribute); @@ -111,8 +119,8 @@ public void getCorsFile(String urlPath, HttpServletResponse response) { logger.error(String.format(BASE64_DECODE_ERROR_MSG, urlPath),ex); return; } - if (urlPath.toLowerCase().startsWith("file:") || urlPath.toLowerCase().startsWith("file%3") - || !urlPath.toLowerCase().startsWith("http")) { + if (urlPath.toLowerCase().startsWith(FILE_SCHEME) || urlPath.toLowerCase().startsWith("file%3") + || !urlPath.toLowerCase().startsWith("http")) { logger.info("读取跨域文件异常,可能存在非法访问,urlPath:{}", urlPath); return; } From 678f695823341a8ec340ca6459c28dc8640ce59d Mon Sep 17 00:00:00 2001 From: gkchp Date: Thu, 17 Nov 2022 14:28:14 +0800 Subject: [PATCH 2/2] =?UTF-8?q?#374=20Windows=20=E4=B8=8B=E5=85=BC?= =?UTF-8?q?=E5=AE=B9=20file:path=20=E6=8A=BD=E8=B1=A1=E5=87=BA=E6=96=B9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/keking/service/FileHandlerService.java | 4 ++++ .../main/java/cn/keking/utils/WebUtils.java | 18 ++++++++++++++++++ .../controller/OnlinePreviewController.java | 9 +-------- .../cn/keking/web/filter/TrustDirFilter.java | 3 +++ 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/server/src/main/java/cn/keking/service/FileHandlerService.java b/server/src/main/java/cn/keking/service/FileHandlerService.java index 272a7a3c0..9562c4cf5 100644 --- a/server/src/main/java/cn/keking/service/FileHandlerService.java +++ b/server/src/main/java/cn/keking/service/FileHandlerService.java @@ -14,6 +14,7 @@ import org.apache.pdfbox.rendering.ImageType; import org.apache.pdfbox.rendering.PDFRenderer; import org.apache.pdfbox.tools.imageio.ImageIOUtil; +import org.artofsolving.jodconverter.util.PlatformUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; @@ -276,6 +277,9 @@ public FileAttribute getFileAttribute(String url, HttpServletRequest req) { attribute.setType(type); attribute.setName(fileName); attribute.setSuffix(suffix); + if (PlatformUtils.isWindows()) { + url = WebUtils.enrichFileSchemeUrl(url); + } url = WebUtils.encodeUrlFileName(url); attribute.setUrl(url); if (req != null) { diff --git a/server/src/main/java/cn/keking/utils/WebUtils.java b/server/src/main/java/cn/keking/utils/WebUtils.java index 38472eaf0..47a1acc10 100644 --- a/server/src/main/java/cn/keking/utils/WebUtils.java +++ b/server/src/main/java/cn/keking/utils/WebUtils.java @@ -11,6 +11,7 @@ import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.HashMap; +import java.util.Locale; import java.util.Map; /** @@ -18,6 +19,8 @@ * create : 2020-12-27 1:30 上午 **/ public class WebUtils { + public static final String FILE_SCHEME = "file:"; + public static final String FILE_SCHEME_FULL = "file:///"; /** * 获取标准的URL @@ -185,4 +188,19 @@ public static String getHost(String urlStr) { } return null; } + + /** + * 将文件链接中的 file: 替换为 file:///
+ * 因为在 Windows 系统中,io.mola.galimatias.URL.parse() 方法在解析 file: 时会出错
+ * 详细问题描述 + * + * @param fileUrl 文件 url + * @return 处理后的 url + */ + public static String enrichFileSchemeUrl(String fileUrl) { + if (fileUrl.toLowerCase(Locale.ROOT).startsWith(FILE_SCHEME) && !fileUrl.toLowerCase(Locale.ROOT).startsWith(FILE_SCHEME + "/")) { + return FILE_SCHEME_FULL + fileUrl.substring(FILE_SCHEME.length()); + } + return fileUrl; + } } diff --git a/server/src/main/java/cn/keking/web/controller/OnlinePreviewController.java b/server/src/main/java/cn/keking/web/controller/OnlinePreviewController.java index d79498c1d..705f48e1f 100644 --- a/server/src/main/java/cn/keking/web/controller/OnlinePreviewController.java +++ b/server/src/main/java/cn/keking/web/controller/OnlinePreviewController.java @@ -11,7 +11,6 @@ import io.mola.galimatias.GalimatiasParseException; import jodd.io.NetUtil; import org.apache.commons.codec.binary.Base64; -import org.artofsolving.jodconverter.util.PlatformUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; @@ -31,6 +30,7 @@ import java.util.List; import static cn.keking.service.FilePreview.PICTURE_FILE_PREVIEW_PAGE; +import static cn.keking.utils.WebUtils.FILE_SCHEME; /** * @author yudian-it @@ -39,8 +39,6 @@ public class OnlinePreviewController { public static final String BASE64_DECODE_ERROR_MSG = "Base64解码失败,请检查你的 %s 是否采用 Base64 + urlEncode 双重编码了!"; - public static final String FILE_SCHEME = "file:"; - public static final String FILE_SCHEME_FULL = "file:///"; private final Logger logger = LoggerFactory.getLogger(OnlinePreviewController.class); private final FilePreviewFactory previewFactory; @@ -64,11 +62,6 @@ public String onlinePreview(String url, Model model, HttpServletRequest req) { String errorMsg = String.format(BASE64_DECODE_ERROR_MSG, "url"); return otherFilePreview.notSupportedFile(model, errorMsg); } - if (PlatformUtils.isWindows()) { - if (fileUrl.startsWith(FILE_SCHEME) && !fileUrl.startsWith(FILE_SCHEME + "/")) { - fileUrl = FILE_SCHEME_FULL + fileUrl.substring(FILE_SCHEME.length()); - } - } FileAttribute fileAttribute = fileHandlerService.getFileAttribute(fileUrl, req); model.addAttribute("file", fileAttribute); FilePreview filePreview = previewFactory.get(fileAttribute); diff --git a/server/src/main/java/cn/keking/web/filter/TrustDirFilter.java b/server/src/main/java/cn/keking/web/filter/TrustDirFilter.java index ec0cee402..cae41da3b 100644 --- a/server/src/main/java/cn/keking/web/filter/TrustDirFilter.java +++ b/server/src/main/java/cn/keking/web/filter/TrustDirFilter.java @@ -56,6 +56,9 @@ public void destroy() { private boolean allowPreview(String urlPath) { try { + if (PlatformUtils.isWindows()) { + urlPath = WebUtils.enrichFileSchemeUrl(urlPath); + } URL url = WebUtils.normalizedURL(urlPath); if ("file".equals(url.getProtocol().toLowerCase(Locale.ROOT))) { String filePath = URLDecoder.decode(url.getPath(), StandardCharsets.UTF_8.name());