Render git:// links in Markdown
README.md and other Markdown pages sometimes contains links to Git
repositories using git:// protocol. This is by default rejected by
Soy sanitizers, but its reasonable to allow within the context of a
Markdown page in a Git repository.
Change-Id: Ibfa389335a25d2315d929c9f67082b4099328bac
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/doc/MarkdownToHtml.java b/gitiles-servlet/src/main/java/com/google/gitiles/doc/MarkdownToHtml.java
index 2dcebdd..d5218e7 100644
--- a/gitiles-servlet/src/main/java/com/google/gitiles/doc/MarkdownToHtml.java
+++ b/gitiles-servlet/src/main/java/com/google/gitiles/doc/MarkdownToHtml.java
@@ -364,6 +364,11 @@
String href(String target) {
if (target.startsWith("#") || HtmlBuilder.isValidHttpUri(target)) {
return target;
+ } else if (target.startsWith("git:")) {
+ if (HtmlBuilder.isValidGitUri(target)) {
+ return target;
+ }
+ return FilterNormalizeUri.INSTANCE.getInnocuousOutput();
}
String anchor = "";
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/doc/html/HtmlBuilder.java b/gitiles-servlet/src/main/java/com/google/gitiles/doc/html/HtmlBuilder.java
index 9639176..3239fe1 100644
--- a/gitiles-servlet/src/main/java/com/google/gitiles/doc/html/HtmlBuilder.java
+++ b/gitiles-servlet/src/main/java/com/google/gitiles/doc/html/HtmlBuilder.java
@@ -85,6 +85,17 @@
private static final FilterNormalizeUri URI = FilterNormalizeUri.INSTANCE;
private static final FilterImageDataUri IMAGE_DATA = FilterImageDataUri.INSTANCE;
+ private static final Pattern GIT_URI =
+ Pattern.compile(
+ "^"
+ +
+ // Reject paths containing /../ or ending in /..
+ "(?![^#?]*/(?:\\.|%2E){2}(?:[/?#]|\\z))"
+ +
+ // Accept git://host/path
+ "git://[^/]+/.+",
+ Pattern.CASE_INSENSITIVE);
+
public static boolean isValidCssDimension(String val) {
return val != null && val.matches("(?:[1-9][0-9]*px|100%|[1-9][0-9]?%)");
}
@@ -99,6 +110,10 @@
return IMAGE_DATA.getValueFilter().matcher(url).find();
}
+ public static boolean isValidGitUri(String val) {
+ return GIT_URI.matcher(val).find();
+ }
+
private final StringBuilder htmlBuf;
private final Appendable textBuf;
private String tag;
@@ -159,7 +174,7 @@
}
private String anchorHref(String val) {
- if (URI.getValueFilter().matcher(val).find()) {
+ if (URI.getValueFilter().matcher(val).find() || isValidGitUri(val)) {
return URI.escape(val);
}
return URI.getInnocuousOutput();
diff --git a/gitiles-servlet/src/test/java/com/google/gitiles/doc/DocServletTest.java b/gitiles-servlet/src/test/java/com/google/gitiles/doc/DocServletTest.java
index 9d2b437..25f3d7f 100644
--- a/gitiles-servlet/src/test/java/com/google/gitiles/doc/DocServletTest.java
+++ b/gitiles-servlet/src/test/java/com/google/gitiles/doc/DocServletTest.java
@@ -132,4 +132,20 @@
String html = buildHtml("/repo/+doc/master/README.md");
assertThat(html).contains("<a href=\"/b/repo/+/master/x\">c</a>");
}
+
+ @Test
+ public void gitUrlLink() throws Exception {
+ repo.branch("master").commit().add("README.md", "[c](git://example.com/repo.git)").create();
+
+ String html = buildHtml("/repo/+doc/master/README.md");
+ assertThat(html).contains("<a href=\"git://example.com/repo.git\">c</a>");
+ }
+
+ @Test
+ public void invalidGitUrlLink() throws Exception {
+ repo.branch("master").commit().add("README.md", "[c](git://example.com/repo/..)").create();
+
+ String html = buildHtml("/repo/+doc/master/README.md");
+ assertThat(html).contains("<a href=\"#zSoyz\">c</a>");
+ }
}
diff --git a/gitiles-servlet/src/test/java/com/google/gitiles/doc/LinkTest.java b/gitiles-servlet/src/test/java/com/google/gitiles/doc/LinkTest.java
index fdffffc..ad9f941 100644
--- a/gitiles-servlet/src/test/java/com/google/gitiles/doc/LinkTest.java
+++ b/gitiles-servlet/src/test/java/com/google/gitiles/doc/LinkTest.java
@@ -63,6 +63,25 @@
}
@Test
+ public void gitLink() {
+ MarkdownToHtml md =
+ MarkdownToHtml.builder()
+ .setGitilesView(view)
+ .setConfig(new MarkdownConfig(config))
+ .setFilePath("index.md")
+ .build();
+ String url;
+
+ url = "git://example.com/repo.git";
+ assertThat(md.href(url)).isEqualTo(url);
+
+ assertThat(md.href("git:example.com/repo.git")).isEqualTo("#zSoyz");
+ assertThat(md.href("git://")).isEqualTo("#zSoyz");
+ assertThat(md.href("git://example.com/../root")).isEqualTo("#zSoyz");
+ assertThat(md.href("git://example.com/root/..")).isEqualTo("#zSoyz");
+ }
+
+ @Test
public void absolutePath() {
MarkdownToHtml md =
MarkdownToHtml.builder()