diff --git a/src/main/java/at/ac/uibk/gitsearch/service/SearchService.java b/src/main/java/at/ac/uibk/gitsearch/service/SearchService.java index 2b278ab508babb23919d51fd81995e777bbf1e2b..f2cb9990eaa0e7a5e773bdd76d019db7d2d839d5 100644 --- a/src/main/java/at/ac/uibk/gitsearch/service/SearchService.java +++ b/src/main/java/at/ac/uibk/gitsearch/service/SearchService.java @@ -1,11 +1,5 @@ package at.ac.uibk.gitsearch.service; -import at.ac.uibk.gitsearch.repository.gitlab.GitLabRepository; -import at.ac.uibk.gitsearch.repository.search.MetaDataRepository; -import at.ac.uibk.gitsearch.security.AuthoritiesConstants.AuthoritiesConstantEnum; -import at.ac.uibk.gitsearch.security.jwt.TokenProvider; -import at.ac.uibk.gitsearch.security.jwt.TokenProvider.GitLabAccessInfo; -import at.ac.uibk.gitsearch.service.dto.AutoCompleteEntry; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -25,6 +19,7 @@ import java.util.stream.Stream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; + import org.apache.commons.lang3.StringUtils; import org.codeability.sharing.plugins.api.search.SearchInputDTO; import org.codeability.sharing.plugins.api.search.SearchInputMetadataDTO; @@ -39,6 +34,13 @@ import org.springframework.security.core.userdetails.User; import org.springframework.stereotype.Service; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; +import at.ac.uibk.gitsearch.repository.gitlab.GitLabRepository; +import at.ac.uibk.gitsearch.repository.search.MetaDataRepository; +import at.ac.uibk.gitsearch.security.AuthoritiesConstants.AuthoritiesConstantEnum; +import at.ac.uibk.gitsearch.security.jwt.TokenProvider; +import at.ac.uibk.gitsearch.security.jwt.TokenProvider.GitLabAccessInfo; +import at.ac.uibk.gitsearch.service.dto.AutoCompleteEntry; + /** * Service for exercise/course search results * <p> diff --git a/src/main/java/at/ac/uibk/gitsearch/service/ShoppingBasketService.java b/src/main/java/at/ac/uibk/gitsearch/service/ShoppingBasketService.java index 4d984f1a489a3bac3245153ee00d5e4446324abe..14e892b157fb91554a412c812f7c2b059f3ca3bd 100644 --- a/src/main/java/at/ac/uibk/gitsearch/service/ShoppingBasketService.java +++ b/src/main/java/at/ac/uibk/gitsearch/service/ShoppingBasketService.java @@ -1,15 +1,5 @@ package at.ac.uibk.gitsearch.service; -import at.ac.uibk.gitsearch.repository.gitlab.GitLabRepository; -import at.ac.uibk.gitsearch.security.jwt.TokenProvider.GitLabAccessInfo; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; import java.io.IOException; import java.io.InputStream; import java.io.PipedInputStream; @@ -22,6 +12,7 @@ import java.util.UUID; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; + import org.apache.commons.lang3.StringUtils; import org.checkerframework.checker.nullness.qual.Nullable; import org.codeability.sharing.plugins.api.ShoppingBasket; @@ -33,8 +24,21 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.util.AntPathMatcher; import org.springframework.util.StreamUtils; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +import at.ac.uibk.gitsearch.repository.gitlab.GitLabRepository; +import at.ac.uibk.gitsearch.security.jwt.TokenProvider.GitLabAccessInfo; + /** * Service for exercise/course search results * <p> @@ -336,12 +340,15 @@ public class ShoppingBasketService { while (zipInEntry != null) { String fileName = zipInEntry.getName(); + boolean isDirectory = zipInEntry.isDirectory(); if (fileName.startsWith(prefix)) { String newName = fileName.substring(prefix.length()); String fileWithSubPath = getWithoutPathPrefix(newName, exerciseFolderPath); if (fileWithSubPath != null) { // process this file newName = fileWithSubPath; - if (!StringUtils.isEmpty(newName) && !filterOut(newName, filterOut)) { + if (!StringUtils.isEmpty(newName) + && !filterOut(newName, filterOut, + isDirectory)) { ZipEntry zipOutEntry = new ZipEntry(newName); if (zipInEntry.isDirectory()) { log.debug("ignoring directory {}", fileName); @@ -394,11 +401,43 @@ public class ShoppingBasketService { return null; } - private boolean filterOut(String fileName, String[] filterOut) { + /** + * tests filters against fileName. Protected for test purposes. Do not use + * outside this methd + * + * @param filePath + * the filename (with folder path) to check + * @param filterOut + * the list of filters + * @param isDirectory + * check for directories + * @return + */ + protected static boolean filterOut(String filePath, String[] filterOut, + boolean isDirectory) { + if (filePath == null) + return false; + AntPathMatcher antPathMatcher = new AntPathMatcher(); for (String filter : filterOut) { - if (fileName.startsWith(filter)) { - return fileName.length() == filter.length() || fileName.charAt(filter.length()) == '/'; - } + if (filter == null) { + log.warn("filter should never be null!"); + continue; + } + String filePathToTest = filePath; + // just adapt current path to pattern + if (filePathToTest + .startsWith(AntPathMatcher.DEFAULT_PATH_SEPARATOR) + && !filter + .startsWith(AntPathMatcher.DEFAULT_PATH_SEPARATOR)) + filePathToTest = filePathToTest.substring(1); + if (!filePathToTest + .startsWith(AntPathMatcher.DEFAULT_PATH_SEPARATOR) + && filter.startsWith(AntPathMatcher.DEFAULT_PATH_SEPARATOR)) + filePathToTest = AntPathMatcher.DEFAULT_PATH_SEPARATOR + + filePathToTest; + if (antPathMatcher.match(filter, filePathToTest)) { + return true; + } } return false; } diff --git a/src/test/java/at/ac/uibk/gitsearch/service/ShoppingBasketServiceTest.java b/src/test/java/at/ac/uibk/gitsearch/service/ShoppingBasketServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c28e9e3057a26c2ad122165061e3ddae6116ebe6 --- /dev/null +++ b/src/test/java/at/ac/uibk/gitsearch/service/ShoppingBasketServiceTest.java @@ -0,0 +1,61 @@ +package at.ac.uibk.gitsearch.service; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.jupiter.api.Test; + +public class ShoppingBasketServiceTest { + + @Test + public void simpleFilterOutTests() { + assertFalse(ShoppingBasketService.filterOut("someFile.txt", + new String[]{}, false)); + assertFalse(ShoppingBasketService.filterOut("someFile.txt", + new String[]{"some"}, false)); + assertTrue(ShoppingBasketService.filterOut("someFile.txt", + new String[]{"some*"}, false)); + assertFalse(ShoppingBasketService.filterOut("someFile.txt", + new String[]{"some*.pdf"}, false)); + assertTrue(ShoppingBasketService.filterOut("someFile.txt", + new String[]{"some*.txt"}, false)); + } + @Test + public void filterOutTestsWithLeadingRoot() { + assertFalse(ShoppingBasketService.filterOut("/someFile.txt", + new String[]{}, false)); + assertFalse(ShoppingBasketService.filterOut("/someFile.txt", + new String[]{"**/some"}, false)); + assertTrue(ShoppingBasketService.filterOut("/someFile.txt", + new String[]{"**/some*"}, false)); + assertFalse(ShoppingBasketService.filterOut("/someFile.txt", + new String[]{"**/some*.pdf"}, false)); + assertTrue(ShoppingBasketService.filterOut("/someFile.txt", + new String[]{"**/some*.txt"}, false)); + } + + @Test + public void filterOutTestsWithDirectories() { + assertFalse(ShoppingBasketService.filterOut("someDir", new String[]{}, + true)); + assertFalse(ShoppingBasketService.filterOut("someDir", + new String[]{"some/"}, true)); + assertTrue(ShoppingBasketService.filterOut("someDir", + new String[]{"/some*"}, true)); + assertTrue(ShoppingBasketService.filterOut("someDir", + new String[]{"some*"}, true)); + assertTrue(ShoppingBasketService.filterOut("someDir/", + new String[]{"some*/"}, true)); + assertFalse(ShoppingBasketService.filterOut("someDir", + new String[]{"*/some/"}, true)); + assertFalse(ShoppingBasketService.filterOut("parent/someDir", + new String[]{"*/some/"}, true)); + assertFalse(ShoppingBasketService.filterOut("parent/someDir", + new String[]{"someDir/"}, true)); + assertTrue(ShoppingBasketService.filterOut("parent/someDir", + new String[]{"**/someDir"}, true)); + assertTrue(ShoppingBasketService.filterOut("parent/someDir", + new String[]{"**/some*"}, true)); + + } +}