Skip to content

Commit

Permalink
wrote own dialect to bypass restrictions
Browse files Browse the repository at this point in the history
  • Loading branch information
christlang committed Jan 4, 2022
1 parent 52b98f4 commit 742f21b
Show file tree
Hide file tree
Showing 7 changed files with 189 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,23 @@
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.thymeleaf.context.Context;
import org.thymeleaf.context.IContext;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

@Controller
public class ExamplesController {

SvgService svgService;

public ExamplesController(SvgService svgService) {
this.svgService = svgService;
}

@GetMapping("/examples")
public String index() {
return "examples/index";
Expand All @@ -20,8 +33,14 @@ public String restrictedAccessThymeleafExample(@RequestParam(value="index", defa
}

@GetMapping("/examples/restrictedAccessThymeleafExampleSvg")
@ResponseBody
public String restrictedAccessThymeleafExampleSvg(@RequestParam(value="index", defaultValue = "0") String index,Model model) {
model.addAttribute("index", index);
return "/examples/restrictedAccessThymeleafExampleSVG";

Map<String, Object> variables = new HashMap<>();
variables.put("index", index);

IContext context = new Context(Locale.GERMAN, variables);

return svgService.createSvg("/examples/restrictedAccessThymeleafExample.svg", context);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package de.synyx.cl.learning.spring.thymeleaf;

import de.synyx.cl.learning.spring.thymeleaf.svg.dialect.SvgDialect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Service;
import org.thymeleaf.context.IContext;
import org.thymeleaf.spring5.ISpringTemplateEngine;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.thymeleaf.templateresolver.ITemplateResolver;

@Service
public class SvgService {

/**
* this is the entrypoint-prefix where the {@link #svgTemplateEngine} searches for the
* given template name. e.g. blabla/helloWorld -> ${PREFIX}/blabla/helloWorld
*/
private static final String RESOURCES_TEMPLATES_DIR_PREFIX = "templates/";

private final ISpringTemplateEngine svgTemplateEngine;

@Autowired
public SvgService(final MessageSource messageSource) {
this.svgTemplateEngine = this.svgTemplateEngine(messageSource);
}

public String createSvg(final String templateName, final IContext templateContext) {
return this.svgTemplateEngine.process(templateName, templateContext);
}

private ISpringTemplateEngine svgTemplateEngine(final MessageSource messageSource) {
final SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(this.svgXmlTemplateResolver());
engine.addDialect(new SvgDialect());
engine.setMessageSource(messageSource);
return engine;
}

private ITemplateResolver svgXmlTemplateResolver() {
final ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
resolver.setPrefix(RESOURCES_TEMPLATES_DIR_PREFIX);
resolver.setCacheable(false);
resolver.setTemplateMode(TemplateMode.HTML);
return resolver;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package de.synyx.cl.learning.spring.thymeleaf.svg.dialect;

import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.context.ITemplateContext;
import org.thymeleaf.engine.AttributeName;
import org.thymeleaf.model.IProcessableElementTag;
import org.thymeleaf.processor.element.AbstractAttributeTagProcessor;
import org.thymeleaf.processor.element.IElementTagStructureHandler;
import org.thymeleaf.standard.expression.IStandardExpression;
import org.thymeleaf.standard.expression.IStandardExpressionParser;
import org.thymeleaf.standard.expression.StandardExpressions;
import org.thymeleaf.templatemode.TemplateMode;

public class AttributeTagProcessorFactory extends AbstractAttributeTagProcessor {

public static AbstractAttributeTagProcessor create(String dialectPrefix, String attributeName) {
return new AttributeTagProcessorFactory(dialectPrefix, attributeName);
}

private final String attributeNameToHandle;
private static final int PRECEDENCE = 10000;


public AttributeTagProcessorFactory(final String dialectPrefix, String attributeName) {
super(
TemplateMode.HTML, // This processor will apply only to HTML mode
dialectPrefix, // Prefix to be applied to name for matching
null, // No tag name: match any tag name
false, // No prefix to be applied to tag name
attributeName, // Name of the attribute that will be matched
true, // Apply dialect prefix to attribute name
PRECEDENCE, // Precedence (inside dialect's precedence)
true); // Remove the matched attribute afterwards

this.attributeNameToHandle = attributeName;
}


protected void doProcess(
final ITemplateContext context, final IProcessableElementTag tag,
final AttributeName attributeName, final String attributeValue,
final IElementTagStructureHandler structureHandler) {

final IEngineConfiguration configuration = context.getConfiguration();

final IStandardExpressionParser parser =
StandardExpressions.getExpressionParser(configuration);

final IStandardExpression expression = parser.parseExpression(context, attributeValue);

final String output = (String) expression.execute(context);

structureHandler.setAttribute(attributeNameToHandle, output);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package de.synyx.cl.learning.spring.thymeleaf.svg.dialect;

import org.thymeleaf.dialect.AbstractProcessorDialect;
import org.thymeleaf.processor.IProcessor;

import java.util.HashSet;
import java.util.Set;

/**
* Needed to replace attributes that have no special name, that usually are addressed by th:attr.
*
* th:attr got some restrictions on thymeleaf 3.0.12
* see https://github.com/thymeleaf/thymeleaf/issues/809
* new is not allowed
* static access to code is not allowed
*
* this is the workaround inspired by
* https://www.thymeleaf.org/doc/articles/sayhelloextendingthymeleaf5minutes.html
* https://www.thymeleaf.org/doc/articles/sayhelloagainextendingthymeleafevenmore5minutes.html
*
* will replace
* svg:x1="${variable}" by x1="variableContent"
*
*/
public class SvgDialect extends AbstractProcessorDialect {

public SvgDialect() {
super(
"SVG-Dialect", // Dialect name
"svg", // Dialect prefix (hello:*)
1000); // Dialect precedence
}


/*
* Initialize the dialect's processors.
*
* Note the dialect prefix is passed here because, although we set
* "svg" to be the dialect's prefix at the constructor, that only
* works as a default, and at engine configuration time the user
* might have chosen a different prefix to be used.
*/
public Set<IProcessor> getProcessors(final String dialectPrefix) {
final Set<IProcessor> processors = new HashSet<>();
// here we can identify all attributes that should be replaced dynamically
processors.add(AttributeTagProcessorFactory.create(dialectPrefix, "y1"));
processors.add(AttributeTagProcessorFactory.create(dialectPrefix, "y2"));
processors.add(AttributeTagProcessorFactory.create(dialectPrefix, "stroke"));
return processors;
}


}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 6 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,16 @@ spring init --dependencies=web,thymeleaf,devtools --package-name de.synyx.cl.lea
## restricted access unter Thymeleaf

* https://github.com/thymeleaf/thymeleaf/issues/809
* Fehler sollte mit thymeleaf version 3.0.12 auftreten (tut es aber nicht)
* mehr Details: https://github.com/thymeleaf/thymeleaf/issues/816#issuecomment-826401631
* Fehler sollte mit thymeleaf version 3.0.12 auftreten
* aber nur in th:attr nicht in th:text
* möglicher Workaround eigener Dialekt
* https://www.thymeleaf.org/doc/articles/sayhelloextendingthymeleaf5minutes.html

```shell
cd Service
mvn spring-boot:run
browser http://localhost:8080/examples/restrictedAccessThymeleafExample
```

* StandardExpressionExecutionContext

0 comments on commit 742f21b

Please sign in to comment.