diff --git a/README.md b/README.md index 340b1e855..ade292403 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,12 @@ includes integrated support for internationalization. For more information please visit the [website](https://pebbletemplates.io). +# Breaking changes in version 4.1.x + +- If you do not provide a custom Loader, Pebble will now use only a `ClasspathLoader` by default, same as the spring autoconfiguration. + Before that, it would have used an instance of the `DelegatingLoader` which consists of a `ClasspathLoader` and a `FileLoader` behind the scenes to find your templates. +- Modify the `FileLoader` to use a mandatory sandboxed base directory parameter. + # Breaking changes in version 4.0.x - Use one of the following artifactId according to the spring boot version that you are using diff --git a/docs/pom.xml b/docs/pom.xml index a29d31ab7..035100085 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -5,7 +5,7 @@ io.pebbletemplates pebble-project - 4.0.1-SNAPSHOT + 4.1.0-SNAPSHOT docs diff --git a/docs/src/orchid/resources/changelog/v4_0_1.md b/docs/src/orchid/resources/changelog/v4_0_1.md deleted file mode 100644 index 23d688929..000000000 --- a/docs/src/orchid/resources/changelog/v4_0_1.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -version: '4.0.1' ---- - -- Use a default existing format of `yyyy-MM-dd'T'HH:mm:ssZ` when using date filter with a string (#677) -- NaN mus return false instead of throwing an exception (#695) -- Look for exact method / field match when doing reflection. Look for method get/is/has if none match -- Update some dependencies (#709) diff --git a/docs/src/orchid/resources/changelog/v4_1_0.md b/docs/src/orchid/resources/changelog/v4_1_0.md new file mode 100644 index 000000000..4d168c1a2 --- /dev/null +++ b/docs/src/orchid/resources/changelog/v4_1_0.md @@ -0,0 +1,17 @@ +--- +version: '4.1.0' +--- + +# BREAKING CHANGES +- Modify the `FileLoader` to use a mandatory sandboxed base directory parameter. (#715) +- If you do not provide a custom Loader, Pebble will now use only a `ClasspathLoader` by default, same as the spring autoconfiguration. (#715) + Before that, it would have used an instance of the `DelegatingLoader` which consists of a `ClasspathLoader` and a `FileLoader` behind the scenes to find your templates. + +# New Features +- Use a default existing format of `yyyy-MM-dd'T'HH:mm:ssZ` when using date filter with a string (#677) +- Look for exact method / field match when doing reflection. Look for method get/is/has if none match +- Update some dependencies (#709) + +# Bug Fixes +- NaN must return false instead of throwing an exception (#695) +- [CVE-2025-1686](https://nvd.nist.gov/vuln/detail/CVE-2025-1686). diff --git a/docs/src/orchid/resources/wiki/guide/installation.md b/docs/src/orchid/resources/wiki/guide/installation.md index ecfcd7b7b..3556702cf 100644 --- a/docs/src/orchid/resources/wiki/guide/installation.md +++ b/docs/src/orchid/resources/wiki/guide/installation.md @@ -61,18 +61,17 @@ finding your templates. Pebble ships with the following loader implementations: +- `DelegatingLoader`: Delegates responsibility to a collection of children loaders. - `ClasspathLoader`: Uses a classloader to search the current classpath. -- `FileLoader`: Finds templates using a filesystem path. +- `FileLoader`: Finds templates using a filesystem path. Must provide a mandatory absolute base path. - `ServletLoader`: Uses a servlet context to find the template. This is the recommended loader for use within an application server but is not enabled by default. - `Servlet5Loader`: Same as `ServletLoader`, but for Jakarta Servlet 5.0 or newer. -- `StringLoader`: Considers the name of the template to be the contents of the template. -- `DelegatingLoader`: Delegates responsibility to a collection of children loaders. - `MemoryLoader`: Loader that supports inheritance and doesn't require a filesystem. This is useful for applications +- `StringLoader`: Considers the name of the template to be the contents of the template. Should not be used in a production environment. It is primarily for testing and debugging. Many tags may not work when using this loader, such as "extends", "imports", etc. that retrieve templates from a database for example. -If you do not provide a custom Loader, Pebble will use an instance of the `DelegatingLoader` by default. -This delegating loader will use a `ClasspathLoader` and a `FileLoader` behind the scenes to find your templates. +If you do not provide a custom Loader, Pebble will use an instance of the `ClasspathLoader` by default. ## Pebble Engine Settings @@ -85,7 +84,7 @@ All the settings are set during the construction of the `PebbleEngine` object. | `tagCache` | An implementation of a ConcurrentMap cache that the Pebble engine will use for {{ anchor('cache tag', 'cache') }}. | Default implementation is `ConcurrentMapTagCache` and another implementation based on Caffeine is available (`CaffeineTagCache`) | | `defaultLocale` | The default locale which will be passed to each compiled template. The templates then use this locale for functions such as i18n, etc. A template can also be given a unique locale during evaluation. | `Locale.getDefault()` | | `executorService` | An `ExecutorService` that allows the usage of some advanced multithreading features, such as the `parallel` tag. | `null` | -| `loader` | An implementation of the `Loader` interface which is used to find templates. | An implementation of the `DelegatingLoader` which uses a `ClasspathLoader` and a `FileLoader` behind the scenes. | +| `loader` | An implementation of the `Loader` interface which is used to find templates. | An implementation of the `ClasspathLoader` | | `strictVariables` | If set to true, Pebble will throw an exception if you try to access a variable or attribute that does not exist (or an attribute of a null variable). If set to false, your template will treat non-existing variables/attributes as null without ever skipping a beat. | `false` | | `methodAccessValidator` | Pebble provides two implementations. NoOpMethodAccessValidator which do nothing and BlacklistMethodAccessValidator which checks that the method being called is not blacklisted. | `BlacklistMethodAccessValidator` | `literalDecimalTreatedAsInteger` | option for treating literal decimals as `int`. Otherwise it is `long`. | `false` | diff --git a/pebble-spring/pebble-legacy-spring-boot-starter/pom.xml b/pebble-spring/pebble-legacy-spring-boot-starter/pom.xml index 6785ccbd9..ebf7be1a7 100644 --- a/pebble-spring/pebble-legacy-spring-boot-starter/pom.xml +++ b/pebble-spring/pebble-legacy-spring-boot-starter/pom.xml @@ -4,7 +4,7 @@ pebble-spring io.pebbletemplates - 4.0.1-SNAPSHOT + 4.1.0-SNAPSHOT pebble-legacy-spring-boot-starter diff --git a/pebble-spring/pebble-spring-boot-starter/pom.xml b/pebble-spring/pebble-spring-boot-starter/pom.xml index a6f3b5498..5ff60a036 100644 --- a/pebble-spring/pebble-spring-boot-starter/pom.xml +++ b/pebble-spring/pebble-spring-boot-starter/pom.xml @@ -4,7 +4,7 @@ pebble-spring io.pebbletemplates - 4.0.1-SNAPSHOT + 4.1.0-SNAPSHOT pebble-spring-boot-starter diff --git a/pebble-spring/pebble-spring6/pom.xml b/pebble-spring/pebble-spring6/pom.xml index ab0f8e8fa..60cae355b 100644 --- a/pebble-spring/pebble-spring6/pom.xml +++ b/pebble-spring/pebble-spring6/pom.xml @@ -4,7 +4,7 @@ pebble-spring io.pebbletemplates - 4.0.1-SNAPSHOT + 4.1.0-SNAPSHOT pebble-spring6 diff --git a/pebble-spring/pebble-spring7/pom.xml b/pebble-spring/pebble-spring7/pom.xml index d16fbbe0b..afe535c94 100644 --- a/pebble-spring/pebble-spring7/pom.xml +++ b/pebble-spring/pebble-spring7/pom.xml @@ -4,7 +4,7 @@ pebble-spring io.pebbletemplates - 4.0.1-SNAPSHOT + 4.1.0-SNAPSHOT pebble-spring7 diff --git a/pebble-spring/pom.xml b/pebble-spring/pom.xml index 26e24394c..7acdc37f0 100644 --- a/pebble-spring/pom.xml +++ b/pebble-spring/pom.xml @@ -4,7 +4,7 @@ io.pebbletemplates pebble-project - 4.0.1-SNAPSHOT + 4.1.0-SNAPSHOT pebble-spring diff --git a/pebble/pom.xml b/pebble/pom.xml index 392653f32..2b0892902 100644 --- a/pebble/pom.xml +++ b/pebble/pom.xml @@ -3,7 +3,7 @@ io.pebbletemplates pebble-project - 4.0.1-SNAPSHOT + 4.1.0-SNAPSHOT pebble diff --git a/pebble/src/main/java/io/pebbletemplates/pebble/PebbleEngine.java b/pebble/src/main/java/io/pebbletemplates/pebble/PebbleEngine.java index 648374a57..38a9296fc 100644 --- a/pebble/src/main/java/io/pebbletemplates/pebble/PebbleEngine.java +++ b/pebble/src/main/java/io/pebbletemplates/pebble/PebbleEngine.java @@ -9,6 +9,8 @@ package io.pebbletemplates.pebble; +import io.pebbletemplates.pebble.attributes.methodaccess.BlacklistMethodAccessValidator; +import io.pebbletemplates.pebble.attributes.methodaccess.MethodAccessValidator; import io.pebbletemplates.pebble.cache.CacheKey; import io.pebbletemplates.pebble.cache.PebbleCache; import io.pebbletemplates.pebble.cache.tag.ConcurrentMapTagCache; @@ -16,38 +18,31 @@ import io.pebbletemplates.pebble.cache.template.ConcurrentMapTemplateCache; import io.pebbletemplates.pebble.cache.template.NoOpTemplateCache; import io.pebbletemplates.pebble.error.LoaderException; +import io.pebbletemplates.pebble.extension.*; +import io.pebbletemplates.pebble.extension.escaper.EscapingStrategy; import io.pebbletemplates.pebble.lexer.LexerImpl; import io.pebbletemplates.pebble.lexer.Syntax; import io.pebbletemplates.pebble.lexer.TokenStream; +import io.pebbletemplates.pebble.loader.ClasspathLoader; +import io.pebbletemplates.pebble.loader.Loader; +import io.pebbletemplates.pebble.loader.StringLoader; import io.pebbletemplates.pebble.node.RootNode; import io.pebbletemplates.pebble.parser.Parser; import io.pebbletemplates.pebble.parser.ParserImpl; import io.pebbletemplates.pebble.parser.ParserOptions; -import io.pebbletemplates.pebble.attributes.methodaccess.BlacklistMethodAccessValidator; -import io.pebbletemplates.pebble.attributes.methodaccess.MethodAccessValidator; -import io.pebbletemplates.pebble.extension.escaper.EscapingStrategy; -import io.pebbletemplates.pebble.loader.ClasspathLoader; -import io.pebbletemplates.pebble.loader.DelegatingLoader; -import io.pebbletemplates.pebble.loader.FileLoader; -import io.pebbletemplates.pebble.loader.Loader; -import io.pebbletemplates.pebble.loader.StringLoader; -import io.pebbletemplates.pebble.extension.*; import io.pebbletemplates.pebble.template.EvaluationOptions; import io.pebbletemplates.pebble.template.PebbleTemplate; import io.pebbletemplates.pebble.template.PebbleTemplateImpl; +import io.pebbletemplates.pebble.utils.TypeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.Reader; -import java.util.ArrayList; -import java.util.List; import java.util.Locale; import java.util.concurrent.ExecutorService; import java.util.function.Function; -import io.pebbletemplates.pebble.utils.TypeUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * The main class used for compiling templates. The PebbleEngine is responsible for delegating * responsibility to the lexer, parser, compiler, and template cache. @@ -584,10 +579,7 @@ public PebbleEngine build() { // default loader if (this.loader == null) { - List> defaultLoadingStrategies = new ArrayList<>(); - defaultLoadingStrategies.add(new ClasspathLoader()); - defaultLoadingStrategies.add(new FileLoader()); - this.loader = new DelegatingLoader(defaultLoadingStrategies); + this.loader = new ClasspathLoader(); } // default locale diff --git a/pebble/src/main/java/io/pebbletemplates/pebble/loader/FileLoader.java b/pebble/src/main/java/io/pebbletemplates/pebble/loader/FileLoader.java index fd6dd0e61..9fb3924eb 100644 --- a/pebble/src/main/java/io/pebbletemplates/pebble/loader/FileLoader.java +++ b/pebble/src/main/java/io/pebbletemplates/pebble/loader/FileLoader.java @@ -10,18 +10,12 @@ import io.pebbletemplates.pebble.error.LoaderException; import io.pebbletemplates.pebble.utils.PathUtils; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.UnsupportedEncodingException; +import java.io.*; +import java.nio.file.Path; +import java.nio.file.Paths; /** * This loader searches for a file located anywhere on the filesystem. It uses java.io.File to @@ -34,69 +28,35 @@ public class FileLoader implements Loader { private static final Logger logger = LoggerFactory.getLogger(FileLoader.class); private String prefix; - private String suffix; - private String charset = "UTF-8"; + public FileLoader(String prefix) { + this.setPrefix(prefix); + } + @Override public Reader getReader(String templateName) { - // try to load File - InputStream is = null; File file = this.getFile(templateName); - if (file.exists() && file.isFile()) { - try { - is = new FileInputStream(file); - } catch (FileNotFoundException e) { - } - } - - if (is == null) { - throw new LoaderException(null, - "Could not find template \"" + templateName + "\""); - } - try { + InputStream is = new FileInputStream(file); return new BufferedReader(new InputStreamReader(is, this.charset)); + } catch (FileNotFoundException e) { + throw new LoaderException(e, String.format("Could not find template [prefix='%s', templateName='%s']", this.prefix, templateName)); } catch (UnsupportedEncodingException e) { + throw new LoaderException(e, String.format("Invalid charset '%s'", this.charset)); } - - return null; } private File getFile(String templateName) { - // add the prefix and ensure the prefix ends with a separator character - StringBuilder path = new StringBuilder(); - if (this.getPrefix() != null) { - - path.append(this.getPrefix()); - - if (!this.getPrefix().endsWith(String.valueOf(File.separatorChar))) { - path.append(File.separatorChar); - } - } - templateName = templateName + (this.getSuffix() == null ? "" : this.getSuffix()); + templateName = PathUtils.sanitize(templateName, File.separatorChar); - logger.trace("Looking for template in {}{}.", path.toString(), templateName); + Path path = Paths.get(this.getPrefix(), templateName); + logger.trace("Looking for template in {}.", path); - /* - * if template name contains path segments, move those segments into the - * path variable. The below technique needs to know the difference - * between the path and file name. - */ - String[] pathSegments = PathUtils.PATH_SEPARATOR_REGEX.split(templateName); - - if (pathSegments.length > 1) { - // file name is the last segment - templateName = pathSegments[pathSegments.length - 1]; - } - for (int i = 0; i < (pathSegments.length - 1); i++) { - path.append(pathSegments[i]).append(File.separatorChar); - } - - // try to load File - return new File(path.toString(), templateName); + this.checkIfDirectoryTraversal(templateName); + return path.toFile(); } public String getSuffix() { @@ -114,7 +74,17 @@ public String getPrefix() { @Override public void setPrefix(String prefix) { - this.prefix = prefix; + if (prefix == null) { + throw new LoaderException(null, "Prefix cannot be null"); + } + String trimmedPrefix = prefix.trim(); + if (trimmedPrefix.isEmpty()) { + throw new LoaderException(null, "Prefix cannot be empty"); + } + if (!Paths.get(trimmedPrefix).isAbsolute()) { + throw new LoaderException(null, "Prefix must be an absolute path"); + } + this.prefix = trimmedPrefix; } public String getCharset() { @@ -140,4 +110,23 @@ public String createCacheKey(String templateName) { public boolean resourceExists(String templateName) { return this.getFile(templateName).exists(); } + + private void checkIfDirectoryTraversal(String templateName) { + Path baseDirPath = Paths.get(prefix); + Path userPath = Paths.get(templateName); + if (userPath.isAbsolute()) { + throw new LoaderException(null, String.format("templateName '%s' must be relative", templateName)); + } + + // Join the two paths together, then normalize so that any ".." elements + // in the userPath can remove parts of baseDirPath. + // (e.g. "/foo/bar/baz" + "../attack" -> "/foo/bar/attack") + Path resolvedPath = baseDirPath.resolve(userPath).normalize(); + + // Make sure the resulting path is still within the required directory. + // (In the example above, "/foo/bar/attack" is not.) + if (!resolvedPath.startsWith(baseDirPath)) { + throw new LoaderException(null, String.format("template is not in the base directory path [baseDir='%s', templateName='%s']", this.prefix, templateName)); + } + } } diff --git a/pebble/src/main/java/io/pebbletemplates/pebble/utils/PathUtils.java b/pebble/src/main/java/io/pebbletemplates/pebble/utils/PathUtils.java index 6f9f482f8..e5241c87a 100644 --- a/pebble/src/main/java/io/pebbletemplates/pebble/utils/PathUtils.java +++ b/pebble/src/main/java/io/pebbletemplates/pebble/utils/PathUtils.java @@ -44,7 +44,7 @@ public static String resolveRelativePath(String relativePath, String anchorPath, return null; } - private static String sanitize(String path, char expectedSeparator) { + public static String sanitize(String path, char expectedSeparator) { return PATH_SEPARATOR_REGEX.matcher(path) .replaceAll(Matcher.quoteReplacement(String.valueOf(expectedSeparator))); } diff --git a/pebble/src/test/java/io/pebbletemplates/pebble/FileLoaderTest.java b/pebble/src/test/java/io/pebbletemplates/pebble/FileLoaderTest.java new file mode 100644 index 000000000..aa958f58c --- /dev/null +++ b/pebble/src/test/java/io/pebbletemplates/pebble/FileLoaderTest.java @@ -0,0 +1,132 @@ +package io.pebbletemplates.pebble; + +import io.pebbletemplates.pebble.error.LoaderException; +import io.pebbletemplates.pebble.error.PebbleException; +import io.pebbletemplates.pebble.loader.FileLoader; +import io.pebbletemplates.pebble.loader.Loader; +import io.pebbletemplates.pebble.template.PebbleTemplate; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.net.URISyntaxException; +import java.nio.file.Paths; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class FileLoaderTest { + + @Test + void testFileLoaderPrefixNull() { + assertThrows(LoaderException.class, () -> new FileLoader(null)); + } + + @Test + void testFileLoaderPrefixEmpty() { + assertThrows(LoaderException.class, () -> new FileLoader(" ")); + } + + @Test + void testFileLoaderPrefixRelativePath() { + assertThrows(LoaderException.class, () -> new FileLoader(" ../bar ")); + } + + @Test + void testFileLoader() throws PebbleException, IOException, URISyntaxException { + String prefix = Paths.get(this.getClass().getClassLoader().getResource("templates").toURI()).toString(); + Loader loader = new FileLoader(prefix); + loader.setSuffix(".suffix"); + PebbleEngine engine = new PebbleEngine.Builder().loader(loader).strictVariables(false).build(); + PebbleTemplate template1 = engine.getTemplate("template.loaderTest.peb"); + Writer writer1 = new StringWriter(); + template1.evaluate(writer1); + assertEquals("SUCCESS", writer1.toString()); + } + + @Test + void testFileLoaderAbsoluteTemplateName() throws PebbleException, URISyntaxException { + String prefix = Paths.get(this.getClass().getClassLoader().getResource("templates").toURI()).toString(); + Loader loader = new FileLoader(prefix); + loader.setSuffix(".suffix"); + PebbleEngine engine = new PebbleEngine.Builder().loader(loader).strictVariables(false).build(); + assertThrows(LoaderException.class, () -> engine.getTemplate("/template.loaderTest.peb")); + } + + @Test + void testFileLoaderTemplateNameIsADirectory() throws PebbleException, URISyntaxException { + String prefix = Paths.get(this.getClass().getClassLoader().getResource("templates").toURI()).toString(); + Loader loader = new FileLoader(prefix); + PebbleEngine engine = new PebbleEngine.Builder().loader(loader).strictVariables(false).build(); + assertThrows(LoaderException.class, () -> engine.getTemplate("loader")); + } + + @Test + void testFileLoaderRelativeTemplateName() throws PebbleException, IOException, URISyntaxException { + String prefix = Paths.get(this.getClass().getClassLoader().getResource("templates").toURI()).getParent().toString(); + Loader loader = new FileLoader(prefix); + loader.setSuffix(".suffix"); + PebbleEngine engine = new PebbleEngine.Builder().loader(loader).strictVariables(false).build(); + PebbleTemplate template1 = engine.getTemplate("templates/template.loaderTest.peb"); + Writer writer1 = new StringWriter(); + template1.evaluate(writer1); + assertEquals("SUCCESS", writer1.toString()); + } + + @Test + void testFileLoaderPathTraversal() throws PebbleException, URISyntaxException { + String prefix = Paths.get(this.getClass().getClassLoader().getResource("templates").toURI()).toString(); + Loader loader = new FileLoader(prefix); + loader.setSuffix(".peb"); + PebbleEngine engine = new PebbleEngine.Builder().loader(loader).strictVariables(false).build(); + assertThrows(LoaderException.class, () -> engine.getTemplate("../template-tests/DoubleNestedIfStatement")); + } + + @ParameterizedTest + @ValueSource(strings = {"%2e%2e%2f", "%2e%2e/", "..%2f", "%2e%2e%5c", "%2e%2e\\", "..%5c", "%252e%252e%255c", "..%255c"}) + void testFileLoaderPathTraversalEncoded(String relativePath) throws URISyntaxException { + String prefix = Paths.get(this.getClass().getClassLoader().getResource("templates").toURI()).toString(); + Loader loader = new FileLoader(prefix); + loader.setSuffix(".peb"); + PebbleEngine engine = new PebbleEngine.Builder().loader(loader).strictVariables(false).build(); + assertThrows(LoaderException.class, () -> engine.getTemplate(relativePath + "template-tests/DoubleNestedIfStatement")); + } + + @Test + void testFileLoaderUnsupportedCharset() throws PebbleException, URISyntaxException { + String prefix = Paths.get(this.getClass().getClassLoader().getResource("templates").toURI()).toString(); + Loader loader = new FileLoader(prefix); + loader.setCharset("foobar"); + PebbleEngine engine = new PebbleEngine.Builder().loader(loader).strictVariables(false).build(); + assertThrows(LoaderException.class, () -> engine.getTemplate("template.loaderTest.peb")); + } + + /** + * Tests if relative includes work. Issue #162. + */ + @Test + void testFileLoaderPathWithBackslash() throws IOException, URISyntaxException { + String prefix = Paths.get(this.getClass().getClassLoader().getResource("templates").toURI()).toString(); + PebbleEngine pebble = new PebbleEngine.Builder().loader(new FileLoader(prefix)).build(); + PebbleTemplate template = pebble.getTemplate("relativepath/subdirectory1/template.forwardslashes.peb".replace("/", "\\")); // ensure backslashes in all environments + Writer writer = new StringWriter(); + template.evaluate(writer); + assertEquals("included", writer.toString()); + } + + /** + * Issue #162. + */ + @Test + void testFileLoaderPathWithForwardSlash() throws IOException, URISyntaxException { + String prefix = Paths.get(this.getClass().getClassLoader().getResource("templates").toURI()).toString(); + PebbleEngine pebble = new PebbleEngine.Builder().loader(new FileLoader(prefix)).build(); + PebbleTemplate template = pebble.getTemplate("relativepath/subdirectory1/template.backwardslashes.peb"); + Writer writer = new StringWriter(); + template.evaluate(writer); + assertEquals("included", writer.toString()); + } +} diff --git a/pebble/src/test/java/io/pebbletemplates/pebble/LoaderTest.java b/pebble/src/test/java/io/pebbletemplates/pebble/LoaderTest.java index 7394f4bef..4c632e0c7 100644 --- a/pebble/src/test/java/io/pebbletemplates/pebble/LoaderTest.java +++ b/pebble/src/test/java/io/pebbletemplates/pebble/LoaderTest.java @@ -15,7 +15,6 @@ import org.junit.jupiter.api.Test; import java.io.*; -import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; @@ -69,19 +68,6 @@ void testClassLoaderLoaderWithNestedTemplateInJar() throws PebbleException, IOEx } - @Test - void testFileLoader() throws PebbleException, IOException, URISyntaxException { - Loader loader = new FileLoader(); - loader.setSuffix(".suffix"); - PebbleEngine engine = new PebbleEngine.Builder().loader(loader).strictVariables(false).build(); - URL url = this.getClass().getResource("/templates/template.loaderTest.peb"); - PebbleTemplate template1 = engine.getTemplate(new File(url.toURI()).getPath()); - Writer writer1 = new StringWriter(); - template1.evaluate(writer1); - assertEquals("SUCCESS", writer1.toString()); - - } - @Test void testDelegatingLoader() throws PebbleException, IOException { List> loaders = new ArrayList<>(); diff --git a/pebble/src/test/java/io/pebbletemplates/pebble/TestRelativePath.java b/pebble/src/test/java/io/pebbletemplates/pebble/TestRelativePath.java index 5eabda4dc..6f9bc42e9 100644 --- a/pebble/src/test/java/io/pebbletemplates/pebble/TestRelativePath.java +++ b/pebble/src/test/java/io/pebbletemplates/pebble/TestRelativePath.java @@ -1,17 +1,12 @@ package io.pebbletemplates.pebble; import io.pebbletemplates.pebble.error.PebbleException; -import io.pebbletemplates.pebble.loader.FileLoader; import io.pebbletemplates.pebble.template.PebbleTemplate; - import org.junit.jupiter.api.Test; -import java.io.File; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; -import java.net.URISyntaxException; -import java.net.URL; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -65,38 +60,4 @@ void testRelativeImports() throws PebbleException, IOException { assertEquals("", writer.toString().replaceAll("\\r?\\n", "").replace("\t", "")); } - - /** - * Tests if relative includes work. Issue #162. - */ - @Test - void testPathWithBackslashesWithRelativePathWithForwardSlashes() - throws PebbleException, IOException, URISyntaxException { - PebbleEngine pebble = new PebbleEngine.Builder().loader(new FileLoader()).build(); - URL url = this.getClass() - .getResource("/templates/relativepath/subdirectory1/template.forwardslashes.peb"); - PebbleTemplate template = pebble - .getTemplate(new File(url.toURI()).getPath() - .replace("/", "\\")); // ensure backslashes in all environments - Writer writer = new StringWriter(); - template.evaluate(writer); - assertEquals("included", writer.toString()); - } - - /** - * Issue #162. - */ - @Test - void testPathWithForwardSlashesWithRelativePathWithBackwardSlashes() - throws PebbleException, IOException, URISyntaxException { - PebbleEngine pebble = new PebbleEngine.Builder().loader(new FileLoader()).build(); - URL url = this.getClass() - .getResource("/templates/relativepath/subdirectory1/template.backwardslashes.peb"); - PebbleTemplate template = pebble - .getTemplate(new File(url.toURI()).getPath() - .replace("\\", "/")); // ensure forward slashes in all environments - Writer writer = new StringWriter(); - template.evaluate(writer); - assertEquals("included", writer.toString()); - } } diff --git a/pom.xml b/pom.xml index d67b99f93..d19647073 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 io.pebbletemplates pebble-project - 4.0.1-SNAPSHOT + 4.1.0-SNAPSHOT pom