Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion js/RichText/UserMention.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
*/

/* global tinymce */
/* global _ */

window.GLPI = window.GLPI || {};
window.GLPI.RichText = window.GLPI.RichText || {};
Expand Down Expand Up @@ -157,6 +158,6 @@ window.GLPI.RichText.UserMention = class {
generateUserMentionHtml(user) {
return `<span contenteditable="false"
data-user-mention="true"
data-user-id="${user.id}">@${user.name}</span>&nbsp;`;
data-user-id="${_.escape(user.id)}">@${_.escape(user.name)}</span>&nbsp;`;
}
};
10 changes: 5 additions & 5 deletions js/cable.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});

}
Expand All @@ -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);
});
}

Expand All @@ -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);
});
Expand Down
57 changes: 29 additions & 28 deletions js/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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');
});
Expand All @@ -375,7 +376,7 @@ function selectAll(id) {
* @param id
**/
function deselectAll(id) {
$('#'+id).val('').trigger('change');
$('#' + CSS.escape(id)).val('').trigger('change');
}


Expand All @@ -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');
}
Expand Down Expand Up @@ -612,7 +613,7 @@ var getExtIcon = function(ext) {
url = CFG_GLPI.root_doc+'/pics/icones/defaut-dist.png';
}

return '<img src="'+url+'" title="'+ext+'">';
return '<img src="' + _.escape(url) + '" title="' + _.escape(ext) + '">';
};

/**
Expand Down Expand Up @@ -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($('<div id="'+map_id+'" style="height: ' + height + '"></div>'));
parent_elt.append($('<div id="'+_.escape(map_id)+'" style="height: ' + _.escape(height) + '"></div>'));
var map = L.map(map_id, {fullscreenControl: true, minZoom: 2}).setView(initial_view.position, initial_view.zoom);

//setup tiles and © messages
Expand All @@ -764,7 +765,7 @@ var initMap = function(parent_elt, map_id, height, initial_view = {position: [0,

var showMapForLocation = function(elt) {
var _id = $(elt).data('fid');
var _items_id = $('#' + _id).val();
var _items_id = $('#' + CSS.escape(_id)).val();

if (_items_id == 0) {
return;
Expand All @@ -785,7 +786,7 @@ var showMapForLocation = function(elt) {
url: CFG_GLPI.root_doc + '/ajax/getMapPoint.php',
data: {
itemtype: 'Location',
items_id: $('#' + _id).val()
items_id: $('#' + CSS.escape(_id)).val()
}
}).done(function(data) {
if (data.success === false) {
Expand Down Expand Up @@ -850,7 +851,7 @@ var templateResult = function(result) {
_elt.attr('title', result.title);

if (typeof query.term !== 'undefined' && typeof result.rendered_text !== 'undefined') {
_elt.html(result.rendered_text);
_elt.html(result.rendered_text); // rendered_text is expected to be a safe HTML string
} else {
if (!result.text) {
return null;
Expand Down Expand Up @@ -1051,8 +1052,8 @@ var escapeMarkupText = function (text) {
* @return void
*/
function updateProgress(progressid) {
var progress = $("progress#progress"+progressid).first();
$("div[data-progressid='"+progressid+"']").each(function(i, item) {
var progress = $("#"+CSS.escape(progressid)).first();
$("div[data-progressid='"+CSS.escape(progressid)+"']").each(function(i, item) {
var j_item = $(item);
var fg = j_item.find(".progress-fg").first();
var calcWidth = (progress.attr('value') / progress.attr('max')) * 100;
Expand Down Expand Up @@ -1219,7 +1220,7 @@ function updateItemOnEvent(dropdown_ids, target, url, params = {}, events = ['ch
//TODO Manage buffer time

const cleaned_zone_id = zone.replace('[', '_').replace(']', '_');
const zone_obj = $(`#${cleaned_zone_id}`);
const zone_obj = $(`#${CSS.escape(cleaned_zone_id)}`);

zone_obj.on(event, () => {
const conditional = (min_size >= 0 || force_load_for.length > 0);
Expand All @@ -1233,9 +1234,9 @@ function updateItemOnEvent(dropdown_ids, target, url, params = {}, events = ['ch
if (typeof v === "string") {
const reqs = v.match(/^__VALUE(\d+)__$/);
if (reqs !== null) {
resolved_params[k] = $('#'+dropdown_ids[reqs[0]]).val();
resolved_params[k] = $('#'+CSS.escape(dropdown_ids[reqs[0]])).val();
} else if (v === '__VALUE__') {
resolved_params[k] = $('#'+dropdown_ids[0]).val();
resolved_params[k] = $('#'+CSS.escape(dropdown_ids[0])).val();
} else {
resolved_params[k] = v;
}
Expand Down Expand Up @@ -1354,11 +1355,11 @@ function tableToDetails(table) {
if (in_details) {
details += '</pre></details>';
}
details += `<details><summary>${e.innerText}</summary><pre>`;
details += `<details><summary>${_.escape(e.innerText)}</summary><pre>`;
in_details = true;
} else {
if (in_details) {
details += e.innerText;
details += _.escape(e.innerText);
}
}
});
Expand Down Expand Up @@ -1555,27 +1556,27 @@ $(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");
}

/**
* Converts a normal text field to a password field
* @param {string} item The ID of the field to be hidden
*/
function hideDisclosablePasswordField(item) {
$("#" + item).prop("type", "password");
$("#" + CSS.escape(item)).prop("type", "password");
}

/**
* Copies the password from a disclosable password field to the clipboard
* @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 {
Expand All @@ -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);
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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();
}
Expand All @@ -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,
Expand Down Expand Up @@ -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();
}
Expand Down
8 changes: 4 additions & 4 deletions js/fileupload.js
Original file line number Diff line number Diff line change
Expand Up @@ -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"]');
Expand Down Expand Up @@ -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, ''));
Expand Down Expand Up @@ -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 = $('<p></p>')
Expand Down Expand Up @@ -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
Expand Down
23 changes: 12 additions & 11 deletions js/glpi_dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

/* eslint no-var: 0 */
/* global bootstrap */
/* global _ */

/**
* Create a dialog window
Expand Down Expand Up @@ -81,14 +82,14 @@ var glpi_html_dialog = function({
var bclass = ("class" in button) ? button.class : 'btn-secondary';

buttons_html+= `
<button type="button" id="${bid}"
class="btn ${bclass}" data-bs-dismiss="modal">
<button type="button" id="${_.escape(bid)}"
class="btn ${_.escape(bclass)}" data-bs-dismiss="modal">
${label}
</button>`;

// add click event on button
if ('click' in button) {
$(document).on('click', `#${bid}`, (event) => {
$(document).on('click', `#${CSS.escape(bid)}`, (event) => {
button.click(event);
});
}
Expand All @@ -105,8 +106,8 @@ var glpi_html_dialog = function({

const data_bs_focus = !bs_focus ? 'data-bs-focus="false"' : '';

var modal = `<div class="modal fade ${modalclass}" id="${id}" role="dialog" ${data_bs_focus} aria-labelledby="${id}_title">
<div class="modal-dialog ${dialogclass}">
var modal = `<div class="modal fade ${_.escape(modalclass)}" id="${_.escape(id)}" role="dialog" ${data_bs_focus} aria-labelledby="${_.escape(id)}_title">
<div class="modal-dialog ${_.escape(dialogclass)}">
<div class="modal-content">
<div class="modal-header">
<h2 id="${id}_title" class="fs-4 modal-title" tabindex="-1">${title}</h2>
Expand Down Expand Up @@ -136,7 +137,7 @@ var glpi_html_dialog = function({
// create global events
myModalEl.addEventListener('shown.bs.modal', (event) => {
// focus first element in modal
$(`#${id}`).find("input, textarea, select").first().trigger("focus");
$(`#${CSS.escape(id)}`).find("input, textarea, select").first().trigger("focus");

// call show event
show(event);
Expand All @@ -150,7 +151,7 @@ var glpi_html_dialog = function({
}

// remove html on modal close
$(`#${id}`).remove();
$(`#${CSS.escape(id)}`).remove();
});

return id;
Expand Down Expand Up @@ -355,9 +356,9 @@ const glpi_toast = (title, message, css_class, options = {}) => {
if (!valid_locations.includes(location)) {
location = 'bottom-right';
}
const html = `<div class='toast-container ${location} p-3 messages_after_redirect'>
<div id='toast_js_${toast_id}' class='toast ${animation_classes}' role='alert' aria-live='assertive' aria-atomic='true'>
<div class='toast-header ${css_class}'>
const html = `<div class='toast-container ${_.escape(location)} p-3 messages_after_redirect'>
<div id='toast_js_${toast_id}' class='toast ${_.escape(animation_classes)}' role='alert' aria-live='assertive' aria-atomic='true'>
<div class='toast-header ${_.escape(css_class)}'>
<strong class='me-auto'>${title}</strong>
<button type='button' class='btn-close' data-bs-dismiss='toast' aria-label='${__('Close')}'></button>
</div>
Expand All @@ -368,7 +369,7 @@ const glpi_toast = (title, message, css_class, options = {}) => {
</div>`;
$('body').append(html);

const toast = new bootstrap.Toast(document.querySelector(`#toast_js_${toast_id}`), {
const toast = new bootstrap.Toast(document.querySelector(`#toast_js_${CSS.escape(toast_id)}`), {
delay: options.delay,
});
toast.show();
Expand Down
Loading