AJAX is about writing your user GUI in HTML, with user interactivity defined in client-side Javascript, and getting server data via HTTP requests, the response being returned usually in the form of XML structures.
Sajax (the Simple AJAX toolkit) is an AJAX module from Kepler.
The source
Here is some changing suggestions to the file $PREFIX/share/lua/5.1/sajax/sajax.lua. To get the changes (for evaluation!), just copy all code blocks in this page and paste into a new file sajax.lua (backup the old one first).
Module declaration
Just to make easier the work, the module will be declarate like this:
module("sajax", package.seeall)
And the follow line is kept:
local export_list = {}
This variable receives the functions exported by sajax.export().
The Xavante's check
There is a if statement in the code that checks if the xavante table exists, and if it has the httpd key.
But it sounds like legacy, because in many checkups the then-block never runs.
Then here we removed this if statement and the then-block.
It really needs to be checked yet.
The request_uri() function
Again it sounds like legacy.
This function has a if statement checking string.find(uri, "?") soon after a local attributes "" to uri (i.e. the then-block will never run).
There's also here a vulnerability, because Sajax does not support any session data information.
The suggested code to solve it:
local function request_uri(funcname)
local uri = cgilua.servervariable "SCRIPT_NAME"
uri = cgilua.mkurlpath(uri, { rs = funcname })
return uri
end
It must be changed.
The handle_client_request() function
There's no real change since the Tomás' diff file yet.
function handle_client_request()
if not cgi.rs then return end
-- Bust cache in the head
cgilua.header("Expires", "Mon, 26 Jul 1997 05:00:00 GMT") -- Date in the past
cgilua.header("Last-Modified", os.date "!%%a, %%d %%b %%Y %%H:%%M:%%S GMT")
-- always modified
cgilua.header("Cache-Control", "no-cache, must-revalidate") -- HTTP/1.1
cgilua.header("Pragma", "no-cache") -- HTTP/1.0
local funcname = cgi.rs
if not export_list[funcname] then
cgilua.put(string.format("-:%%s not callable", funcname))
else
-- TODO: Json may be introduced here
local func = export_list[funcname]
local rsargs = cgi["rsargs[]"]
local ok, result
if type(rsargs) == "table" then
ok, result = pcall(func, unpack(rsargs))
else
ok, result = pcall(func, rsargs)
end
if not ok then
cgilua.put(string.format("-:internal error in '%%s'\n\n%%s", funcname, result))
return
end
cgilua.put "+:"
cgilua.put(result)
end
return true
end
The export() function
No changes. This function just saves the exported functions into the export_list table.
function export(funcname, func)
export_list[funcname] = func
end
The functions: get_common_js() and show_common_js()
No changes (since Tomás) again. This chunk shows the JavaScript functions needed to create the XMLHttpRequest object and to make it deal with the server-side functions.
local function get_common_js()
return [=[
// remote scripting library
// (c) copyright 2005 modernmethod, inc
var sajax_debug_mode = false;
function sajax_debug(text) {
if (sajax_debug_mode)
alert("RSD: " + text);
}
function sajax_init_object() {
sajax_debug("rs_init_object() called..");
var A;
try {
A=new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
A=new ActiveXObject("Microsoft.XMLHTTP");
} catch (oc) {
A=null;
}
}
if(!A && typeof XMLHttpRequest != "undefined")
A = new XMLHttpRequest();
if (!A)
sajax_debug("Could not create connection object.");
return A;
}
function sajax_do_call(func_name, url, args) {
var i, x, n;
// TODO: here is where Json can be
for (i = 0; i < args.length-1; i++)
url = url + "&rsargs[]=" + escape(args[i]);
url = url + "&rsrnd=" + new Date().getTime();
x = sajax_init_object();
x.open("GET", url, true);
x.onreadystatechange = function() {
if (x.readyState != 4)
return;
sajax_debug("received " + x.responseText);
var status;
var data;
status = x.responseText.charAt(0);
data = x.responseText.substring(2);
if (status == "-")
alert("Error: " + data);
else
args[args.length-1](data);
}
x.send(null);
sajax_debug(func_name + " url = " + url);
sajax_debug(func_name + " waiting..");
delete x;
}
]=]
end
function show_common_js()
cgilua.put(get_common_js())
end
The functions: get_one_stub() and show_one_stub()
This code shows the JavaScript functions related to each server-side Lua function.
local function get_one_stub(funcname)
local uri = request_uri(funcname)
return (string.format([=[
// wrapper for %%s
function x_%%s() {
// count args; build URL
sajax_do_call("%%s", "%%s", x_%%s.arguments);
}
]=],
funcname, funcname, funcname, uri, funcname
))
end
local function show_one_stub(funcname)
cgilua.put (get_one_stub(funcname))
end
Has the JavaScript been shown?
The js_has_been_shown variable shows if the JavaScript code is already shown:
local js_has_been_shown = false
It could be at the head of the sajax.lua.
The functions: get_javascript() and show_javascript()
The first function returns the needed JavaScript chunk. The second one shows it with cgilua.put():
function get_javascript()
local js = {}
if not js_has_been_shown then
table.insert(js, get_common_js())
js_has_been_shown = true
end
for fn in pairs(export_list) do
table.insert(js, get_one_stub(fn))
end
return (table.concat(js))
end
function show_javascript ()
cgilua.put(get_javascript())
end
The init() function
This function does nothing for now.
function init()
end
Where do we go?
We are evaluating to rewrite Sajax to work with WSAPI, what will take a lot of recoding.