310 lines
6.7 KiB
Lua

--[[
util.lua - Utility functions for the Lua sandbox
Enhanced with web development utilities
]]--
local util = {}
-- ======================================================================
-- CORE UTILITY FUNCTIONS
-- ======================================================================
-- Generate a random token
function util.generate_token(length)
return __generate_token(length or 32)
end
-- ======================================================================
-- HTML ENTITY FUNCTIONS
-- ======================================================================
-- HTML entity mapping for common characters
local html_entities = {
["&"] = "&",
["<"] = "&lt;",
[">"] = "&gt;",
['"'] = "&quot;",
["'"] = "&#39;",
["/"] = "&#x2F;",
["`"] = "&#x60;",
["="] = "&#x3D;"
}
-- Convert special characters to HTML entities (like htmlspecialchars)
function util.html_special_chars(str)
if type(str) ~= "string" then
return str
end
return __html_special_chars(str)
end
-- Convert all applicable characters to HTML entities (like htmlentities)
function util.html_entities(str)
if type(str) ~= "string" then
return str
end
return __html_entities(str)
end
-- Convert HTML entities back to characters (simple version)
function util.html_entity_decode(str)
if type(str) ~= "string" then
return str
end
str = str:gsub("&lt;", "<")
str = str:gsub("&gt;", ">")
str = str:gsub("&quot;", '"')
str = str:gsub("&#39;", "'")
str = str:gsub("&amp;", "&")
return str
end
-- Convert newlines to <br> tags
function util.nl2br(str)
if type(str) ~= "string" then
return str
end
return str:gsub("\r\n", "<br>"):gsub("\n", "<br>"):gsub("\r", "<br>")
end
-- ======================================================================
-- URL FUNCTIONS
-- ======================================================================
-- URL encode a string
function util.url_encode(str)
if type(str) ~= "string" then
return str
end
str = str:gsub("\n", "\r\n")
str = str:gsub("([^%w %-%_%.%~])", function(c)
return string.format("%%%02X", string.byte(c))
end)
str = str:gsub(" ", "+")
return str
end
-- URL decode a string
function util.url_decode(str)
if type(str) ~= "string" then
return str
end
str = str:gsub("+", " ")
str = str:gsub("%%(%x%x)", function(h)
return string.char(tonumber(h, 16))
end)
return str
end
-- ======================================================================
-- VALIDATION FUNCTIONS
-- ======================================================================
-- Email validation
function util.is_email(str)
if type(str) ~= "string" then
return false
end
-- Simple email validation pattern
local pattern = "^[%w%.%%%+%-]+@[%w%.%%%+%-]+%.%w%w%w?%w?$"
return str:match(pattern) ~= nil
end
-- URL validation
function util.is_url(str)
if type(str) ~= "string" then
return false
end
-- Simple URL validation
local pattern = "^https?://[%w-_%.%?%.:/%+=&%%]+$"
return str:match(pattern) ~= nil
end
-- IP address validation (IPv4)
function util.is_ipv4(str)
if type(str) ~= "string" then
return false
end
local pattern = "^(%d%d?%d?)%.(%d%d?%d?)%.(%d%d?%d?)%.(%d%d?%d?)$"
local a, b, c, d = str:match(pattern)
if not (a and b and c and d) then
return false
end
a, b, c, d = tonumber(a), tonumber(b), tonumber(c), tonumber(d)
return a <= 255 and b <= 255 and c <= 255 and d <= 255
end
-- Integer validation
function util.is_int(str)
if type(str) == "number" then
return math.floor(str) == str
elseif type(str) ~= "string" then
return false
end
return str:match("^-?%d+$") ~= nil
end
-- Float validation
function util.is_float(str)
if type(str) == "number" then
return true
elseif type(str) ~= "string" then
return false
end
return str:match("^-?%d+%.?%d*$") ~= nil
end
-- Boolean validation
function util.is_bool(value)
if type(value) == "boolean" then
return true
elseif type(value) ~= "string" and type(value) ~= "number" then
return false
end
local v = type(value) == "string" and value:lower() or value
return v == "1" or v == "true" or v == "on" or v == "yes" or
v == "0" or v == "false" or v == "off" or v == "no" or
v == 1 or v == 0
end
-- Convert to boolean
function util.to_bool(value)
if type(value) == "boolean" then
return value
elseif type(value) ~= "string" and type(value) ~= "number" then
return false
end
local v = type(value) == "string" and value:lower() or value
return v == "1" or v == "true" or v == "on" or v == "yes" or v == 1
end
-- Sanitize string (simple version)
function util.sanitize_string(str)
if type(str) ~= "string" then
return ""
end
return util.html_special_chars(str)
end
-- Sanitize to integer
function util.sanitize_int(value)
if type(value) ~= "string" and type(value) ~= "number" then
return 0
end
value = tostring(value)
local result = value:match("^-?%d+")
return result and tonumber(result) or 0
end
-- Sanitize to float
function util.sanitize_float(value)
if type(value) ~= "string" and type(value) ~= "number" then
return 0
end
value = tostring(value)
local result = value:match("^-?%d+%.?%d*")
return result and tonumber(result) or 0
end
-- Sanitize URL
function util.sanitize_url(str)
if type(str) ~= "string" then
return ""
end
-- Basic sanitization by removing control characters
str = str:gsub("[\000-\031]", "")
-- Make sure it's a valid URL
if util.is_url(str) then
return str
end
-- Try to prepend http:// if it's missing
if not str:match("^https?://") and util.is_url("http://" .. str) then
return "http://" .. str
end
return ""
end
-- Sanitize email
function util.sanitize_email(str)
if type(str) ~= "string" then
return ""
end
-- Remove all characters except common email characters
str = str:gsub("[^%a%d%!%#%$%%%&%'%*%+%-%/%=%?%^%_%`%{%|%}%~%@%.%[%]]", "")
-- Return only if it's a valid email
if util.is_email(str) then
return str
end
return ""
end
-- ======================================================================
-- SECURITY FUNCTIONS
-- ======================================================================
-- Basic XSS prevention
function util.xss_clean(str)
if type(str) ~= "string" then
return str
end
-- Convert problematic characters to entities
local result = util.html_special_chars(str)
-- Remove JavaScript event handlers
result = result:gsub("on%w+%s*=", "")
-- Remove JavaScript protocol
result = result:gsub("javascript:", "")
-- Remove CSS expression
result = result:gsub("expression%s*%(", "")
return result
end
-- Base64 encode
function util.base64_encode(str)
if type(str) ~= "string" then
return str
end
return __base64_encode(str)
end
-- Base64 decode
function util.base64_decode(str)
if type(str) ~= "string" then
return str
end
return __base64_decode(str)
end
return util