diff --git a/js/RichText/UserMention.js b/js/RichText/UserMention.js
index 6d2930918e6..4c4718930a9 100644
--- a/js/RichText/UserMention.js
+++ b/js/RichText/UserMention.js
@@ -32,6 +32,7 @@
*/
/* global tinymce */
+/* global _ */
window.GLPI = window.GLPI || {};
window.GLPI.RichText = window.GLPI.RichText || {};
@@ -157,6 +158,6 @@ window.GLPI.RichText.UserMention = class {
generateUserMentionHtml(user) {
return `@${user.name} `;
+ data-user-id="${_.escape(user.id)}">@${_.escape(user.name)} `;
}
};
diff --git a/js/cable.js b/js/cable.js
index dd07d44e70c..3742e7fd14e 100644
--- a/js/cable.js
+++ b/js/cable.js
@@ -42,8 +42,8 @@ function refreshAssetBreadcrumb(itemtype, items_id, dom_to_update) {
itemtype: itemtype,
}
}).done((html_breadcrum) => {
- $(`#${dom_to_update}`).empty();
- $(`#${dom_to_update}`).append(html_breadcrum);
+ $(`#${CSS.escape(dom_to_update)}`).empty();
+ $(`#${CSS.escape(dom_to_update)}`).append(html_breadcrum);
});
}
@@ -59,8 +59,8 @@ function refreshNetworkPortDropdown(itemtype, items_id, dom_to_update) {
itemtype: itemtype,
}
}).done((html_data) => {
- $(`#${dom_to_update}`).empty();
- $(`#${dom_to_update}`).append(html_data);
+ $(`#${CSS.escape(dom_to_update)}`).empty();
+ $(`#${CSS.escape(dom_to_update)}`).append(html_data);
});
}
@@ -77,7 +77,7 @@ function refreshSocketDropdown(itemtype, items_id, socketmodels_id, dom_name) {
dom_name: dom_name
}
}).done((html_data) => {
- const parent_dom = $(`select[name="${dom_name}"]`).parent().parent();
+ const parent_dom = $(`select[name="${CSS.escape(dom_name)}"]`).parent().parent();
parent_dom.empty();
parent_dom.append(html_data);
});
diff --git a/js/common.js b/js/common.js
index 72da960b085..8963e926b8e 100644
--- a/js/common.js
+++ b/js/common.js
@@ -174,7 +174,7 @@ function displayOtherSelectOptions(select_object, other_option_name) {
**/
function checkAsCheckboxes(reference, container_id, checkboxes_selector = 'input[type="checkbox"]') {
reference = typeof(reference) === 'string' ? document.getElementById(reference) : reference;
- $('#' + container_id + ' ' + checkboxes_selector + ':enabled')
+ $('#' + CSS.escape(container_id) + ' ' + checkboxes_selector + ':enabled')
.prop('checked', $(reference).is(':checked'));
return true;
@@ -236,14 +236,14 @@ function showHideDiv(id, img_name = '', img_src_close = '', img_src_open = '') {
var _deco;
var _img;
if (!_awesome) {
- _img = $('img[name=' + img_name + ']');
+ _img = $('img[name=' + CSS.escape(img_name) + ']');
if (_elt.is(':visible')) {
_img.attr('src', img_src_close);
} else {
_img.attr('src', img_src_open);
}
} else {
- _deco = $('#'+img_name);
+ _deco = $('#' + CSS.escape(img_name));
if (_elt.is(':visible')) {
_deco
.removeClass(img_src_open)
@@ -361,7 +361,8 @@ function submitGetLink(target, fields) {
* @param id
**/
function selectAll(id) {
- var element =$('#'+id);var selected = [];
+ var element = $('#'+CSS.escape(id));
+ var selected = [];
element.find('option').each(function(i,e){
selected[selected.length]=$(e).attr('value');
});
@@ -375,7 +376,7 @@ function selectAll(id) {
* @param id
**/
function deselectAll(id) {
- $('#'+id).val('').trigger('change');
+ $('#' + CSS.escape(id)).val('').trigger('change');
}
@@ -393,7 +394,7 @@ function massiveUpdateCheckbox(criterion, reference) {
if (typeof(reference) == 'boolean') {
value = reference;
} else if (typeof(reference) == 'string') {
- value = $('#' + reference).prop('checked');
+ value = $('#' + CSS.escape(reference)).prop('checked');
} else if (typeof(reference) == 'object') {
value = $(reference).prop('checked');
}
@@ -612,7 +613,7 @@ var getExtIcon = function(ext) {
url = CFG_GLPI.root_doc+'/pics/icones/defaut-dist.png';
}
- return '';
+ return '
';
};
/**
@@ -752,7 +753,7 @@ var initMap = function(parent_elt, map_id, height, initial_view = {position: [0,
}
//add map, set a default arbitrary location
- parent_elt.append($('
`; + details += `${_.escape(e.innerText)}
`; in_details = true; } else { if (in_details) { - details += e.innerText; + details += _.escape(e.innerText); } } }); @@ -1555,7 +1556,7 @@ $(document.body).on('shown.bs.tab', 'a[data-bs-toggle="tab"]', (e) => { * @param {string} item The ID of the field to be shown */ function showDisclosablePasswordField(item) { - $("#" + item).prop("type", "text"); + $("#" + CSS.escape(item)).prop("type", "text"); } /** @@ -1563,7 +1564,7 @@ function showDisclosablePasswordField(item) { * @param {string} item The ID of the field to be hidden */ function hideDisclosablePasswordField(item) { - $("#" + item).prop("type", "password"); + $("#" + CSS.escape(item)).prop("type", "password"); } /** @@ -1571,11 +1572,11 @@ function hideDisclosablePasswordField(item) { * @param {string} item The ID of the field to be copied */ function copyDisclosablePasswordFieldToClipboard(item) { - const is_password_input = $("#" + item).prop("type") === "password"; + const is_password_input = $("#" + CSS.escape(item)).prop("type") === "password"; if (is_password_input) { showDisclosablePasswordField(item); } - $("#" + item).select(); + $("#" + CSS.escape(item)).select(); try { document.execCommand("copy"); } catch { @@ -1591,7 +1592,7 @@ function copyDisclosablePasswordFieldToClipboard(item) { * @param element_id The ID of the table to be converted */ function initSortableTable(element_id) { - const element = $(`#${element_id}`); + const element = $(`#${CSS.escape(element_id)}`); const sort_table = (column_index) => { const current_sort = element.data('sort'); element.data('sort', column_index); @@ -1700,7 +1701,7 @@ if (typeof GlpiCommonAjaxController == "function") { function setupAjaxDropdown(config) { // Field ID is used as a selector, so we need to escape special characters // to avoid issues with jQuery. - const field_id = $.escapeSelector(config.field_id); + const field_id = CSS.escape(config.field_id); const select2_el = $('#' + field_id).select2({ containerCssClass: config.container_css_class, @@ -1796,7 +1797,7 @@ function setupAjaxDropdown(config) { $('label[for=' + field_id + ']').on('click', function () { $('#' + field_id).select2('open'); }); $('#' + field_id).on('select2:open', function (e) { - const search_input = document.querySelector(`.select2-search__field[aria-controls='select2-${e.target.id}-results']`); + const search_input = document.querySelector(`.select2-search__field[aria-controls='select2-${CSS.escape(e.target.id)}-results']`); if (search_input) { search_input.focus(); } @@ -1809,7 +1810,7 @@ function setupAdaptDropdown(config) { // Field ID is used as a selector, so we need to escape special characters // to avoid issues with jQuery. - const field_id = $.escapeSelector(config.field_id); + const field_id = CSS.escape(config.field_id); const options = { width: config.width, @@ -1909,8 +1910,8 @@ function setupAdaptDropdown(config) $('label[for=' + field_id + ']').on('click', function () { $('#' + field_id).select2('open'); }); - $('#' + field_id).on('select2:open', function () { - const search_input = document.querySelector(`.select2-search__field[aria-controls='select2-\${e.target.id}-results']`); + $('#' + field_id).on('select2:open', function (e) { + const search_input = document.querySelector(`.select2-search__field[aria-controls='select2-${CSS.escape(e.target.id)}-results']`); if (search_input) { search_input.focus(); } diff --git a/js/fileupload.js b/js/fileupload.js index 895090e6740..c5e82813253 100644 --- a/js/fileupload.js +++ b/js/fileupload.js @@ -43,7 +43,7 @@ function uploadFile(file, editor) { // Search for fileupload container. // First try to find an uplaoder having same name as editor element. - var uploader = $(`[data-uploader-name="${editor.getElement().name}"]`); + var uploader = $(`[data-uploader-name="${CSS.escape(editor.getElement().name)}"]`); if (uploader.length === 0) { // Fallback to uploader using default name uploader = $(editor.getElement()).closest('form').find('[data-uploader-name="filename"]'); @@ -81,7 +81,7 @@ var handleUploadedFile = function (files, files_data, input_name, container, edi editor = tinyMCE.get(editor_id); const uploaded_image = uploaded_images.find((entry) => entry.filename === file.name); const matching_image = uploaded_image !== undefined - ? editor.dom.select(`img[data-upload_id="${uploaded_image.upload_id}"]`) + ? editor.dom.select(`img[data-upload_id="${CSS.escape(uploaded_image.upload_id)}"]`) : []; if (matching_image.length > 0) { editor.dom.setAttrib(matching_image, 'id', tag_data.tag.replace(/#/g, '')); @@ -123,7 +123,7 @@ var handleUploadedFile = function (files, files_data, input_name, container, edi * @param {Object} container The fileinfo container */ var displayUploadedFile = function(file, tag, editor, input_name, filecontainer) { - var fileindex = $(`input[name^="_${input_name}["]`).length; + var fileindex = $(`input[name^="_${CSS.escape(input_name)}["]`).length; var ext = file.name.split('.').pop(); var p = $('') @@ -173,7 +173,7 @@ var displayUploadedFile = function(file, tag, editor, input_name, filecontainer) var deleteImagePasted = function(elementsIdToRemove, tagToRemove, editor) { // Remove file display lines $.each(elementsIdToRemove, (index, element) => { - $(`#${element}`).remove(); + $(`#${CSS.escape(element)}`).remove(); }); if (typeof editor !== "undefined" && editor !== null diff --git a/js/glpi_dialog.js b/js/glpi_dialog.js index 0d34a28a71c..e5731cd971a 100644 --- a/js/glpi_dialog.js +++ b/js/glpi_dialog.js @@ -33,6 +33,7 @@ /* eslint no-var: 0 */ /* global bootstrap */ +/* global _ */ /** * Create a dialog window @@ -81,14 +82,14 @@ var glpi_html_dialog = function({ var bclass = ("class" in button) ? button.class : 'btn-secondary'; buttons_html+= ` -