diff --git a/src/main/scala/gitbucket/core/view/helpers.scala b/src/main/scala/gitbucket/core/view/helpers.scala
index b61c0d6..33fdce9 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.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,19 @@
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).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("\"", """)
+ (x ++ (Seq(
+ if(pos < m.start) Some(HtmlFormat.escape(text.substring(pos, m.start))) else None,
+ Some(Html(s"""${url}"""))
+ ).flatten), m.end)
+ }
+ // append rest fragment
+ val out = if (pos < text.length) x :+ HtmlFormat.escape(text.substring(pos)) else x
+
+ HtmlFormat.fill(out)
}
}
diff --git a/src/test/scala/gitbucket/core/view/HelpersSpec.scala b/src/test/scala/gitbucket/core/view/HelpersSpec.scala
index 41d0053..80d7eee 100644
--- a/src/test/scala/gitbucket/core/view/HelpersSpec.scala
+++ b/src/test/scala/gitbucket/core/view/HelpersSpec.scala
@@ -32,7 +32,28 @@
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"""
+ }
}
-
}
-