mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-16 19:33:11 +02:00
zip and response issues (#5786)
This commit is contained in:
@@ -100,6 +100,11 @@ public class FileToPdf {
|
|||||||
while (entry != null) {
|
while (entry != null) {
|
||||||
Path filePath =
|
Path filePath =
|
||||||
tempUnzippedDir.getPath().resolve(sanitizeZipFilename(entry.getName()));
|
tempUnzippedDir.getPath().resolve(sanitizeZipFilename(entry.getName()));
|
||||||
|
Path normalizedTargetDir = tempUnzippedDir.getPath().toAbsolutePath().normalize();
|
||||||
|
Path normalizedFilePath = filePath.toAbsolutePath().normalize();
|
||||||
|
if (!normalizedFilePath.startsWith(normalizedTargetDir)) {
|
||||||
|
throw new IOException("Zip entry path escapes target directory: " + entry.getName());
|
||||||
|
}
|
||||||
if (!entry.isDirectory()) {
|
if (!entry.isDirectory()) {
|
||||||
Files.createDirectories(filePath.getParent());
|
Files.createDirectories(filePath.getParent());
|
||||||
if (entry.getName().toLowerCase(Locale.ROOT).endsWith(".html")
|
if (entry.getName().toLowerCase(Locale.ROOT).endsWith(".html")
|
||||||
|
|||||||
+2
-2
@@ -166,7 +166,7 @@ public class ConvertWebsiteToPDF {
|
|||||||
private String fetchRemoteHtml(String url) throws IOException, InterruptedException {
|
private String fetchRemoteHtml(String url) throws IOException, InterruptedException {
|
||||||
HttpClient client =
|
HttpClient client =
|
||||||
HttpClient.newBuilder()
|
HttpClient.newBuilder()
|
||||||
.followRedirects(HttpClient.Redirect.NORMAL)
|
.followRedirects(HttpClient.Redirect.NEVER)
|
||||||
.connectTimeout(Duration.ofSeconds(10))
|
.connectTimeout(Duration.ofSeconds(10))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@ public class ConvertWebsiteToPDF {
|
|||||||
HttpResponse<String> response =
|
HttpResponse<String> response =
|
||||||
client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
|
client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
|
||||||
|
|
||||||
if (response.statusCode() >= 400 || response.body() == null) {
|
if (response.statusCode() >= 300 || response.body() == null) {
|
||||||
throw ExceptionUtils.createIOException(
|
throw ExceptionUtils.createIOException(
|
||||||
"error.httpRequestFailed",
|
"error.httpRequestFailed",
|
||||||
"Failed to retrieve remote HTML. Status: {0}",
|
"Failed to retrieve remote HTML. Status: {0}",
|
||||||
|
|||||||
+13
-14
@@ -29,6 +29,8 @@ import jakarta.servlet.http.HttpServletResponse;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
import stirling.software.common.util.ExceptionUtils;
|
import stirling.software.common.util.ExceptionUtils;
|
||||||
import stirling.software.common.util.ExceptionUtils.*;
|
import stirling.software.common.util.ExceptionUtils.*;
|
||||||
import stirling.software.common.util.RegexPatternUtils;
|
import stirling.software.common.util.RegexPatternUtils;
|
||||||
@@ -866,21 +868,18 @@ public class GlobalExceptionHandler {
|
|||||||
response.setContentType("application/problem+json");
|
response.setContentType("application/problem+json");
|
||||||
response.setCharacterEncoding("UTF-8");
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
|
||||||
String errorJson =
|
// Use ObjectMapper to properly escape JSON values and prevent XSS
|
||||||
String.format(
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
"""
|
java.util.Map<String, Object> errorMap = new java.util.LinkedHashMap<>();
|
||||||
{
|
errorMap.put("type", "about:blank");
|
||||||
"type": "about:blank",
|
errorMap.put("title", "Not Acceptable");
|
||||||
"title": "Not Acceptable",
|
errorMap.put("status", 406);
|
||||||
"status": 406,
|
errorMap.put("detail", "The requested resource could not be returned in an acceptable format. Error responses are returned as JSON.");
|
||||||
"detail": "The requested resource could not be returned in an acceptable format. Error responses are returned as JSON.",
|
errorMap.put("instance", request.getRequestURI());
|
||||||
"instance": "%s",
|
errorMap.put("timestamp", Instant.now().toString());
|
||||||
"timestamp": "%s",
|
errorMap.put("hints", java.util.Arrays.asList("Error responses are always returned as application/json or application/problem+json", "Set Accept header to include application/json for proper error handling"));
|
||||||
"hints": ["Error responses are always returned as application/json or application/problem+json", "Set Accept header to include application/json for proper error handling"]
|
|
||||||
}
|
|
||||||
""",
|
|
||||||
request.getRequestURI(), Instant.now().toString());
|
|
||||||
|
|
||||||
|
String errorJson = mapper.writeValueAsString(errorMap);
|
||||||
response.getWriter().write(errorJson);
|
response.getWriter().write(errorJson);
|
||||||
response.getWriter().flush();
|
response.getWriter().flush();
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -298,7 +298,7 @@ public class ConvertWebsiteToPdfTest {
|
|||||||
HttpResponse<String> response = Mockito.mock();
|
HttpResponse<String> response = Mockito.mock();
|
||||||
|
|
||||||
httpClientStatic.when(HttpClient::newBuilder).thenReturn(builder);
|
httpClientStatic.when(HttpClient::newBuilder).thenReturn(builder);
|
||||||
when(builder.followRedirects(HttpClient.Redirect.NORMAL)).thenReturn(builder);
|
when(builder.followRedirects(HttpClient.Redirect.NEVER)).thenReturn(builder);
|
||||||
when(builder.connectTimeout(any(Duration.class))).thenReturn(builder);
|
when(builder.connectTimeout(any(Duration.class))).thenReturn(builder);
|
||||||
when(builder.build()).thenReturn(client);
|
when(builder.build()).thenReturn(client);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user