Barracuda Lua 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:
data The received chunk.
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:

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:
-1Invalid name or name not accepted by IOINTF implementation.A DOS 8.3 file system may return this code for long file names
-2Resource not found.
-3Resource exists and cannot be overwritten.
-4Path (parent directory) not found.
-5No access or resource locked by file system.
-6A directory resource is not empty.
-7No space left on device.
-8Some kind of IO error. The extra error code may contain more information.
-9Memory allocation error when working with resource.
-50Method not implemented.
-100Cannot uncompress the file since no ZLIB implemenation is installed in the server.
-101IoIntf_OpenResGzip is not willing to compress the data. This informs the caller that IoIntf_OpenRes must be used instead.
-102Error in compressed data.
-200Encrypted ZIP file requires AES, but AES is not enabled in ZipIo.c. Recompile with ZIP_ENCRYPTION.
-201Unknown AES encryption or not an AES encrypted ZIP file.
-202File is AES encrypted, but you did not provide a password.
-203Wrong password for AES encrypted file.
-204Password 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.
-205The 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>")
?>