Skip to content

Commit

Permalink
[GWC-1172] Improve handling special characters in the GWC Seed Form
Browse files Browse the repository at this point in the history
  • Loading branch information
sikeoka authored and aaime committed Oct 16, 2023
1 parent 32ad113 commit c0ca08a
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
package org.geowebcache.rest.service;

import static org.apache.commons.text.StringEscapeUtils.escapeHtml4;
import static org.geowebcache.seed.TileBreeder.TILE_FAILURE_RETRY_COUNT_DEFAULT;
import static org.geowebcache.seed.TileBreeder.TILE_FAILURE_RETRY_WAIT_TIME_DEFAULT;
import static org.geowebcache.seed.TileBreeder.TOTAL_FAILURES_BEFORE_ABORTING_DEFAULT;
Expand Down Expand Up @@ -356,7 +357,10 @@ private void makeModifiableParameters(StringBuilder doc, TileLayer tl) {
String key = pf.getKey();
String defaultValue = pf.getDefaultValue();
List<String> legalValues = pf.getLegalValues();
doc.append("<tr><td>").append(key.toUpperCase()).append(": ").append("</td><td>");
doc.append("<tr><td>")
.append(escapeHtml4(key.toUpperCase()))
.append(": ")
.append("</td><td>");
String parameterId = "parameter_" + key;
if (pf instanceof StringParameterFilter) {
Map<String, String> keysValues = makeParametersMap(defaultValue, legalValues);
Expand Down Expand Up @@ -487,7 +491,7 @@ private void makeBboxHints(StringBuilder doc, TileLayer tl) {
GridSubset subset = tl.getGridSubset(gridSetId);
doc.append(
"<li>"
+ gridSetId
+ escapeHtml4(gridSetId)
+ ": "
+ subset.getOriginalExtent().toString()
+ "</li>\n");
Expand All @@ -501,11 +505,11 @@ private void makeTextInput(StringBuilder doc, String id, int size) {
private void makeTextInput(StringBuilder doc, String id, int size, String defaultValue) {
doc.append(
"<input name=\""
+ id
+ escapeHtml4(id)
+ "\" type=\"text\" size=\""
+ size
+ "\" value=\""
+ defaultValue
+ escapeHtml4(defaultValue)
+ "\"/>");
}

Expand Down Expand Up @@ -603,7 +607,7 @@ private void makeGridSetPulldown(StringBuilder doc, TileLayer tl) {

private void makePullDown(
StringBuilder doc, String id, Map<String, String> keysValues, String defaultKey) {
doc.append("<select name=\"" + id + "\">\n");
doc.append("<select name=\"" + escapeHtml4(id) + "\">\n");

Iterator<Map.Entry<String, String>> iter = keysValues.entrySet().iterator();

Expand All @@ -612,16 +616,16 @@ private void makePullDown(
if (entry.getKey().equals(defaultKey)) {
doc.append(
"<option value=\""
+ entry.getValue()
+ escapeHtml4(entry.getValue())
+ "\" selected=\"selected\">"
+ entry.getKey()
+ escapeHtml4(entry.getKey())
+ "</option>\n");
} else {
doc.append(
"<option value=\""
+ entry.getValue()
+ escapeHtml4(entry.getValue())
+ "\">"
+ entry.getKey()
+ escapeHtml4(entry.getKey())
+ "</option>\n");
}
}
Expand All @@ -631,7 +635,10 @@ private void makePullDown(

private void makeFormHeader(StringBuilder doc, TileLayer tl) {
doc.append("<h4>Create a new task:</h4>\n");
doc.append("<form id=\"seed\" action=\"./" + tl.getName() + "\" method=\"post\">\n");
doc.append(
"<form id=\"seed\" action=\"./"
+ escapeHtml4(tl.getName())
+ "\" method=\"post\">\n");
doc.append("<table border=\"0\" cellspacing=\"10\">\n");
}

Expand Down Expand Up @@ -720,9 +727,9 @@ private void makeTaskList(StringBuilder doc, TileLayer tl, boolean listAll) {
doc.append("<td style=\"text-align:right\">").append(task.getTaskId()).append("</td>");
doc.append("<td>");
if (!layerName.equals(task.getLayerName())) {
doc.append("<a href=\"./").append(task.getLayerName()).append("\">");
doc.append("<a href=\"./").append(escapeHtml4(task.getLayerName())).append("\">");
}
doc.append(task.getLayerName());
doc.append(escapeHtml4(task.getLayerName()));
if (!layerName.equals(task.getLayerName())) {
doc.append("</a>");
}
Expand All @@ -745,7 +752,7 @@ private void makeTaskList(StringBuilder doc, TileLayer tl, boolean listAll) {
if (tasks) {
doc.append("</table>");
}
doc.append("<p><a href=\"./" + layerName + "\">Refresh list</a></p>\n");
doc.append("<p><a href=\"./" + escapeHtml4(layerName) + "\">Refresh list</a></p>\n");
}

private String toTimeString(long timeSeconds, final long tilesDone, final long tilesTotal) {
Expand Down Expand Up @@ -786,7 +793,7 @@ private String toTimeString(long timeSeconds, final long tilesDone, final long t
private String makeThreadKillForm(Long key, TileLayer tl) {
String ret =
"<form form id=\"kill\" action=\"./"
+ tl.getName()
+ escapeHtml4(tl.getName())
+ "\" method=\"post\">"
+ "<input type=\"hidden\" name=\"kill_thread\" value=\"1\" />"
+ "<input type=\"hidden\" name=\"thread_id\" value=\""
Expand Down Expand Up @@ -814,7 +821,7 @@ private String makeKillallThreadsForm(TileLayer tl, boolean listAll) {

doc.append("<table><tr><td>");
doc.append("<form form id=\"list\" action=\"./")
.append(layerName)
.append(escapeHtml4(layerName))
.append("\" method=\"post\">\n");
doc.append("List ");
doc.append("<select name=\"list\" onchange=\"this.form.submit();\">\n");
Expand All @@ -839,15 +846,15 @@ private String makeKillallThreadsForm(TileLayer tl, boolean listAll) {
doc.append("</td></tr><tr><td>");

doc.append("<form form id=\"kill\" action=\"./")
.append(layerName)
.append(escapeHtml4(layerName))
.append("\" method=\"post\">\n");
doc.append("<span>Kill \n");
doc.append("<select name=\"kill_all\">\n");
doc.append("<option value=\"all\">all</option>\n");
doc.append("<option value=\"running\">running</option>\n");
doc.append("<option value=\"pending\">pending</option>\n");
doc.append("</select>\n");
doc.append(" Tasks for Layer '").append(layerName).append("'.");
doc.append(" Tasks for Layer '").append(escapeHtml4(layerName)).append("'.");
doc.append("<input type=\"submit\" value=\" Submit\">");
doc.append("</span>\n");
doc.append("</form>\n");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,27 @@
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasProperty;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.collections4.iterators.EmptyIterator;
import org.easymock.EasyMock;
import org.geowebcache.MockWepAppContextRule;
import org.geowebcache.filter.parameters.ParameterFilter;
import org.geowebcache.filter.parameters.RegexParameterFilter;
import org.geowebcache.filter.parameters.StringParameterFilter;
import org.geowebcache.grid.BoundingBox;
import org.geowebcache.grid.GridSubset;
import org.geowebcache.layer.TileLayer;
Expand All @@ -58,6 +65,41 @@ public void setUp() throws Exception {
service.setTileBreeder(breeder);
}

@Test
public void testEscaping() throws Exception {
String unescapedLayer = "layer\"><";
String escapedLayer = "layer&quot;&gt;&lt;";
String unescapedString = "string\"><";
String escapedString = "string&quot;&gt;&lt;";
String unescapedRegex = "regex\"><";
String escapedRegex = "regex&quot;&gt;&lt;";
StringParameterFilter stringFilter = new StringParameterFilter();
stringFilter.setKey(unescapedString);
RegexParameterFilter regexFilter = new RegexParameterFilter();
regexFilter.setKey(unescapedRegex);
List<ParameterFilter> filters = Arrays.asList(stringFilter, regexFilter);

TileLayer tl = EasyMock.createMock("tl", TileLayer.class);
expect(breeder.findTileLayer(unescapedLayer)).andReturn(tl);
expect(tl.getName()).andStubReturn(unescapedLayer);
expect(breeder.getRunningAndPendingTasks()).andReturn(Collections.emptyIterator()).times(2);
expect(tl.getGridSubsets()).andReturn(Collections.emptySet()).times(4);
expect(tl.getMimeTypes()).andReturn(Collections.emptyList());
expect(tl.getParameterFilters()).andReturn(filters);
replay(tl, breeder);
ResponseEntity<?> response = service.handleGet(null, unescapedLayer);
verify(tl, breeder);

assertEquals(HttpStatus.OK, response.getStatusCode());
String body = (String) response.getBody();
assertThat(body, not(containsString(unescapedLayer)));
assertThat(body, containsString(escapedLayer));
assertThat(body, not(containsString(unescapedString)));
assertThat(body, containsString(escapedString));
assertThat(body, not(containsString(unescapedRegex)));
assertThat(body, containsString(escapedRegex));
}

@Test
public void testKill() {
Map<String, String> form = new HashMap<>();
Expand Down

0 comments on commit c0ca08a

Please sign in to comment.