Moonshark/core/runner/CookieModule.go
2025-04-05 13:55:50 -05:00

187 lines
4.6 KiB
Go

package runner
import (
"net/http"
"time"
luajit "git.sharkk.net/Sky/LuaJIT-to-Go"
)
// extractCookie grabs cookies from the Lua state
func extractCookie(state *luajit.State) *http.Cookie {
cookie := &http.Cookie{
Path: "/", // Default path
}
// Get name
state.GetField(-1, "name")
if !state.IsString(-1) {
state.Pop(1)
return nil // Name is required
}
cookie.Name = state.ToString(-1)
state.Pop(1)
// Get value
state.GetField(-1, "value")
if state.IsString(-1) {
cookie.Value = state.ToString(-1)
}
state.Pop(1)
// Get path
state.GetField(-1, "path")
if state.IsString(-1) {
cookie.Path = state.ToString(-1)
}
state.Pop(1)
// Get domain
state.GetField(-1, "domain")
if state.IsString(-1) {
cookie.Domain = state.ToString(-1)
}
state.Pop(1)
// Get expires
state.GetField(-1, "expires")
if state.IsNumber(-1) {
expiry := int64(state.ToNumber(-1))
cookie.Expires = time.Unix(expiry, 0)
}
state.Pop(1)
// Get max age
state.GetField(-1, "max_age")
if state.IsNumber(-1) {
cookie.MaxAge = int(state.ToNumber(-1))
}
state.Pop(1)
// Get secure
state.GetField(-1, "secure")
if state.IsBoolean(-1) {
cookie.Secure = state.ToBoolean(-1)
}
state.Pop(1)
// Get http only
state.GetField(-1, "http_only")
if state.IsBoolean(-1) {
cookie.HttpOnly = state.ToBoolean(-1)
}
state.Pop(1)
return cookie
}
// LuaCookieModule provides cookie functionality to Lua scripts
const LuaCookieModule = `
-- Cookie module implementation
local cookie = {
-- Set a cookie
set = function(name, value, options, ...)
if type(name) ~= "string" then
error("cookie.set: name must be a string", 2)
end
-- Get or create response
local resp = __http_responses[1] or {}
resp.cookies = resp.cookies or {}
__http_responses[1] = resp
-- Handle options as table or legacy params
local opts = {}
if type(options) == "table" then
opts = options
elseif options ~= nil then
-- Legacy support: options is actually 'expires'
opts.expires = options
-- Check for other legacy params (4th-7th args)
local args = {...}
if args[1] then opts.path = args[1] end
if args[2] then opts.domain = args[2] end
if args[3] then opts.secure = args[3] end
if args[4] ~= nil then opts.http_only = args[4] end
end
-- Create cookie table
local cookie = {
name = name,
value = value or "",
path = opts.path or "/",
domain = opts.domain
}
-- Handle expiry
if opts.expires then
if type(opts.expires) == "number" then
if opts.expires > 0 then
cookie.max_age = opts.expires
local now = os.time()
cookie.expires = now + opts.expires
elseif opts.expires < 0 then
cookie.expires = 1
cookie.max_age = 0
else
-- opts.expires == 0: Session cookie
-- Do nothing (omitting both expires and max-age creates a session cookie)
end
end
end
-- Security flags
cookie.secure = (opts.secure ~= false)
cookie.http_only = (opts.http_only ~= false)
-- Store in cookies table
local n = #resp.cookies + 1
resp.cookies[n] = cookie
return true
end,
-- Get a cookie value
get = function(name)
if type(name) ~= "string" then
error("cookie.get: name must be a string", 2)
end
-- Access values directly from current environment
local env = getfenv(2)
-- Check if context exists and has cookies
if env.ctx and env.ctx.cookies and env.ctx.cookies[name] then
return tostring(env.ctx.cookies[name])
end
return nil
end,
-- Remove a cookie
remove = function(name, path, domain)
if type(name) ~= "string" then
error("cookie.remove: name must be a string", 2)
end
-- Create an expired cookie
return cookie.set(name, "", {expires = 0, path = path or "/", domain = domain})
end
}
-- Install cookie module
_G.cookie = cookie
-- Make sure the cookie module is accessible in sandbox
if __env_system and __env_system.base_env then
__env_system.base_env.cookie = cookie
end
`
// CookieModuleInitFunc returns an initializer for the cookie module
func CookieModuleInitFunc() StateInitFunc {
return func(state *luajit.State) error {
return state.DoString(LuaCookieModule)
}
}