From 104635f8c5aebb6a9783eac9a60ffaa3e3681d59 Mon Sep 17 00:00:00 2001 From: Kirill Solomko Date: Mon, 26 Apr 2021 16:16:45 +0200 Subject: [PATCH] TT#120309 fix datatable escape html rendering * in mRender (custom_renderers), "data" variable is a string, therefore data.escapeHtml could not be used * add new function argument "opt", where it is a dedicated hash containing custom passable options, so it now looks as function(data, type, full, opt) * adapted the existing code to include/use the new argument where applicable Change-Id: I4957eece3b2d0f6359cbc8f36caf5a350d7bad95 (cherry picked from commit 87bdb695604a003166e36486356297b7a0e1ff66) --- lib/NGCP/Panel/Controller/Billing.pm | 2 +- lib/NGCP/Panel/Controller/Customer.pm | 2 +- lib/NGCP/Panel/Field/ProfileNetwork.pm | 4 ++-- lib/NGCP/Panel/Utils/Billing.pm | 2 +- share/templates/helpers/datatables.tt | 15 +++++++++------ share/templates/helpers/datatables_field.tt | 6 +++--- share/templates/helpers/datatables_multifield.tt | 6 +++--- share/templates/timeset/event_list.tt | 4 ++-- 8 files changed, 22 insertions(+), 19 deletions(-) diff --git a/lib/NGCP/Panel/Controller/Billing.pm b/lib/NGCP/Panel/Controller/Billing.pm index ccad2b80dd..a7d8b3cb8c 100644 --- a/lib/NGCP/Panel/Controller/Billing.pm +++ b/lib/NGCP/Panel/Controller/Billing.pm @@ -345,7 +345,7 @@ sub fees_list :Chained('base') :PathPart('fees') :CaptureArgs(0) { { name => 'source', search => 1, title => $c->loc('Source Pattern') }, { name => 'destination', search => 1, title => $c->loc('Destination Pattern') }, { name => 'match_mode', search => 0, title => $c->loc('Match Mode'), - custom_renderer => 'function ( data, type, full ) {'. + custom_renderer => 'function ( data, type, full, opt ) {'. 'if(full.match_mode == "regex_longest_pattern"){return "' . $c->loc('Regular expression - longest pattern') . '";}'. 'else if(full.match_mode == "regex_longest_match"){return "' . $c->loc('Regular expression - longest match') . '";}'. 'else if(full.match_mode == "prefix"){return "' . $c->loc('Prefix string') . '";}'. diff --git a/lib/NGCP/Panel/Controller/Customer.pm b/lib/NGCP/Panel/Controller/Customer.pm index ec365f5799..394625b34c 100644 --- a/lib/NGCP/Panel/Controller/Customer.pm +++ b/lib/NGCP/Panel/Controller/Customer.pm @@ -51,7 +51,7 @@ sub list_customer :Chained('/') :PathPart('customer') :CaptureArgs(0) { { name => "contact.email", search => 1, title => $c->loc("Contact Email") }, { name => "contact.firstname", search => 1, title => '' }, { name => "contact.lastname", search => 1, title => $c->loc("Name"), - custom_renderer => 'function ( data, type, full ) { var sep = (full.contact_firstname && full.contact_lastname) ? " " : ""; return (full.contact_firstname || "") + sep + (full.contact_lastname || ""); }' }, + custom_renderer => 'function ( data, type, full, opt ) { var sep = (full.contact_firstname && full.contact_lastname) ? " " : ""; return (full.contact_firstname || "") + sep + (full.contact_lastname || ""); }' }, { name => "product.name", search => 1, title => $c->loc("Product") }, { name => 'billing_profile_name', accessor => "billing_profile_name", search => 0, title => $c->loc('Billing Profile'), literal_sql => '""' }, diff --git a/lib/NGCP/Panel/Field/ProfileNetwork.pm b/lib/NGCP/Panel/Field/ProfileNetwork.pm index 9b957e9e4e..bec472d44b 100644 --- a/lib/NGCP/Panel/Field/ProfileNetwork.pm +++ b/lib/NGCP/Panel/Field/ProfileNetwork.pm @@ -12,7 +12,7 @@ has_field 'profile_id' => ( ajax_src => '/billing/ajax', table_titles => ['#', 'Reseller', 'Profile'], table_fields => ['id', 'reseller_name', 'name'], - custom_renderers => { name => 'function ( data, type, full ) { if(data.length > 13) data = data.substring(0,10) + \'...\'; return data; }'} + custom_renderers => { name => 'function ( data, type, full, opt ) { if(data.length > 13) data = data.substring(0,10) + \'...\'; return data; }'} ); has_field 'network_id' => ( @@ -25,7 +25,7 @@ has_field 'network_id' => ( ajax_src => '/network/ajax', table_titles => ['#', 'Reseller', 'Network'], table_fields => ['id', 'reseller_name', 'name'], - custom_renderers => { name => 'function ( data, type, full ) { if(data.length > 13) data = data.substring(0,10) + \'...\'; return data; }'} + custom_renderers => { name => 'function ( data, type, full, opt ) { if(data.length > 13) data = data.substring(0,10) + \'...\'; return data; }'} ); no Moose; diff --git a/lib/NGCP/Panel/Utils/Billing.pm b/lib/NGCP/Panel/Utils/Billing.pm index 86078ce268..ad9a36e98e 100644 --- a/lib/NGCP/Panel/Utils/Billing.pm +++ b/lib/NGCP/Panel/Utils/Billing.pm @@ -499,7 +499,7 @@ sub get_datatable_cols { my ($c) = @_; return ( { name => "prepaid", "search" => 0, "title" => $c->loc("Prepaid"), - custom_renderer => 'function ( data, type, full ) { data.escapeHtml = false; return \'\'; }' }, + custom_renderer => 'function ( data, type, full, opt ) { opt.escapeHtml = false; return \'\'; }' }, { name => "contract_cnt", "search" => 0, "title" => $c->loc("Used (contracts)"), }, { name => "package_cnt", "search" => 0, "title" => $c->loc("Used (packages)"), }, diff --git a/share/templates/helpers/datatables.tt b/share/templates/helpers/datatables.tt index 59d073c2e2..2109816a57 100644 --- a/share/templates/helpers/datatables.tt +++ b/share/templates/helpers/datatables.tt @@ -112,7 +112,7 @@ $(document).ready(function() { "className": 'hidden', "hidden": true, [%END%] - "mRender": function ( data, type, full ) { + "mRender": function ( data, type, full, opt ) { [% IF !helper.options.${f}.dont_skip_empty_data %] if(data == null) return ''; @@ -120,14 +120,17 @@ $(document).ready(function() { if(data == null) data = ''; [% END %] + if (typeof opt !== 'object') { + opt = {}; + } + opt.escapeHtml = true; // always escape HTML by default [% IF helper.custom_renderers.${f} -%] - data.escapeHtml = true; //true by default; var renderCustom = [% helper.custom_renderers.${f} -%]; [% ELSE -%] - var renderCustom = function(data, type, full) { data.escapeHtml = true; return data; }; + var renderCustom = function(data, type, full, opt) { return data; }; [% END -%] - var str = String(renderCustom(data, type, full)); - if (data.escapeHtml) { + var str = String(renderCustom(data, type, full, opt)); + if (opt.escapeHtml) { return str.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"');//" } return str; @@ -135,7 +138,7 @@ $(document).ready(function() { "bSortable": [% IF helper.column_sortable_map.${f} %] true [% ELSE %] false [% END %] }, [% END -%] - { "mRender": function ( data, type, full ) { + { "mRender": function ( data, type, full, opt ) { var html = '' + '
'; [% diff --git a/share/templates/helpers/datatables_field.tt b/share/templates/helpers/datatables_field.tt index 5365b38512..1b2ce0f0aa 100644 --- a/share/templates/helpers/datatables_field.tt +++ b/share/templates/helpers/datatables_field.tt @@ -38,20 +38,20 @@ $(document).ready(function() { [%IF table_titles.${index} %] { "mData": "[% f.replace('\.','_') %]", - "mRender": function ( data, type, full ) { + "mRender": function ( data, type, full, opt ) { if(data == null) return ''; [% IF custom_renderers.${f} -%] var renderCustom = [% custom_renderers.${f} -%]; [% ELSE -%] - var renderCustom = function(data, type, full) { return data; }; + var renderCustom = function(data, type, full, opt) { return data; }; [% END -%] return String(renderCustom(data, type, full)).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); } }, [% END -%] [% END -%] - { "mRender": function ( data, type, full ) { + { "mRender": function ( data, type, full, opt ) { return ''; }, "mData": null, diff --git a/share/templates/helpers/datatables_multifield.tt b/share/templates/helpers/datatables_multifield.tt index 73bfc3d6d1..571a0ed1d0 100644 --- a/share/templates/helpers/datatables_multifield.tt +++ b/share/templates/helpers/datatables_multifield.tt @@ -53,19 +53,19 @@ $(document).ready(function() { [% FOREACH f IN table_fields -%] { "mData": "[% f %]", - "mRender": function ( data, type, full ) { + "mRender": function ( data, type, full, opt ) { if(data == null) return ''; [% IF custom_renderers.${f} -%] var renderCustom = [% custom_renderers.${f} -%]; [% ELSE -%] - var renderCustom = function(data, type, full) { return data; }; + var renderCustom = function(data, type, full, opt) { return data; }; [% END -%] return String(renderCustom(data, type, full)).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); } }, [% END -%] - { "mRender": function ( data, type, full ) { + { "mRender": function ( data, type, full, opt ) { return ''; }, "mData": null, diff --git a/share/templates/timeset/event_list.tt b/share/templates/timeset/event_list.tt index af99194145..e52e02e011 100644 --- a/share/templates/timeset/event_list.tt +++ b/share/templates/timeset/event_list.tt @@ -10,7 +10,7 @@ var RRule; require(['rrule'], function (rrule) { RRule = rrule; }); -function toText(data, type, full) { +function toText(data, type, full, opt) { var rrule_text = ''; var dtstart, dtend, freq; var dtstart_obj; @@ -249,7 +249,7 @@ $( document ).ready(function() { helper.form_object = form; helper.ajax_uri = c.uri_for_action( "/timeset/event_ajax", [c.req.captures.0] ); helper.custom_renderers => { - ical => 'function ( data, type, full ) { return toText(data, type, full); }' + ical => 'function ( data, type, full, opt ) { return toText(data, type, full, opt); }' }; UNLESS c.user.read_only;