@@ -174,7 +174,7 @@ function displayOtherSelectOptions(select_object, other_option_name) {
174
174
**/
175
175
function checkAsCheckboxes ( reference , container_id , checkboxes_selector = 'input[type="checkbox"]' ) {
176
176
reference = typeof ( reference ) === 'string' ? document . getElementById ( reference ) : reference ;
177
- $ ( '#' + container_id + ' ' + checkboxes_selector + ':enabled' )
177
+ $ ( '#' + CSS . escape ( container_id ) + ' ' + checkboxes_selector + ':enabled' )
178
178
. prop ( 'checked' , $ ( reference ) . is ( ':checked' ) ) ;
179
179
180
180
return true ;
@@ -236,14 +236,14 @@ function showHideDiv(id, img_name = '', img_src_close = '', img_src_open = '') {
236
236
var _deco ;
237
237
var _img ;
238
238
if ( ! _awesome ) {
239
- _img = $ ( 'img[name=' + img_name + ']' ) ;
239
+ _img = $ ( 'img[name=' + CSS . escape ( img_name ) + ']' ) ;
240
240
if ( _elt . is ( ':visible' ) ) {
241
241
_img . attr ( 'src' , img_src_close ) ;
242
242
} else {
243
243
_img . attr ( 'src' , img_src_open ) ;
244
244
}
245
245
} else {
246
- _deco = $ ( '#' + img_name ) ;
246
+ _deco = $ ( '#' + CSS . escape ( img_name ) ) ;
247
247
if ( _elt . is ( ':visible' ) ) {
248
248
_deco
249
249
. removeClass ( img_src_open )
@@ -361,7 +361,8 @@ function submitGetLink(target, fields) {
361
361
* @param id
362
362
**/
363
363
function selectAll ( id ) {
364
- var element = $ ( '#' + id ) ; var selected = [ ] ;
364
+ var element = $ ( '#' + CSS . escape ( id ) ) ;
365
+ var selected = [ ] ;
365
366
element . find ( 'option' ) . each ( function ( i , e ) {
366
367
selected [ selected . length ] = $ ( e ) . attr ( 'value' ) ;
367
368
} ) ;
@@ -375,7 +376,7 @@ function selectAll(id) {
375
376
* @param id
376
377
**/
377
378
function deselectAll ( id ) {
378
- $ ( '#' + id ) . val ( '' ) . trigger ( 'change' ) ;
379
+ $ ( '#' + CSS . escape ( id ) ) . val ( '' ) . trigger ( 'change' ) ;
379
380
}
380
381
381
382
@@ -393,7 +394,7 @@ function massiveUpdateCheckbox(criterion, reference) {
393
394
if ( typeof ( reference ) == 'boolean' ) {
394
395
value = reference ;
395
396
} else if ( typeof ( reference ) == 'string' ) {
396
- value = $ ( '#' + reference ) . prop ( 'checked' ) ;
397
+ value = $ ( '#' + CSS . escape ( reference ) ) . prop ( 'checked' ) ;
397
398
} else if ( typeof ( reference ) == 'object' ) {
398
399
value = $ ( reference ) . prop ( 'checked' ) ;
399
400
}
@@ -612,7 +613,7 @@ var getExtIcon = function(ext) {
612
613
url = CFG_GLPI . root_doc + '/pics/icones/defaut-dist.png' ;
613
614
}
614
615
615
- return '<img src="' + url + '" title="' + ext + '">' ;
616
+ return '<img src="' + _ . escape ( url ) + '" title="' + _ . escape ( ext ) + '">' ;
616
617
} ;
617
618
618
619
/**
@@ -752,7 +753,7 @@ var initMap = function(parent_elt, map_id, height, initial_view = {position: [0,
752
753
}
753
754
754
755
//add map, set a default arbitrary location
755
- parent_elt . append ( $ ( '<div id="' + map_id + '" style="height: ' + height + '"></div>' ) ) ;
756
+ parent_elt . append ( $ ( '<div id="' + _ . escape ( map_id ) + '" style="height: ' + _ . escape ( height ) + '"></div>' ) ) ;
756
757
var map = L . map ( map_id , { fullscreenControl : true , minZoom : 2 } ) . setView ( initial_view . position , initial_view . zoom ) ;
757
758
758
759
//setup tiles and © messages
@@ -764,7 +765,7 @@ var initMap = function(parent_elt, map_id, height, initial_view = {position: [0,
764
765
765
766
var showMapForLocation = function ( elt ) {
766
767
var _id = $ ( elt ) . data ( 'fid' ) ;
767
- var _items_id = $ ( '#' + _id ) . val ( ) ;
768
+ var _items_id = $ ( '#' + CSS . escape ( _id ) ) . val ( ) ;
768
769
769
770
if ( _items_id == 0 ) {
770
771
return ;
@@ -785,7 +786,7 @@ var showMapForLocation = function(elt) {
785
786
url : CFG_GLPI . root_doc + '/ajax/getMapPoint.php' ,
786
787
data : {
787
788
itemtype : 'Location' ,
788
- items_id : $ ( '#' + _id ) . val ( )
789
+ items_id : $ ( '#' + CSS . escape ( _id ) ) . val ( )
789
790
}
790
791
} ) . done ( function ( data ) {
791
792
if ( data . success === false ) {
@@ -850,7 +851,7 @@ var templateResult = function(result) {
850
851
_elt . attr ( 'title' , result . title ) ;
851
852
852
853
if ( typeof query . term !== 'undefined' && typeof result . rendered_text !== 'undefined' ) {
853
- _elt . html ( result . rendered_text ) ;
854
+ _elt . html ( result . rendered_text ) ; // rendered_text is expected to be a safe HTML string
854
855
} else {
855
856
if ( ! result . text ) {
856
857
return null ;
@@ -1051,8 +1052,8 @@ var escapeMarkupText = function (text) {
1051
1052
* @return void
1052
1053
*/
1053
1054
function updateProgress ( progressid ) {
1054
- var progress = $ ( "progress#progress" + progressid ) . first ( ) ;
1055
- $ ( "div[data-progressid='" + progressid + "']" ) . each ( function ( i , item ) {
1055
+ var progress = $ ( "#" + CSS . escape ( progressid ) ) . first ( ) ;
1056
+ $ ( "div[data-progressid='" + CSS . escape ( progressid ) + "']" ) . each ( function ( i , item ) {
1056
1057
var j_item = $ ( item ) ;
1057
1058
var fg = j_item . find ( ".progress-fg" ) . first ( ) ;
1058
1059
var calcWidth = ( progress . attr ( 'value' ) / progress . attr ( 'max' ) ) * 100 ;
@@ -1219,7 +1220,7 @@ function updateItemOnEvent(dropdown_ids, target, url, params = {}, events = ['ch
1219
1220
//TODO Manage buffer time
1220
1221
1221
1222
const cleaned_zone_id = zone . replace ( '[' , '_' ) . replace ( ']' , '_' ) ;
1222
- const zone_obj = $ ( `#${ cleaned_zone_id } ` ) ;
1223
+ const zone_obj = $ ( `#${ CSS . escape ( cleaned_zone_id ) } ` ) ;
1223
1224
1224
1225
zone_obj . on ( event , ( ) => {
1225
1226
const conditional = ( min_size >= 0 || force_load_for . length > 0 ) ;
@@ -1233,9 +1234,9 @@ function updateItemOnEvent(dropdown_ids, target, url, params = {}, events = ['ch
1233
1234
if ( typeof v === "string" ) {
1234
1235
const reqs = v . match ( / ^ _ _ V A L U E ( \d + ) _ _ $ / ) ;
1235
1236
if ( reqs !== null ) {
1236
- resolved_params [ k ] = $ ( '#' + dropdown_ids [ reqs [ 0 ] ] ) . val ( ) ;
1237
+ resolved_params [ k ] = $ ( '#' + CSS . escape ( dropdown_ids [ reqs [ 0 ] ] ) ) . val ( ) ;
1237
1238
} else if ( v === '__VALUE__' ) {
1238
- resolved_params [ k ] = $ ( '#' + dropdown_ids [ 0 ] ) . val ( ) ;
1239
+ resolved_params [ k ] = $ ( '#' + CSS . escape ( dropdown_ids [ 0 ] ) ) . val ( ) ;
1239
1240
} else {
1240
1241
resolved_params [ k ] = v ;
1241
1242
}
@@ -1354,11 +1355,11 @@ function tableToDetails(table) {
1354
1355
if ( in_details ) {
1355
1356
details += '</pre></details>' ;
1356
1357
}
1357
- details += `<details><summary>${ e . innerText } </summary><pre>` ;
1358
+ details += `<details><summary>${ _ . escape ( e . innerText ) } </summary><pre>` ;
1358
1359
in_details = true ;
1359
1360
} else {
1360
1361
if ( in_details ) {
1361
- details += e . innerText ;
1362
+ details += _ . escape ( e . innerText ) ;
1362
1363
}
1363
1364
}
1364
1365
} ) ;
@@ -1555,27 +1556,27 @@ $(document.body).on('shown.bs.tab', 'a[data-bs-toggle="tab"]', (e) => {
1555
1556
* @param {string } item The ID of the field to be shown
1556
1557
*/
1557
1558
function showDisclosablePasswordField ( item ) {
1558
- $ ( "#" + item ) . prop ( "type" , "text" ) ;
1559
+ $ ( "#" + CSS . escape ( item ) ) . prop ( "type" , "text" ) ;
1559
1560
}
1560
1561
1561
1562
/**
1562
1563
* Converts a normal text field to a password field
1563
1564
* @param {string } item The ID of the field to be hidden
1564
1565
*/
1565
1566
function hideDisclosablePasswordField ( item ) {
1566
- $ ( "#" + item ) . prop ( "type" , "password" ) ;
1567
+ $ ( "#" + CSS . escape ( item ) ) . prop ( "type" , "password" ) ;
1567
1568
}
1568
1569
1569
1570
/**
1570
1571
* Copies the password from a disclosable password field to the clipboard
1571
1572
* @param {string } item The ID of the field to be copied
1572
1573
*/
1573
1574
function copyDisclosablePasswordFieldToClipboard ( item ) {
1574
- const is_password_input = $ ( "#" + item ) . prop ( "type" ) === "password" ;
1575
+ const is_password_input = $ ( "#" + CSS . escape ( item ) ) . prop ( "type" ) === "password" ;
1575
1576
if ( is_password_input ) {
1576
1577
showDisclosablePasswordField ( item ) ;
1577
1578
}
1578
- $ ( "#" + item ) . select ( ) ;
1579
+ $ ( "#" + CSS . escape ( item ) ) . select ( ) ;
1579
1580
try {
1580
1581
document . execCommand ( "copy" ) ;
1581
1582
} catch {
@@ -1591,7 +1592,7 @@ function copyDisclosablePasswordFieldToClipboard(item) {
1591
1592
* @param element_id The ID of the table to be converted
1592
1593
*/
1593
1594
function initSortableTable ( element_id ) {
1594
- const element = $ ( `#${ element_id } ` ) ;
1595
+ const element = $ ( `#${ CSS . escape ( element_id ) } ` ) ;
1595
1596
const sort_table = ( column_index ) => {
1596
1597
const current_sort = element . data ( 'sort' ) ;
1597
1598
element . data ( 'sort' , column_index ) ;
@@ -1700,7 +1701,7 @@ if (typeof GlpiCommonAjaxController == "function") {
1700
1701
function setupAjaxDropdown ( config ) {
1701
1702
// Field ID is used as a selector, so we need to escape special characters
1702
1703
// to avoid issues with jQuery.
1703
- const field_id = $ . escapeSelector ( config . field_id ) ;
1704
+ const field_id = CSS . escape ( config . field_id ) ;
1704
1705
1705
1706
const select2_el = $ ( '#' + field_id ) . select2 ( {
1706
1707
containerCssClass : config . container_css_class ,
@@ -1796,7 +1797,7 @@ function setupAjaxDropdown(config) {
1796
1797
1797
1798
$ ( 'label[for=' + field_id + ']' ) . on ( 'click' , function ( ) { $ ( '#' + field_id ) . select2 ( 'open' ) ; } ) ;
1798
1799
$ ( '#' + field_id ) . on ( 'select2:open' , function ( e ) {
1799
- const search_input = document . querySelector ( `.select2-search__field[aria-controls='select2-${ e . target . id } -results']` ) ;
1800
+ const search_input = document . querySelector ( `.select2-search__field[aria-controls='select2-${ CSS . escape ( e . target . id ) } -results']` ) ;
1800
1801
if ( search_input ) {
1801
1802
search_input . focus ( ) ;
1802
1803
}
@@ -1809,7 +1810,7 @@ function setupAdaptDropdown(config)
1809
1810
{
1810
1811
// Field ID is used as a selector, so we need to escape special characters
1811
1812
// to avoid issues with jQuery.
1812
- const field_id = $ . escapeSelector ( config . field_id ) ;
1813
+ const field_id = CSS . escape ( config . field_id ) ;
1813
1814
1814
1815
const options = {
1815
1816
width : config . width ,
@@ -1909,8 +1910,8 @@ function setupAdaptDropdown(config)
1909
1910
$ ( 'label[for=' + field_id + ']' ) . on ( 'click' , function ( ) {
1910
1911
$ ( '#' + field_id ) . select2 ( 'open' ) ;
1911
1912
} ) ;
1912
- $ ( '#' + field_id ) . on ( 'select2:open' , function ( ) {
1913
- const search_input = document . querySelector ( `.select2-search__field[aria-controls='select2-\${ e.target.id}-results']` ) ;
1913
+ $ ( '#' + field_id ) . on ( 'select2:open' , function ( e ) {
1914
+ const search_input = document . querySelector ( `.select2-search__field[aria-controls='select2-${ CSS . escape ( e . target . id ) } -results']` ) ;
1914
1915
if ( search_input ) {
1915
1916
search_input . focus ( ) ;
1916
1917
}
0 commit comments