From d451bab0d1ce7d41c605be72f3b16117f203d98c Mon Sep 17 00:00:00 2001 From: Michael Bien Date: Sun, 11 Jul 2021 09:04:29 +0200 Subject: [PATCH 1/3] Added EscapeSourceCodePlugin, a WeblogEntryPlugin to escape angle brackes from code within pre tags. --- .../plugins/entry/EscapeSourceCodePlugin.java | 88 ++++++++++ .../roller/weblogger/config/roller.properties | 3 +- .../entry/EscapeSourceCodePluginTest.java | 157 ++++++++++++++++++ 3 files changed, 247 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/org/apache/roller/weblogger/business/plugins/entry/EscapeSourceCodePlugin.java create mode 100644 app/src/test/java/org/apache/roller/weblogger/business/plugins/entry/EscapeSourceCodePluginTest.java diff --git a/app/src/main/java/org/apache/roller/weblogger/business/plugins/entry/EscapeSourceCodePlugin.java b/app/src/main/java/org/apache/roller/weblogger/business/plugins/entry/EscapeSourceCodePlugin.java new file mode 100644 index 0000000000..845b08ed35 --- /dev/null +++ b/app/src/main/java/org/apache/roller/weblogger/business/plugins/entry/EscapeSourceCodePlugin.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. The ASF licenses this file to You + * under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. For additional information regarding + * copyright in this work, please see the NOTICE file in the top level + * directory of this distribution. + */ + +package org.apache.roller.weblogger.business.plugins.entry; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.apache.roller.weblogger.WebloggerException; +import org.apache.roller.weblogger.pojos.Weblog; +import org.apache.roller.weblogger.pojos.WeblogEntry; + + +import static java.util.regex.Pattern.*; + +/** + * Escapes angle brackets inside pre tags (code tags which follow right after pre are not escaped). + */ +public class EscapeSourceCodePlugin implements WeblogEntryPlugin { + + private static final String LT = "<"; // '<' + + private static final Pattern PRE_PATTERN = Pattern.compile( + "]*>" + "(.*?)" + "", MULTILINE | DOTALL | CASE_INSENSITIVE); + + private static final Pattern CODE_PATTERN = Pattern.compile( + "]*>" + "(.*?)" + "", MULTILINE | DOTALL | CASE_INSENSITIVE); + + @Override + public String getName() { + return "Sourcecode Escaper"; + } + + @Override + public String getDescription() { + return "Escapes angle brackets inside pre tags, code tags are retained."; + } + + @Override + public void init(Weblog weblog) throws WebloggerException {} + + @Override + public String render(WeblogEntry entry, String str) { + + StringBuilder result = new StringBuilder(str.length()+32); + + Matcher pre_matcher = PRE_PATTERN.matcher(str); + + while(pre_matcher.find()) { + + String pre_full = pre_matcher.group(0); + String pre_inner = pre_matcher.group(1); + + Matcher code_matcher = CODE_PATTERN.matcher(pre_inner); + + if (code_matcher.find()) { + String code_inner = code_matcher.group(1); + pre_matcher.appendReplacement(result, pre_full.replace(code_inner, escape(code_inner))); + } else { + pre_matcher.appendReplacement(result, pre_full.replace(pre_inner, escape(pre_inner))); + } + + } + pre_matcher.appendTail(result); + + return result.toString(); + } + + // we only have to escape the opening angle bracket for valid html/xhtml + private static String escape(String code_inner) { + return code_inner.replace("<", LT); + } + +} diff --git a/app/src/main/resources/org/apache/roller/weblogger/config/roller.properties b/app/src/main/resources/org/apache/roller/weblogger/config/roller.properties index c82086b39a..af29d08c2d 100644 --- a/app/src/main/resources/org/apache/roller/weblogger/config/roller.properties +++ b/app/src/main/resources/org/apache/roller/weblogger/config/roller.properties @@ -548,7 +548,8 @@ guice.backend.module=org.apache.roller.weblogger.business.jpa.JPAWebloggerModule plugins.page=\ org.apache.roller.weblogger.business.plugins.entry.ConvertLineBreaksPlugin \ ,org.apache.roller.weblogger.business.plugins.entry.ObfuscateEmailPlugin \ -,org.apache.roller.weblogger.business.plugins.entry.SmileysPlugin +,org.apache.roller.weblogger.business.plugins.entry.SmileysPlugin\ +,org.apache.roller.weblogger.business.plugins.entry.EscapeSourceCodePlugin # The list of configured WeblogEntryEditors available to users diff --git a/app/src/test/java/org/apache/roller/weblogger/business/plugins/entry/EscapeSourceCodePluginTest.java b/app/src/test/java/org/apache/roller/weblogger/business/plugins/entry/EscapeSourceCodePluginTest.java new file mode 100644 index 0000000000..ff7b5853c3 --- /dev/null +++ b/app/src/test/java/org/apache/roller/weblogger/business/plugins/entry/EscapeSourceCodePluginTest.java @@ -0,0 +1,157 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. The ASF licenses this file to You + * under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. For additional information regarding + * copyright in this work, please see the NOTICE file in the top level + * directory of this distribution. + */ + +package org.apache.roller.weblogger.business.plugins.entry; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author mbien + */ +public class EscapeSourceCodePluginTest { + + @Test + public void passthrough() { + + EscapeSourceCodePlugin instance = new EscapeSourceCodePlugin(); + + String input = "Stay a while and listen."; + assertEquals(input, instance.render(null, input)); + + input = "\n" + + "\n" + + " \n" + + " Hi!\n" + + " \n" + + " \n" + + "

Hello There

\n" + + " \n" + + ""; + assertEquals(input, instance.render(null, input)); + + input = "\n" + + "\n" + + " \n" + + " Hi!\n" + + " \n" + + " \n" + + "
Hello There
\n" + // pre + " Hello There\n" + // code + " \n" + + ""; + assertEquals(input, instance.render(null, input)); + + } + + @Test + public void substitution1() { + + EscapeSourceCodePlugin instance = new EscapeSourceCodePlugin(); + + String input = "
<>
"; + String expected = "
<>
"; + + assertEquals(expected, instance.render(null, input)); + + } + + @Test + public void substitution2() { + + EscapeSourceCodePlugin instance = new EscapeSourceCodePlugin(); + + String input = "\n\n" + + "\n" + + " \n" + + " Hi!\n" + + " \n" + + " \n" + + "
private final Map> map = new HashMap<>();
\n"+ + " \n" + + ""; + + String expected = "\n\n" + + "\n" + + " \n" + + " Hi!\n" + + " \n" + + " \n" + + "
private final Map<String, List<?>> map = new HashMap<>();
\n"+ + " \n" + + ""; + assertEquals(expected, instance.render(null, input)); + + } + + @Test + public void substitution3() { + + EscapeSourceCodePlugin instance = new EscapeSourceCodePlugin(); + + String input = "\n" + + "\n" + + " \n" + + " Hi!\n" + + " \n" + + " \n" + + "

some java

\n" + + "
\n" +
+                "          \n"+
+                "              private final Map> map = new HashMap<>();\n"+
+                "          \n" +
+                "      
\n" + + "

some xml

\n" + + "
\n" +
+                "          \n"+
+                "              \n"+
+                "                  asdf\n"+
+                "              \n"+
+                "          \n" +
+                "      
\n" + + " \n" + + ""; + + String expected = "\n" + + "\n" + + " \n" + + " Hi!\n" + + " \n" + + " \n" + + "

some java

\n" + + "
\n" +
+                "          \n"+
+                "              private final Map<String, List<?>> map = new HashMap<>();\n"+
+                "          \n" +
+                "      
\n" + + "

some xml

\n" + + "
\n" +
+                "          \n"+
+                "              <foo id = '5'>\n"+
+                "                  <bar>asdf</bar>\n"+
+                "              </foo>\n"+
+                "          \n" +
+                "      
\n" + + " \n" + + ""; + assertEquals(expected, instance.render(null, input)); + + } + +} From d8a976fde73549633c4388cf4d3b907882558b32 Mon Sep 17 00:00:00 2001 From: Michael Bien Date: Wed, 14 Jul 2021 07:26:09 +0200 Subject: [PATCH 2/3] renamed EscapeSourceCodePlugin to EncodePreTagsPlugin. --- ...eCodePlugin.java => EncodePreTagsPlugin.java} | 16 ++++++++-------- .../roller/weblogger/config/roller.properties | 2 +- ...ginTest.java => EncodePreTagsPluginTest.java} | 10 +++++----- 3 files changed, 14 insertions(+), 14 deletions(-) rename app/src/main/java/org/apache/roller/weblogger/business/plugins/entry/{EscapeSourceCodePlugin.java => EncodePreTagsPlugin.java} (84%) rename app/src/test/java/org/apache/roller/weblogger/business/plugins/entry/{EscapeSourceCodePluginTest.java => EncodePreTagsPluginTest.java} (94%) diff --git a/app/src/main/java/org/apache/roller/weblogger/business/plugins/entry/EscapeSourceCodePlugin.java b/app/src/main/java/org/apache/roller/weblogger/business/plugins/entry/EncodePreTagsPlugin.java similarity index 84% rename from app/src/main/java/org/apache/roller/weblogger/business/plugins/entry/EscapeSourceCodePlugin.java rename to app/src/main/java/org/apache/roller/weblogger/business/plugins/entry/EncodePreTagsPlugin.java index 845b08ed35..26894968c1 100644 --- a/app/src/main/java/org/apache/roller/weblogger/business/plugins/entry/EscapeSourceCodePlugin.java +++ b/app/src/main/java/org/apache/roller/weblogger/business/plugins/entry/EncodePreTagsPlugin.java @@ -28,9 +28,9 @@ import static java.util.regex.Pattern.*; /** - * Escapes angle brackets inside pre tags (code tags which follow right after pre are not escaped). + * Encodes angle brackets inside pre tags (code tags which follow right after pre are not encoded). */ -public class EscapeSourceCodePlugin implements WeblogEntryPlugin { +public class EncodePreTagsPlugin implements WeblogEntryPlugin { private static final String LT = "<"; // '<' @@ -42,12 +42,12 @@ public class EscapeSourceCodePlugin implements WeblogEntryPlugin { @Override public String getName() { - return "Sourcecode Escaper"; + return "Pre Tag Encoder"; } @Override public String getDescription() { - return "Escapes angle brackets inside pre tags, code tags are retained."; + return "Encodes angle brackets inside pre tags, code tags are kept unaltered."; } @Override @@ -69,9 +69,9 @@ public String render(WeblogEntry entry, String str) { if (code_matcher.find()) { String code_inner = code_matcher.group(1); - pre_matcher.appendReplacement(result, pre_full.replace(code_inner, escape(code_inner))); + pre_matcher.appendReplacement(result, pre_full.replace(code_inner, encode(code_inner))); } else { - pre_matcher.appendReplacement(result, pre_full.replace(pre_inner, escape(pre_inner))); + pre_matcher.appendReplacement(result, pre_full.replace(pre_inner, encode(pre_inner))); } } @@ -80,8 +80,8 @@ public String render(WeblogEntry entry, String str) { return result.toString(); } - // we only have to escape the opening angle bracket for valid html/xhtml - private static String escape(String code_inner) { + // we only have to encode the opening angle bracket for valid html/xhtml + private static String encode(String code_inner) { return code_inner.replace("<", LT); } diff --git a/app/src/main/resources/org/apache/roller/weblogger/config/roller.properties b/app/src/main/resources/org/apache/roller/weblogger/config/roller.properties index af29d08c2d..2d439eaa8e 100644 --- a/app/src/main/resources/org/apache/roller/weblogger/config/roller.properties +++ b/app/src/main/resources/org/apache/roller/weblogger/config/roller.properties @@ -549,7 +549,7 @@ plugins.page=\ org.apache.roller.weblogger.business.plugins.entry.ConvertLineBreaksPlugin \ ,org.apache.roller.weblogger.business.plugins.entry.ObfuscateEmailPlugin \ ,org.apache.roller.weblogger.business.plugins.entry.SmileysPlugin\ -,org.apache.roller.weblogger.business.plugins.entry.EscapeSourceCodePlugin +,org.apache.roller.weblogger.business.plugins.entry.EncodePreTagsPlugin # The list of configured WeblogEntryEditors available to users diff --git a/app/src/test/java/org/apache/roller/weblogger/business/plugins/entry/EscapeSourceCodePluginTest.java b/app/src/test/java/org/apache/roller/weblogger/business/plugins/entry/EncodePreTagsPluginTest.java similarity index 94% rename from app/src/test/java/org/apache/roller/weblogger/business/plugins/entry/EscapeSourceCodePluginTest.java rename to app/src/test/java/org/apache/roller/weblogger/business/plugins/entry/EncodePreTagsPluginTest.java index ff7b5853c3..4dfbe18af0 100644 --- a/app/src/test/java/org/apache/roller/weblogger/business/plugins/entry/EscapeSourceCodePluginTest.java +++ b/app/src/test/java/org/apache/roller/weblogger/business/plugins/entry/EncodePreTagsPluginTest.java @@ -25,12 +25,12 @@ /** * @author mbien */ -public class EscapeSourceCodePluginTest { +public class EncodePreTagsPluginTest { @Test public void passthrough() { - EscapeSourceCodePlugin instance = new EscapeSourceCodePlugin(); + EncodePreTagsPlugin instance = new EncodePreTagsPlugin(); String input = "Stay a while and listen."; assertEquals(input, instance.render(null, input)); @@ -63,7 +63,7 @@ public void passthrough() { @Test public void substitution1() { - EscapeSourceCodePlugin instance = new EscapeSourceCodePlugin(); + EncodePreTagsPlugin instance = new EncodePreTagsPlugin(); String input = "
<>
"; String expected = "
<>
"; @@ -75,7 +75,7 @@ public void substitution1() { @Test public void substitution2() { - EscapeSourceCodePlugin instance = new EscapeSourceCodePlugin(); + EncodePreTagsPlugin instance = new EncodePreTagsPlugin(); String input = "\n\n" + "\n" + @@ -103,7 +103,7 @@ public void substitution2() { @Test public void substitution3() { - EscapeSourceCodePlugin instance = new EscapeSourceCodePlugin(); + EncodePreTagsPlugin instance = new EncodePreTagsPlugin(); String input = "\n" + "\n" + From 2950e9dbcb0d8fe89b0b9b4e1ae1a8b625264afe Mon Sep 17 00:00:00 2001 From: Michael Bien Date: Fri, 6 Aug 2021 17:45:58 +0200 Subject: [PATCH 3/3] quote $ and \ to not confuse the Matcher. --- .../weblogger/business/plugins/entry/EncodePreTagsPlugin.java | 2 +- .../business/plugins/entry/EncodePreTagsPluginTest.java | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/apache/roller/weblogger/business/plugins/entry/EncodePreTagsPlugin.java b/app/src/main/java/org/apache/roller/weblogger/business/plugins/entry/EncodePreTagsPlugin.java index 26894968c1..00c8650a1b 100644 --- a/app/src/main/java/org/apache/roller/weblogger/business/plugins/entry/EncodePreTagsPlugin.java +++ b/app/src/main/java/org/apache/roller/weblogger/business/plugins/entry/EncodePreTagsPlugin.java @@ -82,7 +82,7 @@ public String render(WeblogEntry entry, String str) { // we only have to encode the opening angle bracket for valid html/xhtml private static String encode(String code_inner) { - return code_inner.replace("<", LT); + return Matcher.quoteReplacement(code_inner.replace("<", LT)); // matchers hate $ and \ } } diff --git a/app/src/test/java/org/apache/roller/weblogger/business/plugins/entry/EncodePreTagsPluginTest.java b/app/src/test/java/org/apache/roller/weblogger/business/plugins/entry/EncodePreTagsPluginTest.java index 4dfbe18af0..e5861f84df 100644 --- a/app/src/test/java/org/apache/roller/weblogger/business/plugins/entry/EncodePreTagsPluginTest.java +++ b/app/src/test/java/org/apache/roller/weblogger/business/plugins/entry/EncodePreTagsPluginTest.java @@ -84,6 +84,8 @@ public void substitution2() { " \n" + " \n" + "
private final Map> map = new HashMap<>();
\n"+ + "
$JDK/bin/java -version
\n"+ + "
\\\\
\n"+ " \n" + ""; @@ -94,6 +96,8 @@ public void substitution2() { " \n" + " \n" + "
private final Map<String, List<?>> map = new HashMap<>();
\n"+ + "
$JDK/bin/java -version
\n"+ + "
\\\\
\n"+ " \n" + ""; assertEquals(expected, instance.render(null, input));