From 19b5d30806de23a7b18566281ea262a93c68b517 Mon Sep 17 00:00:00 2001 From: Lightning11wins Date: Fri, 5 Jun 2026 12:28:52 -0600 Subject: [PATCH 1/5] Add a safe client-side implementation of eval, (replacing the previous unsafe version). --- centrallix-os/sys/js/ht_render.js | 64 ++++++++++++++++++++++++--- centrallix/expression/exp_generator.c | 2 +- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/centrallix-os/sys/js/ht_render.js b/centrallix-os/sys/js/ht_render.js index 12c5b7faf..5bbd5ce9c 100644 --- a/centrallix-os/sys/js/ht_render.js +++ b/centrallix-os/sys/js/ht_render.js @@ -310,14 +310,64 @@ function cxjs_right(s,l) if (s == null || l == null) return null; return s.substr(s.length-l); } -function cxjs_eval(x) - { - var _this = null; - var _context = null; - if (x == null) return null; - if (typeof x == 'object') x = x.toString(); - return eval(x); + +function cxjs_eval(_context, _this, expr, permflags) + { + console.log('eval', _context, _this, expr, permflags); + if (expr === null || expr === undefined) return null; + expr_str = String(expr).trim(); + if (expr_str === '') return null; + + const first_char = expr_str.charAt(0); + const last_char = expr_str.charAt(expr_str.length - 1); + + // Eval integer. + if (/^-?\d+$/.test(expr_str)) + return parseInt(expr_str, 10); + + // Eval floating point. + if (/^-?\d+\.\d*$/.test(expr_str) || /^-?\d*\.\d+$/.test(expr_str)) + return parseFloat(expr_str); + + // Eval double-quoted string. + if (expr_str.length >= 2 && first_char === '"' && last_char === '"') + return expr_str.substring(1, expr_str.length - 1); + + // Eval single-quoted string. + if (expr_str.length >= 2 && first_char === "'" && last_char === "'") + return expr_str.substring(1, expr_str.length - 1); + + // Eval :property or :object:property + if (first_char === ':') + { + const rest = expr_str.substring(1); + const colon2 = rest.indexOf(':'); + if (colon2 < 0) + { + // :property - current object (event params) reference + if (_this != null && (!permflags || permflags.indexOf('C') >= 0)) + { + const v = _this[rest]; + return (typeof v !== 'undefined') ? v : null; + } + } + else + { + // :object:property + if (_context != null && (!permflags || permflags.indexOf('O') >= 0)) + { + const objname = rest.substring(0, colon2); + const propname = rest.substring(colon2 + 1); + const obj = wgtrGetNode(_context, objname); + if (obj) return wgtrGetProperty(obj, propname); + } + } + } + + console.warn("Failed to eval expression: \"" + expr_str + "\""); + return null; } + function cxjs_isnull(v,d) { if (v == null) diff --git a/centrallix/expression/exp_generator.c b/centrallix/expression/exp_generator.c index fc521a39d..0b34a243e 100644 --- a/centrallix/expression/exp_generator.c +++ b/centrallix/expression/exp_generator.c @@ -457,7 +457,7 @@ exp_internal_GenerateText_js(pExpression exp, pExpGen eg) return -1; } exp_internal_WriteText(eg, eg->TmpBuf); - if (!strcmp(exp->Name, "substitute")) + if (!strcmp(exp->Name, "substitute") || !strcmp(exp->Name, "eval")) { /** This function requires awareness of its object/property scope **/ exp_internal_WriteText(eg, "_context,_this,"); From b63f9f5b219e88ab90ee78a845012c37f2241fbf Mon Sep 17 00:00:00 2001 From: Lightning11wins Date: Fri, 5 Jun 2026 14:25:51 -0600 Subject: [PATCH 2/5] Add support for booleans and null values to eval. --- centrallix-os/sys/js/ht_render.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/centrallix-os/sys/js/ht_render.js b/centrallix-os/sys/js/ht_render.js index 5bbd5ce9c..2a581583b 100644 --- a/centrallix-os/sys/js/ht_render.js +++ b/centrallix-os/sys/js/ht_render.js @@ -313,14 +313,19 @@ function cxjs_right(s,l) function cxjs_eval(_context, _this, expr, permflags) { - console.log('eval', _context, _this, expr, permflags); if (expr === null || expr === undefined) return null; - expr_str = String(expr).trim(); + const expr_str = String(expr).trim(); if (expr_str === '') return null; const first_char = expr_str.charAt(0); const last_char = expr_str.charAt(expr_str.length - 1); + // Eval boolean and null literals. + const expr_lower = expr_str.toLowerCase(); + if (expr_lower === 'true') return true; + if (expr_lower === 'false') return false; + if (expr_lower === 'null') return null; + // Eval integer. if (/^-?\d+$/.test(expr_str)) return parseInt(expr_str, 10); @@ -365,6 +370,7 @@ function cxjs_eval(_context, _this, expr, permflags) } console.warn("Failed to eval expression: \"" + expr_str + "\""); + return null; } From 93b78b655829c6d0e1253205ea56e5f72162e6bc Mon Sep 17 00:00:00 2001 From: Lightning11wins Date: Mon, 8 Jun 2026 11:53:16 -0600 Subject: [PATCH 3/5] Fix handling of :property and ::property. --- centrallix-os/sys/js/ht_render.js | 37 ++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/centrallix-os/sys/js/ht_render.js b/centrallix-os/sys/js/ht_render.js index 2a581583b..44888f7eb 100644 --- a/centrallix-os/sys/js/ht_render.js +++ b/centrallix-os/sys/js/ht_render.js @@ -311,8 +311,9 @@ function cxjs_right(s,l) return s.substr(s.length-l); } -function cxjs_eval(_context, _this, expr, permflags) +function cxjs_eval(_context, _this, expr, permflags, cur_obj_name, par_obj_name) { + console.log(_context, _this, expr, permflags, cur_obj_name, par_obj_name); if (expr === null || expr === undefined) return null; const expr_str = String(expr).trim(); if (expr_str === '') return null; @@ -341,24 +342,44 @@ function cxjs_eval(_context, _this, expr, permflags) // Eval single-quoted string. if (expr_str.length >= 2 && first_char === "'" && last_char === "'") return expr_str.substring(1, expr_str.length - 1); - - // Eval :property or :object:property + + // Eval :property, ::property, or :object:property if (first_char === ':') { const rest = expr_str.substring(1); const colon2 = rest.indexOf(':'); if (colon2 < 0) { - // :property - current object (event params) reference - if (_this != null && (!permflags || permflags.indexOf('C') >= 0)) + // :property - current object reference + if (!permflags || permflags.indexOf('C') >= 0) + { + if (cur_obj_name !== null && cur_obj_name !== undefined) + { + const cur_node = wgtrGetNode(_context, cur_obj_name); + if (cur_node) return wgtrGetProperty(cur_node, rest); + } + else if (_this !== null && _this !== undefined) + { + const v = _this[rest]; + return (typeof v === 'undefined') ? null : v; + } + } + } + else if (colon2 < 1) + { + // ::property - parent object reference (C's ParentID) + if (!permflags || permflags.indexOf('P') >= 0) { - const v = _this[rest]; - return (typeof v !== 'undefined') ? v : null; + const prop = rest.substring(1); + const par_node = (par_obj_name !== null && par_obj_name !== undefined) + ? wgtrGetNode(_context, par_obj_name) + : wgtrGetParent(_context); + if (par_node) return wgtrGetProperty(par_node, prop); } } else { - // :object:property + // :object:property - named object reference if (_context != null && (!permflags || permflags.indexOf('O') >= 0)) { const objname = rest.substring(0, colon2); From ed41ab4880b1f846858b5e3201b4480f913a65c4 Mon Sep 17 00:00:00 2001 From: Lightning11wins Date: Tue, 16 Jun 2026 14:42:08 -0600 Subject: [PATCH 4/5] Fix Greg's comments. --- centrallix-os/sys/js/ht_render.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/centrallix-os/sys/js/ht_render.js b/centrallix-os/sys/js/ht_render.js index fed447f77..b0ad6c548 100644 --- a/centrallix-os/sys/js/ht_render.js +++ b/centrallix-os/sys/js/ht_render.js @@ -360,8 +360,7 @@ function cxjs_eval(_context, _this, expr, permflags, cur_obj_name, par_obj_name) } else if (_this !== null && _this !== undefined) { - const v = _this[rest]; - return (typeof v === 'undefined') ? null : v; + return wgtrGetProperty(_this, rest); } } } @@ -373,7 +372,7 @@ function cxjs_eval(_context, _this, expr, permflags, cur_obj_name, par_obj_name) const prop = rest.substring(1); const par_node = (par_obj_name !== null && par_obj_name !== undefined) ? wgtrGetNode(_context, par_obj_name) - : wgtrGetParent(_context); + : wgtrGetParent(_this); if (par_node) return wgtrGetProperty(par_node, prop); } } From 9198f5c8014c16aded9fc3079270e2a9d006eb75 Mon Sep 17 00:00:00 2001 From: Lightning11wins Date: Tue, 16 Jun 2026 15:46:28 -0600 Subject: [PATCH 5/5] Fix missing edge case noticed by Greg. --- centrallix-os/sys/js/ht_render.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/centrallix-os/sys/js/ht_render.js b/centrallix-os/sys/js/ht_render.js index b0ad6c548..872b32244 100644 --- a/centrallix-os/sys/js/ht_render.js +++ b/centrallix-os/sys/js/ht_render.js @@ -360,7 +360,9 @@ function cxjs_eval(_context, _this, expr, permflags, cur_obj_name, par_obj_name) } else if (_this !== null && _this !== undefined) { - return wgtrGetProperty(_this, rest); + return (wgtrIsNode(_this)) + ? wgtrGetProperty(_this, rest) + : (_this[rest] ?? null); } } }