Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow "_" for sanitize Report Name #36

Merged
merged 4 commits into from Oct 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 24 additions & 4 deletions src/main/java/htmlpublisher/HtmlPublisherTarget.java
Expand Up @@ -90,6 +90,8 @@ public class HtmlPublisherTarget extends AbstractDescribableImpl<HtmlPublisherTa

private String includes;

private Boolean escapeUnderscores;

/**
* @deprecated Use {@link #HtmlPublisherTarget(java.lang.String, java.lang.String, java.lang.String, java.lang.String, boolean, boolean, boolean)}.
*/
Expand Down Expand Up @@ -165,6 +167,19 @@ public boolean getAllowMissing() {
return this.allowMissing;
}

public boolean getEscapeUnderscores() {
if (this.escapeUnderscores == null) {
return true;
} else {
return this.escapeUnderscores;
}
}

@DataBoundSetter
public void setEscapeUnderscores(boolean escapeUnderscores) {
this.escapeUnderscores = escapeUnderscores;
}

/**
* Actually not safe, this allowed directory traversal (SECURITY-784).
* @return
Expand All @@ -176,12 +191,17 @@ private String getLegacySanitizedName() {
}

public String getSanitizedName() {
return sanitizeReportName(this.reportName);
return sanitizeReportName(this.reportName, getEscapeUnderscores());
}

@Restricted(NoExternalUse.class)
public static String sanitizeReportName(String reportName) {
Pattern p = Pattern.compile("[^a-zA-Z0-9-]");
public static String sanitizeReportName(String reportName, boolean escapeUnderscores) {
Pattern p;
if (escapeUnderscores) {
p = Pattern.compile("[^a-zA-Z0-9-]");
} else {
p = Pattern.compile("[^a-zA-Z0-9-_]");
}
Matcher m = p.matcher(reportName);
StringBuffer sb = new StringBuffer();
while (m.find()) {
Expand Down Expand Up @@ -543,4 +563,4 @@ public boolean equals(Object obj) {
public static class DescriptorImpl extends Descriptor<HtmlPublisherTarget> {
public String getDisplayName() { return ""; }
}
}
}
Expand Up @@ -19,7 +19,7 @@
<f:textbox default="HTML Report"/>
</f:entry>

<f:advanced title="${%Publishing options}">
<f:advanced title="${%Publishing options}">
<f:entry field="keepAll" title="${%keepAll.title}">
<f:checkbox />
</f:entry>
Expand All @@ -34,5 +34,8 @@
<f:entry field="includes" title="${%reportFiles.includes}" description="${%reportFiles.includesHelp}">
<f:textbox default="**/*"/>
</f:entry>
<f:entry field="escapeUnderscores" title="${%escapeUnderscores.title}">
<f:checkbox default="true"/>
</f:entry>
</f:advanced>
</j:jelly>
Expand Up @@ -6,4 +6,5 @@ reportFiles.includesHelp=Follows the Ant glob syntax, such as **/*.html,**/*.css
reportName.title=Report title
keepAll.title=Keep past HTML reports
alwaysLinkToLastBuild.title=Always link to last build
allowMissing.title=Allow missing report
allowMissing.title=Allow missing report
escapeUnderscores.title=Escape underscores in Report Title
@@ -0,0 +1,3 @@
<div>
If checked, underscores in the report title will be escaped to '_5f' when stored on disk. If unchecked, they will not be escaped.
</div>
11 changes: 11 additions & 0 deletions src/test/java/htmlpublisher/HtmlPublisherTest.java
@@ -1,5 +1,6 @@
package htmlpublisher;

import org.junit.Assert;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
Expand All @@ -24,4 +25,14 @@ public void testSpacesTrimmed() {
assertEquals(target.getReportDir(), "target");
assertEquals(target.getReportFiles(), "tab1.html");
}

@Test
public void testEscapeUnderscores() {
// test underscores escaped when requested
assertEquals(HtmlPublisherTarget.sanitizeReportName("foo_bar", true), HtmlPublisherTarget.sanitizeReportName("foo_5fbar", false));

// test underscores not escaped when not requested
assertEquals(HtmlPublisherTarget.sanitizeReportName("foo_bar", false), HtmlPublisherTarget.sanitizeReportName("foo_bar", false));

}
}
12 changes: 6 additions & 6 deletions src/test/java/htmlpublisher/Security784Test.java
Expand Up @@ -62,15 +62,15 @@ public void testReportNameSanitization() throws Exception {
// start with general 'sanity' requirements

// failed in previous releases
Assert.assertNotEquals(HtmlPublisherTarget.sanitizeReportName("foo bar"), HtmlPublisherTarget.sanitizeReportName("foo_bar"));
Assert.assertNotEquals(HtmlPublisherTarget.sanitizeReportName("foo bar", false), HtmlPublisherTarget.sanitizeReportName("foo_bar", false));

// don't collapse repeated chars
Assert.assertNotEquals(HtmlPublisherTarget.sanitizeReportName("foo!bar"), HtmlPublisherTarget.sanitizeReportName("foo!!!!bar"));
Assert.assertNotEquals(HtmlPublisherTarget.sanitizeReportName("foo!bar", false), HtmlPublisherTarget.sanitizeReportName("foo!!!!bar", false));

// now be specific -- we escape non alphanumeric UTF-8 chars to their hex code with a '_' prefix
Assert.assertEquals("foo_21bar", HtmlPublisherTarget.sanitizeReportName("foo!bar"));
Assert.assertEquals("foo_20bar", HtmlPublisherTarget.sanitizeReportName("foo bar"));
Assert.assertEquals("_20foo_20bar_20", HtmlPublisherTarget.sanitizeReportName(" foo bar "));
Assert.assertEquals("_e5b79d_e58fa3", HtmlPublisherTarget.sanitizeReportName("川口")); // U+5DDD U+53E3
Assert.assertEquals("foo_21bar", HtmlPublisherTarget.sanitizeReportName("foo!bar", false));
Assert.assertEquals("foo_20bar", HtmlPublisherTarget.sanitizeReportName("foo bar", false));
Assert.assertEquals("_20foo_20bar_20", HtmlPublisherTarget.sanitizeReportName(" foo bar ", false));
Assert.assertEquals("_e5b79d_e58fa3", HtmlPublisherTarget.sanitizeReportName("川口", false)); // U+5DDD U+53E3
}
}