From 8f79932ab1259267560541bbef2ae290d68d42e6 Mon Sep 17 00:00:00 2001 From: Martin Raifer Date: Mon, 6 Jun 2022 12:42:27 +0200 Subject: [PATCH] prevent html injection in combobox dopdowns and use returned wikidata label language for html `lang` metadata --- modules/presets/field.js | 1 + modules/ui/combobox.js | 17 +++++++---------- modules/ui/fields/combo.js | 4 ++-- modules/ui/fields/wikidata.js | 10 +++++++--- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/modules/presets/field.js b/modules/presets/field.js index e24918454..ee81d38a3 100644 --- a/modules/presets/field.js +++ b/modules/presets/field.js @@ -22,6 +22,7 @@ export function presetField(fieldID, field) { _this.t = (scope, options) => t(`_tagging.presets.fields.${fieldID}.${scope}`, options); _this.t.html = (scope, options) => t.html(`_tagging.presets.fields.${fieldID}.${scope}`, options); + _this.t.append = (scope, options) => t.append(`_tagging.presets.fields.${fieldID}.${scope}`, options); _this.hasTextForStringId = (scope) => localizer.hasTextForStringId(`_tagging.presets.fields.${fieldID}.${scope}`); _this.title = () => _this.overrideLabel || _this.t('label', { 'default': fieldID }); diff --git a/modules/ui/combobox.js b/modules/ui/combobox.js index aefa6ea72..b331212f0 100644 --- a/modules/ui/combobox.js +++ b/modules/ui/combobox.js @@ -7,7 +7,8 @@ import { utilGetSetValue, utilRebind, utilTriggerEvent } from '../util'; // It is keyed on the `value` of the entry. Data should be an array of objects like: // [{ // value: 'string value', // required -// display: 'label html' // optional +// display: 'label function' // optional, if present will be called with d3 selection +// to modify/append, see localizer's t.append // title: 'hover text' // optional // terms: ['search terms'] // optional // }, ...] @@ -386,16 +387,12 @@ export function uiCombobox(context, klass) { return 'combobox-option ' + (d.klass || ''); }) .attr('title', function(d) { return d.title; }) - .html(function(d) { - // d.display can be an object - if ( typeof d.display === 'object' && - !Array.isArray(d.display) && - d.display !== null - ) { - return d.display.label.value; + .each(function(d) { + if (d.display) { + d.display(d3_select(this)); + } else { + d3_select(this).text(d.value); } - - return d.display || d.value; }) .on('mouseenter', _mouseEnterHandler) .on('mouseleave', _mouseLeaveHandler) diff --git a/modules/ui/fields/combo.js b/modules/ui/fields/combo.js index a80ad1445..2c181e986 100644 --- a/modules/ui/fields/combo.js +++ b/modules/ui/fields/combo.js @@ -140,7 +140,7 @@ export function uiFieldCombo(field, context) { key: v, value: field.t('options.' + v, { default: v }), title: v, - display: field.t.html('options.' + v, { default: v }), + display: field.t.append('options.' + v, { default: v }), klass: field.hasTextForStringId('options.' + v) ? '' : 'raw-option' }; }); @@ -206,7 +206,7 @@ export function uiFieldCombo(field, context) { return { key: k, value: label, - display: field.t.html('options.' + k, { default: k }), + display: field.t.append('options.' + k, { default: k }), title: d.title || label, klass: field.hasTextForStringId('options.' + k) ? '' : 'raw-option' }; diff --git a/modules/ui/fields/wikidata.js b/modules/ui/fields/wikidata.js index 6448c4c75..3842e1756 100644 --- a/modules/ui/fields/wikidata.js +++ b/modules/ui/fields/wikidata.js @@ -150,9 +150,13 @@ export function uiFieldWikidata(field, context) { var result = data.map(function (item) { return { - id: item.id, - value: item.label + ' (' + item.id + ')', - title: item.description, + id: item.id, + value: item.display.label.value + ' (' + item.id + ')', + display: selection => selection.append('span') + .attr('class', 'localized-text') + .attr('lang', item.display.label.language) + .text(item.display.label.value), + title: item.display.description && item.display.description.value, terms: item.aliases }; });