Login or register Large RSS Icon

Sajax

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.

Powered by Sputnik | XHTML 1.1