From a1bacccc092054b3f0c3afc41b2e16c0becaf615 Mon Sep 17 00:00:00 2001 From: Herr Ritschwumm Date: Sat, 30 Jan 2016 15:47:21 +0100 Subject: [PATCH 1/3] add tests, failing right now --- .../gitbucket/core/view/HelpersSpec.scala | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/test/scala/gitbucket/core/view/HelpersSpec.scala b/src/test/scala/gitbucket/core/view/HelpersSpec.scala index 41d00537a..80d7eeeab 100644 --- a/src/test/scala/gitbucket/core/view/HelpersSpec.scala +++ b/src/test/scala/gitbucket/core/view/HelpersSpec.scala @@ -32,7 +32,28 @@ class HelpersSpec extends Specification { after mustEqual """Example Project. http://example.com. (See also https://github.com/)""" } + "properly escape html metacharacters" in { + val before = "<>&" + val after = detectAndRenderLinks(before).toString() + after mustEqual """<>&""" + } + + "escape html metacharacters adjacent to a link" in { + val before = "" + val after = detectAndRenderLinks(before).toString() + after mustEqual """<http://example.com>""" + } + + "stop link recognition at a metacharacter" in { + val before = "http://exahttp://exa<mple.com""" + } + + "make sure there are no double quotes in the href attribute" in { + val before = "http://exa\"mple.com" + val after = detectAndRenderLinks(before).toString() + after mustEqual """http://exa"mple.com""" + } } - } - From 7ba3ca6f151399319ea8423285d8e914f2e7de39 Mon Sep 17 00:00:00 2001 From: Herr Ritschwumm Date: Sat, 30 Jan 2016 16:08:42 +0100 Subject: [PATCH 2/3] properly escape html characters in a description --- src/main/scala/gitbucket/core/view/helpers.scala | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/scala/gitbucket/core/view/helpers.scala b/src/main/scala/gitbucket/core/view/helpers.scala index b61c0d6e5..e8e876041 100644 --- a/src/main/scala/gitbucket/core/view/helpers.scala +++ b/src/main/scala/gitbucket/core/view/helpers.scala @@ -9,7 +9,7 @@ import gitbucket.core.plugin.{RenderRequest, PluginRegistry} import gitbucket.core.service.{RepositoryService, RequestCache} import gitbucket.core.util.{FileUtil, JGitUtil, StringUtil} -import play.twirl.api.Html +import play.twirl.api.{Html, HtmlFormat} /** * Provides helper methods for Twirl templates. @@ -306,6 +306,17 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache private[this] val detectAndRenderLinksRegex = """(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,13}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))""".r def detectAndRenderLinks(text: String): Html = { - Html(detectAndRenderLinksRegex.replaceAllIn(text, m => s"""${m.group(0)}""")) + val matches = detectAndRenderLinksRegex.findAllMatchIn(text).toVector + var pos = 0 + var out = Vector.empty[Html] + for (m <- matches) { + if (pos < m.start) out :+= HtmlFormat.escape(text.substring(pos, m.start)) + val url = m.group(0) + val href = url.replace("\"", """) + out :+= Html(s"""${url}""") + pos = m.end + } + if (pos < text.length) out :+= HtmlFormat.escape(text.substring(pos)) + HtmlFormat.fill(out) } } From 057f029c80ab718ba27fb42dd1ab30e89630df03 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sun, 31 Jan 2016 12:26:09 +0900 Subject: [PATCH 3/3] (refs #1085)Remove var by replacing for expression with foldLeft --- .../scala/gitbucket/core/view/helpers.scala | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/scala/gitbucket/core/view/helpers.scala b/src/main/scala/gitbucket/core/view/helpers.scala index e8e876041..33fdce907 100644 --- a/src/main/scala/gitbucket/core/view/helpers.scala +++ b/src/main/scala/gitbucket/core/view/helpers.scala @@ -306,17 +306,19 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache private[this] val detectAndRenderLinksRegex = """(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,13}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))""".r def detectAndRenderLinks(text: String): Html = { - val matches = detectAndRenderLinksRegex.findAllMatchIn(text).toVector - var pos = 0 - var out = Vector.empty[Html] - for (m <- matches) { - if (pos < m.start) out :+= HtmlFormat.escape(text.substring(pos, m.start)) + val matches = detectAndRenderLinksRegex.findAllMatchIn(text).toSeq + + val (x, pos) = matches.foldLeft((collection.immutable.Seq.empty[Html], 0)){ case ((x, pos), m) => val url = m.group(0) val href = url.replace("\"", """) - out :+= Html(s"""${url}""") - pos = m.end + (x ++ (Seq( + if(pos < m.start) Some(HtmlFormat.escape(text.substring(pos, m.start))) else None, + Some(Html(s"""${url}""")) + ).flatten), m.end) } - if (pos < text.length) out :+= HtmlFormat.escape(text.substring(pos)) + // append rest fragment + val out = if (pos < text.length) x :+ HtmlFormat.escape(text.substring(pos)) else x + HtmlFormat.fill(out) } }