diff --git a/views/dataset-dataentry-page.twig b/views/dataset-dataentry-page.twig index cac32f5daa..4436a310ba 100644 --- a/views/dataset-dataentry-page.twig +++ b/views/dataset-dataentry-page.twig @@ -86,7 +86,33 @@ var multiSelectTitleTrans = "{% trans "Multi Select Mode" %}"; var editModeHelpTrans = "{% trans "Click on any row to edit" %}"; var multiSelectHelpTrans = "{% trans "Select one or more rows to delete" %}"; + const entityMap = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '/': '/', + '`': '`', + '=': '=' + }; + + function sanitizeHtml(string) { + return String(string).replace(/[&<>"'`=\/]/g, function (s) { + return entityMap[s]; + }); + } + + function validateHTMLData(str) { + let doc = new DOMParser().parseFromString(str, "text/html"); + + // If valid html, sanitize and format as a code + if (Array.from(doc.body.childNodes).some(node => node.nodeType === 1)) { + return `${sanitizeHtml(str)}`; + } + return str; + } cols.push({ "name": "id", "data": "id" }); {% for col in dataSet.getColumn() %} @@ -104,7 +130,13 @@ } }); {% else %} - cols.push({ "data": "{{ col.heading }}", "orderable": {% if col.showSort == 1 %}true{% else %}false{% endif %} }); + cols.push({ + "data": "{{ col.heading }}", + "orderable": {% if col.showSort == 1 %}true{% else %}false{% endif %}, + "render": function(data) { + return validateHTMLData(data); + } + }); {% endif %} {% endfor %}