pax_global_header00006660000000000000000000000064122203136240014505gustar00rootroot0000000000000052 comment=9825b905133e14d37a4c179f2d02367ab93f1ef6 xavante-2.3.0/000077500000000000000000000000001222031362400131555ustar00rootroot00000000000000xavante-2.3.0/Makefile000066400000000000000000000015111222031362400146130ustar00rootroot00000000000000# $Id: Makefile,v 1.45 2008/04/04 20:00:00 mascarenhas Exp $ CONFIG= ./config include $(CONFIG) XAVANTE_START= src/xavante_start SAJAX_LUAS = src/sajax/sajax.lua ROOT_LUAS = src/xavante/xavante.lua XAVANTE_LUAS= src/xavante/cgiluahandler.lua src/xavante/encoding.lua src/xavante/filehandler.lua src/xavante/httpd.lua src/xavante/mime.lua src/xavante/patternhandler.lua src/xavante/redirecthandler.lua src/xavante/vhostshandler.lua src/xavante/indexhandler.lua src/xavante/urlhandler.lua src/xavante/ruleshandler.lua src/webdav/davhandler.lua src/webdav/davFileRepository.lua src/webdav/davFileProps.lua DOCS= doc/us/index.html doc/us/license.html doc/us/manual.html doc/us/sajax.html doc/us/xavante.gif all: install: mkdir -p $(LUA_DIR)/xavante cp $(ROOT_LUAS) $(SAJAX_LUAS) $(LUA_DIR) cp $(XAVANTE_LUAS) $(LUA_DIR)/xavante clean: xavante-2.3.0/Makefile.win000066400000000000000000000015231222031362400154120ustar00rootroot00000000000000# $Id: Makefile.win,v 1.24 2008/04/04 20:00:00 mascarenhas Exp $ include config.win XAVANTE_START= src\xavante_start SAJAX_LUAS = src\sajax\sajax.lua XAVANTE_LUAS= src\xavante\cgiluahandler.lua src\xavante\encoding.lua src\xavante\filehandler.lua src\xavante\httpd.lua src\xavante\mime.lua src\xavante\patternhandler.lua src\xavante\redirecthandler.lua src\xavante\ruleshandler.lua src\xavante\vhostshandler.lua src\xavante\indexhandler.lua src\xavante\urlhandler.lua DOCS= doc\us\index.html doc\us\license.html doc\us\manual.html doc\us\sajax.html doc\us\xavante.gif all: install: IF NOT EXIST "$(LUA_DIR)" mkdir "$(LUA_DIR)" copy $(SAJAX_LUAS) "$(LUA_DIR)\sajax.lua" IF NOT EXIST "$(LUA_DIR)\xavante" mkdir "$(LUA_DIR)\xavante" FOR %i IN ($(XAVANTE_LUAS)) DO copy %i "$(LUA_DIR)\xavante" copy src\xavante\xavante.lua "$(LUA_DIR)\" clean: xavante-2.3.0/README000066400000000000000000000142561222031362400140450ustar00rootroot00000000000000Xavante 2.3.0 http://keplerproject.org/xavante/ Xavante is a Lua HTTP 1.1 Web server that uses a modular architecture based on URI mapped handlers. Xavante currently offers a file handler, a redirect handler and a WSAPI handler. Those are used for general files, URI remapping and WSAPI applications respectively. Xavante is free software and uses the same license as Lua. Xavante can be downloaded from its LuaForge page. You can also install Xavante using LuaRocks: luarocks install xavante The Xavante package provides just the Xavante libraries. To see Xavante in action install wsapi-xavante from LuaRocks. Dependencies Xavante dependencies can be separated by the used handlers: Xavante Core * Lua 5.1 or Lua 5.2 * Copas 1.2.0 * LuaSocket 2.1 File Handler (optional) * LuaFileSystem 1.6 The portability of Xavante is determined by its binary components (LuaSocket and LuaFileSystem) and Lua itself. The other components are written in Lua and are as portable as Lua itself. History Xavante 2.3.0 [30/Jan/2013] * Lua 5.2 compatibility * bugfixes Xavante 2.2.1 [21/Oct/2010] * allow 0 as a port value, so the OS assigns one dynamically (contributed by Tim Niemueller * bugfixes in CGILua handler Xavante 2.2.0 [18/Mar/2010] * xavante.cgiluahandler now works with WSAPI 1.2/1.3 without needing kepler_init Xavante 2.1.0 [20/Oct/2009] * Fixes security bug on filehandler with ".." used in paths (access to files outside the doc root) * Added "reload" option to xavante.cgiluahandler, to force new state for every request Xavante 2.0.1 [06/Mar/2009] * Fixes bug [#9094] keep-alive connections don't clear cached data between requests (bug report and patch by John Passaniti) * redirecthandler now treats query strings correctly (bug report by ændrük). Xavante 2.0 [23/May/2008] * New WSAPI based cgiluahandler * Fixed a bug on SAPI.redirect that was not setting the statusline correctly * First version using LuaRocks Xavante 2.0 Beta [21/Nov/2007] * Xavante 2.0 Beta is distributed as a Lua module, the command line and Windows launchers are now part of the Kepler distribution * If you are using Kepler, it is strongly suggested that you replace your previous Xavante config.lua file with the new one installed by Kepler * Allow the definition of the HTTP status by using a "Status" header * Added the Connection: close header to every CGILua request in order to avoid confusions on the content size (patch by Ignacio Burgueño) * xavante.cgiluahandler now accepts an optional table with global names to be passed to the Ring where the request is processed. If this option is not present it looks for a RINGS_CGILUA_GLOBALS global and uses it. * Fixed bug [#1812] - SAPI.Response.Write was not sending all its arguments but the first one (bug found by Ignacio Burgueño) Xavante 1.3.1 [31/Aug/2007] * Replaces the use of the cgi table by cgilua.POST and cgilua.QUERY in the examples * Correcting the behavior of coxpcall when used with C functions (patch by Ignacio Burgueño) * Correcting issues with chucked encoding. Now it only sends the Transfer-Encoding header when necessary. Correcting the handling of cached files in filehandler. (patches by Ignacio Burgueño) * New /web structure, using a dynamic index to documentation in /web/doc/modulename Xavante 1.3 [24/Aug/2007] * Uses Lua 5.1 * Fixed headers to send the header twice if it's defined twice, instead of concat'ing with commas (previous behavior was broken when sending cookies) * Removed the restriction of only handling URLs that corresponded to files in the filesystem. Now cgilua.dispatcher can map URLs like /apps/wiki/... into whatever it needs. Patch by Mauricio Bomfim. * Corrected the PATH_INFO handling for cgilua.dispatcher * Code refactoring by Thomas Harning (Bug [#767]) * Better error handling, using io.stderr instead of print * Added the correct prefix to error codes (by Zachary P. Landau) * Support for caching based on last-modified implemented by Zachary P. Landau, based on the design of HTTP.lua (by PA) * Content Encoding handling using encoding.lua as a configuration file, added svgz encoding and content-type * Fixed bug [#510] filehandler does not send correct headers for a 404 error (found by Matthew Burke) Xavante 1.2 [20/Sep/2006] * Uses Compat-5.1 Release 5 * Handles multivalued HTTP headers * Added HTTP chunked mode response * New startup method, using KEPLER_INIT if available * New configuration option for the Xavante startup message * Redirection sends a 302 status instead of a 301 (less client caching) * Changed xavante/server.lua to xavante/xavante.lua for a simpler require"xavante" instead of require"xavante.server" * Uses Rings instead of VEnv in the CGILua handler * Minor bug fixes in the CGILua handler Xavante 1.1 [12/Jul/2005] * Sajax * Uses Copas.step() to allow more control of the Xavante loop. * Uses coxpcall 1.6 * New documentation with installation examples using Kepler file structure * Code cleanup, minor bug fixes Xavante 1.1 Beta [17/Mar/2005] * First public release * Refactored to use Copas * Source base merged with luahttpd * New configuration file with simpler rules Xavante 1.0 [Feb/2004] * (not released to the public) Credits Xavante 1.3 and up is implemented by Javier Guerra, André Carregal, and Fabio Mascarenhas with the help of Ignacio Burgueño, Zachary P. Landau, Mauricio Bomfim, Matthew Burke, Thomas Harning and others. Xavante 1.2 was implemented by Javier Guerra, André Carregal, Fabio Mascarenhas and Leonardo Godinho. Xavante 1.1 was redesigned and implemented by Javier Guerra and André Carregal. It merged Javier's work with luahttpd and André's work with Copas and Xavante 1.0. luahttpd is now part of Xavante. Xavante 1.0 was designed and implemented by André Carregal as part of the Kepler Project with contributions from Renato Crivano and Danilo Tuler. Xavante 1.0 development was sponsored by Fábrica Digital and Hands. xavante-2.3.0/config000066400000000000000000000005711222031362400143500ustar00rootroot00000000000000# $Id: config,v 1.16 2007/11/17 14:15:23 carregal Exp $ # Default prefix PREFIX = /usr/local # System's libraries directory (where binary libraries are installed) LUA_LIBDIR= $(PREFIX)/lib/lua/5.1 # System's lua directory (where Lua libraries are installed) LUA_DIR= $(PREFIX)/share/lua/5.1 # Complete path to Lua command line interpreter LUA_INTERPRETER= $(PREFIX)/bin/luaxavante-2.3.0/config.win000066400000000000000000000002201222031362400151330ustar00rootroot00000000000000# $Id: config.win,v 1.7 2007/11/17 14:15:23 carregal Exp $ # System's lua directory (where Lua libraries are installed) LUA_DIR= c:\lua5.1\lua xavante-2.3.0/doc/000077500000000000000000000000001222031362400137225ustar00rootroot00000000000000xavante-2.3.0/doc/us/000077500000000000000000000000001222031362400143515ustar00rootroot00000000000000xavante-2.3.0/doc/us/experimental.html000066400000000000000000000453301222031362400177410ustar00rootroot00000000000000 The Xavante Lua Web Server Experimental Modules
Xavante
A Lua Web Server with CGILua support

Experimental Modules

These are a few experimental modules included with Xavante; they're fairly functional but might have very rough edges, or might not seem very useful at first.

In general, these modules can be used when writing new Xavante handlers. In my view (not shared by most Kepler developers), static pages and CGILua are only two particular ways to create websites and webapps. There are many other ways to achieve those goals, and when using Xavante, most of them start with writing a Handler.

A Xavante Handler is just a function that gets called to serve a client request. The Xavante core parses the request's URL, and decides which handler to call. The chosen handler receives as parameters the request and response objects, usually we call these "the (req,res) parameters".

The handler analyses these parameters and produces the desired response, either calling the res:send(data) function repeatedly, or setting the res.content field with a string or an array of strings.

cookies.lua

Cookies are a common feature of many web development platforms. This module is shamelessly copied from the CGILua implementation, and exports three functions to be used from handlers:

value = xavante.cookies.get (req, name)

xavante.cookies.set (res, name, value [, options])

xavante.cookies.delete (res, name [, options])

Where req and res are the request and response objects, respectively, the handler got from the Xavante core, name is the name under which the cookie will be stored in the browser, value is the value to store as a cookie, and options are the cookie's options, given as a name=>value table.

The cookie options are managed by the browser, but as a special case, if options.expires is a number, it's converted into the corresponding date string. This let's you use the os.time() function to specify a relative time.

session.lua

This module lets you store some data and make it persistant from one request to another by the same client. In the current implementation, the session's stored data is just a Lua table, and is only stored in memory. If Xavante is restarted, all session data is lost.

To recognize the client coming back, a cookie is stored in the client's browser with a randomly generated session ID (SID) as the value.

S = xavante.session.open (req, res [, name])

xavante.session.close (req, res [,name])

The name is optional but strongly suggested to use a string unique to your handler, to minimize any chance of collision. Remember to give the same name (if any) to the session.close() function.

The table S would be a new table the first time the client visits this webapp, but will be the same table each subsequent request. You can store any kind of Lua data in this table.

When the user wants to close his session, call the session.close() function. The cookie in his browser will be deleted, and the session table will be detached from the internal storage, so it will be eventually garbage collected.

codeWeb.lua

Xavante was developed to efficiently handle a big number of handlers, each one could manage as big or as little a part of the URL space as desired. There's nothing wrong with having several handlers to manage a single URL each. codeWeb is a module to help you with that kind of setting.

As usual with Lua scripts, the Xavante config file is a script that gets executed at startup time and sets up the running environment. In most cases, this means using the xavante.HTTP {} function to: associate the whole tree to xavante.filehandler, any file ending with .lp or .lua to xavante.cgiluahandler, and any URL ending with / xavante.redirecthandler.

The codeWeb module adds a function to register several handlers, joined as a module, to part of the URL tree:

xavante.codeWeb.addModule (host, urlpath, m [, as_tree])

Where host is the virtual host name, urlpath is the root of the URL subtree where the module gets registered, m is a table in the form m[name]=h, with name as the URL end part, and h as the corresponding handler. The optional boolean as_tree (false by default) tells if each handler should registered as a single URL, or as a subtree itself.

To use this function, the developer writes a module, where the exported functions are the handlers. The head of the subtree (urlpath itself) is managed by the handler called "__main". The function coroWeb.addModule() registers all table elements where the key is a string not beginning with '_' and the value is a function.

Example:

local session = require ("xavante.session")
require ("xavante.coroWeb")
module (arg and arg[1])

--
-- the 'main' handler redirects to .../index
--
function __main (req,res)
    local path = req.parsed_url.path
    if string.sub (path, -1) ~= "/" then path = path.."/" end
    xavante.httpd.redirect (res, path.."index")
end

--
-- this is a hard-coded constant page
--
function index (req, res)

    cookies.set (res, "mycook", "456", {["Max-Age"] = "60"})

    res.content = [[
        <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
        <HTML><HEAD>
            <TITLE>CodeWeb</TITLE>
        </HEAD><BODY>
            <H1>Hi there!</H1>

            look <a href="mira1">this</a>,
            and then <a href="mira2">that</a>.</br>
            <a href="subpage">here</a>'s another page.</br>

        </BODY></HTML>]]
    return res
end

--
-- this two pages use a common session to check user status
--
function mira1 (req, res)
    local ss = session.open (req, res, "mirando")

    res.content = [[
        <HTML><HEAD>
        <TITLE>CodeWeb</TITLE>
        </HEAD><BODY>
    ]]

    if ss.lastvio == "mira1" then
        res.content = res.content .. "<p> repeating.... </p>"
    elseif ss.lastvio == "mira2" then
        res.content = res.content .. "<p> should've come here first... </p>"
    else
        res.content = res.content .. "<p> haven't seen anythig yet! </p>"
    end

    res.content = res.content .. "</BODY></HTML>"

    ss.lastvio = "mira1"
end

function mira2 (req, res)
    local ss = session.open (req, res, "mirando")

    res.content = [[
        <HTML><HEAD>
            <TITLE>CodeWeb</TITLE>
        </HEAD><BODY>
    ]]

    if ss.lastvio == "mira1" then
        res.content = res.content .. "<p> see that? this one is better! </p>"
    elseif ss.lastvio == "mira2" then
        res.content = res.content .. "<p> repeating the second... </p>"
    else
        res.content = res.content .. "<p> see the other one first! </p>"
    end

    res.content = res.content .. "</BODY></HTML>"

    ss.lastvio = "mira2"
end

--
-- this page is loaded and compiled at startup time,
-- but executed at request time
--
subpage = xavante.codeWeb.load_cw ("test.cw");

This sample module defines five handlers: __main(), index(), mira1(), mira2() and subpage(). If this code is in the cw_samp.lua file, and you want it to be accessible under URLs of the form: http://your.server.com/sample, the config file should include a line like this:

xavante.codeWeb.addModule ("_", "/sample", require "cw_samp", true)

This line first does a require "cw_samp", which compiles the module and returns it as a table. Then the xavante.codeWeb.addModule() function registers it under the "/sample" subtree of the default virtual host (named "_"), making the handlers accessible under the URLs:

  • http://your.server.com/sample
  • http://your.server.com/sample/index
  • http://your.server.com/sample/mira1
  • http://your.server.com/sample/mira2
  • http://your.server.com/sample/subpage

The main() handler just redirects any request to index. In some projects this could be the most convenient (and most flexible) way to redirect or remap URLs.

The index() handler stores a cookie of name "mycook" and value "456" at the user's browser, with a maximum age of 60 seconds. Then it just responds with a constant HTML content.

The two handlers mira1() and mira2() use a session called "mirando", to store some data used to deduce the order in which the user clicked on those links and present some annoying messages.

The subpage handler uses the second feature of codeWeb: compiled templates.

A codeWeb template is a file written in the same way as luaPages for CGILua; in fact, the code is mostly copied from CGILua's luaPage translator. The main difference is that a template loaded by codeWeb.load_cw() gets compiled into a handler. This compilation usually happens at startup time, so the response time is as fast as other Xavante handlers.

This is the code of the test_cw template:

<html>
    <?lua
        local cookies = require ("xavante.cookies")

        mycook, mck_opt = cookies.get (req, "mycook")
    ?>
    <?lua if mycook then ?>
        <p>cookie: <?= mycook ?> </p>
        <ul><?lua for k,v in pairs (mck_opt) do ?>
            <li>opt: <?= k ?> = <?= v ?></li>
        <?lua end ?></ul>
    <?lua else ?>
        <p> there's no cookie </p>
    <?lua end ?>
</html>

Note: This is a bad example, there's almost no HTML code and lots of Lua, obscured by the many <?lua ... ?> tags.

As can be seen in the example, the req, and res objects are available. The handler built by the codeWeb.load_cw() is of the form

function (req, res, ...)
    -- translated template code
end

The Xavante core dispatcher is not the only one that can call handlers; any handler could call another handler. This is especially convenient to use several small templates to generate pieces of HTML code, under the controlling logic of an 'outer' handler.

To pass data between an 'outer' handler and a compiled template, just add more parameters after the req and res required parameters. If you wish, you could start your template with some code like:

<?lua
    local myparam1, myparam2 = unpack(arg)
?>

To give local names to your extra parameters.

coroWeb

This module uses sessions to keep track of a user, creating a coroutine to handle it as the code flow. Just write a simple handler, but instead of registering it, wrap it into a coroWeb handler, like this:

--
-- this is a coroHandler, the user progresses
-- through the code with each visit
--
coPage = xavante.coroWeb.handler ("coPage", function (req, res)
        res.content = "<html><body>one..</body></html>"
        req, res = yield ()
        res.content = "<html><body>two..</body></html>"
        req, res = yield ()
        res.content = "<html><body>and three, the end!</body></html>"
    end)

The coroWeb.handler() function takes as paramters a name (used for the session cookie), and a handler (a function with (req,res) parameters), and returns a new handler, which could (for example) be one of many in a codeWeb module.

A coroWeb handler produces some content (with the usual res parameter), and calls yield(). The function flow is suspended, the content is sent to the browser, and the function only gets resumed when the same user returns to the handler (on any URL managed by the same handler). At this point, the yield() function returns, with a new set of req,res parameters.

The handler gets started with each new user to enter the webapp; and the session is closed when the handler finishes.

In this example, the first time the user gets to this URL, he gets a page with "one..", the second time he gets "two..", and the third time he gets "and three, the end!". If he reloads the page a fourth time, the cycle starts again.

A developer could want to write a webapp with a central 'event loop', much like GUI apps are written. To help on this pattern, there's the xavante.coroWeb.event() function.

req,res = xavante.coroWeb.event (req, sh_t [, get_all])

This function should be called in the main loop; it returns a new set of req, res objects each iteration. The first parameter is the usual req object, sh_t is a table of subhandlers, and the optional get_all is a boolean (default false).

An event driven handler should first create the 'main' page on res and call coroWeb.event() with a table filled with the handlers for all possible actions of the user. Each of these subhandlers will be called with the req,res objects corresponding to the user action. If a subhandler returns a string "refresh", or if the main handler set the get_all parameter as true, the coroWeb.event() returns and the main loop should refresh the main page.

A simple example:

coPage2 = xavante.coroWeb.handler ("coPage2", function (req, res)

    local counter = 0
    local count2 = 0
    local sh_t = {
        inc = function () counter = counter+1 return "refresh" end,
        dec = function () counter = counter-1 return "refresh" end,
    }

    while true do
        res.content = string.format ([[
            <html><body>
                    counter: %s (%s)</br>
                <a href="coPage2/inc">inc</a>
                <a href="coPage2/dec">dec</a>
            </body></html>]], counter, count2)

        count2 = count2+1

        req,res = xavante.coroWeb.event (req, sh_t)
    end
end)

The first time a user enters this handler, two local variables, counter and count2 are initialized at 0, and the subhandler table sh_t is filled with two handlers: inc() and dec().

The main loop does three things: sets the response content with a simple page (which includes the counters values and links to the inc and dec subhandlers), increments the count2 variable, and waits for an event.

When the user clicks on a link, the corresponding subhandler is executed and the counter variable is modified. The subhandler then returns a "refresh" string, which causes the event() function to return immediately to the main loop and refresh the main page, with the updated counter variables.

Note that these handlers don't use req and res, so we can leave the parameter lists empty. This is possible because all the data used by the subhandlers is accessible as local variables (local to the enclosing scope), and all the output needed is just refreshing the main page (in the main loop). What's missing from this example is a "logout" link that would let the main loop to finish, and eventually close the thread.

Valid XHTML 1.0!

$Id: experimental.html,v 1.3 2007/11/17 16:09:41 carregal Exp $

xavante-2.3.0/doc/us/index.html000066400000000000000000000303301222031362400163450ustar00rootroot00000000000000 The Xavante Lua Web Server
Xavante
A Lua Web Server with WSAPI support

Overview

Xavante is a Lua HTTP 1.1 Web server that uses a modular architecture based on URI mapped handlers. Xavante currently offers a file handler, a redirect handler and a WSAPI handler. Those are used for general files, URI remapping and WSAPI applications respectively.

Xavante is free software and uses the same license as Lua.

Status

Current version is 2.3.0 and works with Lua 5.1 and Lua 5.2.

Download

Xavante can be downloaded from its Github page, at the Downloads tab.

You can also install Xavante using LuaRocks:

luarocks install xavante

The "xavante" package installs Xavante as a library. To run Xavante as an application please install WSAPI:

luarocks install wsapi-xavante

Dependencies

Xavante dependencies can be separated by the used handlers:

Xavante Core
File Handler (optional)

The portability of Xavante is determined by its binary components (LuaSocket and LuaFileSystem) and Lua itself. The other components are written in Lua and are as portable as Lua itself.

History

Xavante 2.3.0 [30/Jan/2013]
  • support for Lua 5.2
  • bugfixes
Xavante 2.2.1 [21/Oct/2010]
  • allow 0 as a port value, so the OS assigns one dynamically
  • bugfixes in CGILua handler
Xavante 2.2.0 [18/Mar/2010]
  • Changed xavante.cgiluahandler to works with WSAPI 1.2/1.3 without needing kepler_init
Xavante 2.1.0 [20/Oct/2009]
  • Adds "reload" option to xavante.cgiluahandler, to force new state for every request
  • Fixes a bug in File Handler that was allowing the use of ".." to access forbiden directories (bug report by Matthew Wild).
Xavante 2.0.1 [06/Mar/2009]
  • Fixes bug [#9094] keep-alive connections don't clear cached data between requests (bug report and patch by John Passaniti)
  • redirecthandler now treats query strings correctly (bug report by ændrük).
Xavante 2.0 [23/May/2008]
  • New WSAPI based cgiluahandler
  • Fixed a bug on SAPI.redirect that was not setting the statusline correctly
  • First version using LuaRocks
Xavante 2.0 Beta [21/Nov/2007]
  • Xavante 2.0 Beta is distributed as a Lua module, the command line and Windows launchers are now part of the Kepler distribution
  • If you are using Kepler, it is strongly suggested that you replace your previous Xavante config.lua file with the new one installed by Kepler
  • Allow the definition of the HTTP status by using a "Status" header
  • Added the Connection: close header to every CGILua request in order to avoid confusions on the content size (patch by Ignacio Burgueño)
  • xavante.cgiluahandler now accepts an optional table with global names to be passed to the Ring where the request is processed. If this option is not present it looks for a RINGS_CGILUA_GLOBALS global and uses it.
  • Fixed bug [#1812] - SAPI.Response.Write was not sending all its arguments but the first one (bug found by Ignacio Burgueño)
Xavante 1.3.1 [31/Aug/2007]
  • Replaces the use of the cgi table by cgilua.POST and cgilua.QUERY in the examples
  • Correcting the behavior of coxpcall when used with C functions (patch by Ignacio Burgueño)
  • Correcting issues with chucked encoding. Now it only sends the Transfer-Encoding header when necessary. Correcting the handling of cached files in filehandler. (patches by Ignacio Burgueño)
  • New /web structure, using a dynamic index to documentation in /web/doc/modulename
Xavante 1.3 [24/Aug/2007]
  • Uses Lua 5.1
  • Fixed headers to send the header twice if it's defined twice, instead of concat'ing with commas (previous behavior was broken when sending cookies)
  • Removed the restriction of only handling URLs that corresponded to files in the filesystem. Now cgilua.dispatcher can map URLs like /apps/wiki/... into whatever it needs. Patch by Mauricio Bomfim.
  • Corrected the PATH_INFO handling for cgilua.dispatcher
  • Code refactoring by Thomas Harning (Bug [#767])
  • Better error handling, using io.stderr instead of print
  • Added the correct prefix to error codes (by Zachary P. Landau)
  • Support for caching based on last-modified implemented by Zachary P. Landau, based on the design of HTTP.lua (by PA)
  • Content Encoding handling using encoding.lua as a configuration file, added svgz encoding and content-type
  • Fixed bug [#510] filehandler does not send correct headers for a 404 error (found by Matthew Burke)
Xavante 1.2 [20/Sep/2006]
  • Uses Compat-5.1 Release 5
  • Handles multivalued HTTP headers
  • Added HTTP chunked mode response
  • New startup method, using KEPLER_INIT if available
  • New configuration option for the Xavante startup message
  • Redirection sends a 302 status instead of a 301 (less client caching)
  • Changed xavante/server.lua to xavante/xavante.lua for a simpler require"xavante" instead of require"xavante.server"
  • Uses Rings instead of VEnv in the CGILua handler
  • Minor bug fixes in the CGILua handler
Xavante 1.1 [12/Jul/2005]
  • Sajax
  • Uses Copas.step() to allow more control of the Xavante loop.
  • Uses coxpcall 1.6
  • New documentation with installation examples using Kepler file structure
  • Code cleanup, minor bug fixes
Xavante 1.1 Beta [17/Mar/2005]
  • First public release
  • Refactored to use Copas
  • Source base merged with luahttpd
  • New configuration file with simpler rules
Xavante 1.0 [Feb/2004]
  • (not released to the public)

Credits

Xavante 1.3+ was implemented by Javier Guerra, André Carregal, and Fábio Mascarenhas with the help of Ignacio Burgueño, Zachary P. Landau, Mauricio Bomfim, Matthew Burke, Thomas Harning and others.

Xavante 1.2 was implemented by Javier Guerra, André Carregal, Fábio Mascarenhas and Leonardo Godinho.

Xavante 1.1 was redesigned and implemented by Javier Guerra and André Carregal. It merged Javier's work with luahttpd and André's work with Copas and Xavante 1.0. luahttpd is now part of Xavante.

Xavante 1.0 was designed and implemented by André Carregal as part of the Kepler Project with contributions from Renato Crivano and Danilo Tuler. Xavante 1.0 development was sponsored by Fábrica Digital and Hands.

Contact us

For more information please contact us. Comments are welcome!

You can also reach other Xavante developers and users on the Kepler Project mailing list.

Valid XHTML 1.0!

$Id: index.html,v 1.50 2009/08/10 20:18:57 carregal Exp $

xavante-2.3.0/doc/us/license.html000066400000000000000000000110141222031362400166560ustar00rootroot00000000000000 The Xavante Lua Web Server License
Xavante
A Lua Web Server with WSAPI support

Xavante License

Xavante is free software: it can be used for both academic and commercial purposes at absolutely no cost. There are no royalties or GNU-like "copyleft" restrictions. Xavante qualifies as Open Source software. Its licenses are compatible with GPL. Xavante is not in the public domain and Kepler Project keep its copyright. The legal details are below.

The spirit of the license is that you are free to use Xavante for any purpose at no cost without having to ask us. The only requirement is that if you do use Xavante, then you should give us credit by including the appropriate copyright notice somewhere in your product or its documentation.

The Xavante Web Server is designed and implemented by Javier Guerra and André Carregal. The implementation is not derived from licensed software.


Copyright © 2003-2010 Kepler Project.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Valid XHTML 1.0!

$Id: license.html,v 1.16 2008/05/23 20:18:58 carregal Exp $

xavante-2.3.0/doc/us/manual.html000066400000000000000000000122151222031362400165150ustar00rootroot00000000000000 The Xavante Lua Web Server Manual
Xavante
A Lua Web Server with WSAPI support

Installing

You can install Xavante using LuaRocks:

luarocks install xavante

The "xavante" package installs Xavante as a library. To run Xavante as an application please install WSAPI:

luarocks install wsapi-xavante

Configuring

After the Xavante module is loaded, it needs to be configured before being able to serve requests. You need to register the handlers using the xavante.HTTP constructor.

xavante.HTTP defines virtualhosts for each site that will be served. Each virtualhost can define a set of rules for it. Each rule matches a URL Lua pattern with a handler. Xavante currently offers a file handler, a redirect handler and a CGILua handler for general files, URL remapping and CGILua scripts respectively.

A typical use would be:

local hfile = require "xavante.filehandler"
local hcgi = require "xavante.cgiluahandler"
local hredir = require "xavante.redirecthandler"

local xavante = require "xavante"
  
-- Define here where Xavante HTTP documents scripts are located
local webDir = XAVANTE_WEB

local simplerules = {

    { -- URI remapping example
      match = "^[^%./]*/$",
      with = hredir,
      params = {"index.lp"}
    }, 

    { -- cgiluahandler example
      match = {"%.lp$", "%.lp/.*$", "%.lua$", "%.lua/.*$" },
      with = hcgi.makeHandler (webDir)
    },
    
    { -- filehandler example
      match = ".",
      with = hfile,
      params = {baseDir = webDir}
    },
} 

xavante.HTTP{
    server = {host = "*", port = 8080},
    
    defaultHost = {
    	rules = simplerules
    },
}

Note the use of webDir both to set the base directory for the file handler and for the CGILua scripts. These paths should contain the desired directories in your structure.

To use virtual hosts with Xavante, the call to xavante.HTTP would be changed to something like

xavante.HTTP{
    server = {host = "*", port = 8080},
    
    defaultHost = {},
    
    virtualhosts = {
        ["www.sitename.com"] = simplerules
    }
}

Running

If you are using Xavante as a module, then to start it you need to call xavante.start([checkfunction[, timeout]]) passing an optional checking function and connection timeout value. The checking function, if present, will be called periodically to check if Xavante should continue to run. This function can be also used for maintenance tasks or as a callback to your application.

Valid XHTML 1.0!

$Id: manual.html,v 1.46 2008/05/23 20:18:58 carregal Exp $

xavante-2.3.0/doc/us/sajax.html000066400000000000000000000232071222031362400163510ustar00rootroot00000000000000 The Xavante Lua Web Server Sajax
Xavante
A Lua Web Server with WSAPI support

Sajax

Background

Xavante offers a Lua version of Sajax that can be used in AJAX applications. Sajax (the Simple AJAX toolkit) was written in PHP by Thomas Lackner. AJAX is short for "Asynchronous Javascript and Xml", a new name for a not-so-new technology.

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 doesn't use a lot of XML itself, but the JavaScript object used to make the HTTP queries is XMLHttpRequest, so the 'X' in the name remains.

Sajax makes everything easier to do by allowing functions running in the server to be called from JavaScript code running in the client. To do that just register your functions and Sajax will generate JavaScript 'stubs' (small functions that handle the query to the server) with the same name as the server-side functions.

After that, all you have to do is call those functions from the client side Javascript and Sajax handles the magic

Usage

The example below is taken from calculator.lp, based on one of the examples on the Sajax site:

<%
    require "sajax"

    function multiply(x, y)
        return x * y
    end

    sajax.init()
    sajax.export ("multiply", multiply)
    if sajax.handle_client_request () then return end
%>

This code defines a very trivial function and registers it with sajax.export. After all exported functions have been registered, it calls sajax.handle_client_request and finishes the script if there has been a Sajax request.

<head>
	<title>Multiplier</title>
	<script>
	<%
		sajax.show_javascript();
	%>
	
	function do_multiply_cb(z) {
		document.getElementById("z").value = z;
	}
	
	function do_multiply() {
		var x, y;
		
		x = document.getElementById("x").value;
		y = document.getElementById("y").value;
		x_multiply(x, y, do_multiply_cb);
	}
	</script>
</head>

The <head> part of the page includes some JavaScript code. The call to sajax.show_javascript generates the support functions and the JavaScript stub function that will remotely call the registered Lua functions.

The function do_multiply reads two values, x and y from form fields and calls the stub function x_multiply, adding as the last parameter a callback function. The function x_multiply will perform the query to the server, and return immediately. The callback function do_multiply_cb will be called with the server function's return value as the only parameter. In this example, do_multiply_cb puts the multiplication result into a form field.

<body>
	<input type="text" name="x" id="x" value="2" size="3">
	*
	<input type="text" name="y" id="y" value="3" size="3">
	=
	<input type="text" name="z" id="z" value="" size="3">
	<input type="button" name="check" value="Calculate"
		onclick="do_multiply(); return false;">
</body>

The body of the Lua Page contains the HTML fields used by the JavaScript functions, and also the button that calls the do_multiply function. In AJAX, the HTML code is mostly the initial canvas where JavaScript code is executed, using both user events and server responses as inputs to operation.

Notes

  • The sajax.handle_client_request function must be called after all the server-side functions has been registered, but before any other page processing. If the call returns true, the script must be finished immediatly.
  • The JavaScript stubs names are the names under which the server-side functions were exported, with a x_ prefix.
  • The value returned by the server-side function is converted to a string and passed as the parameter to a JavaScript callback. Only one returned value is passed.
  • The JavaScript stub returns immediately after posting the query to the server; to do work after the server-side function has returned, use the callback function. That's the 'Asynchronous' part in AJAX.

How it works

There are two different operation modes in sajax.lua: the generic CGILua mode, and a Xavante specific optimization.

In generic CGILua, sajax.lua works very similar to the PHP version:

  1. When the user enters the URL of the CGILua Script (or Lua Page), all the functions are registered; but handle_client_request returns false, the script continues and produces the whole page, including the JavaScript stubs generated by show_javascript.
  2. A user event calls up some JavaScript, which in turn may call some of the stubs.
  3. The JavaScript stub build a HTTP request with the same URL of the current page, with parameters indicating the function it wants to call, and any other parameter passed by the calling JavaScript code. It also adds the callback function to the request object, posts the request to the server, and returns immediately.
  4. The client query is handled in the server by the same Lua script. The same functions get registered, but this time the handle_client_request function detects the Sajax request, pulls the required function name and other parameters, and calls the registered function. It then builds the response with the returned value, sends it to the client, and returns true to indicate the main Lua Script that the request has been handled and that it should terminate.
  5. The response is handled by the client-side JavaScript; if the response is positive, the callback function is called with the returned value, if the response signals an error, an alert is posted.

If sajax.lua detects that the current webserver is Xavante, it uses a different workflow:

  1. When the user enters the URL of the CGILua Script (or LuaPage), all the functions are registered in the Xavante dispatch table as handlers for URLs of the form:
    http://www.server.com/somedir/script.lp/funcname
    handle_client_request does nothing and always returns false.
  2. The JavaScript stubs call the functions with their specific URL, adding the parameters passed by the calling client side code.
  3. The Xavante dispatch code calls the required function, no CGILua environment is set up.
  4. The returned value is handled in the same way, calling the client-side callback.

It is very important to notice that the CGILua system is called only for the initial page request; the remote function calls don't fetch the filesystem, and the CGILua environment and parsing is bypassed. That means that the server-side functions can't use most CGILua functions, so any session identifying key should be passed as a function parameter.

Valid XHTML 1.0!

$Id: sajax.html,v 1.10 2008/05/23 20:18:58 carregal Exp $

xavante-2.3.0/doc/us/xavante.gif000066400000000000000000000101061222031362400165040ustar00rootroot00000000000000GIF87amv~nnnuuu||| ""%%**4455;;BBEEJJSSUU\\aaddllqqtt{{Ēǔɜ͠ΤѬձ״ټ(%w0VwTVww9Vw$<8UwVw 88Uw(%wW|gwPR9<<TW|W|lNC<T@<hٸ$ e `=l8@<H< 4Uw%wDN7W|gwDm<<q<sHH<^Dm<!,@H*\ȰÇ#JHŋI(!FD~AB c >p@͚6sp  =ph"B>r".Rt@UC.pb͛9uܩ3 "\)0pcFMEA`ͻlX8khmA wCE4:k t@g=TZAld`@ 1QH 9|6^;7xa8"::zv_* fH/y(^OCt7p@:W&*ϞFjBױ)Uo}$y_C2 `{u}ge 5 B^tN, J$'H NrB`UH"¯J@`[ `†JCƀ@$*J %~(7PJj0p / 0`B6"D:&IP"\!e37  h`PWmG tD3[Oe8,@dhfxNptƀ#2(-9+,NfJ3/ \QLޥxٔ@!X5 >DKq]}"4 A~+' ~QX1FE[ɝT!)">H@znnd|dI4CrYDJKkheØ@tbkU%ͳ^mY_ HgBls \DkbuZ+i,[BN!tAК4<4Uٱoc-s~7&B)/\DH{6 <@Y-U[ 8 >x*W E ݌cN)t3ICsak=Q,[ nu .ʈ|فֿ· S6AXWB+5@vD5" VV eD("B)))[+^a/-:RCSֽ&y ]M̄ʥH&6T郑:S02[pFx@C>JQ &ՎGGnm* ">rJQL+D)wu@6!tb&e7e4k ru~aU1: ; 2 NJbC%3]1Br'dw UnHam=1 hV;@?HtOZq"b4`U*QQsp0M!9ăza,gVU9=T_uc/׀c,ck3\V9\B * LׇQ?c:,q rR8 1BNP[i,%Z$}eT aW(gHhO[eAxM DW1p!Vy78Se e!5pJcZ"f'P 8PYRwhECfL"C8h3=x45C(:(*W5NpeHhzO(s,Ph4}qEAGDQSY9:p%27\h:O *G1t41ys}.hF,P]Ot +/8Q l8e!PWAɘ@B@d'1 D?%0+zj *`4Dra`kd_.6@7=0 g;xavante-2.3.0/examples/000077500000000000000000000000001222031362400147735ustar00rootroot00000000000000xavante-2.3.0/examples/config.lua000066400000000000000000000015161222031362400167460ustar00rootroot00000000000000------------------------------------------------------------------------------- -- Xavante configuration file. -- -- -- Authors: Javier Guerra and Andre Carregal -- Copyright (c) 2004-2007 Kepler Project --- -- $Id: config.lua,v 1.1 2007/10/31 17:50:13 carregal Exp $ ------------------------------------------------------------------------------ local xavante = require "xavante.httpd" local hvhost = require "xavante.vhostshandler" local hurl = require "xavante.urlhandler" local hindex = require "xavante.indexhandler" local hfile = require "xavante.filehandler" local hcgilua = require "xavante.cgiluahandler" xavantee.handle_request = hvhost { [""] = hurl { ["/"] = hindex ("/cgi/index.lp"), ["/cgi/"] = hcgilua.makeHandler (XAVANTE_WEB), ["/img/"] = hfile (XAVANTE_WEB.."/img"), } } xavante.register ("*", 8080, "Xavante 1.3") xavante-2.3.0/examples/webdav/000077500000000000000000000000001222031362400162435ustar00rootroot00000000000000xavante-2.3.0/examples/webdav/webdav-server.lua000066400000000000000000000013551222031362400215260ustar00rootroot00000000000000require "xavante" require "xavante.davhandler" local davFileRepository = require "xavante.davFileRepository" local davFileProps = require "xavante.davFileProps" webDir = "." local simplerules = { { match = ".", with = xavante.davhandler, params = { repos_b = davFileRepository.makeSource(), props_b = davFileProps.makeProps(), }, }, } xavante.HTTP{ server = { host = "*", port = 8080, }, defaultHost = { rules = simplerules, }, } -- Displays a message in the console with the used ports xavante.start_message(function (ports) local date = os.date("[%Y-%m-%d %H:%M:%S]") print(string.format("%s Xavante started on port(s) %s", date, table.concat(ports, ", "))) end) xavante.start() xavante-2.3.0/rockspec/000077500000000000000000000000001222031362400147665ustar00rootroot00000000000000xavante-2.3.0/rockspec/xavante-2.0.0-1.rockspec000066400000000000000000000012671222031362400207660ustar00rootroot00000000000000package = "Xavante" version = "2.0.0-1" source = { url = "http://luaforge.net/frs/download.php/3425/xavante-2.0.0.tar.gz", } description = { summary = "Lua Web Server Library", detailed = [[ Xavante is a Lua HTTP 1.1 Web server that uses a modular architecture based on URI mapped handlers. This rock installs Xavante as a library that other applications can use. ]], license = "MIT/X11", homepage = "http://www.keplerproject.org/xavante" } dependencies = { 'copas >= 1.1.3', 'luasocket >= 2.0.2', 'luafilesystem >= 1.4.1' } build = { type = "make", build_pass = false, install_target = "install", install_variables = { LUA_DIR = "$(LUADIR)", } } xavante-2.3.0/rockspec/xavante-2.0.1-1.rockspec000066400000000000000000000024441222031362400207650ustar00rootroot00000000000000package = "Xavante" version = "2.0.1-1" source = { url = "http://luaforge.net/frs/download.php/3966/xavante-2.0.1.tar.gz", } description = { summary = "Lua Web Server Library", detailed = [[ Xavante is a Lua HTTP 1.1 Web server that uses a modular architecture based on URI mapped handlers. This rock installs Xavante as a library that other applications can use. ]], license = "MIT/X11", homepage = "http://www.keplerproject.org/xavante" } dependencies = { 'copas >= 1.1.3', 'luasocket >= 2.0.2', 'luafilesystem >= 1.4.1' } local XAVANTE_LUAS = { "src/xavante/cgiluahandler.lua", "src/xavante/encoding.lua", "src/xavante/filehandler.lua", "src/xavante/httpd.lua", "src/xavante/mime.lua", "src/xavante/patternhandler.lua", "src/xavante/redirecthandler.lua", "src/xavante/vhostshandler.lua", "src/xavante/indexhandler.lua", "src/xavante/urlhandler.lua", "src/xavante/ruleshandler.lua" } build = { type = "module", modules = { sajax = "src/sajax/sajax.lua", xavante = "src/xavante/xavante.lua" } } for i = 1,#(XAVANTE_LUAS) do local src = XAVANTE_LUAS[i] local mod = "xavante." .. src:match("^src/xavante/([^%.]+)%.lua") build.modules[mod] = src end xavante-2.3.0/rockspec/xavante-2.0rc1-1.rockspec000066400000000000000000000012341222031362400212300ustar00rootroot00000000000000package = "Xavante" version = "2.0rc1-1" description = { summary = "Lua Web Server Library", detailed = [[ Xavante is a Lua HTTP 1.1 Web server that uses a modular architecture based on URI mapped handlers. This rock installs Xavante as a library that other applications can use. ]], license = "MIT/X11", homepage = "http://www.keplerproject.org/xavante" } dependencies = { 'luasocket', 'copas 1.1.1', 'luafilesystem 1.4.1rc1' } source = { url = "http://xavante.luaforge.net/xavante-2.0rc1.tar.gz", } build = { type = "make", build_pass = false, install_target = "install", install_variables = { LUA_DIR = "$(LUADIR)", } } xavante-2.3.0/rockspec/xavante-2.1.0-1.rockspec000066400000000000000000000024501222031362400207620ustar00rootroot00000000000000package = "Xavante" version = "2.1.0-1" description = { summary = "Lua Web Server Library", detailed = [[ Xavante is a Lua HTTP 1.1 Web server that uses a modular architecture based on URI mapped handlers. This rock installs Xavante as a library that other applications can use. ]], license = "MIT/X11", homepage = "http://www.keplerproject.org/xavante" } dependencies = { 'luasocket >= 2.0.2', 'copas >= 1.1.5', 'luafilesystem >= 1.4.2' } source = { url = "http://github.com/downloads/keplerproject/xavante/xavante-2.1.0.tar.gz" } local XAVANTE_LUAS = { "src/xavante/cgiluahandler.lua", "src/xavante/encoding.lua", "src/xavante/filehandler.lua", "src/xavante/httpd.lua", "src/xavante/mime.lua", "src/xavante/patternhandler.lua", "src/xavante/redirecthandler.lua", "src/xavante/vhostshandler.lua", "src/xavante/indexhandler.lua", "src/xavante/urlhandler.lua", "src/xavante/ruleshandler.lua" } build = { type = "module", modules = { sajax = "src/sajax/sajax.lua", xavante = "src/xavante/xavante.lua" } } for i = 1,#(XAVANTE_LUAS) do local src = XAVANTE_LUAS[i] local mod = "xavante." .. src:match("^src/xavante/([^%.]+)%.lua") build.modules[mod] = src end xavante-2.3.0/rockspec/xavante-2.2.0-1.rockspec000066400000000000000000000024461222031362400207700ustar00rootroot00000000000000package = "Xavante" version = "2.2.0-1" description = { summary = "Lua Web Server Library", detailed = [[ Xavante is a Lua HTTP 1.1 Web server that uses a modular architecture based on URI mapped handlers. This rock installs Xavante as a library that other applications can use. ]], license = "MIT/X11", homepage = "http://www.keplerproject.org/xavante" } dependencies = { 'luasocket >= 2.0', 'copas >= 1.1.5', 'luafilesystem >= 1.5.0' } source = { url = "http://github.com/downloads/keplerproject/xavante/xavante-2.2.0.tar.gz" } local XAVANTE_LUAS = { "src/xavante/cgiluahandler.lua", "src/xavante/encoding.lua", "src/xavante/filehandler.lua", "src/xavante/httpd.lua", "src/xavante/mime.lua", "src/xavante/patternhandler.lua", "src/xavante/redirecthandler.lua", "src/xavante/vhostshandler.lua", "src/xavante/indexhandler.lua", "src/xavante/urlhandler.lua", "src/xavante/ruleshandler.lua" } build = { type = "module", modules = { sajax = "src/sajax/sajax.lua", xavante = "src/xavante/xavante.lua" } } for i = 1,#(XAVANTE_LUAS) do local src = XAVANTE_LUAS[i] local mod = "xavante." .. src:match("^src/xavante/([^%.]+)%.lua") build.modules[mod] = src end xavante-2.3.0/rockspec/xavante-2.2.1-1.rockspec000066400000000000000000000024461222031362400207710ustar00rootroot00000000000000package = "Xavante" version = "2.2.1-1" description = { summary = "Lua Web Server Library", detailed = [[ Xavante is a Lua HTTP 1.1 Web server that uses a modular architecture based on URI mapped handlers. This rock installs Xavante as a library that other applications can use. ]], license = "MIT/X11", homepage = "http://www.keplerproject.org/xavante" } dependencies = { 'luasocket >= 2.0', 'copas >= 1.1.5', 'luafilesystem >= 1.5.0' } source = { url = "http://github.com/downloads/keplerproject/xavante/xavante-2.2.1.tar.gz" } local XAVANTE_LUAS = { "src/xavante/cgiluahandler.lua", "src/xavante/encoding.lua", "src/xavante/filehandler.lua", "src/xavante/httpd.lua", "src/xavante/mime.lua", "src/xavante/patternhandler.lua", "src/xavante/redirecthandler.lua", "src/xavante/vhostshandler.lua", "src/xavante/indexhandler.lua", "src/xavante/urlhandler.lua", "src/xavante/ruleshandler.lua" } build = { type = "module", modules = { sajax = "src/sajax/sajax.lua", xavante = "src/xavante/xavante.lua" } } for i = 1,#(XAVANTE_LUAS) do local src = XAVANTE_LUAS[i] local mod = "xavante." .. src:match("^src/xavante/([^%.]+)%.lua") build.modules[mod] = src end xavante-2.3.0/rockspec/xavante-2.3.0-1.rockspec000066400000000000000000000024301222031362400207620ustar00rootroot00000000000000package = "Xavante" version = "2.3.0-1" description = { summary = "Lua Web Server Library", detailed = [[ Xavante is a Lua HTTP 1.1 Web server that uses a modular architecture based on URI mapped handlers. This rock installs Xavante as a library that other applications can use. ]], license = "MIT/X11", homepage = "http://www.keplerproject.org/xavante" } dependencies = { 'luasocket >= 2.1', 'copas >= 1.2.0', 'luafilesystem >= 1.6.0' } source = { url = "http://www.keplerproject.org/files/xavante-2.3.0.tar.gz" } local XAVANTE_LUAS = { "src/xavante/cgiluahandler.lua", "src/xavante/encoding.lua", "src/xavante/filehandler.lua", "src/xavante/httpd.lua", "src/xavante/mime.lua", "src/xavante/patternhandler.lua", "src/xavante/redirecthandler.lua", "src/xavante/vhostshandler.lua", "src/xavante/indexhandler.lua", "src/xavante/urlhandler.lua", "src/xavante/ruleshandler.lua" } build = { type = "builtin", modules = { sajax = "src/sajax/sajax.lua", xavante = "src/xavante/xavante.lua" } } for i = 1,#(XAVANTE_LUAS) do local src = XAVANTE_LUAS[i] local mod = "xavante." .. src:match("^src/xavante/([^%.]+)%.lua") build.modules[mod] = src end xavante-2.3.0/rockspec/xavante-cvs-1.rockspec000066400000000000000000000012561222031362400211220ustar00rootroot00000000000000package = "Xavante" version = "cvs-1" description = { summary = "Lua Web Server Library", detailed = [[ Xavante is a Lua HTTP 1.1 Web server that uses a modular architecture based on URI mapped handlers. This rock installs Xavante as a library that other applications can use. ]], license = "MIT/X11", homepage = "http://www.keplerproject.org/xavante" } dependencies = { 'luasocket', 'copas cvs', 'luafilesystem cvs' } source = { url = "cvs://:pserver:anonymous@cvs.luaforge.net:/cvsroot/xavante", cvs_tag = "HEAD" } build = { type = "make", build_pass = false, install_target = "install", install_variables = { LUA_DIR = "$(LUADIR)", } } xavante-2.3.0/rockspec/xavante-cvs-2.rockspec000066400000000000000000000024011222031362400211140ustar00rootroot00000000000000package = "Xavante" version = "cvs-2" description = { summary = "Lua Web Server Library", detailed = [[ Xavante is a Lua HTTP 1.1 Web server that uses a modular architecture based on URI mapped handlers. This rock installs Xavante as a library that other applications can use. ]], license = "MIT/X11", homepage = "http://www.keplerproject.org/xavante" } dependencies = { 'luasocket', 'copas >= 1.1.5', 'luafilesystem >= 1.4.2' } source = { url = "git://github.com/keplerproject/xavante.git" } local XAVANTE_LUAS = { "src/xavante/cgiluahandler.lua", "src/xavante/encoding.lua", "src/xavante/filehandler.lua", "src/xavante/httpd.lua", "src/xavante/mime.lua", "src/xavante/patternhandler.lua", "src/xavante/redirecthandler.lua", "src/xavante/vhostshandler.lua", "src/xavante/indexhandler.lua", "src/xavante/urlhandler.lua", "src/xavante/ruleshandler.lua" } build = { type = "module", modules = { sajax = "src/sajax/sajax.lua", xavante = "src/xavante/xavante.lua" } } for i = 1,#(XAVANTE_LUAS) do local src = XAVANTE_LUAS[i] local mod = "xavante." .. src:match("^src/xavante/([^%.]+)%.lua") build.modules[mod] = src end xavante-2.3.0/src/000077500000000000000000000000001222031362400137445ustar00rootroot00000000000000xavante-2.3.0/src/codeweb/000077500000000000000000000000001222031362400153545ustar00rootroot00000000000000xavante-2.3.0/src/codeweb/codeWeb.lua000066400000000000000000000050031222031362400174250ustar00rootroot00000000000000----------------------------------------------------------------------------- -- Xavante CodeWeb -- -- Author: Javier Guerra -- Copyright (c) 2005 Kepler Project ----------------------------------------------------------------------------- local prep = require "cgilua.prep" local httpd = require "xavante.httpd" local _M = {} -- Adds a module as a website; -- each public function is registered as a page handler -- host,urlpath : where to insert the handlers -- m : table with functions, a module -- register_as_tree: if true, each handler is registered as a directory too function _M.addModule (host, urlpath, m, register_as_tree) if m.__main then httpd.addHandler (host, urlpath, m.__main) end for k,v in pairs (m) do if type (k) == "string" and string.sub (k,1,1) ~= "_" and type (v) == "function" then local pth = urlpath.."/"..k httpd.addHandler (host, pth, v) if register_as_tree then httpd.addHandler (host, pth.."/", v) httpd.addHandler (host, pth.."/*", v) end end end end -- Builds a handler from a template -- the template (loaded from file 'fname') uses LuaPage syntax -- and is converted to a function in the form: "function (req,res,...)" -- if env is a table, the resulting function uses it as environment -- if it's a function, it's environment is used -- if it's a number, it select's the environment from the call stack -- if ommited, 1 is implied, (the calling function's environment) function _M.load_cw (fname, env) env = env or 1 if type (env) == "function" then env = getfenv (env) elseif type (env) == "number" then env = getfenv (env+1) end local fh = assert (io.open (fname)) local prog = fh:read("*a") fh:close() prep.setoutfunc ("res:send_data") prog = prep.translate (prog, "file "..fname) prog = "return function (req,res,...)\n" .. prog .. "\nend" if prog then local f, err = loadstring (prog, "@"..fname) if f then local f_cw = f() if env then setfenv (f_cw, env) end return f_cw else error (err) end end end xavante-2.3.0/src/codeweb/cookies.lua000066400000000000000000000055071222031362400175220ustar00rootroot00000000000000----------------------------------------------------------------------------- -- Xavante Cookies module -- -- Author: Javier Guerra -- inspired by CGILua cookies -- Copyright (c) 2005 Kepler Project ----------------------------------------------------------------------------- local url = require "socket.url" local xavante = require "xavante" local _M = {} local function read_cookies (req) req.cookies = req.cookies or {} local cookies = req.headers.cookie or "" local lastcookie -- get all key="val" pairs for k,v in string.gfind (cookies, '([^%s;=]+)%s*=%s*"([^"]*)"') do if string.sub (k,1,1) == "$" then -- its an option for the last seen cookie if lastcookie then local optname = string.sub (k,2) req.cookies [lastcookie].options [optname] = v end else -- its a new cookie req.cookies [k] = {value = v, options = {}} lastcookie = k end end end function _M.get (req, name) if not req.cookies then _M.read_cookies (req) end local cookie_rec = req.cookies and req.cookies [name] if cookie_rec then return cookie_rec.value, cookie_rec.options end end function _M.set (res, name, value, options) res.cookies = res.cookies or {} res.cookies [name] = {value = value, options = options} end function _M.delete (res, name, options) options = options or {} options.expires = 1 _M.set (res, name, "xxx", options) end function _M.set_res_cookies (res) if not res or not res.cookies then return end local set_cookie = {} for name, r in pairs (res.cookies) do local set_string = string.format ([[%s="%s";Version="1"]], name, r.value) local options = r.options if options then if type (options.expires) == "number" then options.expires = os.date("!%A, %d-%b-%Y %H:%M:%S GMT", options.expires) end for k,v in pairs (r.options) do if v == "" or type (v) == "boolean" then set_string = set_string..string.format ([[;%s]], k) else set_string = set_string..string.format ([[;%s="%s"]], k, v) end end end table.insert (set_cookie, set_string) end res.headers ["Set-Cookie"] = table.concat (set_cookie) end xavante.cookies = _M return _M xavante-2.3.0/src/codeweb/coroWeb.lua000066400000000000000000000040671222031362400174660ustar00rootroot00000000000000----------------------------------------------------------------------------- -- webThreads: Xavante resumable handlers framework -- -- Author: Javier Guerra -- Copyright (c) 2005 Kepler Project ----------------------------------------------------------------------------- local session = require "xavante.session" module (arg and arg[1]) -- original coroutine functions local o_resume, o_yield = coroutine.resume, coroutine.yield -- creates a resume/yield pair local function _ortoroutines (err) err = err or error local _tag = {} return function (co, ...) local r,sts repeat r = { o_resume (co, unpack (arg)) } sts = coroutine.status (co) if not r[1] then err (r[2]) end table.remove (r,1) if r[1] ~= _tag and sts == "suspended" then arg = { o_yield (unpack (r)) } end until r[1] == _tag or sts == "dead" table.remove (r,1) return unpack (r) end, function (...) return o_yield (_tag, unpack (arg)) end end local function _error (res, err) res:send_data ("

error:"..err.."

") end resume, yield = _ortoroutines () -- -- creates a xavante handler -- params: -- name (string) : session name to use -- h (function) : thread to handle -- function handler (name, h) return function (req, res) local sess = session.open (req, res, name) sess.coHandler = sess.coHandler or coroutine.create (h) resume (sess.coHandler, req, res) if coroutine.status (sess.coHandler) == "dead" then session.close (req, res, name) end return res end end -- -- gets user actions as events -- params: -- in_req (table) : 'req' parameter -- sh_t (table) : namesubhandlers function event (in_req, sh_t, get_all) local req, res local subH, ret repeat req, res = yield () subH = sh_t [req.relpath] if subH and type (subH) == "function" then ret = subH (req, res) end if ret then xavante.httpd.redirect (res, ret) elseif ret == "refresh" then xavante.httpd.redirect (res, in_req.parsed_url.path) req, res = yield () end until not subH or get_all or ret == "refresh" return req, res endxavante-2.3.0/src/codeweb/session.lua000066400000000000000000000022001222031362400175340ustar00rootroot00000000000000----------------------------------------------------------------------------- -- Xavante sessions handler -- -- Author: Javier Guerra -- Copyright (c) 2005 Kepler Project ----------------------------------------------------------------------------- local cookies = require "xavante.cookies" module (arg and arg[1]) local _sessions = {} local _max_age = 3600 -- one hour local _def_name = "XVTE_SESS" local MIN_SID = 11111111 local MAX_SID = 99999999 local function new_sid () local sid = 0 while sid MAX_SID or _sessions[sid] do sid = math.random (MAX_SID) end return sid end function set_max_age (mx) _max_age = mx end function open (req, res, name) name = (name or _def_name) .. "_SID" local sid = cookies.get (req, name) or new_sid () _sessions [sid] = _sessions [sid] or {data={}} local sess = _sessions [sid] sess.expires = os.time() + _max_age cookies.set (res, name, sid, {expires=sess.expires}) return sess.data end function close (req, res, name) name = (name or _def_name) .. "_SID" local sid = cookies.get (req, name) if sid then _sessions [sid] = nil end cookies.delete (res, name) endxavante-2.3.0/src/codeweb/timer.lua000066400000000000000000000020361222031362400172000ustar00rootroot00000000000000module (arg and arg[1]) local timer_mt = { __index = {} } local timer = timer_mt.__index -- create new event list function new () return setmetatable ({jobs={}}, timer_mt) end -- add event -- f() is called no sooner than time t function timer:add (t, f) local job={time=t, func=f} local ins = -1 for i,v in ipairs (self.jobs) do if v.time > t then ins = i break end end if ins > 0 then table.insert (self.jobs, ins, job) else table.insert (self.jobs, job) end end -- add relatike event -- f() is called no sooner than time now+t -- (t is seconds in most systems) function timer:add_rel (t, f) return self:add (os.time() + t, f) end -- add repeatig event -- f() is called no more often than once each t -- (seconds in most systems) function timer:add_rep (t, f) local function w () f () return self:add_rel (t, w) end return self:add_rel (t, w) end -- called periodically function timer:tick () while self.jobs[1] and os.time() >= self.jobs[1].time do local job = table.remove (self.jobs, 1) job.func() end endxavante-2.3.0/src/sajax/000077500000000000000000000000001222031362400150525ustar00rootroot00000000000000xavante-2.3.0/src/sajax/sajax.lua000066400000000000000000000227701222031362400166730ustar00rootroot00000000000000-- $Id: sajax.lua,v 1.6 2009/03/16 22:53:10 carregal Exp $ local cgilua = require "cgilua" local table = require "table" local string = require "string" local os = require "os" local pairs, type, unpack, tostring, xpcall = pairs, type, unpack, tostring, xpcall local xavante = require "xavante" local httpd = require "xavante.httpd" local _M = {} local export_list = {} local request_uri if xavante and httpd then request_uri = function (funcname) return cgilua.mkabsoluteurl (cgilua.mkurlpath (cgilua.servervariable"SCRIPT_NAME" .. "/" .. funcname.. "?rs=rs")) end function _M.handle_client_request () return false end local function register_path (funcname) return cgilua.mkurlpath (cgilua.servervariable"SCRIPT_NAME" .. "/" .. funcname) end local function handle_prefix (req, res) res.headers ["Expires"] = "Mon, 26 Jul 1997 05:00:00 GMT" -- Date in the past res.headers ["Last-Modified"] = os.date ("!%a, %d %b %Y %H:%M:%S GMT") -- always modified res.headers ["Cache-Control"] = "no-cache, must-revalidate" -- HTTP/1.1 res.headers ["Pragma"] = "no-cache" -- HTTP/1.0 local qry = req.parsed_url.query or "" local rsargs = {} for rs_arg in string.gfind (qry, "rsargs%[%]=([^&=]*)&?") do table.insert (rsargs, rs_arg) end return rsargs end function _M.export (funcname, func) export_list[funcname] = func httpd.addHandler (nil, register_path (funcname), function (req, res) local isok, result = xpcall (function () return func (unpack (handle_prefix (req, res))) end, tostring) result = result or "" if isok then res.content = "+:" .. result else res.content = "-:" .. result end return res end) end else request_uri = function (funcname) local uri = "" if string.find (uri, "?") then uri = uri .. "&rs=" .. cgilua.urlcode.escape (funcname) else uri = uri .. "?rs=" .. cgilua.urlcode.escape (funcname) end return uri end function _M.handle_client_request () if not cgilua.QUERY.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 = cgilua.QUERY.rs if not export_list[funcname] then cgilua.put (string.format ("-:%s not callable", funcname)) else local func = export_list[funcname] local rsargs = cgilua.QUERY["rsargs[]"] local result if not rsargs then result = func() elseif type (rsargs) == "string" then result = func (rsargs) elseif type (rsargs) == "table" then result = func (unpack (rsargs)) else return end cgilua.put ("+:") cgilua.put (result) end return true end function _M.export (funcname, func) export_list[funcname] = func end end local function get_common_js () return [[ // remote scripting library // released under BSD license // (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; 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; } function sajax_call(func_name, script, callback, args) { var url = script + "?rs=" + func_name; args.push(callback); sajax_do_call(func_name, url, args); } ]] end function _M.show_common_js() cgilua.put (get_common_js ()) end 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)) --[[ var i, x, n; var url = "%s"; var a = x_%s.arguments; for (i = 0; i < a.length-1; i++) url = url + "&rsargs[]=" + escape(a[i]); url = url + "&rsrnd=" + new Date().getTime(); x = rs_init_object(); x.open("GET", url, true); x.onreadystatechange = function() { if (x.readyState != 4) return; rs_debug("received " + x.responseText); var status; var data; status = x.responseText.charAt(0); data = x.responseText.substring(2); if (status == "-") alert("Error: " + callback_n); else a[a.length-1](data); } x.send(null); rs_debug("x_%s url = " + url); rs_debug("x_%s waiting.."); delete x; } ] ], funcname, funcname, uri, funcname, funcname, funcname)) --]] end local function show_one_stub (funcname) cgilua.put (get_one_stub (funcname)) end local js_has_been_shown = false function _M.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 _M.show_javascript () cgilua.put (_M.get_javascript ()) end function _M.init () end return _M xavante-2.3.0/src/webdav/000077500000000000000000000000001222031362400152145ustar00rootroot00000000000000xavante-2.3.0/src/webdav/davFileProps.lua000066400000000000000000000033421222031362400203170ustar00rootroot00000000000000----------------------------------------------------------------------------- -- Xavante webDAV Properties with file backend -- Author: Javier Guerra -- Copyright (c) 2005 Javier Guerra ----------------------------------------------------------------------------- local lfs = require "lfs" local props_mt = { __index = {} } local props = props_mt.__index -- equivalent to 'mkdir -p path' local function mkdir_p (path) local walk = "" for p in string.gfind (path, "[^/]+") do walk = walk.."/"..p attr = lfs.attributes (walk) if not attr then lfs.mkdir (walk) else if attr.mode ~= "directory" then return nil, string.format ("%s existe y no es directorio", walk) end end end end function props:getPropNames (path) path = self.rootDir..path local function gen () local attr = lfs.attributes (path) if not attr or attr.mode ~= "directory" then return nil end for prop in lfs.dir (path) do if string.sub (prop, 1,1) ~= "." then coroutine.yield (prop) end end end return coroutine.wrap (gen) end function props:getProp (path, propname) local f = io.open (self.rootDir..path.."/"..propname) if not f then return nil end local val = f:read ("*a") f:close () return val end function props:setProp (path, propname, value) if not value then os.remove (self.rootDir..path.."/"..propname) return end mkdir_p (self.rootDir..path) local f = assert (io.open (self.rootDir..path.."/"..propname, "wb")) f:write (value) f:close () end function props:delete (path) os.remove (self.rootDir..path..'/') end local M = {} function M.makeProps (params) params = params or {} params.rootDir = params.rootDir or ".PROPS/" mkdir_p (params.rootDir) return setmetatable (params, props_mt) end return M xavante-2.3.0/src/webdav/davFileRepository.lua000066400000000000000000000123271222031362400213760ustar00rootroot00000000000000----------------------------------------------------------------------------- -- Xavante webDAV file repository -- Author: Javier Guerra -- Copyright (c) 2005 Javier Guerra ----------------------------------------------------------------------------- local lfs = require "lfs" require "xavante.mime" local source_mt = { __index = {} } local source = source_mt.__index local resource_mt = { __index = {} } local resource = resource_mt.__index function source:getRoot () return self.rootDir end function source:getResource (rootUrl, path) local diskpath = self.rootDir .. path if diskpath:sub(-1) == '/' then diskpath = diskpath:sub(1, -2) end local attr = lfs.attributes (diskpath) if not attr then return end local _,_,pfx = string.find (rootUrl, "^(.*/)[^/]-$") if attr.mode == "directory" and string.sub (path, -1) ~= "/" then path = path .."/" end return setmetatable ({ source = self, path = path, diskpath = diskpath, attr = attr, pfx = pfx }, resource_mt) end function source:createResource (rootUrl, path) local diskpath = self.rootDir .. path if diskpath:sub(-1) == '/' then diskpath = diskpath:sub(1, -2) end local attr = lfs.attributes (diskpath) if not attr then io.open (diskpath, "wb"):close () attr = lfs.attributes (diskpath) end local _,_,pfx = string.find (rootUrl, "^(.*/)[^/]-$") return setmetatable ({ source = self, path = path, diskpath = diskpath, attr = attr, pfx = pfx }, resource_mt) end function source:createCollection (rootUrl, path) local diskpath = self.rootDir .. path return lfs.mkdir (diskpath) end local _liveprops = {} _liveprops["DAV:creationdate"] = function (self) return os.date ("!%a, %d %b %Y %H:%M:%S GMT", self.attr.change) end _liveprops["DAV:displayname"] = function (self) local name = "" for part in string.gfind (self.path, "[^/]+") do name = part end return name end _liveprops["DAV:source"] = function (self) return self:getHRef () end _liveprops["DAV:supportedlock"] = function (self) return [[ ]] end _liveprops["DAV:getlastmodified"] = function (self) return os.date ("!%a, %d %b %Y %H:%M:%S GMT", self.attr.modification) end _liveprops["DAV:resourcetype"] = function (self) if self.attr.mode == "directory" then return "" else return "" end end _liveprops["DAV:getcontenttype"] = function (self) return self:getContentType () end _liveprops["DAV:getcontentlength"] = function (self) return self:getContentSize () end function resource:getContentType () if self.attr.mode == "directory" then return "httpd/unix-directory" end local _,_,exten = string.find (self.path, "%.([^.]*)$") exten = exten or "" return xavante.mimetypes [exten] or "" end function resource:getContentSize () if self.attr.mode == "file" then return self.attr.size else return 0 end end function resource:getContentData () local function gen () local f = io.open (self.diskpath, "rb") if not f then return end local block repeat block = f:read (8192) if block then coroutine.yield (block) end until not block f:close () end return coroutine.wrap (gen) end function resource:addContentData (b) local f = assert (io.open (self.diskpath, "a+b")) f:seek ("end") f:write (b) f:close () end function resource:delete () local ok, err = os.remove (self.diskpath) if not ok then err = string.format ([[HTTP/1.1 424 %s]], err) end return ok, err end function resource:getItems (depth) local gen local path = self.path local diskpath = self.diskpath local rootdir = self.source.rootDir if depth == "0" then gen = function () coroutine.yield (self) end elseif depth == "1" then gen = function () if self.attr.mode == "directory" then if string.sub (diskpath, -1) ~= "/" then diskpath = diskpath .."/" end if string.sub (path, -1) ~= "/" then path = path .."/" end for entry in lfs.dir (diskpath) do if string.sub (entry, 1,1) ~= "." then coroutine.yield (self.source:getResource (self.pfx, path..entry)) end end end coroutine.yield (self) end else local function recur (p) local attr = assert (lfs.attributes (rootdir .. p)) if attr.mode == "directory" then for entry in lfs.dir (rootdir .. p) do if string.sub (entry, 1,1) ~= "." then recur (p.."/"..entry) end end coroutine.yield (self.source:getResource (self.pfx, p)) end end gen = function () recur (path) end end if gen then return coroutine.wrap (gen) end end function resource:getPath () return self.path end function resource:getHRef () local _,_,sfx = string.find (self.path, "^/*(.*)$") return self.pfx..sfx end function resource:getPropNames () return pairs (_liveprops) end function resource:getProp (propname) local liveprop = _liveprops [propname] if liveprop then return liveprop (self) end end function resource:setProp (propname, value) return false end local M = {} function M.makeSource (params) params = params or {} params.rootDir = params.rootDir or "." return setmetatable (params, source_mt) end return M xavante-2.3.0/src/webdav/davhandler.lua000066400000000000000000000324051222031362400200330ustar00rootroot00000000000000----------------------------------------------------------------------------- -- Xavante webDAV handler -- Author: Javier Guerra -- Copyright (c) 2005 Javier Guerra ----------------------------------------------------------------------------- require "lxp.lom" require "socket.url" local httpd = require "xavante.httpd" local url = socket.url -- returns a copy of the string without any -- leading or trailing whitespace local function trim (s) return (string.gsub (string.gsub (s, "^%s*", ""), "%s*$", "")) end -- reverts a LOM-style attribute array to XML form local function attrstostr (a) local out = {} for i,attr in ipairs (a) do table.insert (out, string.format ('%s = "%s"', attr, a[attr])) end return table.concat (out, " ") end -- outputs a LOM XML object back in XML text form -- params: -- x: LOM XML object -- of: output function, uses print() if not given local function lomtoxml (x, of) if type (x) == "string" then return of (x) end of = of or print local attrs = "" -- does it have any attributes? if x.attr [1] then attrs = " " .. attrstostr (x.attr) end -- is there any content? if x[1] then of ("<" .. x.tag .. attrs .. ">") for i in ipairs (x) do lomtoxml (x[i], of) end of ("") else of ("<" .. x.tag .. attrs .. "/>") end end -- gets request content, and parses it as XML -- returns LOM object local function req_xml (req) local sz = req.headers ["content-length"] local indata if sz then indata = req.socket:receive (sz) else indata = function () return req.socket:receive () end end return lxp.lom.parse (indata) end -- expands namespace tags in-situ -- returns the same LOM object after processing local function xml_ns (x, dict) if not x then return end if type (x) == "string" then return x end dict = dict or {} -- adds any new namespace to the dictionary for i,attr_name in ipairs (x.attr) do -- default namespace if attr_name == "xmlns" then dict [""] = x.attr [attr_name] end -- named namespaces local _,_, ns_var = string.find (attr_name, "xmlns:(.*)$") if ns_var then dict [ns_var] = x.attr [attr_name] end end -- modifies this node's tag local _,_, ns = string.find (x.tag, "^(.*):") if ns and dict [ns] then local pat = string.format ("^%s:", ns) x.tag = string.gsub (x.tag, pat, dict[ns]) end if not ns and dict [""] then x.tag = dict [""] .. x.tag end -- recurses to child nodes for _, sub in ipairs (x) do xml_ns (sub, dict) end return x end -- iterator for traversing only childs in a LOM object -- whith a given tagname. local function lomChildsByTagName (x, tagname) if not x then return function () return nil end end local function gen (x) for _,elem in ipairs (x) do if type(elem) == "table" then if elem.tag and elem.tag == tagname then coroutine.yield (elem) end end end end return coroutine.wrap (function () gen (x) end) end -- iterator for traversing all elements in a LOM object -- whith a given tagname (at any depth). local function lomElementsByTagName (x, tagname) if not x then return function () return nil end end local function gen (x) for _,elem in ipairs (x) do if type(elem) == "table" then if elem.tag and elem.tag == tagname then coroutine.yield (elem) end gen (elem) end end end return coroutine.wrap (function () gen (x) end) end -- iterates on the childs of a LOM node -- use as: -- for subnode, tagname in lomChilds (node) do ... end local function lomChilds (x) if not x then return function () return nil end end local function gen () for _, elem in ipairs (x) do if type (elem) == "table" and elem.tag then coroutine.yield (elem, elem.tag) end end end return coroutine.wrap (gen) end -- returns all the text content of a LOM node local function lomContent (x) if not x then return "" end local out = {} local function of (s) table.insert (out, s) end for _, child in ipairs (x) do lomtoxml (child, of) end return table.concat (out) end -- returns a table member of a table, creates it if needed -- params: -- t: table -- k: key local function maketabletable (t,k) t[k] = t[k] or {} return t[k] end -- if a tagname has inconvenient characters -- replaces part of if with a (possibly new) -- namespace reference -- params: -- ns: namespace dictionary -- name: tagname to reduce -- returns new tagname, ns is modified in-place if needed local function reducename (ns, name) if string.find (name, "[:/?#]") then local _,_,pfx,sfx = string.find (name, "(.*%W)(%w+)") local n = 0 for k,v in pairs (ns) do n = n+1 if v == pfx then return string.format ("%s:%s", k, sfx) end end local newns = "lm"..n ns [newns] = pfx return string.format ("%s:%s", newns, sfx) else return name end end -- returns a XML attr string encoding a namespace dictionary local function nsattr (ns) local attr = {} for k,v in pairs (ns) do table.insert (attr, string.format ([[xmlns:%s="%s"]], k, v)) end return table.concat (attr, " ") end local function addProp (outtable, propname, propval) if propval then local propentry = maketabletable (outtable, "HTTP/1.1 200 OK") if propval == "" then table.insert (propentry, string.format ([[<%s/>]], propname)) else table.insert (propentry, string.format ([[<%s>%s]], propname, propval, propname)) end else local propentry = maketabletable (outtable, "HTTP/1.1 404 NotFound") table.insert (propentry, string.format ([[<%s/>]], propname)) end end local function addPropstat (outtable, propstat) local codes = {} for stat in pairs (propstat) do table.insert (codes, stat) end table.sort (codes) for _, stat in ipairs (codes) do props = propstat [stat] if props then table.insert (outtable, [[]]) table.insert (outtable, [[]]) for _,prop in ipairs (props) do table.insert (outtable, prop) end table.insert (outtable, [[]]) table.insert (outtable, string.format ([[%s]], stat)) table.insert (outtable, [[]]) end end end local function dav_propfind (req, res, repos_b, props_b) res.statusline = "HTTP/1.1 207 Multi-Status" res.headers ["Content-Type"] = 'text/xml; charset="utf-8"' local depth = req.headers.depth local path = req.relpath local data = xml_ns (req_xml (req)) -- print ("path:", path, req.relpath) -- print ("depth:", depth) -- print ("como xml:") lomtoxml (data) print () local resource_q = repos_b:getResource (req.match, path) if not resource_q then return httpd.err_404 (req, res) end local content = {} table.insert (content, [[]]) table.insert (content, [[]]) local namespace = {} assert (data.tag == "DAV:propfind") for resource in resource_q:getItems (depth) do -- print ("resource:", resource.path) local propstat = {} namespace.D="DAV:" for findtype, findtype_tn in lomChilds (data) do if findtype_tn == "DAV:prop" then for _, propname in lomChilds (findtype) do local propval = resource:getProp (propname) if not propval and props_b then propval = props_b:getProp (req.relpath, propname) end local shortname = reducename (namespace, propname) addProp (propstat, shortname, propval) end elseif findtype_tn == "DAV:propname" then for propname in resource:getPropNames () do local shortname = reducename (namespace, propname) addProp (propstat, shortname, "") end if props_b then for propname in props_b:getPropNames (req.relpath) do local shortname = reducename (namespace, propname) addProp (propstat, shortname, "") end end elseif findtype_tn == "DAV:allprop" then for propname in resource:getPropNames () do local shortname = reducename (namespace, propname) local propval = resource:getProp (propname) addProp (propstat, shortname, propval) end if props_b then for propname in props_b:getPropNames (req.relpath) do local shortname = reducename (namespace, propname) local propval = props_b:getProp (req.relpath, propname) addProp (propstat, shortname, propval) end end end end namespace.D = nil table.insert (content, string.format ([[]], nsattr (namespace))) table.insert (content, string.format ([[%s]], resource:getHRef())) addPropstat (content, propstat) table.insert (content, [[]]) end table.insert (content, [[]]) -- for _,l in ipairs (content) do print (l) end res.content = content return res end local function dav_proppatch (req, res, repos_b, props_b) res.statusline = "HTTP/1.1 207 Multi-Status" res.headers ["Content-Type"] = 'text/xml; charset="utf-8"' local path = req.relpath local data = xml_ns (req_xml (req)) -- print ("como xml:") lomtoxml (data) print () local resource = repos_b:getResource (req.match, path) if not resource then return httpd.err_404 (req, res) end local content = {} table.insert (content, [[]]) local namespace = {D="DAV:"} local propstat = {} assert (data.tag == "DAV:propertyupdate") for cmd_node, cmd_name in lomChilds (data) do for nd in lomChildsByTagName (cmd_node, "DAV:prop") do local status = nil for prop_node, propname in lomChilds (nd) do if cmd_name == "DAV:set" then props_b:setProp (path, propname, lomContent (prop_node)) status = "HTTP/1.1 200 OK" elseif cmd_name == "DAV:remove" then props_b:setProp (path, propname, nil) status = "HTTP/1.1 200 OK" end if status then local propentry = maketabletable (content, status) table.insert (propentry, string.format ([[<%s/>]], reducename (namespace, propname))) end end end end table.insert (content, string.format ([[]], nsattr (namespace))) table.insert (content, [[]]) table.insert (content, string.format ([[%s]], resource:getHRef())) addPropstat (content, propstat) table.insert (content, [[]]) table.insert (content, [[]]) res.content = content return res end local function dav_options (req, res, repos_b, props_b) res.headers ["DAV"] = "1,2" res.content = "" return res end local function dav_get (req, res, repos_b, props_b) local resource = repos_b:getResource (req.match, req.relpath) if not resource then return httpd.err_404 (req, res) end res.headers ["Content-Type"] = resource:getContentType () res.headers ["Content-Length"] = resource:getContentSize () or 0 res:send_headers () for block in resource:getContentData () do res:send_data (block) end return res end local function dav_put (req, res, repos_b) local path = req.relpath local resource = repos_b:getResource (req.match, path) or repos_b:createResource (req.match, path) if req.headers["content-range"] then return httpd.err_405 (req, res) end local contentlength = assert (req.headers ["content-length"]) + 0 local bsz while contentlength > 0 do if contentlength > 4096 then bsz = 4096 else bsz = contentlength end resource:addContentData (req.socket:receive (bsz)) contentlength = contentlength - bsz end res:send_headers () return res end local function dav_mkcol (req, res, repos_b) local path = req.relpath local resource = repos_b:getResource (req.match, path) if resource then res.statusline = "HTTP/1.1 405 Method Not Allowed" res.content = "" return res end local done, err = repos_b:createCollection (req.match, path) if done then res.statusline = "HTTP/1.1 201 Created" else res.statusline = "HTTP/1.1 403 Forbidden" end res.content = "" return res end local function dav_delete (req, res, repos_b, props_b) local path = req.relpath local resource = repos_b:getResource (req.match, path) if not resource then return http.err_404 end -- NOTE: this should iterate depth-first for r in resource:getItems ("Infinity") do local ok, err = resource:delete () if not ok then res.statusline = "HTTP/1.1 207 Multi-Status" res.content = string.format ([[ %s %s ]], resource:getHRef(), err) return res end props_b:delete (resource:getPath ()) -- TODO end --res.statusline = "HTTP/1.1 204 No Content" local done, err = resource:delete () if done then res.statusline = "HTTP/1.1 204 No Content" props_b:delete (path) else res.statusline = "HTTP/1.1 403 Forbidden" end res.content = "" return res end local function dav_lock (req, res, repos_b) local data = xml_ns (req_xml (req)) print ("como xml:") lomtoxml (data) print () return res end local dav_cmd_dispatch = { PROPFIND = dav_propfind, PROPPATCH = dav_proppatch, OPTIONS = dav_options, GET = dav_get, PUT = dav_put, MKCOL = dav_mkcol, DELETE = dav_delete, LOCK = dav_lock, } function xavante.davhandler (params) return function (req, res) -- print (req.cmd_mth, req.parsed_url.path) -- for k,v in pairs (req.headers) do print (k,v) end local savePath = req.parsed_url.path req.parsed_url.path = '/' req.match = socket.url.build(req.parsed_url) req.parsed_url.path = savePath local dav_handler = dav_cmd_dispatch [req.cmd_mth] if dav_handler then return dav_handler (req, res, params.repos_b, params.props_b) end end end xavante-2.3.0/src/xavante/000077500000000000000000000000001222031362400154125ustar00rootroot00000000000000xavante-2.3.0/src/xavante/cgiluahandler.lua000066400000000000000000000023341222031362400207210ustar00rootroot00000000000000----------------------------------------------------------------------------- -- Xavante CGILua handler -- -- Authors: Javier Guerra and Andre Carregal -- Copyright (c) 2004-2007 Kepler Project -- -- $Id: cgiluahandler.lua,v 1.46 2009/05/20 22:28:42 mascarenhas Exp $ ----------------------------------------------------------------------------- local xavante = require "wsapi.xavante" local common = require "wsapi.common" local _M = {} local bootstrap = [[ function print(...) remotedostring("print(...)", ...) end io.stdout = { write = function (...) remotedostring("io.write(...)", ...) end } io.stderr = { write = function (...) remotedostring("io.stderr(...)", ...) end } ]] ------------------------------------------------------------------------------- -- Returns the CGILua handler ------------------------------------------------------------------------------- function _M.makeHandler (diskpath, params) params = setmetatable(params or {}, { __index = { modname = "wsapi.sapi", bootstrap = bootstrap } }) local sapi_loader = common.make_isolated_launcher(params) return xavante.makeHandler(sapi_loader, nil, diskpath) end return _M xavante-2.3.0/src/xavante/encoding.lua000066400000000000000000000006761222031362400177140ustar00rootroot00000000000000----------------------------------------------------------------------------- -- Xavante Content-Encondings -- -- Authors: Javier Guerra and Andre Carregal -- Copyright (c) 2004-2007 Kepler Project -- -- $Id: encoding.lua,v 1.2 2007/01/12 17:50:03 carregal Exp $ ----------------------------------------------------------------------------- local xavante = require "xavante" xavante.encodings = { svgz = "x-gzip", } return xavante.encodings xavante-2.3.0/src/xavante/filehandler.lua000066400000000000000000000122031222031362400203700ustar00rootroot00000000000000----------------------------------------------------------------------------- -- Xavante File handler -- -- Authors: Javier Guerra and Andre Carregal -- Copyright (c) 2004-2007 Kepler Project -- -- $Id: filehandler.lua,v 1.26 2009/08/11 01:48:07 mascarenhas Exp $ ---------------------------------------------------------------------------- local lfs = require "lfs" local url = require "socket.url" local mime = require "xavante.mime" local enc = require "xavante.encoding" local xavante = require "xavante" local httpd = require "xavante.httpd" xavante.mimetypes = xavante.mimetypes or {} xavante.encodings = xavante.encodings or {} -- gets the mimetype from the filename's extension local function mimefrompath (path) local _,_,exten = string.find (path, "%.([^.]*)$") if exten then return xavante.mimetypes [exten] else return nil end end -- gets the encoding from the filename's extension local function encodingfrompath (path) local _,_,exten = string.find (path, "%.([^.]*)$") if exten then return xavante.encodings [exten] else return nil end end -- on partial requests seeks the file to -- the start of the requested range and returns -- the number of bytes requested. -- on full requests returns nil local function getrange (req, f) local range = req.headers["range"] if not range then return nil end local s,e, r_A, r_B = string.find (range, "(%d*)%s*-%s*(%d*)") if s and e then r_A = tonumber (r_A) r_B = tonumber (r_B) if r_A then f:seek ("set", r_A) if r_B then return r_B + 1 - r_A end else if r_B then f:seek ("end", - r_B) end end end return nil end -- sends data from the open file f -- to the response object res -- sends only numbytes, or until the end of f -- if numbytes is nil local function sendfile (f, res, numbytes) local block local whole = not numbytes local left = numbytes local blocksize = 8192 if not whole then blocksize = math.min (blocksize, left) end while whole or left > 0 do block = f:read (blocksize) if not block then return end if not whole then left = left - string.len (block) blocksize = math.min (blocksize, left) end res:send_data (block) end end local function in_base(path) local l = 0 if path:sub(1, 1) ~= "/" then path = "/" .. path end for dir in path:gmatch("/([^/]+)") do if dir == ".." then l = l - 1 elseif dir ~= "." then l = l + 1 end if l < 0 then return false end end return true end -- main handler local function filehandler (req, res, baseDir) if req.cmd_mth ~= "GET" and req.cmd_mth ~= "HEAD" then return httpd.err_405 (req, res) end if not in_base(req.relpath) then return httpd.err_403 (req, res) end local path = baseDir .."/".. req.relpath res.headers ["Content-Type"] = mimefrompath (path) res.headers ["Content-Encoding"] = encodingfrompath (path) local attr = lfs.attributes (path) if not attr then return httpd.err_404 (req, res) end assert (type(attr) == "table") if attr.mode == "directory" then req.parsed_url.path = req.parsed_url.path .. "/" res.statusline = "HTTP/1.1 301 Moved Permanently" res.headers["Location"] = url.build (req.parsed_url) res.content = "redirect" return res end res.headers["Content-Length"] = attr.size local f = io.open (path, "rb") if not f then return httpd.err_404 (req, res) end res.headers["last-modified"] = os.date ("!%a, %d %b %Y %H:%M:%S GMT", attr.modification) local lms = req.headers["if-modified-since"] or 0 local lm = res.headers["last-modified"] or 1 if lms == lm then res.headers["Content-Length"] = 0 res.statusline = "HTTP/1.1 304 Not Modified" res.content = "" res.chunked = false res:send_headers() f:close() return res end if req.cmd_mth == "GET" then local range_len = getrange (req, f) if range_len then res.statusline = "HTTP/1.1 206 Partial Content" res.headers["Content-Length"] = range_len end sendfile (f, res, range_len) else res.content = "" res:send_headers () end f:close () return res end return function (baseDir) if type(baseDir) == "table" then baseDir = baseDir.baseDir end return function (req, res) return filehandler (req, res, baseDir) end end xavante-2.3.0/src/xavante/httpd.lua000066400000000000000000000266521222031362400172530ustar00rootroot00000000000000----------------------------------------------------------------------------- -- Xavante HTTP handler -- -- Authors: Javier Guerra and Andre Carregal -- Copyright (c) 2004-2007 Kepler Project -- -- $Id: httpd.lua,v 1.45 2009/08/10 20:00:59 mascarenhas Exp $ ----------------------------------------------------------------------------- local string = require "string" local table = require "table" local os = require "os" local io = require "io" local socket = require "socket" local url = require "socket.url" local copas = require "copas" local _M = {} local _serversoftware = "" local _serverports = {} function _M.strsplit (str) local words = {} for w in string.gmatch (str, "%S+") do table.insert (words, w) end return words end -- Manages one connection, maybe several requests -- params: -- skt : client socket function _M.connection (skt) copas.setErrorHandler (_M.errorhandler) skt:setoption ("tcp-nodelay", true) local srv, port = skt:getsockname () local req = { rawskt = skt, srv = srv, port = port, copasskt = copas.wrap (skt), } req.socket = req.copasskt req.serversoftware = _serversoftware while _M.read_method (req) do local res _M.read_headers (req) repeat req.params = nil _M.parse_url (req) res = _M.make_response (req) until _M.handle_request (req, res) ~= "reparse" _M.send_response (req, res) req.socket:flush () if not res.keep_alive then break end end end function _M.errorhandler (msg, co, skt) msg = tostring(msg) io.stderr:write(" Xavante Error: "..msg.."\n", " "..tostring(co).."\n", " "..tostring(skt).."\n") skt:send ("HTTP/1.0 200 OK\r\n") skt:send (string.format ("Date: %s\r\n\r\n", os.date ("!%a, %d %b %Y %H:%M:%S GMT"))) skt:send (string.format ([[ Xavante Error!

Xavante Error!

%s

]], string.gsub (msg, "\n", "
\n"))) end -- gets and parses the request line -- params: -- req: request object -- returns: -- true if ok -- false if connection closed -- sets: -- req.cmd_mth: http method -- req.cmd_url: url requested (as sent by the client) -- req.cmd_version: http version (usually 'HTTP/1.1') function _M.read_method (req) local err req.cmdline, err = req.socket:receive () if not req.cmdline then return nil end req.cmd_mth, req.cmd_url, req.cmd_version = unpack (_M.strsplit (req.cmdline)) req.cmd_mth = string.upper (req.cmd_mth or 'GET') req.cmd_url = req.cmd_url or '/' return true end -- gets and parses the request header fields -- params: -- req: request object -- sets: -- req.headers: table of header fields, as name => value function _M.read_headers (req) local headers = {} local prevval, prevname while 1 do local l,err = req.socket:receive () if (not l or l == "") then req.headers = headers return end local _,_, name, value = string.find (l, "^([^: ]+)%s*:%s*(.+)") name = string.lower (name or '') if name then prevval = headers [name] if prevval then value = prevval .. "," .. value end headers [name] = value prevname = name elseif prevname then headers [prevname] = headers [prevname] .. l end end end function _M.parse_url (req) local def_url = string.format ("http://%s%s", req.headers.host or "", req.cmd_url or "") req.parsed_url = url.parse (def_url or '') req.parsed_url.port = req.parsed_url.port or req.port req.built_url = url.build (req.parsed_url) req.relpath = url.unescape (req.parsed_url.path) end -- sets the default response headers function _M.default_headers (req) return { Date = os.date ("!%a, %d %b %Y %H:%M:%S GMT"), Server = _serversoftware, } end function _M.add_res_header (res, h, v) if string.lower(h) == "status" then res.statusline = "HTTP/1.1 "..v else local prevval = res.headers [h] if (prevval == nil) then res.headers[h] = v elseif type (prevval) == "table" then table.insert (prevval, v) else res.headers[h] = {prevval, v} end end end -- sends the response headers -- params: -- res: response object -- uses: -- res.sent_headers : if true, headers are already sent, does nothing -- res.statusline : response status, if nil, sends 200 OK -- res.headers : table of header fields to send local function send_res_headers (res) if (res.sent_headers) then return end if package.loaded["xavante.cookies"] then local cookies = require "xavante.cookies" xavante.cookies.set_res_cookies (res) end res.statusline = res.statusline or "HTTP/1.1 200 OK" res.socket:send (res.statusline.."\r\n") for name, value in pairs (res.headers) do if type(value) == "table" then for _, value in ipairs(value) do res.socket:send (string.format ("%s: %s\r\n", name, value)) end else res.socket:send (string.format ("%s: %s\r\n", name, value)) end end res.socket:send ("\r\n") res.sent_headers = true; end -- sends content directly to client -- sends headers first, if necesary -- params: -- res ; response object -- data : content data to send local function send_res_data (res, data) if not res.sent_headers then send_res_headers (res) end if not data or data == "" then return end if data then if res.chunked then res.socket:send (string.format ("%X\r\n", string.len (data))) res.socket:send (data) res.socket:send ("\r\n") else res.socket:send (data) end end end function _M.make_response (req) local res = { req = req, socket = req.socket, headers = _M.default_headers (req), add_header = _M.add_res_header, send_headers = send_res_headers, send_data = send_res_data, } return res end -- sends prebuilt content to the client -- if possible, sets Content-Length: header field -- params: -- req : request object -- res : response object -- uses: -- res.content : content data to send -- sets: -- res.keep_alive : if possible to keep using the same connection function _M.send_response (req, res) if res.content then if not res.sent_headers then if (type (res.content) == "table" and not res.chunked) then res.content = table.concat (res.content) end if type (res.content) == "string" then res.headers["Content-Length"] = string.len (res.content) end end else if not res.sent_headers then res.statusline = "HTTP/1.1 204 No Content" res.headers["Content-Length"] = 0 end end if res.chunked then res:add_header ("Transfer-Encoding", "chunked") end if res.chunked or ((res.headers ["Content-Length"]) and req.headers ["connection"] == "Keep-Alive") then res.headers ["Connection"] = "Keep-Alive" res.keep_alive = true else res.keep_alive = nil end if res.content then if type (res.content) == "table" then for _,v in ipairs (res.content) do res:send_data (v) end else res:send_data (res.content) end else res:send_headers () end if res.chunked then res.socket:send ("0\r\n\r\n") end end function _M.getparams (req) if not req.parsed_url.query then return nil end if req.params then return req.params end local params = {} req.params = params for parm in string.gmatch (req.parsed_url.query, "([^&]+)") do local k,v = string.match (parm, "(.*)=(.*)") k = url.unescape (k) v = url.unescape (v) if k ~= nil then if params[k] == nil then params[k] = v elseif type (params[k]) == "table" then table.insert (params[k], v) else params[k] = {params[k], v} end end end return params end function _M.err_404 (req, res) res.statusline = "HTTP/1.1 404 Not Found" res.headers ["Content-Type"] = "text/html" res.content = string.format ([[ 404 Not Found

Not Found

The requested URL %s was not found on this server.

]], req.built_url); return res end function _M.err_403 (req, res) res.statusline = "HTTP/1.1 403 Forbidden" res.headers ["Content-Type"] = "text/html" res.content = string.format ([[ 403 Forbidden

Forbidden

You are not allowed to access the requested URL %s .

]], req.built_url); return res end function _M.err_405 (req, res) res.statusline = "HTTP/1.1 405 Method Not Allowed" res.content = string.format ([[ 405 Method Not Allowed

Not Found

The Method %s is not allowed for URL %s on this server.

]], req.cmd_mth, req.built_url); return res end function _M.redirect (res, d) res.headers ["Location"] = d res.statusline = "HTTP/1.1 302 Found" res.content = "redirect" end function _M.register (host, port, serversoftware) local _server = assert(socket.bind(host, port)) _serversoftware = serversoftware local _ip, _port = _server:getsockname() _serverports[_port] = true copas.addserver(_server, _M.connection) end function _M.get_ports() local ports = {} for k, _ in pairs(_serverports) do table.insert(ports, tostring(k)) end return ports end return _M xavante-2.3.0/src/xavante/indexhandler.lua000066400000000000000000000015351222031362400205660ustar00rootroot00000000000000----------------------------------------------------------------------------- -- Xavante index handler -- -- Authors: Javier Guerra -- Copyright (c) 2006-2007 Kepler Project -- -- $Id: indexhandler.lua,v 1.4 2007/11/27 15:57:05 carregal Exp $ ----------------------------------------------------------------------------- local function indexhandler (req, res, indexname) local indexUrl = string.gsub (req.cmd_url, "/[^/]*$", indexname) indexUrl = string.format ("http://%s%s", req.headers.host or "", indexUrl) res:add_header ("Location", indexUrl) res.statusline = "HTTP/1.1 302 Found" res.content = "redirect" res:send_headers() return res end return function (indexname) return function (req, res) return indexhandler (req, res, indexname) end end xavante-2.3.0/src/xavante/mime.lua000066400000000000000000000125661222031362400170560ustar00rootroot00000000000000----------------------------------------------------------------------------- -- Xavante MIME types -- -- Authors: Javier Guerra and Andre Carregal -- Copyright (c) 2004-2007 Kepler Project -- -- $Id: mime.lua,v 1.7 2007/08/20 22:20:44 carregal Exp $ ----------------------------------------------------------------------------- local xavante = require "xavante" -- Extracted from Apache's mime.types -- This file controls what Internet media types are sent to the client for -- given file extension(s). Sending the correct media type to the client -- is important so they know how to handle the content of the file. -- Extra types can either be added here or by using an AddType directive -- in your config files. For more information about Internet media types, -- please read RFC 2045, 2046, 2047, 2048, and 2077. The Internet media type -- registry is at . xavante.mimetypes = { ez = "application/andrew-inset", atom = "application/atom+xml", hqx = "application/mac-binhex40", cpt = "application/mac-compactpro", mathml = "application/mathml+xml", doc = "application/msword", bin = "application/octet-stream", dms = "application/octet-stream", lha = "application/octet-stream", lzh = "application/octet-stream", exe = "application/octet-stream", class = "application/octet-stream", so = "application/octet-stream", dll = "application/octet-stream", dmg = "application/octet-stream", oda = "application/oda", ogg = "application/ogg", pdf = "application/pdf", ai = "application/postscript", eps = "application/postscript", ps = "application/postscript", rdf = "application/rdf+xml", smi = "application/smil", smil = "application/smil", gram = "application/srgs", grxml = "application/srgs+xml", mif = "application/vnd.mif", xul = "application/vnd.mozilla.xul+xml", xls = "application/vnd.ms-excel", ppt = "application/vnd.ms-powerpoint", rm = "application/vnd.rn-realmedia", wbxml = "application/vnd.wap.wbxml", wmlc = "application/vnd.wap.wmlc", wmlsc = "application/vnd.wap.wmlscriptc", vxml = "application/voicexml+xml", bcpio = "application/x-bcpio", vcd = "application/x-cdlink", pgn = "application/x-chess-pgn", cpio = "application/x-cpio", csh = "application/x-csh", dcr = "application/x-director", dir = "application/x-director", dxr = "application/x-director", dvi = "application/x-dvi", spl = "application/x-futuresplash", gtar = "application/x-gtar", hdf = "application/x-hdf", xhtml = "application/xhtml+xml", xht = "application/xhtml+xml", js = "application/x-javascript", skp = "application/x-koan", skd = "application/x-koan", skt = "application/x-koan", skm = "application/x-koan", latex = "application/x-latex", xml = "application/xml", xsl = "application/xml", dtd = "application/xml-dtd", nc = "application/x-netcdf", cdf = "application/x-netcdf", sh = "application/x-sh", shar = "application/x-shar", swf = "application/x-shockwave-flash", xslt = "application/xslt+xml", sit = "application/x-stuffit", sv4cpio = "application/x-sv4cpio", sv4crc = "application/x-sv4crc", tar = "application/x-tar", tcl = "application/x-tcl", tex = "application/x-tex", texinfo = "application/x-texinfo", texi = "application/x-texinfo", t = "application/x-troff", tr = "application/x-troff", roff = "application/x-troff", man = "application/x-troff-man", me = "application/x-troff-me", ms = "application/x-troff-ms", ustar = "application/x-ustar", src = "application/x-wais-source", zip = "application/zip", au = "audio/basic", snd = "audio/basic", mid = "audio/midi", midi = "audio/midi", kar = "audio/midi", mpga = "audio/mpeg", mp2 = "audio/mpeg", mp3 = "audio/mpeg", aif = "audio/x-aiff", aiff = "audio/x-aiff", aifc = "audio/x-aiff", m3u = "audio/x-mpegurl", ram = "audio/x-pn-realaudio", ra = "audio/x-pn-realaudio", wav = "audio/x-wav", pdb = "chemical/x-pdb", xyz = "chemical/x-xyz", bmp = "image/bmp", cgm = "image/cgm", gif = "image/gif", ief = "image/ief", jpeg = "image/jpeg", jpg = "image/jpeg", jpe = "image/jpeg", png = "image/png", svg = "image/svg+xml", svgz = "image/svg+xml", tiff = "image/tiff", tif = "image/tiff", djvu = "image/vnd.djvu", djv = "image/vnd.djvu", wbmp = "image/vnd.wap.wbmp", ras = "image/x-cmu-raster", ico = "image/x-icon", pnm = "image/x-portable-anymap", pbm = "image/x-portable-bitmap", pgm = "image/x-portable-graymap", ppm = "image/x-portable-pixmap", rgb = "image/x-rgb", xbm = "image/x-xbitmap", xpm = "image/x-xpixmap", xwd = "image/x-xwindowdump", igs = "model/iges", iges = "model/iges", msh = "model/mesh", mesh = "model/mesh", silo = "model/mesh", wrl = "model/vrml", vrml = "model/vrml", ics = "text/calendar", ifb = "text/calendar", css = "text/css", html = "text/html", htm = "text/html", asc = "text/plain", txt = "text/plain", rtx = "text/richtext", rtf = "text/rtf", sgml = "text/sgml", sgm = "text/sgml", tsv = "text/tab-separated-values", wml = "text/vnd.wap.wml", wmls = "text/vnd.wap.wmlscript", etx = "text/x-setext", mpeg = "video/mpeg", mpg = "video/mpeg", mpe = "video/mpeg", qt = "video/quicktime", mov = "video/quicktime", mxu = "video/vnd.mpegurl", avi = "video/x-msvideo", movie = "video/x-sgi-movie", ice = "x-conference/x-cooltalk", } return xavante.mimetypesxavante-2.3.0/src/xavante/patternhandler.lua000066400000000000000000000017231222031362400211330ustar00rootroot00000000000000----------------------------------------------------------------------------- -- Xavante URL patterns handler -- -- Authors: Fabio Mascarenhas -- Copyright (c) 2006 Kepler Project -- -- $Id: patternhandler.lua,v 1.2 2008/03/10 23:38:31 mascarenhas Exp $ ----------------------------------------------------------------------------- local httpd = require "xavante.httpd" local function match_url (req, conf) local path = req.relpath for _, rule in ipairs(conf) do for _, pat in ipairs(rule.pattern) do local cap = { string.match(path, pat) } if #cap > 0 then req.handler = rule.handler return cap end end end end return function (conf) if not conf or type (conf) ~= "table" then return nil end return function (req, res) local cap = match_url (req, conf) or {} local h = req.handler or httpd.err_404 return h (req, res, cap) end end xavante-2.3.0/src/xavante/redirecthandler.lua000066400000000000000000000037171222031362400212640ustar00rootroot00000000000000------------------------------------------------------------------------------- -- Xavante redirect handler -- -- Authors: Javier Guerra and Andre Carregal -- Copyright (c) 2004-2007 Kepler Project -- -- $Id: redirecthandler.lua,v 1.11 2008/07/25 18:40:31 mascarenhas Exp $ ------------------------------------------------------------------------------- local url = require "socket.url" local httpd = require "xavante.httpd" local _M = {} -- params = { dest, action } -- dest can be of three kinds: -- absolute: begins with protocol string or '/', the entire path is replaced with dest -- concat: begins with ':', dest is appended to the path -- relative: dest is appended to the dirname of the path -- if used with patternhandler, dest can use the captures with %1, %2 etc. -- action can be "redirect" or "rewrite", default is "rewrite", except when -- dest starts with a protocol string local function redirect (req, res, dest, action, cap) dest = string.gsub(dest, "%%(%d)", function (capn) return cap[tonumber(capn)] or "" end) dest = string.gsub(dest, "%%%%", "%") local path = req.parsed_url.path local pfx = string.sub (dest, 1,1) if pfx == "/" then path = dest elseif pfx == ":" then path = path .. string.sub (dest, 2) elseif dest:find("^[%w]+://") then path = dest action = "redirect" else path = string.gsub (path, "/[^/]*$", "") .. "/" .. dest end local path, query = path:match("^([^?]+)(%??.*)$") req.parsed_url.path = path req.built_url = url.build (req.parsed_url) .. (query or "") req.cmd_url = string.gsub (req.built_url, "^[^:]+://[^/]+", "") if action == "redirect" then httpd.redirect(res, path .. (query or "")) return res elseif type(action) == "function" then return action(req, res, cap) else return "reparse" end end function _M.makeHandler (params) return function (req, res, cap) return redirect (req, res, params[1], params[2], cap) end end return _Mxavante-2.3.0/src/xavante/ruleshandler.lua000066400000000000000000000060601222031362400206070ustar00rootroot00000000000000----------------------------------------------------------------------------- -- Xavante URL rules handler -- -- Authors: Javier Guerra and Fabio Mascarenhas -- Copyright (c) 2006-2007 Kepler Project -- -- $Id: ruleshandler.lua,v 1.2 2007/08/20 22:20:44 carregal Exp $ ----------------------------------------------------------------------------- local httpd = require "xavante.httpd" -- this is a coroutine-based iterator: -- path_perputer takes a path and yields once for each handler key to try -- first is the full path -- next, anything with the same extension on the same directory -- next, anything on the directory -- strips the last subdirectory from the path, and repeats the last two patterns -- for example, if the query was /first/second/file.ext , tries: -- /first/second/file.ext -- /first/second/*.ext -- /first/second/* -- /first/*.ext -- /first/* -- /*.ext -- /* -- and, if the query was for a directory like /first/second/last/ , it tries: -- /first/second/last/ -- /first/second/ -- /first/ -- / local function path_permuter (path) coroutine.yield (path) local _,_,ext = string.find (path, "%.([^./]*)$") local notdir = (string.sub (path, -1) ~= "/") while path ~= "" do path = string.gsub (path, "/[^/]*$", "") if notdir then if ext then coroutine.yield (path .."/*."..ext) end coroutine.yield (path .."/*") else coroutine.yield (path.."/") end end end -- given a path, returns an iterator to traverse all permutations local function path_iterator (path) return coroutine.wrap (function () path_permuter (path) end) end -- parses the url, and gets the appropiate handler function -- starts with the full path, and goes up to the root -- until it finds a handler for the request method local function match_url (req, conf) local path = req.relpath local h, set for p in path_iterator (path) do h = conf [p] if h then req.match = p break end end if req.match then local _,_,pfx = string.find (req.match, "^(.*/)[^/]-$") assert (string.sub (path, 1, string.len (pfx)) == pfx) req.relpath = string.sub (path, string.len (pfx)+1) end req.handler = h end return function (conf) if not conf or type (conf) ~= "table" then return nil end return function (req, res) match_url (req, conf) local h = req.handler or httpd.err_404 return h (req, res) end end xavante-2.3.0/src/xavante/urlhandler.lua000066400000000000000000000026451222031362400202640ustar00rootroot00000000000000----------------------------------------------------------------------------- -- Xavante URL paths handler -- -- Authors: Javier Guerra -- Copyright (c) 2006-2007 Kepler Project -- -- $Id: urlhandler.lua,v 1.3 2007/08/20 22:20:44 carregal Exp $ ----------------------------------------------------------------------------- local httpd = require "xavante.httpd" local function path_p (s, p) if not p then return s end if p=="" then return nil end return string.gsub (p, "[^/]*/?$", "") end local function path_iterator (path) return path_p, path end local function match_url (req, conf) local path = req.relpath local h = nil for p in path_iterator (path) do h = conf [p] if h then req.match = p break end end if req.match then local _,_,pfx = string.find (req.match, "^(.*/)[^/]-$") assert (string.sub (path, 1, string.len (pfx)) == pfx) req.relpath = string.sub (path, string.len (pfx)+1) end req.handler = h end return function (conf) if not conf or type (conf) ~= "table" then return nil end return function (req, res) match_url (req, conf) local h = req.handler or httpd.err_404 return h (req, res) end end xavante-2.3.0/src/xavante/vhostshandler.lua000066400000000000000000000010221222031362400207740ustar00rootroot00000000000000----------------------------------------------------------------------------- -- Xavante virtual hosts handler -- -- Authors: Javier Guerra -- Copyright (c) 2006-2007 Kepler Project -- -- $Id: vhostshandler.lua,v 1.3 2007/08/20 22:20:44 carregal Exp $ ----------------------------------------------------------------------------- return function (vhosts) return function (req, res) local h = vhosts [req.headers.host] or vhosts [""] return h (req, res) end end xavante-2.3.0/src/xavante/xavante.lua000066400000000000000000000070571222031362400175740ustar00rootroot00000000000000------------------------------------------------------------------------------- -- Xavante main module -- -- Handles HTTP 1.1 requests and responses with Copas. -- Uses CGILua as native template engine. -- -- See xavante/config.lua for configuration details. -- -- Authors: Javier Guerra and Andre Carregal -- Copyright (c) 2004 Kepler Project -- -- $Id: xavante.lua,v 1.13 2009/03/06 23:44:23 carregal Exp $ ------------------------------------------------------------------------------- local _M = {} local copas = require "copas" local httpd = require "xavante.httpd" local string = require "string" local phandler = require "xavante.patternhandler" local vhosts = require "xavante.vhostshandler" -- Meta information is public even begining with an "_" _M._COPYRIGHT = "Copyright (C) 2004-2010 Kepler Project" _M._DESCRIPTION = "A Copas based Lua Web server with WSAPI support" _M._VERSION = "Xavante 2.2.0" local _startmessage = function (ports) print(string.format("Xavante started on port(s) %s", table.concat(ports, ", "))) end local function _buildRules(rules) local rules_table = {} for rule_n, rule in ipairs(rules) do local handler if type (rule.with) == "function" then if rule.params then handler = rule.with(rule.params) else handler = rule.with end elseif type (rule.with) == "table" then handler = rule.with.makeHandler(rule.params) else error("Error on config.lua. The rule has an invalid 'with' field.") end local match = rule.match if type(match) == "string" then match = {rule.match} end rules_table[rule_n] = { pattern = {}, handler = handler } for pat_n, pat in ipairs(match) do rules_table[rule_n].pattern[pat_n] = pat end end return rules_table end ------------------------------------------------------------------------------- -- Sets startup message ------------------------------------------------------------------------------- function _M.start_message(msg) _startmessage = msg end ------------------------------------------------------------------------------- -- Register the server configuration ------------------------------------------------------------------------------- function _M.HTTP(config) -- normalizes the configuration config.server = config.server or {host = "*", port = 80} local vhosts_table = {} if config.defaultHost then vhosts_table[""] = phandler(_buildRules(config.defaultHost.rules)) end if type(config.virtualhosts) == "table" then for hostname, host in pairs(config.virtualhosts) do vhosts_table[hostname] = phandler(_buildRules(host.rules)) end end httpd.handle_request = vhosts(vhosts_table) httpd.register(config.server.host, config.server.port, _M._VERSION) end ------------------------------------------------------------------------------- -- Starts the server ------------------------------------------------------------------------------- function _M.start(isFinished, timeout) _startmessage(httpd.get_ports()) while true do if isFinished and isFinished() then break end copas.step(timeout) end end ------------------------------------------------------------------------------- -- Methods to define and return Xavante directory structure ------------------------------------------------------------------------------- function _M.webdir() return _M._webdir end function _M.setwebdir(dir) _M._webdir = dir end return _M xavante-2.3.0/web/000077500000000000000000000000001222031362400137325ustar00rootroot00000000000000xavante-2.3.0/web/calculator.lp000066400000000000000000000015301222031362400164170ustar00rootroot00000000000000<% local sajax = require "sajax" function multiply(x, y) return x * y end sajax.init() sajax.export ("multiply", multiply) if sajax.handle_client_request () then return end %> Multiplier * = xavante-2.3.0/web/loop.lp000066400000000000000000000002721222031362400152410ustar00rootroot00000000000000 CGILua loop test

Executes a long loop, used by concurrency tests

<% for i = 1, 30000 do %> i = $|i|$
<% end %>