diff --git a/runner/lua/sandbox.lua b/runner/lua/sandbox.lua index c7fae30..f09e249 100644 --- a/runner/lua/sandbox.lua +++ b/runner/lua/sandbox.lua @@ -421,31 +421,13 @@ local csrf = { -- TEMPLATE RENDER FUNCTIONS -- ====================================================================== --- Shared utilities -local __template_util = { - escape_html = function(s) - local entities = {['&']='&', ['<']='<', ['>']='>', ['"']='"', ["'"]='''} - return (s:gsub([=[["><'&]]=], entities)) - end, - - build_output = function(chunks) - return table.concat(chunks) - end, - - add_text = function(output, text) - if text and #text > 0 then - table.insert(output, text) - end - end, - - add_value = function(output, value, escaped) - local str = tostring(value or "") - table.insert(output, escaped and __template_util.escape_html(str) or str) - end -} - -- Template processing with code execution _G.render = function(template_str, env) + local function escape_html(s) + local entities = {['&']='&', ['<']='<', ['>']='>', ['"']='"', ["'"]='''} + return (s:gsub([=[["><'&]]=], entities)) + end + local function get_line(s, ln) for line in s:gmatch("([^\n]*)\n?") do if ln == 1 then return line end @@ -534,7 +516,7 @@ _G.render = function(template_str, env) setfenv(fn, runtime_env) local output_buffer = {} - fn(tostring, __template_util.escape_html, output_buffer, 0) + fn(tostring, escape_html, output_buffer, 0) return table.concat(output_buffer) end @@ -553,16 +535,30 @@ _G.parse = function(template_str, env) elseif unescaped_start then next_pos, placeholder_end, name, escaped = unescaped_start, unescaped_end, unescaped_name, false else - __template_util.add_text(output, template_str:sub(pos)) + local text = template_str:sub(pos) + if text and #text > 0 then + table.insert(output, text) + end break end - __template_util.add_text(output, template_str:sub(pos, next_pos - 1)) - __template_util.add_value(output, env[name], escaped) + local text = template_str:sub(pos, next_pos - 1) + if text and #text > 0 then + table.insert(output, text) + end + + local value = env[name] + local str = tostring(value or "") + if escaped then + local entities = {['&']='&', ['<']='<', ['>']='>', ['"']='"', ["'"]='''} + str = str:gsub([=[["><'&]]=], entities) + end + table.insert(output, str) + pos = placeholder_end + 1 end - return __template_util.build_output(output) + return table.concat(output) end -- Indexed placeholder processing @@ -580,17 +576,31 @@ _G.iparse = function(template_str, values) elseif unescaped_start then next_pos, placeholder_end, escaped = unescaped_start, unescaped_end, false else - __template_util.add_text(output, template_str:sub(pos)) + local text = template_str:sub(pos) + if text and #text > 0 then + table.insert(output, text) + end break end - __template_util.add_text(output, template_str:sub(pos, next_pos - 1)) - __template_util.add_value(output, values[value_index], escaped) + local text = template_str:sub(pos, next_pos - 1) + if text and #text > 0 then + table.insert(output, text) + end + + local value = values[value_index] + local str = tostring(value or "") + if escaped then + local entities = {['&']='&', ['<']='<', ['>']='>', ['"']='"', ["'"]='''} + str = str:gsub([=[["><'&]]=], entities) + end + table.insert(output, str) + pos = placeholder_end + 1 value_index = value_index + 1 end - return __template_util.build_output(output) + return table.concat(output) end -- ======================================================================