From 228f1b866a9cfd75eb8c81b4adc031efd1dd70f8 Mon Sep 17 00:00:00 2001 From: Steve Ikeoka Date: Thu, 18 Apr 2024 12:45:51 -0700 Subject: [PATCH] [GWC-1234] Refactor inline JavaScript in the Demo Page --- .../main/java/org/geowebcache/demo/Demo.java | 384 +++--------------- .../org/geowebcache/rest/webresources/demo.js | 278 +++++++++++++ .../test/java/org/geowebcache/DemoTest.java | 51 ++- 3 files changed, 373 insertions(+), 340 deletions(-) create mode 100644 geowebcache/core/src/main/resources/org/geowebcache/rest/webresources/demo.js diff --git a/geowebcache/core/src/main/java/org/geowebcache/demo/Demo.java b/geowebcache/core/src/main/java/org/geowebcache/demo/Demo.java index f5d4c9a81..5faae2d8e 100644 --- a/geowebcache/core/src/main/java/org/geowebcache/demo/Demo.java +++ b/geowebcache/core/src/main/java/org/geowebcache/demo/Demo.java @@ -15,7 +15,6 @@ package org.geowebcache.demo; import static org.apache.commons.text.StringEscapeUtils.escapeHtml4; -import static org.owasp.encoder.Encode.forJavaScript; import java.io.IOException; import java.util.ArrayList; @@ -50,7 +49,6 @@ import org.geowebcache.mime.MimeType; import org.geowebcache.mime.XMLMime; import org.geowebcache.util.ServletUtils; -import org.owasp.encoder.Encode; import org.springframework.util.Assert; public class Demo { @@ -291,7 +289,7 @@ private static String generateHTML(TileLayer layer, String gridSetStr, String fo formatMime = layer.getDefaultMimeType(); } - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); String openLayersPath = "../rest/web/openlayers3/"; @@ -306,7 +304,7 @@ private static String generateHTML(TileLayer layer, String gridSetStr, String fo + "body { font-family: sans-serif; font-weight: bold; font-size: .8em; }\n" + "body { border: 0px; margin: 0px; padding: 0px; }\n" + "#map { width: 85%; height: 85%; border: 0px; padding: 0px; }\n" - + "#info iframe {border: none;}\n" + + "#info iframe { width: 100%; height: 250px; border: none; }\n" + ".ol-scale-value {top: 24px; right: 8px; position: absolute; }\n" + ".ol-zoom-value {top: 40px; right: 8px; position: absolute; }\n" + "\n"); @@ -315,80 +313,26 @@ private static String generateHTML(TileLayer layer, String gridSetStr, String fo buf.append("\n"); - buf.append( - "\n"); + buf.append("\n" + "\n"); + buf.append("
") + .append(makeModifiableParameters(layer)) + .append("
\n"); + + buf.append("
\n" + "
\n"); + + // add parameters in hidden inputs + makeHiddenInput(buf, "dpi", Double.toString(gridSubset.getDotsPerInch())); + makeHiddenInput(buf, "gridsetName", gridSubset.getGridSet().getName()); + makeHiddenInput( + buf, + "gridNames", + Arrays.stream(gridSubset.getGridNames()) + .map(s -> String.format("\"%s\"", s)) + .collect(Collectors.joining(", ", "[", "]"))); + makeHiddenInput(buf, "format", formatStr); + makeHiddenInput(buf, "layerName", layerName); + makeHiddenInput(buf, "SRS", gridSubset.getSRS().toString()); String unit = ""; double mpu = gridSet.getMetersPerUnit(); @@ -401,270 +345,51 @@ private static String generateHTML(TileLayer layer, String gridSetStr, String fo mpu, Math.PI * (6378137 + 6356752) / 360, Math.PI * (6378137 - 6356752) / 360)) { unit = "degrees"; } + makeHiddenInput(buf, "unit", unit); - buf.append("var projection = new ol.proj.Projection({\n") - .append("code: '") - .append(gridSubset.getSRS().toString()) - .append("',\n") - .append("units: '") - .append(unit) - .append("',\n") - .append("axisOrientation: 'neu'\n") - .append("});\n"); - buf.append("var resolutions = ") - .append(Arrays.toString(gridSubset.getResolutions())) - .append(";\n"); + makeHiddenInput(buf, "resolutions", Arrays.toString(gridSubset.getResolutions())); + makeHiddenInput(buf, "tileWidth", Integer.toString(gridSubset.getTileWidth())); + makeHiddenInput(buf, "tileHeight", Integer.toString(gridSubset.getTileHeight())); + makeHiddenInput(buf, "minX", Double.toString(bbox.getMinX())); + makeHiddenInput(buf, "maxY", Double.toString(bbox.getMaxY())); + makeHiddenInput(buf, "isVector", Boolean.toString(formatMime.isVector())); if (formatMime.isVector()) { - buf.append( - "params = {\n" - + " 'REQUEST': 'GetTile',\n" - + " 'SERVICE': 'WMTS',\n" - + " 'VERSION': '1.0.0',\n" - + " 'LAYER': layerName,\n" - + " 'STYLE': style,\n" - + " 'TILEMATRIX': gridsetName + ':{z}',\n" - + " 'TILEMATRIXSET': gridsetName,\n" - + " 'FORMAT': format,\n" - + " 'TILECOL': '{x}',\n" - + " 'TILEROW': '{y}'\n" - + "};\n" - + "\n"); - buf.append( - "function constructSource() {\n" - + " var url = baseUrl+'?'\n" - + " for (var param in params) {\n" - + " url = url + param + '=' + params[param] + '&';\n" - + " }\n" - + " url = url.slice(0, -1);\n" - + "\n" - + " var source = new ol.source.VectorTile({\n" - + " url: url,\n"); // Examine mime type for correct VT format String vtName = formatMime.getInternalName(); if (ApplicationMime.mapboxVector.getInternalName().equals(vtName)) { - buf.append(" format: new ol.format.MVT({}),\n"); + makeHiddenInput(buf, "vtFormatName", "MVT"); } else if (ApplicationMime.topojson.getInternalName().equals(vtName)) { - buf.append(" format: new ol.format.TopoJSON({}),\n"); + makeHiddenInput(buf, "vtFormatName", "TopoJSON"); } else if (ApplicationMime.geojson.getInternalName().equals(vtName)) { - buf.append(" format: new ol.format.GeoJSON({}),\n"); + makeHiddenInput(buf, "vtFormatName", "GeoJSON"); } - buf.append(" projection: projection,\n" + " tileGrid: new ol.tilegrid.WMTS({\n"); - buf.append(" tileSize: [") - .append(gridSubset.getTileWidth()) - .append(",") - .append(gridSubset.getTileHeight()) - .append("],\n"); - buf.append(" origin: [") - .append(bbox.getMinX()) - .append(", ") - .append(bbox.getMaxY()) - .append("],\n"); - buf.append( - " resolutions: resolutions,\n" - + " matrixIds: gridNames\n" - + " }),\n" - + " wrapX: true\n" - + " });\n" - + " return source;\n" - + "}\n" - + "\n" - + "var layer = new ol.layer.VectorTile({\n" - + " source: constructSource()\n" - + "});\n" - + "\n"); - } else { - buf.append( - "baseParams = ['VERSION','LAYER','STYLE','TILEMATRIX','TILEMATRIXSET','SERVICE','FORMAT'];\n" - + "\n" - + "params = {\n" - + " 'VERSION': '1.0.0',\n" - + " 'LAYER': layerName,\n" - + " 'STYLE': style,\n" - + " 'TILEMATRIX': gridNames,\n" - + " 'TILEMATRIXSET': gridsetName,\n" - + " 'SERVICE': 'WMTS',\n" - + " 'FORMAT': format\n" - + "};\n" - + "\n"); - buf.append( - "function constructSource() {\n" - + " var url = baseUrl+'?'\n" - + " for (var param in params) {\n" - + " if (baseParams.indexOf(param.toUpperCase()) < 0) {\n" - + " url = url + param + '=' + params[param] + '&';\n" - + " }\n" - + " }\n" - + " url = url.slice(0, -1);\n" - + "\n" - + " var source = new ol.source.WMTS({\n" - + " url: url,\n" - + " layer: params['LAYER'],\n" - + " matrixSet: params['TILEMATRIXSET'],\n" - + " format: params['FORMAT'],\n" - + " projection: projection,\n" - + " tileGrid: new ol.tilegrid.WMTS({\n"); - buf.append(" tileSize: [") - .append(gridSubset.getTileWidth()) - .append(",") - .append(gridSubset.getTileHeight()) - .append("],\n"); - buf.append(" extent: [") - .append(bbox.getMinX()) - .append(",") - .append(bbox.getMinY()) - .append(",") - .append(bbox.getMaxX()) - .append(",") - .append(bbox.getMaxY()) - .append("],\n"); - + makeHiddenInput(buf, "maxX", Double.toString(bbox.getMaxX())); + makeHiddenInput(buf, "minY", Double.toString(bbox.getMinY())); + makeHiddenInput(buf, "fullGrid", Boolean.toString(gridSubset.fullGridSetCoverage())); if (gridSubset.fullGridSetCoverage()) { - buf.append(" origins: ["); + StringBuilder origin = new StringBuilder().append("["); for (int i = 0; i < gridSubset.getResolutions().length; i++) { if (i != 0) { - buf.append(","); + origin.append(","); } BoundingBox subbox = gridSubset.getCoverageBounds(i); - buf.append("[") + origin.append("[") .append(subbox.getMinX()) .append(", ") .append(subbox.getMaxY()) .append("]"); } - buf.append("],\n"); + makeHiddenInput(buf, "origins", origin.append("]").toString()); } else { - buf.append(" origin: [") - .append(bbox.getMinX()) - .append(", ") - .append(bbox.getMaxY()) - .append("],\n"); + makeHiddenInput(buf, "origin", "[" + bbox.getMinX() + ", " + bbox.getMaxY() + "]"); } - buf.append( - " resolutions: resolutions,\n" - + " matrixIds: params['TILEMATRIX']\n" - + " }),\n" - + " style: params['STYLE'],\n" - + " wrapX: true\n" - + " });\n" - + " return source;\n" - + "}\n" - + "\n" - + "var layer = new ol.layer.Tile({\n" - + " source: constructSource()\n" - + "});\n" - + "\n"); } - buf.append( - "var view = new ol.View({\n" - + " center: [0, 0],\n" - + " zoom: 2,\n" - + " resolutions: resolutions,\n" - + " projection: projection,\n"); - buf.append(" extent: [").append(bbox.toString()).append("]\n"); - buf.append( - "});\n" - + "\n" - + "var map = new ol.Map({\n" - + " controls: ol.control.defaults({attribution: false}).extend([\n" - + " new ol.control.MousePosition(),\n" - + " new ScaleControl(),\n" - + " new ZoomControl()\n" - + " ]),\n" - + " layers: [layer],\n" - + " target: 'map',\n" - + " view: view\n" - + "});\n"); - buf.append("map.getView().fit([") - .append(zoomBounds.toString()) - .append("], map.getSize());\n"); - buf.append( - "\n" - + "window.setParam = function(name, value) {\n" - + " if (name == \"STYLES\") {\n" - + " name = \"STYLE\"\n" - + " }\n" - + " params[name] = value;\n" - + " layer.setSource(constructSource());\n" - + " map.updateSize();\n" - + "} \n" - + "\n" - + "map.on('singleclick', function(evt) {\n" - + " document.getElementById('info').innerHTML = '';\n" - + "\n" - + " var source = layer.getSource();\n" - + " var resolution = view.getResolution();\n" - + " var tilegrid = source.getTileGrid();\n" - + " var tileResolutions = tilegrid.getResolutions();\n" - + " var zoomIdx, diff = Infinity;\n" - + "\n" - + " for (var i = 0; i < tileResolutions.length; i++) {\n" - + " var tileResolution = tileResolutions[i];\n" - + " var diffP = Math.abs(resolution-tileResolution);\n" - + " if (diffP < diff) {\n" - + " diff = diffP;\n" - + " zoomIdx = i;\n" - + " }\n" - + " if (tileResolution < resolution) {\n" - + " break;\n" - + " }\n" - + " }\n" - + " var tileSize = tilegrid.getTileSize(zoomIdx);\n" - + " var tileOrigin = tilegrid.getOrigin(zoomIdx);\n" - + "\n" - + " var fx = (evt.coordinate[0] - tileOrigin[0]) / (resolution * tileSize[0]);\n" - + " var fy = (tileOrigin[1] - evt.coordinate[1]) / (resolution * tileSize[1]);\n" - + " var tileCol = Math.floor(fx);\n" - + " var tileRow = Math.floor(fy);\n" - + " var tileI = Math.floor((fx - tileCol) * tileSize[0]);\n" - + " var tileJ = Math.floor((fy - tileRow) * tileSize[1]);\n" - + " var matrixIds = tilegrid.getMatrixIds()[zoomIdx];\n" - + " var matrixSet = source.getMatrixSet();\n" - + "\n" - + " var url = baseUrl+'?'\n" - + " for (var param in params) {\n" - + " if (param.toUpperCase() == 'TILEMATRIX') {\n" - + " url = url + 'TILEMATRIX='+matrixIds+'&';\n" - + " } else {\n" - + " url = url + param + '=' + params[param] + '&';\n" - + " }\n" - + " }\n" - + "\n" - + " url = url\n" - + " + 'SERVICE=WMTS&REQUEST=GetFeatureInfo'\n" - + " + '&INFOFORMAT=' + infoFormat\n" - + " + '&TileCol=' + tileCol\n" - + " + '&TileRow=' + tileRow\n" - + " + '&I=' + tileI\n" - + " + '&J=' + tileJ;\n" - + "\n" - + " if (url) {\n" - + " document.getElementById('info').innerHTML = 'Loading... please wait...';\n" - + " var xmlhttp = new XMLHttpRequest();" - + " xmlhttp.onreadystatechange = function() {\n" - + " if (xmlhttp.readyState == XMLHttpRequest.DONE ) {\n" - + " if (xmlhttp.status == 200) {\n" - + " document.getElementById('info').innerHTML = xmlhttp.responseText;\n" - + " }\n" - + " else {\n" - + " document.getElementById('info').innerHTML = '';\n" - + " }\n" - + " }\n" - + " }\n" - + " xmlhttp.open('GET', url, true);\n" - + " xmlhttp.send();\n" - + " }\n" - + "});\n" - + "}\n"); - buf.append("\n" + "\n" + "\n"); - buf.append("
") - .append(makeModifiableParameters(layer)) - .append("
\n"); - - buf.append("
\n" + "
\n\n" + ""); - return buf.toString(); + makeHiddenInput(buf, "bbox", "[" + bbox + "]"); + makeHiddenInput(buf, "zoomBounds", "[" + zoomBounds + "]"); + return buf.append("\n").toString(); } private static String makeModifiableParameters(TileLayer tl) { @@ -731,14 +456,17 @@ private static Map makeParametersMap( return map; } + private static void makeHiddenInput(StringBuilder doc, String id, String value) { + doc.append("\n"); + } + private static void makePullDown( StringBuilder doc, String id, Map keysValues, String defaultKey) { - doc.append( - "\n"); Iterator> iter = keysValues.entrySet().iterator(); @@ -768,13 +496,7 @@ private static void makePullDown( private static void makeTextInput(StringBuilder doc, String id, int size) { doc.append( - "\n"); + "\n"); } private static boolean doubleEquals(double d1, double d2) { diff --git a/geowebcache/core/src/main/resources/org/geowebcache/rest/webresources/demo.js b/geowebcache/core/src/main/resources/org/geowebcache/rest/webresources/demo.js new file mode 100644 index 000000000..0a675b263 --- /dev/null +++ b/geowebcache/core/src/main/resources/org/geowebcache/rest/webresources/demo.js @@ -0,0 +1,278 @@ + +window.onload = function() { + + function getValue(id) { + return document.getElementById('hidden_' + id).value; + } + + function ScaleControl(opt_options) { + var options = opt_options || {}; + var element = document.createElement('div'); + element.setAttribute('id', 'scale'); + element.className = 'ol-scale-value'; + ol.control.Control.call(this, { + element: element, + target: options.target + }); + }; + ol.inherits(ScaleControl, ol.control.Control); + ScaleControl.prototype.setMap = function(map) { + map.on('postrender', function() { + var view = map.getView(); + var resolution = view.getResolution(); + var dpi = parseFloat(getValue('dpi')); + var mpu = map.getView().getProjection().getMetersPerUnit(); + var scale = resolution * mpu * 39.37 * dpi; + if (scale >= 9500 && scale <= 950000) { + scale = Math.round(scale / 1000) + 'K'; + } else if (scale >= 950000) { + scale = Math.round(scale / 1000000) + 'M'; + } else { + scale = Math.round(scale); + } + document.getElementById('scale').innerHTML = 'Scale = 1 : ' + scale; + }, this); + ol.control.Control.prototype.setMap.call(this, map); + } + + function ZoomControl(opt_options) { + var options = opt_options || {}; + var element = document.createElement('div'); + element.setAttribute('id', 'zoom'); + element.className = 'ol-zoom-value'; + ol.control.Control.call(this, { + element: element, + target: options.target + }); + }; + ol.inherits(ZoomControl, ol.control.Control); + ZoomControl.prototype.setMap = function(map) { + map.on('moveend', function() { + var view = map.getView(); + document.getElementById('zoom').innerHTML = 'Zoom level = ' + view.getZoom(); + }, this); + ol.control.Control.prototype.setMap.call(this, map); + } + + var gridsetName = getValue('gridsetName'); + var gridNames = JSON.parse(getValue('gridNames')); + var baseUrl = '../service/wmts'; + var style = ''; + var format = getValue('format') + var infoFormat = 'text/html'; + var layerName = getValue('layerName') + var projection = new ol.proj.Projection({ + code: getValue('SRS'), + units: getValue('unit'), + axisOrientation: 'neu' + }); + var resolutions = JSON.parse(getValue('resolutions')); + + if (getValue('isVector') == 'true') { + var params = { + 'REQUEST': 'GetTile', + 'SERVICE': 'WMTS', + 'VERSION': '1.0.0', + 'LAYER': layerName, + 'STYLE': style, + 'TILEMATRIX': gridsetName + ':{z}', + 'TILEMATRIXSET': gridsetName, + 'FORMAT': format, + 'TILECOL': '{x}', + 'TILEROW': '{y}' + }; + + function constructSource() { + var url = baseUrl+'?' + for (var param in params) { + url = url + param + '=' + params[param] + '&'; + } + url = url.slice(0, -1); + + var sourceParams = { + url: url, + projection: projection, + tileGrid: new ol.tilegrid.WMTS({ + tileSize: [ + parseInt(getValue('tileWidth')), + parseInt(getValue('tileHeight')) + ], + origin: [ + parseFloat(getValue('minX')), + parseFloat(getValue('maxY')) + ], + resolutions: resolutions, + matrixIds: gridNames + }), + wrapX: true + }; + if (getValue('vtFormatName') == 'MVT') { + sourceParams.format = new ol.format.MVT({}); + } else if (getValue('vtFormatName') == 'TopoJSON') { + sourceParams.format = new ol.format.TopoJSON({}); + } else if (getValue('vtFormatName') == 'GeoJSON') { + sourceParams.format = new ol.format.GeoJSON({}); + } + var source = new ol.source.VectorTile(sourceParams); + return source; + } + + var layer = new ol.layer.VectorTile({ + source: constructSource() + }); + } else { + baseParams = ['VERSION','LAYER','STYLE','TILEMATRIX','TILEMATRIXSET','SERVICE','FORMAT']; + + var params = { + 'VERSION': '1.0.0', + 'LAYER': layerName, + 'STYLE': style, + 'TILEMATRIX': gridNames, + 'TILEMATRIXSET': gridsetName, + 'SERVICE': 'WMTS', + 'FORMAT': format + }; + + function constructSource() { + var url = baseUrl+'?' + for (var param in params) { + if (baseParams.indexOf(param.toUpperCase()) < 0) { + url = url + param + '=' + params[param] + '&'; + } + } + url = url.slice(0, -1); + + var tileGridParameters = { + tileSize: [ + parseInt(getValue('tileWidth')), + parseInt(getValue('tileHeight')) + ], + extent: [ + parseFloat(getValue('minX')), + parseFloat(getValue('minY')), + parseFloat(getValue('maxX')), + parseFloat(getValue('maxY')) + ], + resolutions: resolutions, + matrixIds: params['TILEMATRIX'] + }; + if (getValue('fullGrid') == 'true') { + tileGridParameters.origins = JSON.parse(getValue('origins')); + } else { + tileGridParameters.origin = JSON.parse(getValue('origin')); + } + var source = new ol.source.WMTS({ + url: url, + layer: params['LAYER'], + matrixSet: params['TILEMATRIXSET'], + format: params['FORMAT'], + projection: projection, + tileGrid: new ol.tilegrid.WMTS(tileGridParameters), + style: params['STYLE'], + wrapX: true + }); + return source; + } + + var layer = new ol.layer.Tile({ + source: constructSource() + }); + } + + var view = new ol.View({ + center: [0, 0], + zoom: 2, + resolutions: resolutions, + projection: projection, + extent: JSON.parse(getValue('bbox')) + }); + + var map = new ol.Map({ + controls: ol.control.defaults({attribution: false}).extend([ + new ol.control.MousePosition(), + new ScaleControl(), + new ZoomControl() + ]), + layers: [layer], + target: 'map', + view: view + }); + map.getView().fit(JSON.parse(getValue('zoomBounds')), map.getSize()); + + function setParam(name, value) { + if (name == 'STYLES') { + name = 'STYLE' + } + params[name] = value; + layer.setSource(constructSource()); + map.updateSize(); + } + + map.on('singleclick', function(evt) { + document.getElementById('info').innerHTML = ''; + + var source = layer.getSource(); + var resolution = view.getResolution(); + var tilegrid = source.getTileGrid(); + var tileResolutions = tilegrid.getResolutions(); + var zoomIdx, diff = Infinity; + + for (var i = 0; i < tileResolutions.length; i++) { + var tileResolution = tileResolutions[i]; + var diffP = Math.abs(resolution-tileResolution); + if (diffP < diff) { + diff = diffP; + zoomIdx = i; + } + if (tileResolution < resolution) { + break; + } + } + var tileSize = tilegrid.getTileSize(zoomIdx); + var tileOrigin = tilegrid.getOrigin(zoomIdx); + + var fx = (evt.coordinate[0] - tileOrigin[0]) / (resolution * tileSize[0]); + var fy = (tileOrigin[1] - evt.coordinate[1]) / (resolution * tileSize[1]); + var tileCol = Math.floor(fx); + var tileRow = Math.floor(fy); + var tileI = Math.floor((fx - tileCol) * tileSize[0]); + var tileJ = Math.floor((fy - tileRow) * tileSize[1]); + var matrixIds = tilegrid.getMatrixIds()[zoomIdx]; + var matrixSet = source.getMatrixSet(); + + var url = baseUrl+'?' + for (var param in params) { + if (param.toUpperCase() == 'TILEMATRIX') { + url = url + 'TILEMATRIX='+matrixIds+'&'; + } else { + url = url + param + '=' + params[param] + '&'; + } + } + + url = url + + 'SERVICE=WMTS&REQUEST=GetFeatureInfo' + + '&INFOFORMAT=' + infoFormat + + '&TileCol=' + tileCol + + '&TileRow=' + tileRow + + '&I=' + tileI + + '&J=' + tileJ; + document.getElementById('info').innerHTML = + ''; + }); + + // set event handlers + function paramHandler(event) { + setParam(event.target.name, event.target.value); + } + var inputs = document.getElementsByTagName('select'); + for (var i = 0; i < inputs.length; i++) { + inputs[i].onchange = paramHandler; + } + inputs = document.getElementsByTagName('input'); + for (i = 0; i < inputs.length; i++) { + if (inputs[i].type == 'text') { + inputs[i].onblur = paramHandler; + } + } + +}; diff --git a/geowebcache/core/src/test/java/org/geowebcache/DemoTest.java b/geowebcache/core/src/test/java/org/geowebcache/DemoTest.java index ada179693..c5d6dde10 100644 --- a/geowebcache/core/src/test/java/org/geowebcache/DemoTest.java +++ b/geowebcache/core/src/test/java/org/geowebcache/DemoTest.java @@ -1,8 +1,8 @@ package org.geowebcache; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.not; -import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -136,10 +136,8 @@ public void testEscapingWithoutLayer() throws Exception { public void testEscapingWithLayer() throws Exception { String unescapedLayer = "layer'\"><"; String escapedLayer = "layer'"><"; - String escapedLayerJS = "layer\\x27\\x22><"; String unescapedSubset = "ESPG:1234'\"><"; String escapedSubset = "ESPG:1234'"><"; - String escapedSubsetJS = "ESPG:1234\\x27\\x22><"; GridSet gridSet = mock(GridSet.class); when(gridSet.getName()).thenReturn(unescapedSubset); @@ -161,10 +159,8 @@ public void testEscapingWithLayer() throws Exception { String unescapedString = "string'\"><"; String escapedString = "string'"><"; - String escapedStringJS = "string\\x27\\x22><"; String unescapedRegex = "regex'\"><"; String escapedRegex = "regex'"><"; - String escapedRegexJS = "regex\\x27\\x22><"; StringParameterFilter stringFilter = new StringParameterFilter(); stringFilter.setKey(unescapedString); RegexParameterFilter regexFilter = new RegexParameterFilter(); @@ -180,15 +176,52 @@ public void testEscapingWithLayer() throws Exception { assertThat(result, not(containsString(unescapedLayer))); assertThat(result, containsString(escapedLayer)); - assertThat(result, containsString(escapedLayerJS)); assertThat(result, not(containsString(unescapedSubset))); assertThat(result, containsString(escapedSubset)); - assertThat(result, containsString(escapedSubsetJS)); assertThat(result, not(containsString(unescapedString))); assertThat(result, containsString(escapedString)); - assertThat(result, containsString(escapedStringJS)); assertThat(result, not(containsString(unescapedRegex))); assertThat(result, containsString(escapedRegex)); - assertThat(result, containsString(escapedRegexJS)); + } + + @Test + public void testRemovedInlineJavaScript() throws Exception { + GridSet gridSet = mock(GridSet.class); + when(gridSet.getName()).thenReturn("EPSG:4326"); + + GridSubset subSet = mock(GridSubset.class); + when(subSet.getName()).thenReturn("EPSG:4326"); + when(subSet.getGridSet()).thenReturn(gridSet); + when(subSet.getGridNames()).thenReturn(new String[] {"EPSG:4326"}); + when(subSet.getSRS()).thenReturn(SRS.getEPSG4326()); + when(subSet.getGridSetBounds()).thenReturn(BoundingBox.WORLD4326); + when(subSet.getOriginalExtent()).thenReturn(BoundingBox.WORLD4326); + + TileLayer layer = mock(TileLayer.class); + when(layer.getName()).thenReturn("layer"); + when(layer.isAdvertised()).thenReturn(true); + when(layer.getGridSubsets()).thenReturn(Collections.singleton("EPSG:4326")); + when(layer.getGridSubset("EPSG:4326")).thenReturn(subSet); + when(layer.getDefaultMimeType()).thenReturn(MimeType.createFromFormat("image/png")); + + StringParameterFilter stringFilter = new StringParameterFilter(); + stringFilter.setKey("STRING"); + RegexParameterFilter regexFilter = new RegexParameterFilter(); + regexFilter.setKey("REGEX"); + when(layer.getParameterFilters()).thenReturn(Arrays.asList(stringFilter, regexFilter)); + + TileLayerDispatcher tld = mock(TileLayerDispatcher.class); + when(tld.getTileLayer("layer")).thenReturn(layer); + + MockHttpServletResponse response = new MockHttpServletResponse(); + Demo.makeMap(tld, null, "layer", new MockHttpServletRequest(), response); + String result = response.getContentAsString(); + + assertThat( + result, containsString("")); + assertThat(result, containsString("")); + assertThat(result, not(containsString("