From: Felix Dörre Date: Thu, 28 Jul 2016 15:44:38 +0000 (+0200) Subject: add: an non-HTML-encoding mode for templates for e.g. producing emails X-Git-Url: https://code.wpia.club/?p=gigi.git;a=commitdiff_plain;h=dd2df5279f12cb801851244785a9ebc2566b6ef5 add: an non-HTML-encoding mode for templates for e.g. producing emails fixes #50 Change-Id: Ide91f467068d3d740c32ce67c3505fe61ef89b47 --- diff --git a/src/org/cacert/gigi/output/template/Outputable.java b/src/org/cacert/gigi/output/template/Outputable.java index 02fea411..1e6d9f10 100644 --- a/src/org/cacert/gigi/output/template/Outputable.java +++ b/src/org/cacert/gigi/output/template/Outputable.java @@ -10,6 +10,8 @@ import org.cacert.gigi.localisation.Language; */ public interface Outputable { + public static final String OUT_KEY_PLAIN = "output-content-plain"; + /** * Writes this object's content to the given output stream. * diff --git a/src/org/cacert/gigi/output/template/PlainOutputable.java b/src/org/cacert/gigi/output/template/PlainOutputable.java index 1ab34975..3c56b7fa 100644 --- a/src/org/cacert/gigi/output/template/PlainOutputable.java +++ b/src/org/cacert/gigi/output/template/PlainOutputable.java @@ -11,12 +11,16 @@ public class PlainOutputable implements Outputable { String text; public PlainOutputable(String text) { - this.text = HTMLEncoder.encodeHTML(text); + this.text = text; } @Override public void output(PrintWriter out, Language l, Map vars) { - out.print(text); + if (vars.containsKey(OUT_KEY_PLAIN)) { + out.print(text); + } else { + out.print(HTMLEncoder.encodeHTML(text)); + } } } diff --git a/src/org/cacert/gigi/output/template/SprintfCommand.java b/src/org/cacert/gigi/output/template/SprintfCommand.java index 51ea9cf2..64ede782 100644 --- a/src/org/cacert/gigi/output/template/SprintfCommand.java +++ b/src/org/cacert/gigi/output/template/SprintfCommand.java @@ -78,7 +78,7 @@ public final class SprintfCommand implements Translatable { Matcher m = replacant.matcher(parts); int pos = 0; while (m.find()) { - out.print(HTMLEncoder.encodeHTML(parts.substring(pos, m.start()))); + out.print(escape(vars, parts.substring(pos, m.start()))); String var = store[Integer.parseInt(m.group(1))]; if (var.startsWith("$!")) { Template.outputVar(out, l, vars, var.substring(3, var.length() - 1), true); @@ -92,7 +92,14 @@ public final class SprintfCommand implements Translatable { pos = m.end(); } - out.print(HTMLEncoder.encodeHTML(parts.substring(pos))); + out.print(escape(vars, parts.substring(pos))); + } + + private String escape(Map vars, String target) { + if (vars.containsKey(OUT_KEY_PLAIN)) { + return target; + } + return HTMLEncoder.encodeHTML(target); } @Override diff --git a/src/org/cacert/gigi/output/template/Template.java b/src/org/cacert/gigi/output/template/Template.java index e8088571..9dbe4dc7 100644 --- a/src/org/cacert/gigi/output/template/Template.java +++ b/src/org/cacert/gigi/output/template/Template.java @@ -201,6 +201,9 @@ public class Template implements Outputable { } protected static void outputVar(PrintWriter out, Language l, Map vars, String varname, boolean unescaped) { + if (vars.containsKey(Outputable.OUT_KEY_PLAIN)) { + unescaped = true; + } Object s = vars.get(varname); if (s == null) { diff --git a/src/org/cacert/gigi/output/template/TranslateCommand.java b/src/org/cacert/gigi/output/template/TranslateCommand.java index d291e9d4..6532d946 100644 --- a/src/org/cacert/gigi/output/template/TranslateCommand.java +++ b/src/org/cacert/gigi/output/template/TranslateCommand.java @@ -26,7 +26,12 @@ public final class TranslateCommand implements Translatable { @Override public void output(PrintWriter out, Language l, Map vars) { - out.print(HTMLEncoder.encodeHTML(l.getTranslation(raw))); + String translation = l.getTranslation(raw); + if (vars.containsKey(Outputable.OUT_KEY_PLAIN)) { + out.print(translation); + } else { + out.print(HTMLEncoder.encodeHTML(translation)); + } } /** diff --git a/src/org/cacert/gigi/pages/error/AccessDenied.java b/src/org/cacert/gigi/pages/error/AccessDenied.java index 60c48bf2..4908c75a 100644 --- a/src/org/cacert/gigi/pages/error/AccessDenied.java +++ b/src/org/cacert/gigi/pages/error/AccessDenied.java @@ -1,6 +1,7 @@ package org.cacert.gigi.pages.error; import java.io.IOException; +import java.util.Collections; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -15,7 +16,7 @@ public class AccessDenied extends Page { @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { - getDefaultTemplate().output(resp.getWriter(), Page.getLanguage(req), null); + getDefaultTemplate().output(resp.getWriter(), Page.getLanguage(req), Collections.emptyMap()); } @Override diff --git a/tests/org/cacert/gigi/template/TestTemplateUnescaped.java b/tests/org/cacert/gigi/template/TestTemplateUnescaped.java new file mode 100644 index 00000000..8c8a5683 --- /dev/null +++ b/tests/org/cacert/gigi/template/TestTemplateUnescaped.java @@ -0,0 +1,46 @@ +package org.cacert.gigi.template; + +import static org.junit.Assert.*; + +import java.io.PrintWriter; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.Collections; +import java.util.HashMap; +import java.util.Locale; + +import org.cacert.gigi.localisation.Language; +import org.cacert.gigi.output.template.Outputable; +import org.cacert.gigi.output.template.Template; +import org.junit.Test; + +public class TestTemplateUnescaped { + + private String testExecute(HashMap vars, String input) { + Template t = new Template(new StringReader(input)); + StringWriter str = new StringWriter(); + PrintWriter pw = new PrintWriter(str); + t.output(pw, Language.getInstance(Locale.ENGLISH), vars); + pw.flush(); + return str.toString(); + } + + HashMap vars = new HashMap<>(Collections.singletonMap(Outputable.OUT_KEY_PLAIN, "yes")); + + @Test + public void testVarNoEscape() { + vars.put("var", "val"); + assertEquals("vall", testExecute(vars, "l")); + vars.put("var", "val<"); + assertEquals("vall")); + assertEquals("vall")); + vars.put("var", "val\">"); + assertEquals("val\">l", testExecute(vars, "l")); + assertEquals("val\">l", testExecute(vars, "l")); + } + + @Test + public void testTranslateNoEscape() { + assertEquals("\"tex<>l", testExecute(vars, "?>l")); + } +}