Lua Server Pages (LSP)
Overview
LSP provides a simple, fast way of creating web pages. LSP is similar to CSP
and JSP, except that
LSP does not need to be compiled, however LSP can be compiled if desired.
Lua script can be freely intermixed with HTML or XML. LSP tags are XML compliant
<?lsp ?>. Code between these tags is executed as Lua code. Expressions are
provided by the <?lsp= ?> tag. The result of an expression is emitted as
HTML/XML.
The standard LSP tags are recognized by most HTML editing tools and hence these tools can be used
for creating dynamic LSP pages.
LSP can used as an adjunct to CSP. CSP pages can include LSP pages and vice versa.
LSP is extensible, there are many third party tools and libraries that are available for Lua,
given that the libraries support the target platform LSP can use these libraries. In turn Lua is
also extensible, it is a straight forward process to create your own extension libraries for
specialist interfaces. Lua libraries are available for databases (ODBC, Postgre, MySQL, SQLLite, etc..),
sockets and internet protocols like SNMP, LDAP, SMTP, FTP etc, Robotics, AI and various File Systems.
Like CSP, LSP can be loaded from a compressed directory.
LSP pages are available for any target platforms supported by the Barracuda Web Server.
A standalone executable Lua interpreter and a compiler are also provided.
The standalone compiler is useful for testing LSP prior to deployment without the aid of a Web
server.
Barracuda LSP Lua Library Objects
Each LSP page is provided with some predefined variables and objects, namely;
request, response,
cookie, session and page.
LSP provides Helper functions and extensions to the standard
Lua Libraries.
request object
The request object is available to every LSP page, it has the following methods:
- allow({methods, ...,} [, usedefaults])
-
The allow() method checks if the HTTP request method is one of the
HTTP methods specified in the parameter list. The
function returns false if the request method is not one the allowed methods
and sets the status code is set to 405 (method not allowed).
If the request method is allowed then allow() returns true.
allow() also returns false when the request method is 'OPTIONS'.
By default the methods OPTIONS and HEAD are added automatically to a allowed option list,
setting the second paraneter to false prevents these defaults from being automatically added.
This function is typically used at the start of a LSP.
e.g.
--only allow GET and POST for this page
if not request:allow{"GET", "POST"} then return end
-- valid request lets continue
print"hello world"
- checktime(time)
-
Handles the "If-Modified-Since" request header.
The time parameter is effectively what you wish to be the last modified
time of the LSP.
If the parameter time is newer or the same as the request "If-Modified-Since" time
then the function returns true.
If the parameter time is older than the request "If-Modified-Since" time
time the function returns false and
sends a "304 Not modified" response to the client.
The time is in the format provided by os.time().
! You cannot write to the output stream if this function returns false.
e.g.
-- switch off the default cache headers
response:setheader"Cache-control"
response:setheader"Pragma"
--check the modified time (anything up to a day old)
if not request:checktime(os.time() - (60*60*24)) then return end
-- lets provide the updated page
print"hello world"
- user()
- returns the name, application name and authentication type of an authenticated user for
this request, if one exists
for the request. If there is no authenticated user then the function returns false and the application name.
Possible values of the authentication type are; 'form', 'basic' and 'digest'.
- logout([url][[,]all])
- Logout the request user and terminates the session. The optional parameter url is where to redirect the user after logging out. The user is redirected to '/' if 'url' is not set. The optional parameter 'all' defaults to false. Set 'all' to true if you like to terminate all of the user's active sessions. A user may be logged in using more than one client. One must typically set all=true when changing password as all clients must be terminated or the clients may get a 403 response.
If there is no authenticated user then false is returned.
- cookie(cookie name)
- returns the named cookie object.
- header([header name])
-
returns a string with the value of the named HTTP header. If no parameter is provided
then a table containing all request header name/value pairs is returned.
- domain()
-
Returns the host header without any port number.
Typically used with name-based virtual hosting.
The returned value is always lowercase.
- method()
- returns the name of the request method. e.g. GET, POST, etc
- data([name ...])
-
when name is not provided
returns a table containing any POST or QUERY data sent to the server. The
table may be empty if there is no POST or QUERY data.
When one or names are provided the values of these names are returned.
Note this function will not return multiple values. If this is required use datapairs().
e.g.
--get some values
custnbr = request:data("custnbr") --get the value of custnbr
name, num = request:data("name", "num") --get two values
--display posted values
for name,value in pairs(request:data()) do
print(name,'=',value)
end
- datapairs()
-
An iterator that will traverse of all name/value pairs that
have been sent to the server with POST or GET.
e.g.
--display all posted values
for name,value in request:datapairs()) do
print(name,'=',value)
end
- rawrdr([blocksize])
- Returns a function that can be used as an iterator for reading PUT and POST data. You cannot use this function for posted www-url-encoded or multi-part data. The function throws an exception if the following conditions are met:
- Request is missing content-length and not chunk encoding.
- Request is of type URL encoded data. URL encoded data is handled directly by the server. See request:data or request:datapairs for more information.
- Request is of type multipart/form-data. You must use request:multipart
- The returned function also takes an optional blocksize as its only parameter. The default blocksize varies depending on the platform. For example Windows is usually 512 and UNIX is usually 1024.
- The iterator returned transparently handles chunk encoded data. A client can either set a content length or send data using chunk encoding.
- multipart(callbacks[,bufsize][,keepAlive])
- Decode multi-part encoded POST data. Calling this function starts a multi byte parser, which calls your callbacks as data is parsed from the data stream.
- The parser allocates "bufsize" bytes for temporary storage. The buffer must not be smaller than the content size of the largest input field element of type "text" or textarea. The default value is 8K.
- You can optionally set keepAlive to false if you would like that the web-server closes the connection after the upload is completed and you have sent a response message to the client.
- Argument callbacks is a table with callback functions:
- formdata(name, value)
- beginfile(name, filename, contenttype, transferencoding)
- filedata(data)
- end()
- error(emsg)
- The functions are optional. The data is simply discarded if the multi byte stream contains data not handled by a callback. The function(s) can terminate the multi byte stream parsing by returning false.
- Callback function formdata is called for each input field in the form. For example, the function will be called twice if you have the following form:
<form method="post" enctype="multipart/form-data">
<input type="text" name="Text input" />
<textarea name="Text area" cols="40" rows="3"></textarea>
</form>
- Callback functions beginfile and filedata are called if the form contains an input of type "file". For example, the function beginfile will be called twice if you have the following form and the filedata function is called repeatedly to give you data as it trickles in.
<form method="post" enctype="multipart/form-data">
<input type='file' size='40' name='File 1'/>
<input type='file' size='40' name='File 2'/>
</form>
- Callback function beginfile arguments:
| name |
the name as specified in the HTML "input" type |
| fileName |
the name and possible path of the file entered by the user. The path separator is platform dependent. |
| contentType |
the content mime type such as "text/plain". This parameter is NULL if not specified in the multipart data stream. |
| contentTransferEncoding |
the transfer encoding such as "gzip". This parameter is NULL if not specified in the multipart data stream. |
- Callback function filedata arguments:
- Callback function end is called at the end of the multi byte stream sent from the client.
- Callback function error is called if either parsing the multi byte stream failed or the connection closed.
- uri()
- returns the request URI. e.g. /myrequest.lsp
- url()
- returns the request URL. e.g. http://localhost/myrequest.lsp. This value
is also returned by the tostring(request) function.
- session([create])
-
Returns the current session object associated with this request or, if there is no current session
and create is true, returns a new session.
If create is false and the request has no valid session, this method returns false.
To make sure the session is properly maintained, you must call this method before the response is
committed.
The default value of create is `false'.
- version()
- returns the HTTP request version as a string.
- issecure()
- returns true if a HTTPS connection is being used.
- peername()
- returns a string of the client name/IP address.
- sockname()
- returns a string of the server name/IP address.
- setnodelay(on)
- Enables or disables the Nagle algorithm.
- sleep(milliseconds)
- Pauses execution of this request for the specified number of milliseconds.
This function may yield to other Barracuda threads, consequently the function may pause for longer
than the specified period. request:sleep(0)
would simply allow other pending Barracuda threads to
execute (i.e. a yield).
request example
<html>
<!-- request example usage -->
<?lsp
-- has the page been modified in the last 2 minutes
print("<h2>request methods</h2>");
print("<pre>");
request:checktime(response, os.time() - 120)
print("request:checktime(response,os.time() - 120)");
print("request:user() ", request:user())
print("request:cookie'z9ZAqJtI'", request:cookie"z9ZAqJtI")
print("request:header'User-Agent'", request:header"User-Agent")
print("\nAll request headers")
for k,v in next, request:header() do print(k,'=',v) end
print("\nrequest:method() ", request:method())
print("request:uri() ", request:uri())
local t =request:data()
print("request:data() ", request:data())
for k,v in next, t do print("\t",k,'=',v) end
print("\nrequest:session() ", request:session(true))
if request:session() then
print("session id", request:session():id(),"\n")
end
print("request:version() ", request:version())
print("</pre>")
?>
</html>
response object
This object is used when sending response messages back to the client.
The server creates a response object and makes it available to an LSP page.
This object provides methods that can be used when sending messages to the client.
Most of the response methods return nil, error message when an error is encountered.
- # - the length operator
- Return the sum of
writesize() and bytecount().
That is, the effective number of bytes in the response.
example:
Number of bytes sent to the response <lsp= #response ?>
- abspath(path)
-
Converts the input path (not a URL) to an absolute path. If the path is already absolute
it is returned unchanged. The empty string results in the path of the current page being
returned.
- bytecount()
- The number of bytes that have been sent to the client.
- containsheader(header name)
-
Searches the internal response header database for a header with the specified name. If the header
does not exist then the function returns false.
- clearkeepalive()
-
Causes a close of the current connection after the response is sent.
- createcookie(cookie name)
-
Creates a cookie with the provided name. The cookie object is returned.
- downgrade()
-
Changes the protocol to HTTP/1.0.
- encoderedirecturl(url [, withdata])
-
Encodes the specified URL into an absolute URL or,
if encoding is not needed, returns the URL unchanged.
If the withdata parameter is specified and true this method also includes all
url-encoded parameters in the request line and in the body if the client sent a POST message.
- encodeurl(url)
-
Encodes an absolute or relative URL or, if encoding is not needed, returns the URL unchanged.
This method escapes all symbols that cannot be in a URL. The method differs from
encoderedirecturl() in that it only escapes non URL compatible symbols.
- flush()
-
Forces any content in the response write buffer to be written to the client.
A call to this method automatically commits the response, meaning the status code and headers
will be written.
- forward(path)
-
Forwards a request from this LSP page to another resource (LSP page, servlet, CSP file, or HTML file).
This method allows one LSP page to do preliminary processing of a request and another
resource to generate the response (Request delegation).
forward() should be called before the response has been committed to the client (before response
body output has been flushed). If the response already has been committed, this method returns a
nil and an error message. Any data in the response buffer is erased when the request is forwarded.
The forward()ed page gets its own page environment/table, but the Lua environment for
the forward()ed page is same as the originating page. Restated, non-local lua variables
that are set in the forward()ing page will have their values available in the forward()ed
page, and vice versa.
Any error thrown by the forward()ed page will be trapped by the
forward()ing page.
The path is the resource to forward. The path is assumed to be an absolute path
value on the server if the string starts with "/". The path is otherwise assumed to be
relative to the directory of the current page.
This method is similar to method redirect, with the exception that forward bypasses any form of required authentication and/or authentication.
- redirect(path)
-
Internally redirects the request to another resource.
This method is similar to method forward, with the exception that forward bypasses any form of required authentication and/or authentication.
- include(path)
-
Includes the content of a resource (LSP, servlet, CSP page, HTML file, etc) in the response.
In essence, this method enables programmatic server side includes. See the introduction to
Request Delegation for more information.
The response object has its path elements and parameters remain unchanged from the caller's.
The included servlet cannot change the response status code or set headers; any attempt to
make a change is ignored.
The include()ed page gets its own page environment/table, but the Lua environment for
the include()ed page is same as the oriinating page. Restated, non-local lua variables
that are set in the include()ing page will have their values available in the include()ed
page, and vice-versa.
Any error thrown by the include()ed page will be trapped by the
include()ing page.
The included page cannot be gzip'ed if the zlib compression library is not installed in the server.
The path is the resource to include. The path is assumed to be an absolute path
value on the server if the string starts with "/". The path is otherwise assumed to be
relative to the directory of the current page.
- committed()
-
Returns a boolean (true/false) indicating if the response has been committed.
A committed response has already had its status code and headers written
- isforward()
-
Returns true if this is a forward request from another servlet or LSP file.
The second return value is the count of the number of times that the request
has been forwarded.
- initial()
-
Returns false if this is an include or forward from another servlet or LSP file,
that is, the first page called during the request processing. The method returns true if this is a redirected call initiated by method redirect.
- isinclude()
-
Returns true if this is an include from another servlet or LSP file.
The second return value is the count of the number of times that the request
has been included.
- reset([string])
-
Clears any data that exists in the buffer as well as the status code and headers.
Clears the content of the underlying buffer in the response without clearing headers or status code.
The optional string parameter may be "headers" or "buffer", if not supplied both
headers and buffers are cleared.
If the response has been committed, this method returns false.
- senderror(code [, message])
-
Sends an error response as a simple HTML page to the client using the specified status code.
An optional message can be sent with the response code.
If the response has been committed, this method returns false.
- sendredirect(url)
-
Sends a temporary redirect response to the client using the specified redirect location URL.
This function cannot accept relative URLs; the URL is converted to an absolute URL
during this call.
example:
response:sendredirect"start.html";
response:sendredirect"https://127.0.0.1:9357/intro/start.html";
- setcontenttype(type)
-
Sets the "Content-Type" header. type is a type string. e.g. "text/plain"
- setdateheader(name, time)
-
Sets a response header with the given name and date value (time).
The date is specified in terms of seconds. If the header had already been set,
the new value overwrites the previous one. The response:containsheader() method can be
used to test for the presence of a header before setting its value.
name is the name of the header to set (e.g. "Expires").
time the assigned time value in number of seconds elapsed since
midnight (00:00:00), January 1, 1970. This is the time format returned by os.time().
- setdefaultheaders()
-
Sets the most common header values in LSP files.
Sets content type to "text/html" and sets the header "Cache-Control" to "No-Cache".
This method is automatically inserted by the LSP page.
- setheader(name [, value])
-
Sets a HTTP response header with the given name and value.
If the header had already been set, the new value overwrites the previous one.
The response:containsheader method can be used to test for the presence of a header before setting its value.
If the value is not provided then the named header is removed from the response.
setheader() should be called before the response has been committed to the client,
(before response body output has been flushed). If the response already has been
committed, this method returns false.
- setmaxage(seconds)
-
Sets header "Cache-Control: max-age=seconds".
Can, for example, be used by LSP code to override the default headers inserted by the LSP page.
See response:setdefaultheaders() for more information.
- setstatus(status)
-
Sets the status code for this response.
This method is used to set the return status code when there is no error
(for example, for the status code 304 Not Modified). If there is an error, the
senderror() method should be used instead.
setstatus() should be called before the response has been committed to the client (before response
body output has been flushed). If the response already has been committed, this method returns
a non zero value.
- write(string, ...)
-
Sends strings to the client.
The internal process buffers write()s to the client.
Also refer to the print() function.
example
<?lsp
response:write"hello world"
-- create a convenience function for writing data
local fmt = string.format
local function prt(...) response:write(...) end
local function prtf(...) prt(fmt(...)) end
prt("as ","many ", "strings as you like<br />")
prtf("You can format numbers %d<br />", 1234)
?>
- writesize()
- The number of bytes that currently exist in the response write
buffer. flush() should reset this number to zero.
cookie object
A cookie is used for exchanging a small amount of information between a
page and a Web browser.
A cookie's value can uniquely identify a client, so cookies are commonly
used for session management.
A cookie has a name, a single value, and optional attributes such as
a comment, path and domain qualifiers, a maximum age, and a version number.
The cookie implementation is almost identical to the cookie implementation in the JavaTM Enterprise Edition
Typical usage:
cookie = request:getcookie"myCookie";
if not cookie then --If no cookie set for this page
--Create a session cookie
cookie = response:createcookie"myCookie";
--Active cookie i.e. send cookie to client
cookie:activate();
end
--This should never fail
assert(cookie == request:getcookie"myCookie");
- activate()
-
Activates the cookie.
The cookie will not be sent to the client unless this function is called. You cannot
active a cookie if the data is committed, see response:iscommitted() for more information.
- delete()
- Deletes a cookie, previously made persistent with function setMaxAge.
- comment([comment])
- Gets or sets a comment that describes a cookie's purpose.
- domain([domain])
- Gets or sets the domain name set for this cookie.
- maxage([time])
- Gets or sets the maximum age of the cookie, specified in seconds,
By default, 0 indicates the cookie will persist until browser shutdown.
- name()
- returns the name of the cookie.
- path([uri])
- Gets or sets the path on the server to which the browser returns this cookie
- secure([boolean])
-
Either returns true if the browser is sending cookies only over a secure protocol, or false
if the browser can send cookies using any protocol.
If the boolean flag is specified, informs the browser whether the cookie should only be sent
using a secure protocol, such as HTTPS or SSL.
- value([value])
-
Gets or sets the value of the cookie
session object
Provides a way to identify a user across more than one page request or visit to a Web site and to
store information about that user.
The HttpSession container uses this class to create a session between an HTTP client and an
HTTP server. The session persists for a specified time period, across more than one connection or
page request from the user. A session usually corresponds to one user, who may visit a site
many times. The server can maintain a session in many ways such as using cookies or rewriting URLs.
This interface allows you to:
- View and manipulate information about a session, such as the session identifier,
creation time, and last accessed time.
- Bind objects to sessions, allowing user information to persist across multiple
user connections. These objects can be any Lua object. e.g. tables, strings, numbers.
This class is similar (but much easier to use) to the
java Interface HttpSession.
Variables may be assigned and retrieved from the session object. This is done using normal Lua syntax.
Session variable example
<html>
<!-- example session variable usage -->
<?lsp
print("<h2>session variables</h2>");
print("<pre>");
session = request:session() -- returns nil/false if there is no session
if session then
print("we have a session ", session)
session.counter = (session.counter or 0) + 1 --count session usage of this page
session:maxinactiveinterval(60);
print ("id", session:id());
print ("creationtime" ,os.date("%c",session:creationtime()))
print ("lastaccessedtime" ,os.date("%c",session:lastaccessedtime()))
print ("maxinactiveinterval" ,session:maxinactiveinterval())
print ("usecounter" ,session:usecounter())
-- if we have any attributes print them all
if session:attributes() then
table.foreach(session:attributes(), print)
end
end
print("</pre>")
?>
</html>
Any attempt to create session variables with names the same as the session methods will result in an error.
Session variables are destroyed when the session terminates or times out. LSP session variables
are not accessable from CSP pages and vice versa.
A user can create a tool that could potentially overflow the session container.
The Barracuda authentication system makes sure that a session object is not created before the user
is authenticated. It is therefore recommended to create a session object by using the
authentication system.
- attributes()
-
returns a table containing any attributes that have been set for this session.
If no attributes have been set this function returns false.
Attribute values
can be any Lua data type. e.g. strings, numbers, tables etc.
Session attributes can be removed by setting their value to `nil'. e.g. session.myattribute = nil
NOTE: LSP session attributes are private to LSP and are not accessible from CSP pages, nor can LSP
pages access CSP session attributes.
- id()
- Returns a unique string identifier assigned for this session.
- creationtime()
- Returns the time when this session was created, measured in seconds
since midnight January 1, 1970 GMT. This time can be formated with os.date()
- lastaccessedtime()
- Returns the last time the client sent a request associated with
this session, as the number of seconds since midnight January 1, 1970 GMT, and marked by the
time the container received the request.
This time can be formated with os.date()
- maxinactiveinterval([interval])
-
Returns the maximum time interval, in seconds, that the session container will keep this session
open between client accesses.
OR specifies the time, in seconds, between client requests before the session container will
invalidate this session.
- usecounter()
- Get the session usage counter.
- terminate()
- Unbinds any objects bound to this session object,
Destroys the session object and frees the memory for this object. All session variables are
destroyed.
page object
A table containing the following fields, page variables may be added to this table and are persistent (they are maintained across different requests).
- path
- the path name of the resource that was requested. (Not the URL).
- modified
- the last modified time of this page.
This field is a number which can be passed to the Lua function os.date() for formatting.
- size
- the size of this page in bytes.
- url
- The URL which requested this page
- iopath
- The path of the page relative to the IO interface in which it
is installed.
- iodir
- The directory name part of iopath.
Page example
<html>
<!-- example usage -->
<?lsp
print("<h2>page fields</h2>");
print("<pre>");
print("Path = ", page.path)
print("Last Modified Date = ", os.date("%c", page.modified))
print("Page size = ", page.size)
print("URL = ", page.url)
page.count = (page.count or 0) + 1
print("Access count = ", page.count)
print("</pre>")
?>
</html>
json
A library that supports JSON dencoding and decoding.
- json.encode(table)
-
returns a JSON encoded string. The function iterates over the provided
table and converts all table entries to JSON encoding. Userdata, functions
and threads
are set to JSON 'null'.
- json.decode(string)
- Takes a JSON encoded string and decodes it into a Lua table.
JSON null is set to the json.null value.
On error nil and an error message is returned. The message is one of
'parse', 'data', 'interface' or 'memory'.
The input string is assumed to be UTF-8 encoded.
The string parameter can contain multiple JSON tables, in this case multiple
Lua tables (or [nil,message] pairs) are returned.
- json.encodestr(string)
- Encodes a string as JSON string.
- json.null
- A userdata that represents the JSON null value.
ba
A library that provides a number of Barracuda utility and IO functions.
- ba.aesencode(key,string)
-
Encrypts a string using AES encryption and returns the encrypted string as a B64 encoded string.
key: The key can be any string, but is preferably created with function ba.aeskey()
string: The string to be encrypted and converted to B64 encoding.
This function is typically used as a substitute for creating a session object. The LSP page can instead store the session state as a hidden variable in the dynamically created page returned to the browser. The following example illustrates how to encode and decode state information in a hidden variable.
Encoding:
-- Data to be encoded and stored in hidden variable
local stateInfo={x=10,y="Top Secret"}
local data=ba.aesdecode(app.key, json.encode(stateInfo))
Decoding:
-- Data received via hidden variable from client
local stateInfo = json.decode(ba.aesdecode(app.key, request:data"MyHiddenVariable"))
- ba.aeskey([len[,seed]])
-
Create a 16 or 32 byte long key that can be used by ba.aesencode() and ba.aesdecode(). The key is typically created at startup in the .preload script and stored in the app table.
len: The key length must be 16 (AES 128 bit) or 32 (AES 256 bit). The default length is set to 16.
seed: The Key is calculated by successively calling random. You can optionally specify a seed value. The default seed value is a function of the time and the system clock.
- ba.aesdecode(key, string)
Decodes and decrypts a string encrypted and encoded with function ba.aesencode. The key must be the same as the key you used when encoding the string.
-
- ba.b64encode(string)
-
encodes a string as BASE64.
- ba.b64decode(string)
-
decodes a BASE64 string.
- ba.urlencode(string)
-
URL encodes a string.
- ba.urldecode(string)
-
decodes a URL encoded string.
- ba.loadfile(filename)
-
This function is similar to the native Lua loadfile(), but differs
in that it uses the Barracuda VM IO object to read the file that
is loaded.
- ba.mkserver()
-
- ba.deflate(data [,rfc1950])
-
Deflates (compresses) a string or a table of strings and returns the compressed data.
data: The data to be compressed, which must be a string or a table of strings. The function works similarly to the Lua function table.concat when this argument is a table. The table is concatenated and compressed.
rfc1950: Optional Boolean argument, which defaults to false. The default action is to deflate data using RFC1951 -- i.e. compress without adding the ZLIB deflate header. The correct deflate method is to use RFC1950, but the Internet Explorer team did not properly read the specification so IE fails if a ZLIB header is added. All other browsers also accept RFC1951. Set this variable to true if you want all browsers to work except IE.
- ba.openio(["app"|"root"|"vm"])
-
returns a Barracuda IO object. The default option is "root".
Barracuda IO objects have a number of methods associated with
them, it is implementation dependent as to whether these objects represent
disk IO or not.
If the implemented IO object does not implement a particular method a
Lua exception will be thrown.
- baio:open(path[, mode)]
-
opens a resource and returns an object that can be used for IO. The optional mode is the
same as the file modes used in standard Lua.
The objects returned by open() have the following methods:
- fh:close(object)
-
same as standard Lua.
- fh:flush()
-
same as standard Lua.
- fh:read(option)
-
same as standard Lua, except that the only options supported are a number of bytes or the
"*a" (all of the file). There is no default option.
- fh:seek(offset)
-
same as standard Lua.
- fh:write(string, ...)
-
same as standard Lua.
- baio:resourcetype()
-
returns two strings indicating the type of resource where files exist. (e.g disk)
and the type of operating system.
- baio:type(object)
-
returns true if the object is a Barracuda file handle.
- baio:files(dir)
-
returns an iterator that will iterate over all the files in the
named directory. The iterator returns each file name in the
directory.
- baio:stat(path)
-
returns a table of attributes for the named path (file or directory). If
the path does not exist then 'nil' is returned. The fields of the table
are named as follows:
- name - the path name
- mtime - Last modified time
- size - the size of the file (in bytes)
- isdir - true if the path is a directory
- type - either "directory" or "regular"
- baio:realpath(path)
-
returns the realpath (absolute) path name of the provided relative path.
- baio:mkdir(path)
-
creates a new directory.
- baio:rmdir(path)
-
removes a directory.
- baio:remove(path)
-
removes (deletes) a file.
- baio:rename(oldpath, newpath)
-
renames a file or directory.
- baio:loadfile(path)
-
loads a Lua source file. Refer to the Lua base library loadfile() function.
- baio:dofile(path)
-
loads and executes a Lua source file. Refer to the Lua base library dofile() function.
- baio:setpasswd(password)
-
You can set the password if the ZIP file opened with ba.mkio is password protected. Barracuda only supports AES encrypted ZIP files.
- baio:reqpasswd(enable)
-
Enable password protection. If enabled, the file being opened must match the password set with baio:setpasswd. It is possible to replace an encrypted file inside a ZIP file with a non encrypted file. Enabling password protection makes sure your ZIP file is not compromised.
- Error codes:
-
The methods in the IO object returns nil and two error codes if calling the method(s) fail. The first code is an error message, and the second error code is a number from the C implementation. The error number can be any of the following:
| -1 | Invalid name or name not accepted by IOINTF implementation.A DOS 8.3 file system may return this code for long file names |
| -2 | Resource not found. |
| -3 | Resource exists and cannot be overwritten. |
| -4 | Path (parent directory) not found. |
| -5 | No access or resource locked by file system. |
| -6 | A directory resource is not empty. |
| -7 | No space left on device. |
| -8 | Some kind of IO error. The extra error code may contain more information. |
| -9 | Memory allocation error when working with resource. |
| -50 | Method not implemented. |
| -100 | Cannot uncompress the file since no ZLIB implemenation is installed in the server. |
| -101 | IoIntf_OpenResGzip is not willing to compress the data. This informs the caller that IoIntf_OpenRes must be used instead. |
| -102 | Error in compressed data. |
| -200 | Encrypted ZIP file requires AES, but AES is not enabled in ZipIo.c. Recompile with ZIP_ENCRYPTION. |
| -201 | Unknown AES encryption or not an AES encrypted ZIP file. |
| -202 | File is AES encrypted, but you did not provide a password. |
| -203 | Wrong password for AES encrypted file. |
| -204 | Password does not match password in the file being accessed in the ZIP file. The most likely cause is corrupted ZIP file or a compromised ZIP file.
|
| -205 | The file being accessed in the ZIP file is changed from an AES encrypted file to a non-encrypted file. Detection for this error is enabled with baio:reqpasswd. |
- ba.mkio(baseio, path)
-
Dynamically create an IO interface object by opening a directory or a ZIP file. The path must be relative to the base IO.
-
Example. Opening a ZIP file in the application root directory:
local zio = ba.mkio(ba.openio("app"), "myzip.zip")
Lua libraries
All of the standard Lua libraries are implemented with the two exceptions that
the io library is only supported when the target platform supports
ANSI IO (MAC, Windows, POSIX) and the os library functions are implemented
when it is appropriate on the target platform. os.exit() is not implemented
on any Barracuda platform.
Platform independence is achieved by using the ba library.
For POSIX and Windows platforms the os library has small change to
getenv() functionality and the library is augmented with the following functions:
- os.getenv([string])
-
gets the value of the named environment string. If no environment string is
provided then a table of all environment variables is returned.
- os.putenv(name=value [,value])
- Sets a value in the environment. The
string format may be either name=value or one can use two paramters, the first is
the name and the second is the value.
- os.rmvenv(variable)
- Removes a string from the environment.
- os.fullpath(path)
- returns the full path name of the provided path name.
- os.mkdir(dir)
- creates the named directory.
- os.rmdir(dir)
- removes the named directory.
- os.unlink(file)
- unlinks or removes the named file.
- os.access(path[, mode])
- check the named path. mode may be
any combination of the characters "rwxf". For example, os.access("myfile","r") checks the
file for readability. "f" checks the file for existence, this is the default mode.
- os.getcwd()
- returns the current directory.
- os.files(dir)
- returns an iterator that will iterate over all the files
in the named directory.
The iterator returns each file name in the directory and the full path name of the
directory parameter that was originally passed to os.files().
The following example script will recursively print all files and directories in the named directory.
local diriter
function diriter(dir)
for file, path in os.files(dir) do
local fn = path .. file
print(fn)
local st = os.stat(fn)
if string.sub(file,1,1) ~= '.' and st and st.isdir then
diriter(path .. file)
end
end
end
diriter(arg[1])
- os.stat(path)
- returns a table of attributes for the named path.
The fields in the table are the similar to the POSIX stat() function:
- mtime - last modified time
- ctime - last changed time
- atime - last accessed time
- size - size of the file in bytes
- isdir - true if the file is a directory
- isreg - true if the file is a regular file
- mode - the file mode as a string. e.g. "drwx" or "-rwx". Only public modes are shown.
- _mode - the mode as a decimal number.
- type - the type of the file. Possible values are
"regular", "link", "directory", "character device", "block device", "fifo"
"socket" or "?" when the type of file is unknown.
- name - the full path name of the input path.
- dev - as per POSIX
- nlink - as per POSIX
- gid - as per POSIX
- uid - as per POSIX
- ino - as per POSIX
Barracuda global functions
The following functions are available in the request environment.
Unless otherwise stated all functions will return false, message upon error.
- print(string, ...)
- prints strings in the HTML stream as preformatted text.
Each string is separated by a TAB character.
Also refer to the response:write() method.
print() differs from response:write() in that print calls the Lua tostring() function on each
parameter that is passed to print(). print() is useful for generating diagnostics and
small amounts of text on a web page, use response:write() in preference to print().
example
<?lsp
print("hello", "world")
?>
The above example would emit "hello\tworld\n".
- trace(string, ...)
- writes the string to the web server
trace log.
- rndseed(seed)
- Seeds the rnd() function.
- rnd([ [low ,] high])
-
Generates a random number. If no parameters are given a positive integer between 0 and
0x3ffffff is returned. If one parameter is provided then it represents the upper value of a random
integer between 1 and the upper value and if
two parameters are provided it represents the lower and upper limits of a random integer.
- parselsp(file)
- returns a string of the parsed LSP file. As an example
the following code will parse an input file as LSP and write the parsed (Lua) code
to the provided output file.
#!/usr/local/bin/blua
--
-- script to parse lsp
--
-- to produce stripped binaries use
-- blua parselsp.lua in.lua|luac -s -o out.lua -
--
assert(arg and arg[1], "parselsp infile [outfile]")
assert(parselsp, "paselsp not loaded")
ih=assert(io.open(arg[1],"r"))
s=ih:read"*a"
ih:close()
s=assert(parselsp(s))
if arg[2] then io.output(arg[2]) end
io.write(s)
io.close()
Compiled (binary) script
Barracuda converts LSP pages to Lua source code, this source code may in turn be compiled with the
Lua comiler bluac. Compiled code saves time
when loading large pages (compiled code is smaller) and can save memory by optionally removing
debugging information. Compiled code also means that the
LSP source code is not available.
The standalone Lua script <barracuda>/lua/parselsp.lua can be used to parse the LSP pages
into Lua script that can then be compiled by bluac, The compiled code can then replace the source LSP.
Be careful that you do not overwrite the source LSP with the compiled code.
Compiled code enables the Lua parser to be omitted from builds of Barracuda libraries, making the
implemented code size smaller. Compiled code is portable across platforms with the same integer size
and endianess.
Compile and strip debug information.
blua parselsp.lua mypage.lsp|luac -s -o ../copiledlsp/mypage.lsp -
Compile and keep debug information.
blua parselsp.lua mypage.lsp|luac -o ../copiledlsp/mypage.lsp -
parselsp.lua can also be used to diagnose syntax errors in LSP.
LSP environments and OS threads
Lua has the concept of environments. Environments provide scoping for collections of variables.
A global environment is provided for each LSP page and this environment exists only for the current
invocation of the page(i.e. the request), this is referred to as the "request environment".
Any global variables created in a LSP will be saved in this (temporary) request environment.
The request environment is also the environment of any included or forwarded pages. Hence
variables set in a LSP page will be available to included or forwarded pages.
- request environment
- The request environment maintains the following
variables and objects:
Variables can persist across invocations (different requests) of the page by using one of the following persistent Lua
objects:
- page object
- The page object maintains
variables that are available to the specific page.
Variables created in the page table are maintained for the execution life of the Barracuda server.
The "cachelsp" configuration setting has no impact on page variables.
LSP script can only address the page table of the currently executing LSP page.
LSP responses are executed in one or more operating system threads and these threads may yield
during the execution of a Lua Server Page. This means that other users of a page may
update the page table. For example:
<?lsp
-- Using page variables
print("<pre>");
page.count = (page.count or 0) + 1
print("Access count = ", page.count)
print("</pre>")
?>
This code updates the variable count each time the page is displayed. When there multiple users
of the page, the number may increment by more than one each time you refresh the page. Even more interesting
is if we change the code to the following:
<?lsp
-- Using page variables
print("<pre>");
page.count = (page.count or 0) + 1
print("Access count = ", page.count)
request:sleep(10);
print("Access count = ", page.count)
print("</pre>")
?>
then the two values of the access count may be different when we have multiple users.
- session object
- The session object maintains variables that are available to the
the current session. Session variables are destroyed when the session terminates. As an example,a typical use of
Session variables would be to maintain a users shopping basket:
<?lsp
-- Using session variables
print("<pre>");
local session = request:session()
if not session then -- no session ?
print"you must first login using a valid username and password"
else
-- no basket? - create it
session.basket = session.basket or {}
-- add an item to the basket table
session.basket[#session.basket +1] = "something new"
end
print("We have ", #session.basket, " items in the session table")
print("</pre>")
?>
- Lua Globals
- Lua globals (_G) are common to all pages. Variables set in one page/session
may be retrieved in another page/session.
One possible use of Lua Globals might be to maintain common HTML fragments of HTML or even common
chunks of Lua code.
Global variables may be referenced without the _G prefix, however, to create a Global variable the
_G prefix must be applied.
<?lsp
-- Using Lua Globals
print("<pre>");
_G.count = (_G.count or 0) + 1
print("Global LSP Access count = ", _G.count)
print(_G.stdpageheader)
print(_G.copyright)
-- global functions
_G.myfunction()
print("</pre>")
?>