diff --git a/DynmapCore/src/main/java/org/dynmap/Client.java b/DynmapCore/src/main/java/org/dynmap/Client.java index 902bf5bd..b9d2d95e 100644 --- a/DynmapCore/src/main/java/org/dynmap/Client.java +++ b/DynmapCore/src/main/java/org/dynmap/Client.java @@ -4,8 +4,11 @@ import java.io.IOException; import java.io.Writer; import java.util.Random; +import javax.sound.sampled.AudioFormat.Encoding; + import org.json.simple.JSONAware; import org.json.simple.JSONStreamAware; +import org.owasp.html.HtmlPolicyBuilder; import org.owasp.html.PolicyFactory; import org.owasp.html.Sanitizers; import org.dynmap.common.DynmapChatColor; @@ -290,6 +293,43 @@ public class Client { s = Sanitizers.FORMATTING.and(Sanitizers.BLOCKS).and(Sanitizers.IMAGES).and(Sanitizers.LINKS).and(Sanitizers.STYLES); sanitizer = s; } - return sanitizer.sanitize(html); + return s.sanitize(html); } + private static PolicyFactory stripper = null; + public static String stripHTML(String html) { + PolicyFactory s = stripper; + if (s == null) { + // Strip all taks + s = new HtmlPolicyBuilder().toFactory(); + stripper = s; + } + return s.sanitize(html); + } + // Encode plain text string for HTML presentation + public static String encodeForHTML(String text) { + String s = text != null ? text : ""; + StringBuilder str = new StringBuilder(); + + for (int j = 0; j < s.length(); j++) { + char c = s.charAt(j); + switch (c) { + case '"': + str.append("""); + break; + case '&': + str.append("&"); + break; + case '<': + str.append("<"); + break; + case '>': + str.append(">"); + break; + default: + str.append(c); + break; + } + } + return str.toString(); + } } diff --git a/DynmapCore/src/main/java/org/dynmap/markers/impl/AreaMarkerImpl.java b/DynmapCore/src/main/java/org/dynmap/markers/impl/AreaMarkerImpl.java index bed05fb6..265451af 100644 --- a/DynmapCore/src/main/java/org/dynmap/markers/impl/AreaMarkerImpl.java +++ b/DynmapCore/src/main/java/org/dynmap/markers/impl/AreaMarkerImpl.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.dynmap.Client; import org.dynmap.ConfigurationNode; import org.dynmap.DynmapWorld; import org.dynmap.Log; @@ -72,9 +73,9 @@ class AreaMarkerImpl implements AreaMarker, EnterExitMarker { AreaMarkerImpl(String id, String lbl, boolean markup, String world, double x[], double z[], boolean persistent, MarkerSetImpl set) { markerid = id; if(lbl != null) - label = lbl; + label = markup ? lbl : Client.encodeForHTML(lbl); else - label = id; + label = markup ? id : Client.encodeForHTML(id); this.markup = markup; this.corners = new ArrayList(); for(int i = 0; i < x.length; i++) { @@ -104,7 +105,7 @@ class AreaMarkerImpl implements AreaMarker, EnterExitMarker { AreaMarkerImpl(String id, MarkerSetImpl set) { markerid = id; markerset = set; - label = id; + label = Client.encodeForHTML(id); markup = false; desc = null; corners = new ArrayList(); @@ -215,7 +216,12 @@ class AreaMarkerImpl implements AreaMarker, EnterExitMarker { @Override public void setLabel(String lbl, boolean markup) { if(markerset == null) return; - label = lbl; + if (markup) { + label = lbl; + } + else { // If not markup, escape any HTML-active characters (<>&"') + label = Client.encodeForHTML(lbl); + } this.markup = markup; MarkerAPIImpl.areaMarkerUpdated(this, MarkerUpdate.UPDATED); if(ispersistent) diff --git a/DynmapCore/src/main/java/org/dynmap/markers/impl/CircleMarkerImpl.java b/DynmapCore/src/main/java/org/dynmap/markers/impl/CircleMarkerImpl.java index ca3e7be4..ce2b4a7e 100644 --- a/DynmapCore/src/main/java/org/dynmap/markers/impl/CircleMarkerImpl.java +++ b/DynmapCore/src/main/java/org/dynmap/markers/impl/CircleMarkerImpl.java @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.dynmap.Client; import org.dynmap.ConfigurationNode; import org.dynmap.DynmapWorld; import org.dynmap.hdmap.HDPerspective; @@ -64,9 +65,9 @@ class CircleMarkerImpl implements CircleMarker, EnterExitMarker { CircleMarkerImpl(String id, String lbl, boolean markup, String world, double x, double y, double z, double xr, double zr, boolean persistent, MarkerSetImpl set) { markerid = id; if(lbl != null) - label = lbl; + label = markup ? lbl : Client.encodeColorInHTML(lbl); else - label = id; + label = markup ? id : Client.encodeColorInHTML(id); this.markup = markup; this.x = x; this.y = y; this.z = z; this.xr = xr; this.zr = zr; @@ -86,7 +87,7 @@ class CircleMarkerImpl implements CircleMarker, EnterExitMarker { CircleMarkerImpl(String id, MarkerSetImpl set) { markerid = id; markerset = set; - label = id; + label = Client.encodeForHTML(id); markup = false; desc = null; world = normalized_world = "world"; @@ -191,7 +192,7 @@ class CircleMarkerImpl implements CircleMarker, EnterExitMarker { @Override public void setLabel(String lbl, boolean markup) { - label = lbl; + label = markup ? lbl : Client.encodeForHTML(lbl); this.markup = markup; MarkerAPIImpl.circleMarkerUpdated(this, MarkerUpdate.UPDATED); if(ispersistent) diff --git a/DynmapCore/src/main/java/org/dynmap/markers/impl/MarkerAPIImpl.java b/DynmapCore/src/main/java/org/dynmap/markers/impl/MarkerAPIImpl.java index af39003a..c4d1e34d 100644 --- a/DynmapCore/src/main/java/org/dynmap/markers/impl/MarkerAPIImpl.java +++ b/DynmapCore/src/main/java/org/dynmap/markers/impl/MarkerAPIImpl.java @@ -102,14 +102,14 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener { public MarkerUpdated(Marker m, boolean deleted) { this.id = m.getMarkerID(); - this.label = m.getLabel(); + this.label = Client.sanitizeHTML(m.getLabel()); this.x = m.getX(); this.y = m.getY(); this.z = m.getZ(); this.set = m.getMarkerSet().getMarkerSetID(); this.icon = m.getMarkerIcon().getMarkerIconID(); this.markup = m.isLabelMarkup(); - this.desc = m.getDescription(); + this.desc = Client.sanitizeHTML(m.getDescription()); this.dim = m.getMarkerIcon().getMarkerIconSize().getSize(); this.minzoom = m.getMinZoom(); this.maxzoom = m.getMaxZoom(); @@ -153,7 +153,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener { public AreaMarkerUpdated(AreaMarker m, boolean deleted) { this.id = m.getMarkerID(); - this.label = m.getLabel(); + this.label = Client.sanitizeHTML(m.getLabel()); this.ytop = m.getTopY(); this.ybottom = m.getBottomY(); int cnt = m.getCornerCount(); @@ -168,7 +168,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener { opacity = m.getLineOpacity(); fillcolor = String.format("#%06X", m.getFillColor()); fillopacity = m.getFillOpacity(); - desc = m.getDescription(); + desc = Client.sanitizeHTML(m.getDescription()); this.minzoom = m.getMinZoom(); this.maxzoom = m.getMaxZoom(); this.markup = m.isLabelMarkup(); @@ -210,7 +210,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener { public PolyLineMarkerUpdated(PolyLineMarker m, boolean deleted) { this.id = m.getMarkerID(); - this.label = m.getLabel(); + this.label = Client.sanitizeHTML(m.getLabel()); int cnt = m.getCornerCount(); x = new double[cnt]; y = new double[cnt]; @@ -223,7 +223,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener { color = String.format("#%06X", m.getLineColor()); weight = m.getLineWeight(); opacity = m.getLineOpacity(); - desc = m.getDescription(); + desc = Client.sanitizeHTML(m.getDescription()); this.minzoom = m.getMinZoom(); this.maxzoom = m.getMaxZoom(); @@ -268,7 +268,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener { public CircleMarkerUpdated(CircleMarker m, boolean deleted) { this.id = m.getMarkerID(); - this.label = m.getLabel(); + this.label = Client.sanitizeHTML(m.getLabel()); this.x = m.getCenterX(); this.y = m.getCenterY(); this.z = m.getCenterZ(); @@ -279,7 +279,7 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener { opacity = m.getLineOpacity(); fillcolor = String.format("#%06X", m.getFillColor()); fillopacity = m.getFillOpacity(); - desc = m.getDescription(); + desc = Client.sanitizeHTML(m.getDescription()); this.minzoom = m.getMinZoom(); this.maxzoom = m.getMaxZoom(); @@ -3324,10 +3324,10 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener { mi = MarkerAPIImpl.getMarkerIconImpl(MarkerIcon.DEFAULT); mdata.put("icon", mi.getMarkerIconID()); mdata.put("dim", mi.getMarkerIconSize().getSize()); - mdata.put("label", Client.sanitizeHTML(m.getLabel())); + mdata.put("label", m.getLabel()); mdata.put("markup", m.isLabelMarkup()); if(m.getDescription() != null) - mdata.put("desc", Client.sanitizeHTML(m.getDescription())); + mdata.put("desc", m.getDescription()); if (m.getMinZoom() >= 0) { mdata.put("minzoom", m.getMinZoom()); } @@ -3360,10 +3360,10 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener { mdata.put("opacity", m.getLineOpacity()); mdata.put("fillopacity", m.getFillOpacity()); mdata.put("weight", m.getLineWeight()); - mdata.put("label", Client.sanitizeHTML(m.getLabel())); + mdata.put("label", m.getLabel()); mdata.put("markup", m.isLabelMarkup()); if(m.getDescription() != null) - mdata.put("desc", Client.sanitizeHTML(m.getDescription())); + mdata.put("desc", m.getDescription()); if (m.getMinZoom() >= 0) { mdata.put("minzoom", m.getMinZoom()); } @@ -3395,10 +3395,10 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener { mdata.put("color", String.format("#%06X", m.getLineColor())); mdata.put("opacity", m.getLineOpacity()); mdata.put("weight", m.getLineWeight()); - mdata.put("label", Client.sanitizeHTML(m.getLabel())); + mdata.put("label", m.getLabel()); mdata.put("markup", m.isLabelMarkup()); if(m.getDescription() != null) - mdata.put("desc", Client.sanitizeHTML(m.getDescription())); + mdata.put("desc", m.getDescription()); if (m.getMinZoom() >= 0) { mdata.put("minzoom", m.getMinZoom()); } @@ -3425,10 +3425,10 @@ public class MarkerAPIImpl implements MarkerAPI, Event.Listener { mdata.put("opacity", m.getLineOpacity()); mdata.put("fillopacity", m.getFillOpacity()); mdata.put("weight", m.getLineWeight()); - mdata.put("label", Client.sanitizeHTML(m.getLabel())); + mdata.put("label", m.getLabel()); mdata.put("markup", m.isLabelMarkup()); if(m.getDescription() != null) - mdata.put("desc", Client.sanitizeHTML(m.getDescription())); + mdata.put("desc", m.getDescription()); if (m.getMinZoom() >= 0) { mdata.put("minzoom", m.getMinZoom()); } diff --git a/DynmapCore/src/main/java/org/dynmap/markers/impl/MarkerImpl.java b/DynmapCore/src/main/java/org/dynmap/markers/impl/MarkerImpl.java index d9ef4512..17bed676 100644 --- a/DynmapCore/src/main/java/org/dynmap/markers/impl/MarkerImpl.java +++ b/DynmapCore/src/main/java/org/dynmap/markers/impl/MarkerImpl.java @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; +import org.dynmap.Client; import org.dynmap.ConfigurationNode; import org.dynmap.DynmapWorld; import org.dynmap.markers.Marker; @@ -40,9 +41,9 @@ class MarkerImpl implements Marker { MarkerImpl(String id, String lbl, boolean markup, String world, double x, double y, double z, MarkerIconImpl icon, boolean persistent, MarkerSetImpl set) { markerid = id; if(lbl != null) - label = lbl; + label = markup ? lbl : Client.encodeForHTML(lbl); else - label = id; + label = markup ? id : Client.encodeForHTML(lbl); this.markup = markup; this.x = x; this.y = y; this.z = z; this.world = world; @@ -62,7 +63,7 @@ class MarkerImpl implements Marker { MarkerImpl(String id, MarkerSetImpl set) { markerid = id; markerset = set; - label = id; + label = Client.encodeForHTML(id); markup = false; desc = null; x = z = 0; y = 64; world = normalized_world = "world"; @@ -167,7 +168,7 @@ class MarkerImpl implements Marker { @Override public void setLabel(String lbl, boolean markup) { if(markerset == null) return; - label = lbl; + label = markup ? lbl : Client.encodeForHTML(lbl); this.markup = markup; MarkerAPIImpl.markerUpdated(this, MarkerUpdate.UPDATED); if(ispersistent) diff --git a/DynmapCore/src/main/java/org/dynmap/markers/impl/PolyLineMarkerImpl.java b/DynmapCore/src/main/java/org/dynmap/markers/impl/PolyLineMarkerImpl.java index 6575ed29..07ca4010 100644 --- a/DynmapCore/src/main/java/org/dynmap/markers/impl/PolyLineMarkerImpl.java +++ b/DynmapCore/src/main/java/org/dynmap/markers/impl/PolyLineMarkerImpl.java @@ -5,6 +5,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.dynmap.Client; import org.dynmap.ConfigurationNode; import org.dynmap.DynmapWorld; import org.dynmap.markers.PolyLineMarker; @@ -49,9 +50,9 @@ class PolyLineMarkerImpl implements PolyLineMarker { PolyLineMarkerImpl(String id, String lbl, boolean markup, String world, double x[], double[] y, double z[], boolean persistent, MarkerSetImpl set) { markerid = id; if(lbl != null) - label = lbl; + label = markup ? lbl : Client.encodeForHTML(lbl); else - label = id; + label = markup ? id : Client.encodeForHTML(id); this.markup = markup; this.corners = new ArrayList(); for(int i = 0; i < x.length; i++) { @@ -73,7 +74,7 @@ class PolyLineMarkerImpl implements PolyLineMarker { PolyLineMarkerImpl(String id, MarkerSetImpl set) { markerid = id; markerset = set; - label = id; + label = Client.encodeForHTML(id); markup = false; desc = null; corners = new ArrayList(); @@ -163,7 +164,7 @@ class PolyLineMarkerImpl implements PolyLineMarker { @Override public void setLabel(String lbl, boolean markup) { if(markerset == null) return; - label = lbl; + label = markup ? lbl : Client.encodeForHTML(lbl); this.markup = markup; MarkerAPIImpl.polyLineMarkerUpdated(this, MarkerUpdate.UPDATED); if(ispersistent) diff --git a/DynmapCore/src/main/resources/extracted/web/js/markers.js b/DynmapCore/src/main/resources/extracted/web/js/markers.js index 5c3e742d..a929bbcb 100644 --- a/DynmapCore/src/main/resources/extracted/web/js/markers.js +++ b/DynmapCore/src/main/resources/extracted/web/js/markers.js @@ -105,19 +105,12 @@ componentconstructors['markers'] = function(dynmap, configuration) { .addClass('Marker') .addClass('mapMarker') .append($('').addClass('markerIcon'+marker.dim).attr({ src: url })); - if(marker.markup) { + if (marker.label != "") $(div).append($('') .addClass(set.showlabels?'markerName-show':'markerName') .addClass('markerName_' + set.id) .addClass('markerName' + marker.dim) .append(marker.label)); - } - else if(marker.label != "") - $(div).append($('') - .addClass(set.showlabels?'markerName-show':'markerName') - .addClass('markerName_' + set.id) - .addClass('markerName' + marker.dim) - .text(marker.label)); return div; }}); marker.timestamp = ts; @@ -191,9 +184,6 @@ componentconstructors['markers'] = function(dynmap, configuration) { if(area.desc) { $(popup).addClass('AreaPopup').append(area.desc); } - else if(area.markup) { - $(popup).addClass('AreaPopup').append(area.label); - } else { $(popup).text(area.label); } @@ -224,9 +214,6 @@ componentconstructors['markers'] = function(dynmap, configuration) { if(line.desc) { $(popup).addClass('LinePopup').append(line.desc); } - else if(line.markup) { - $(popup).addClass('LinePopup').append(line.label); - } else { $(popup).text(line.label); } @@ -259,9 +246,6 @@ componentconstructors['markers'] = function(dynmap, configuration) { if(circle.desc) { $(popup).addClass('CirclePopup').append(circle.desc); } - else if(circle.markup) { - $(popup).addClass('CirclePopup').append(circle.label); - } else { $(popup).text(circle.label); }