Skip to content

Commit

Permalink
fix: don't serve directories as static files (#11072)
Browse files Browse the repository at this point in the history
Add check to the resource to see
if it is a directory and do not serve
if this is the case.

Fixe #11047
  • Loading branch information
caalador authored May 28, 2021
1 parent 2c07bd3 commit 7bf140b
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,17 @@

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;

Expand Down Expand Up @@ -107,6 +115,10 @@ public boolean isStaticResourceRequest(HttpServletRequest request) {
}
resource = getStaticResource(requestFilename);

if (resource != null && resourceIsDirectory(resource)) {
return false;
}

if (resource == null && shouldFixIncorrectWebjarPaths()
&& isIncorrectWebjarPath(requestFilename)) {
// Flow issue #4601
Expand All @@ -116,6 +128,38 @@ && isIncorrectWebjarPath(requestFilename)) {
return resource != null;
}

private boolean resourceIsDirectory(URL resource) {
if (resource.getPath().endsWith("/")) {
return true;
}
URI resourceURI = null;
try {
resourceURI = resource.toURI();
} catch (URISyntaxException e) {
getLogger().debug("Syntax error in uri from getStaticResource", e);
// Return false as we couldn't determine if the resource is a
// directory.
return false;
}

if (resource.getProtocol().equals("jar")) {
try (FileSystem fileSystem = FileSystems.newFileSystem(resourceURI,
Collections.emptyMap())) {
// Get the file path inside the jar.
final Path path = fileSystem.getPath(resource.getPath()
.substring(resource.getPath().lastIndexOf("!") + 1));

return Files.isDirectory(path);
} catch (IOException e) {
getLogger().debug("failed to read zip file", e);
}
}

// If not a jar check if a file path direcotry.
return resource.getProtocol().equals("file")
&& Files.isDirectory(Paths.get(resourceURI));
}

@Override
public boolean serveStaticResource(HttpServletRequest request,
HttpServletResponse response) throws IOException {
Expand Down Expand Up @@ -184,13 +228,12 @@ && isIncorrectWebjarPath(filenameWithPath)) {
* resource). The {@code null} return value means that the resource won't be
* exposed as a Web resource even if it's a resource available via
* {@link ServletContext}.
*
*
* @param path
* the path for the resource
* @return the resource located at the named path to expose it via Web, or
* {@code null} if there is no resource at that path or it should
* not be exposed
*
* @see VaadinService#getStaticResource(String)
*/
protected URL getStaticResource(String path) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,32 @@

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.Matchers;
import org.mockito.Mockito;

Expand Down Expand Up @@ -255,6 +261,68 @@ public void isNotResourceRequest() throws Exception {
Assert.assertFalse(fileServer.isStaticResourceRequest(request));
}

@Test
public void directoryIsNotResourceRequest() throws Exception {
final TemporaryFolder folder = TemporaryFolder.builder().build();
folder.create();

setupRequestURI("", "", "/frontend");
// generate URL so it is not ending with / so that we test the correct
// method
String rootAbsolutePath = folder.getRoot().getAbsolutePath()
.replaceAll("\\\\", "/");
if (rootAbsolutePath.endsWith("/")) {
rootAbsolutePath = rootAbsolutePath.substring(0,
rootAbsolutePath.length() - 1);
}
final URL folderPath = new URL("file:///" + rootAbsolutePath);

Mockito.when(servletService.getStaticResource("/frontend"))
.thenReturn(folderPath);
Assert.assertFalse("Folder on disk should not be a static resource.",
fileServer.isStaticResourceRequest(request));

// Test any path ending with / to be seen as a directory
setupRequestURI("", "", "/fake");
Mockito.when(servletService.getStaticResource("/fake"))
.thenReturn(new URL("file:///fake/"));
Assert.assertFalse(
"Fake should not check the file system nor be a static resource.",
fileServer.isStaticResourceRequest(request));

File archiveFile = new File(folder.getRoot(), "fake.jar");
archiveFile.createNewFile();
Path tempArchive = archiveFile.toPath();

try (ZipOutputStream zipOutputStream = new ZipOutputStream(
Files.newOutputStream(tempArchive))) {
// Create a file to the zip
zipOutputStream.putNextEntry(new ZipEntry("/file"));
zipOutputStream.closeEntry();
// Create a directory to the zip
zipOutputStream.putNextEntry(new ZipEntry("frontend/"));
zipOutputStream.closeEntry();
}
setupRequestURI("", "", "/frontend/.");
Mockito.when(servletService.getStaticResource("/frontend/."))
.thenReturn(new URL("jar:file:///"
+ tempArchive.toString().replaceAll("\\\\", "/")
+ "!/frontend"));
Assert.assertFalse(
"Folder 'frontend' in jar should not be a static resource.",
fileServer.isStaticResourceRequest(request));
setupRequestURI("", "", "/file.txt");
Mockito.when(servletService.getStaticResource("/file.txt"))
.thenReturn(new URL("jar:file:///"
+ tempArchive.toString().replaceAll("\\\\", "/")
+ "!/file.txt"));
Assert.assertTrue(
"File 'file.txt' inside jar should be a static resource.",
fileServer.isStaticResourceRequest(request));

folder.delete();
}

@Test
public void isNotResourceRequestWithContextPath() throws Exception {
setupRequestURI("/context", "", "/");
Expand Down

0 comments on commit 7bf140b

Please sign in to comment.