httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From minf...@apache.org
Subject svn commit: r1491468 [1/2] - in /httpd/httpd/branches/2.4.x: ./ docs/manual/mod/ modules/lua/
Date Mon, 10 Jun 2013 14:36:57 GMT
Author: minfrin
Date: Mon Jun 10 14:36:56 2013
New Revision: 1491468

URL: http://svn.apache.org/r1491468
Log:
mod_lua: Fully sync 2.4.x with trunk (catch up to r1490700):

2.4.x patch: http://www.humbedooh.com/mod_lua_2013_06_07.patch
Submitted by: humbedooh
Reviewed by: fuankg, minfrin

Modified:
    httpd/httpd/branches/2.4.x/STATUS
    httpd/httpd/branches/2.4.x/docs/manual/mod/mod_lua.xml
    httpd/httpd/branches/2.4.x/modules/lua/README
    httpd/httpd/branches/2.4.x/modules/lua/config.m4
    httpd/httpd/branches/2.4.x/modules/lua/lua_apr.c
    httpd/httpd/branches/2.4.x/modules/lua/lua_apr.h
    httpd/httpd/branches/2.4.x/modules/lua/lua_config.c
    httpd/httpd/branches/2.4.x/modules/lua/lua_config.h
    httpd/httpd/branches/2.4.x/modules/lua/lua_dbd.c
    httpd/httpd/branches/2.4.x/modules/lua/lua_dbd.h
    httpd/httpd/branches/2.4.x/modules/lua/lua_request.c
    httpd/httpd/branches/2.4.x/modules/lua/lua_request.h
    httpd/httpd/branches/2.4.x/modules/lua/lua_vmprep.c
    httpd/httpd/branches/2.4.x/modules/lua/lua_vmprep.h
    httpd/httpd/branches/2.4.x/modules/lua/mod_lua.c
    httpd/httpd/branches/2.4.x/modules/lua/mod_lua.dsp
    httpd/httpd/branches/2.4.x/modules/lua/mod_lua.h

Modified: httpd/httpd/branches/2.4.x/STATUS
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/STATUS?rev=1491468&r1=1491467&r2=1491468&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/STATUS (original)
+++ httpd/httpd/branches/2.4.x/STATUS Mon Jun 10 14:36:56 2013
@@ -100,10 +100,6 @@ PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
       2.4.x patch: trunk patch works modulo CHANGES and mmn bump
       +1: minfrin, jim, sf
 
-    * mod_lua: Fully sync 2.4.x with trunk (catch up to r1490700):
-      2.4.x patch: http://www.humbedooh.com/mod_lua_2013_06_07.patch
-      +1: humbedooh, fuankg, minfrin
-
 
 PATCHES PROPOSED TO BACKPORT FROM TRUNK:
   [ New proposals should be added at the end of the list ]

Modified: httpd/httpd/branches/2.4.x/docs/manual/mod/mod_lua.xml
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/docs/manual/mod/mod_lua.xml?rev=1491468&r1=1491467&r2=1491468&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/docs/manual/mod/mod_lua.xml (original)
+++ httpd/httpd/branches/2.4.x/docs/manual/mod/mod_lua.xml Mon Jun 10 14:36:56 2013
@@ -47,6 +47,13 @@ Until it is declared stable, usage and b
 at any time, even between stable releases of the 2.4.x series.
 Be sure to check the CHANGES file before upgrading.</note>
 
+<note type="warning"><title>Warning</title>
+<p>This module holds a great deal of power over httpd, which is both a 
+strength and a potential security risk. It is <strong>not</strong> recommended 
+that you use this module on a server that is shared with users you do not 
+trust, as it can be abused to change the internal workings of httpd.</p>
+</note>
+
 </summary>
 
 <section id="basicconf"><title>Basic Configuration</title>
@@ -70,10 +77,10 @@ This will cause <code>mod_lua</code> to 
 ending in <code>.lua</code> by invoking that file's
 <code>handle</code> function.
 </p>
-<!--
+
 <p>For more flexibility, see <directive>LuaMapHandler</directive>.
 </p>
--->
+
 </section>
 
 <section id="writinghandlers"><title>Writing Handlers</title>
@@ -88,7 +95,7 @@ something like this:</p>
 
 
 <highlight language="lua">
-<strong>example.lua</strong>
+<strong>example.lua</strong><br/>
 -- example handler
 
 require "string"
@@ -100,19 +107,27 @@ require "string"
 --]]
 function handle(r)
     r.content_type = "text/plain"
-    r:puts("Hello Lua World!\n")
 
     if r.method == 'GET' then
+        r:puts("Hello Lua World!\n")
         for k, v in pairs( r:parseargs() ) do
             r:puts( string.format("%s: %s\n", k, v) )
         end
     elseif r.method == 'POST' then
+        r:puts("Hello Lua World!\n")
         for k, v in pairs( r:parsebody() ) do
             r:puts( string.format("%s: %s\n", k, v) )
         end
-    else
+    elseif r.method == 'PUT' then
+-- use our own Error contents
         r:puts("Unsupported HTTP method " .. r.method)
+        r.status = 405
+        return apache2.ok
+    else
+-- use the ErrorDocument
+        return 501
     end
+    return apache2.OK
 end
 </highlight>
 
@@ -154,7 +169,7 @@ without authentication, or if the authen
 argument:</p>
 
 <highlight language="lua">
-<strong>authz_provider.lua</strong>
+<strong>authz_provider.lua</strong><br/>
 
 require 'apache2'
 
@@ -186,18 +201,92 @@ LuaAuthzProvider foo authz_provider.lua 
 
 <p>Hook functions are how modules (and Lua scripts) participate in the
 processing of requests. Each type of hook exposed by the server exists for
-a specific purpose, such as mapping requests to the filesystem,
-performing access control, or setting mimetypes.  General purpose hooks
-that simply run at handy times in the request lifecycle exist as well.</p>
+a specific purpose, such as mapping requests to the file system,
+performing access control, or setting mime types:</p>
 
-<p>Hook functions are passed the request object as their only argument.
+<table border="1" style="zebra">
+    <tr>
+        <th>Hook phase</th>
+        <th>mod_lua directive</th>
+        <th>Description</th>
+    </tr>
+    <tr>
+        <td>Quick handler</td>
+        <td><directive module="mod_lua">LuaQuickHandler</directive></td>
+        <td>This is the first hook that will be called after a request has 
+            been mapped to a host or virtual host</td>
+    </tr>
+    <tr>
+        <td>Translate name</td>
+        <td><directive module="mod_lua">LuaHookTranslateName</directive></td>
+        <td>This phase translates the requested URI into a filename on the 
+            system. Modules such as <module>mod_alias</module> and
+            <module>mod_rewrite</module> operate in this phase.</td>
+    </tr>
+    <tr>
+        <td>Map to storage</td>
+        <td><directive module="mod_lua">LuaHookMapToStorage</directive></td>
+        <td>This phase maps files to their physical, cached or external/proxied storage. 
+            It can be used by proxy or caching modules</td>
+    </tr>
+    <tr>
+        <td>Check Access</td>
+        <td><directive module="mod_lua">LuaHookAccessChecker</directive></td>
+        <td>This phase checks whether a client has access to a resource. This 
+            phase is run before the user is authenticated, so beware.
+        </td>
+    </tr>
+    <tr>
+        <td>Check User ID</td>
+        <td><directive module="mod_lua">LuaHookCheckUserID</directive></td>
+        <td>This phase it used to check the negotiated user ID</td>
+    </tr>
+    <tr>
+        <td>Check Authorization</td>
+        <td><directive module="mod_lua">LuaHookAuthChecker</directive> or 
+            <directive module="mod_lua">LuaAuthzProvider</directive></td>
+        <td>This phase authorizes a user based on the negotiated credentials, such as 
+            user ID, client certificate etc.
+        </td>
+    </tr>
+    <tr>
+        <td>Check Type</td>
+        <td><directive module="mod_lua">LuaHookTypeChecker</directive></td>
+        <td>This phase checks the requested file and assigns a content type and 
+            a handler to it</td>
+    </tr>
+    <tr>
+        <td>Fixups</td>
+        <td><directive module="mod_lua">LuaHookFixups</directive></td>
+        <td>This is the final "fix anything" phase before the content handlers 
+            are run. Any last-minute changes to the request should be made here.</td>
+    </tr>
+    <tr>
+        <td>Content handler</td>
+        <td>fx. <code>.lua</code> files or through <directive module="mod_lua">LuaMapHandler</directive></td>
+        <td>This is where the content is handled. Files are read, parsed, some are run, 
+            and the result is sent to the client</td>
+    </tr>
+    <tr>
+        <td>Logging</td>
+        <td>(none)</td>
+        <td>Once a request has been handled, it enters several logging phases, 
+            which logs the request in either the error or access log</td>
+    </tr>
+
+</table>
+
+<p>Hook functions are passed the request object as their only argument 
+(except for LuaAuthzProvider, which also gets passed the arguments from 
+the Require directive).
 They can return any value, depending on the hook, but most commonly
-they'll return OK, DONE, or DECLINED, which you can write in lua as
+they'll return OK, DONE, or DECLINED, which you can write in Lua as
 <code>apache2.OK</code>, <code>apache2.DONE</code>, or
 <code>apache2.DECLINED</code>, or else an HTTP status code.</p>
 
+
 <highlight language="lua">
-<strong>translate_name.lua</strong>
+<strong>translate_name.lua</strong><br/>
 -- example hook that rewrites the URI to a filesystem path.
 
 require 'apache2'
@@ -212,15 +301,16 @@ function translate_name(r)
 end
 </highlight>
 
+
 <highlight language="lua">
-<strong>translate_name2.lua</strong>
+<strong>translate_name2.lua</strong><br/>
 --[[ example hook that rewrites one URI to another URI. It returns a
      apache2.DECLINED to give other URL mappers a chance to work on the
      substitution, including the core translate_name hook which maps based
      on the DocumentRoot.
 
-     Note: It is currently undefined as to whether this runs before or after
-     mod_alias.
+     Note: Use the early/late flags in the directive to make it run before
+           or after mod_alias.
 --]]
 
 require 'apache2'
@@ -242,175 +332,326 @@ end
         <dd>
         <p>The request_rec is mapped in as a userdata. It has a metatable
         which lets you do useful things with it. For the most part it
-        has the same fields as the request_rec struct (see httpd.h
-        until we get better docs here) many of which are writeable as
+        has the same fields as the request_rec struct, many of which are writable as
         well as readable.  (The table fields' content can be changed, but the
         fields themselves cannot be set to different tables.)</p>
 
-        <table border="1">
+        <table border="1" style="zebra">
 
         <tr>
           <th><strong>Name</strong></th>
           <th><strong>Lua type</strong></th>
           <th><strong>Writable</strong></th>
+          <th><strong>Description</strong></th>
+        </tr>
+        <tr>
+          <td><code>allowoverrides</code></td>
+          <td>string</td>
+          <td>no</td>
+          <td>The AllowOverride options applied to the current request.</td>
         </tr>
         <tr>
           <td><code>ap_auth_type</code></td>
           <td>string</td>
           <td>no</td>
+          <td>If an authentication check was made, this is set to the type 
+          of authentication (f.x. <code>basic</code>)</td>
         </tr>
         <tr>
           <td><code>args</code></td>
           <td>string</td>
           <td>yes</td>
+          <td>The query string arguments extracted from the request 
+            (f.x. <code>foo=bar&amp;name=johnsmith</code>)</td>
         </tr>
         <tr>
           <td><code>assbackwards</code></td>
           <td>boolean</td>
           <td>no</td>
+          <td>Set to true if this is an HTTP/0.9 style request 
+            (e.g. <code>GET /foo</code> (with no headers) )</td>
+        </tr>
+        <tr>
+          <td><code>auth_name</code></td>
+          <td>string</td>
+          <td>no</td>
+          <td>The realm name used for authorization (if applicable).</td>
+        </tr>
+        <tr>
+          <td><code>banner</code></td>
+          <td>string</td>
+          <td>no</td>
+          <td>The server banner, f.x. <code>Apache HTTP Server/2.4.3 openssl/0.9.8c</code></td>
+        </tr>
+        <tr>
+          <td><code>basic_auth_pw</code></td>
+          <td>string</td>
+          <td>no</td>
+          <td>The basic auth password sent with this request, if any</td>
         </tr>
-
         <tr>
           <td><code>canonical_filename</code></td>
           <td>string</td>
           <td>no</td>
+          <td>The canonical filename of the request</td>
         </tr>
         <tr>
           <td><code>content_encoding</code></td>
           <td>string</td>
           <td>no</td>
+          <td>The content encoding of the current request</td>
         </tr>
         <tr>
           <td><code>content_type</code></td>
           <td>string</td>
           <td>yes</td>
+          <td>The content type of the current request, as determined in the 
+            type_check phase (f.x. <code>image/gif</code> or <code>text/html</code>)</td>
         </tr>
         <tr>
           <td><code>context_prefix</code></td>
           <td>string</td>
           <td>no</td>
+          <td></td>
         </tr>
         <tr>
           <td><code>context_document_root</code></td>
           <td>string</td>
           <td>no</td>
+          <td></td>
         </tr>
 
         <tr>
           <td><code>document_root</code></td>
           <td>string</td>
           <td>no</td>
+          <td>The document root of the host</td>
         </tr>
         <tr>
           <td><code>err_headers_out</code></td>
           <td>table</td>
           <td>no</td>
+          <td>MIME header environment for the response, printed even on errors and
+            persist across internal redirects</td>
         </tr>
         <tr>
           <td><code>filename</code></td>
           <td>string</td>
           <td>yes</td>
+          <td>The file name that the request maps to, f.x. /www/example.com/foo.txt. This can be 
+            changed in the translate-name or map-to-storage phases of a request to allow the 
+            default handler (or script handlers) to serve a different file than what was requested.</td>
         </tr>
         <tr>
           <td><code>handler</code></td>
           <td>string</td>
           <td>yes</td>
+          <td>The name of the <a href="../handler.html">handler</a> that should serve this request, f.x. 
+            <code>lua-script</code> if it is to be served by mod_lua. This is typically set by the 
+            <directive module="mod_mime">AddHandler</directive> or <directive module="core">SetHandler</directive> 
+            directives, but could also be set via mod_lua to allow another handler to serve up a specific request 
+            that would otherwise not be served by it.
+            </td>
         </tr>
 
         <tr>
           <td><code>headers_in</code></td>
           <td>table</td>
           <td>yes</td>
+          <td>MIME header environment from the request. This contains headers such as <code>Host, 
+            User-Agent, Referer</code> and so on.</td>
         </tr>
         <tr>
           <td><code>headers_out</code></td>
           <td>table</td>
           <td>yes</td>
+          <td>MIME header environment for the response.</td>
         </tr>
         <tr>
           <td><code>hostname</code></td>
           <td>string</td>
           <td>no</td>
+          <td>The host name, as set by the <code>Host:</code> header or by a full URI.</td>
+        </tr>
+        <tr>
+          <td><code>is_https</code></td>
+          <td>boolean</td>
+          <td>no</td>
+          <td>Whether or not this request is done via HTTPS</td>
+        </tr>
+        <tr>
+          <td><code>is_initial_req</code></td>
+          <td>boolean</td>
+          <td>no</td>
+          <td>Whether this request is the initial request or a sub-request</td>
+        </tr>
+        <tr>
+          <td><code>limit_req_body</code></td>
+          <td>number</td>
+          <td>no</td>
+          <td>The size limit of the request body for this request, or 0 if no limit.</td>
         </tr>
         <tr>
           <td><code>log_id</code></td>
           <td>string</td>
           <td>no</td>
+          <td>The ID to identify request in access and error log.</td>
         </tr>
         <tr>
           <td><code>method</code></td>
           <td>string</td>
           <td>no</td>
+          <td>The request method, f.x. <code>GET</code> or <code>POST</code>.</td>
         </tr>
         <tr>
           <td><code>notes</code></td>
           <td>table</td>
           <td>yes</td>
+          <td>A list of notes that can be passed on from one module to another.</td>
+        </tr>
+        <tr>
+          <td><code>options</code></td>
+          <td>string</td>
+          <td>no</td>
+          <td>The Options directive applied to the current request.</td>
         </tr>
         <tr>
           <td><code>path_info</code></td>
           <td>string</td>
           <td>no</td>
+          <td>The PATH_INFO extracted from this request.</td>
+        </tr>
+        <tr>
+          <td><code>port</code></td>
+          <td>number</td>
+          <td>no</td>
+          <td>The server port used by the request.</td>
         </tr>
         <tr>
           <td><code>protocol</code></td>
           <td>string</td>
           <td>no</td>
+          <td>The protocol used, f.x. <code>HTTP/1.1</code></td>
         </tr>
         <tr>
           <td><code>proxyreq</code></td>
           <td>string</td>
           <td>yes</td>
+          <td>Denotes whether this is a proxy request or not. This value is generally set in 
+            the post_read_request/translate_name phase of a request.</td>
         </tr>
         <tr>
           <td><code>range</code></td>
           <td>string</td>
           <td>no</td>
+          <td>The contents of the <code>Range:</code> header.</td>
+        </tr>
+        <tr>
+          <td><code>remaining</code></td>
+          <td>number</td>
+          <td>no</td>
+          <td>The number of bytes remaining to be read from the request body.</td>
+        </tr>
+        <tr>
+          <td><code>server_built</code></td>
+          <td>string</td>
+          <td>no</td>
+          <td>The time the server executable was built.</td>
+        </tr>
+        <tr>
+          <td><code>server_name</code></td>
+          <td>string</td>
+          <td>no</td>
+          <td>The server name for this request.</td>
+        </tr>
+        <tr>
+          <td><code>some_auth_required</code></td>
+          <td>boolean</td>
+          <td>no</td>
+          <td>Whether some authorization is/was required for this request.</td>
         </tr>
         <tr>
           <td><code>subprocess_env</code></td>
           <td>table</td>
           <td>yes</td>
+          <td>The environment variables set for this request.</td>
+        </tr>
+        <tr>
+          <td><code>started</code></td>
+          <td>number</td>
+          <td>no</td>
+          <td>The time the server was (re)started, in seconds since the epoch (Jan 1st, 1970)</td>
         </tr>
         <tr>
           <td><code>status</code></td>
           <td>number</td>
           <td>yes</td>
+          <td>The (current) HTTP return code for this request, f.x. <code>200</code> or <code>404</code>.</td>
         </tr>
         <tr>
           <td><code>the_request</code></td>
           <td>string</td>
           <td>no</td>
+          <td>The request string as sent by the client, f.x. <code>GET /foo/bar HTTP/1.1</code>.</td>
         </tr>
         <tr>
           <td><code>unparsed_uri</code></td>
           <td>string</td>
           <td>no</td>
+          <td>The unparsed URI of the request</td>
         </tr>
         <tr>
           <td><code>uri</code></td>
           <td>string</td>
           <td>yes</td>
+          <td>The URI after it has been parsed by httpd</td>
         </tr>
         <tr>
           <td><code>user</code></td>
           <td>string</td>
           <td>yes</td>
+          <td>If an authentication check has been made, this is set to the name of the authenticated user.</td>
         </tr>
         <tr>
           <td><code>useragent_ip</code></td>
           <td>string</td>
           <td>no</td>
+          <td>The IP of the user agent making the request</td>
         </tr>
         </table>
+           </dd>
+    </dl>
+</section>
+<section id="functions"><title>Built in functions</title>
+
+<p>The request_rec object has (at least) the following methods:</p>
+
+<highlight language="lua">
+r:flush()   -- flushes the output buffer.
+            -- Returns true if the flush was successful, false otherwise.
+
+while we_have_stuff_to_send do
+    r:puts("Bla bla bla\n") -- print something to client
+    r:flush() -- flush the buffer (send to client)
+    r:sleep(0.5) -- fake processing time and repeat
+end
+</highlight>
+
+<highlight language="lua">
+r:addoutputfilter(name|function) -- add an output filter:
+
+r:addoutputfilter("fooFilter") -- add the fooFilter to the output stream
+</highlight>
 
-        <p>The request_rec has (at least) the following methods:</p>
+<highlight language="lua">
+r:sendfile(filename) -- sends an entire file to the client, using sendfile if supported by the current platform:
 
-        <highlight language="lua">
-        r:addoutputfilter(name|function) -- add an output filter
-        </highlight>
+if use_sendfile_thing then
+    r:sendfile("/var/www/large_file.img")
+end
+</highlight>
 
-        <highlight language="lua">
+<highlight language="lua">
 r:parseargs() -- returns two tables; one standard key/value table for regular GET data, 
               -- and one for multi-value data (fx. foo=1&amp;foo=2&amp;foo=3):
 
@@ -427,20 +668,256 @@ r:parsebody([sizeLimit]) -- parse the re
 local POST, POSTMULTI = r:parsebody(1024*1024)
 r:puts("Your name is: " .. POST['name'] or "Unknown")
 </highlight>
-        <highlight language="lua">
-        r:puts("hello", " world", "!") -- print to response body
-        </highlight>
-
-        <highlight language="lua">
-        r:write("a single string") -- print to response body
-        </highlight>
-        
-        <highlight language="lua">
+
+<highlight language="lua">
+r:puts("hello", " world", "!") -- print to response body, self explanatory
+</highlight>
+
+<highlight language="lua">
+r:write("a single string") -- print to response body, self explanatory
+</highlight>
+
+<highlight language="lua">
+r:escape_html("&lt;html&gt;test&lt;/html&gt;") -- Escapes HTML code and returns the escaped result
+</highlight>
+
+<highlight language="lua">
+r:base64_encode(string) -- Encodes a string using the Base64 encoding standard:
+
+local encoded = r:base64_encode("This is a test") -- returns VGhpcyBpcyBhIHRlc3Q=
+</highlight>
+
+<highlight language="lua">
+r:base64_decode(string) -- Decodes a Base64-encoded string:
+
+local decoded = r:base64_decode("VGhpcyBpcyBhIHRlc3Q=") -- returns 'This is a test'
+</highlight>
+
+<highlight language="lua">
+r:md5(string) -- Calculates and returns the MD5 digest of a string (binary safe):
+
+local hash = r:md5("This is a test") -- returns ce114e4501d2f4e2dcea3e17b546f339
+</highlight>
+
+<highlight language="lua">
+r:sha1(string) -- Calculates and returns the SHA1 digest of a string (binary safe):
+
+local hash = r:sha1("This is a test") -- returns a54d88e06612d820bc3be72877c74f257b561b19
+</highlight>
+
+<highlight language="lua">
+r:escape(string) -- URL-Escapes a string:
+
+local url = "http://foo.bar/1 2 3 &amp; 4 + 5"
+local escaped = r:escape(url) -- returns 'http%3a%2f%2ffoo.bar%2f1+2+3+%26+4+%2b+5'
+</highlight>
+
+<highlight language="lua">
+r:unescape(string) -- Unescapes an URL-escaped string:
+
+local url = "http%3a%2f%2ffoo.bar%2f1+2+3+%26+4+%2b+5"
+local unescaped = r:escape(url) -- returns 'http://foo.bar/1 2 3 &amp; 4 + 5'
+</highlight>
+
+<highlight language="lua">
+r:mpm_query(number) -- Queries the server for MPM information using ap_mpm_query:
+
+local mpm = r.mpm_query(14)
+if mpm == 1 then
+    r:puts("This server uses the Event MPM")
+end
+</highlight>
+
+<highlight language="lua">
+r:expr(string) -- Evaluates an <a href="../expr.html">expr</a> string.
+
+if r:expr("%{HTTP_HOST} =~ /^www/") then
+    r:puts("This host name starts with www")
+end
+</highlight>
+
+<highlight language="lua">
+r:scoreboard_process(a) -- Queries the server for information about the process at position <code>a</code>:
+
+local process = r:scoreboard_process(1)
+r:puts("Server 1 has PID " .. process.pid)
+</highlight>
+
+<highlight language="lua">
+r:scoreboard_worker(a, b) -- Queries for information about the worker thread, <code>b</code>, in process <code>a</code>:
+
+local thread = r:scoreboard_worker(1, 1)
+r:puts("Server 1's thread 1 has thread ID " .. thread.tid .. " and is in " .. thread.status .. " status")
+</highlight>
+
+
+<highlight language="lua">
+r:clock() -- Returns the current time with microsecond precision
+</highlight>
+
+<highlight language="lua">
+r:requestbody(filename) -- Reads and returns the request body of a request.
+                -- If 'filename' is specified, it instead saves the
+                -- contents to that file:
+                
+local input = r:requestbody()
+r:puts("You sent the following request body to me:\n")
+r:puts(input)
+</highlight>
+
+<highlight language="lua">
+r:add_input_filter(filter_name) -- Adds 'filter_name' as an input filter
+</highlight>
+
+<highlight language="lua">
+r.module_info(module_name) -- Queries the server for information about a module
+
+local mod = r.module_info("mod_lua.c")
+if mod then
+    for k, v in pairs(mod.commands) do
+       r:puts( ("%s: %s\n"):format(k,v)) -- print out all directives accepted by this module
+    end
+end
+</highlight>
+
+<highlight language="lua">
+r:loaded_modules() -- Returns a list of modules loaded by httpd:
+
+for k, module in pairs(r:loaded_modules()) do
+    r:puts("I have loaded module " .. module .. "\n")
+end
+</highlight>
+
+<highlight language="lua">
+r:runtime_dir_relative(filename) -- Compute the name of a run-time file (e.g., shared memory "file") 
+                         -- relative to the appropriate run-time directory. 
+</highlight>
+
+<highlight language="lua">
+r:server_info() -- Returns a table containing server information, such as 
+                -- the name of the httpd executable file, mpm used etc.
+</highlight>
+
+<highlight language="lua">
+r:set_document_root(file_path) -- Sets the document root for the request to file_path
+</highlight>
+
+<!--
+<highlight language="lua">
+r:add_version_component(component_string) - - Adds a component to the server banner.
+</highlight>
+-->
+
+<highlight language="lua">
+r:set_context_info(prefix, docroot) -- Sets the context prefix and context document root for a request
+</highlight>
+
+<highlight language="lua">
+r:os_escape_path(file_path) -- Converts an OS path to a URL in an OS dependent way
+</highlight>
+
+<highlight language="lua">
+r:escape_logitem(string) -- Escapes a string for logging
+</highlight>
+
+<highlight language="lua">
+r.strcmp_match(string, pattern) -- Checks if 'string' matches 'pattern' using strcmp_match (globs).
+                        -- fx. whether 'www.example.com' matches '*.example.com':
+                        
+local match = r.strcmp_match("foobar.com", "foo*.com")
+if match then 
+    r:puts("foobar.com matches foo*.com")
+end
+</highlight>
+
+<highlight language="lua">
+r:set_keepalive() -- Sets the keepalive status for a request. Returns true if possible, false otherwise.
+</highlight>
+
+<highlight language="lua">
+r:make_etag() -- Constructs and returns the etag for the current request.
+</highlight>
+
+<highlight language="lua">
+r:send_interim_response(clear) -- Sends an interim (1xx) response to the client.
+                       -- if 'clear' is true, available headers will be sent and cleared.
+</highlight>
+
+<highlight language="lua">
+r:custom_response(status_code, string) -- Construct and set a custom response for a given status code.
+                               -- This works much like the ErrorDocument directive:
+                               
+r:custom_response(404, "Baleted!")
+</highlight>
+
+<highlight language="lua">
+r.exists_config_define(string) -- Checks whether a configuration definition exists or not:
+
+if r.exists_config_define("FOO") then
+    r:puts("httpd was probably run with -DFOO, or it was defined in the configuration")
+end
+</highlight>
+
+<highlight language="lua">
+r:state_query(string) -- Queries the server for state information
+</highlight>
+
+<highlight language="lua">
+r:stat(filename) -- Runs stat() on a file, and returns a table with file information:
+
+local info = r:stat("/var/www/foo.txt")
+if info then
+    r:puts("This file exists and was last modified at: " .. info.modified)
+end
+</highlight>
+
+<highlight language="lua">
+r:regex(string, pattern, [flags]) -- Runs a regular expression match on a string, returning captures if matched:
+
+local matches = r:regex("foo bar baz", [[foo (\w+) (\S*)]])
+if matches then
+    r:puts("The regex matched, and the last word captured ($2) was: " .. matches[2])
+end
+
+-- Example ignoring case sensitivity:
+local matches = r:regex("FOO bar BAz", [[(foo) bar]], 1)
+
+-- Flags can be a bitwise combination of:
+-- 0x01: Ignore case
+-- 0x02: Multiline search
+</highlight>
+
+<highlight language="lua">
+r:sleep(number_of_seconds) -- Puts the script to sleep for a given number of seconds.
+                   -- This can be a floating point number like 1.25 for extra accuracy.
+</highlight>
+
+<highlight language="lua">
 r:dbacquire(dbType[, dbParams]) -- Acquires a connection to a database and returns a database class.
-                                -- See '<a href="#databases">Database connectivity</a>' for details.
-        </highlight>
-        </dd>
-    </dl>
+                        -- See '<a href="#databases">Database connectivity</a>' for details.
+</highlight>
+
+<highlight language="lua">
+r:ivm_set("key", value) -- Set an Inter-VM variable to hold a specific value.
+                        -- These values persist even though the VM is gone or not being used,
+                        -- and so should only be used if MaxConnectionsPerChild is > 0
+                        -- Values can be numbers, strings and booleans, and are stored on a 
+                        -- per process basis (so they won't do much good with a prefork mpm)
+                        
+r:ivm_get("key")        -- Fetches a variable set by ivm_set. Returns the contents of the variable
+                        -- if it exists or nil if no such variable exists.
+                        
+-- An example getter/setter that saves a global variable outside the VM:
+function handle(r)
+    -- First VM to call this will get no value, and will have to create it
+    local foo = r:ivm_get("cached_data")
+    if not foo then
+        foo = do_some_calcs() -- fake some return value
+        r:ivm_set("cached_data", foo) -- set it globally
+    end
+    r:puts("Cached data is: ", foo)
+end
+</highlight>
 
 </section>
 
@@ -478,10 +955,53 @@ r:dbacquire(dbType[, dbParams]) -- Acqui
   <dd>HTTP status code</dd>
   <dt>apache2.PROXYREQ_NONE, apache2.PROXYREQ_PROXY, apache2.PROXYREQ_REVERSE, apache2.PROXYREQ_RESPONSE</dt>
   <dd>internal constants used by <module>mod_proxy</module></dd>
+  <dt>apache2.AUTHZ_DENIED, apache2.AUTHZ_GRANTED, apache2.AUTHZ_NEUTRAL, apache2.AUTHZ_GENERAL_ERROR, apache2.AUTHZ_DENIED_NO_USER</dt>
+  <dd>internal constants used by <module>mod_authz_core</module></dd>
+
 </dl>
 <p>(Other HTTP status codes are not yet implemented.)</p>
 </section>
 
+<section id="modifying_buckets">
+    <title>Modifying contents with Lua filters</title>
+    <p>
+    Filter functions implemented via <directive module="mod_lua">LuaInputFilter</directive> 
+    or <directive module="mod_lua">LuaOutputFilter</directive> are designed as 
+    three-stage non-blocking functions using coroutines to suspend and resume a 
+    function as buckets are sent down the filter chain. The core structure of 
+    such a function is:
+    </p>
+    <highlight language="lua">
+function filter(r)
+    -- Our first yield is to signal that we are ready to receive buckets.
+    -- Before this yield, we can set up our environment, check for conditions,
+    -- and, if we deem it necessary, decline filtering a request alltogether:
+    if something_bad then
+        return -- This would skip this filter.
+    end
+    -- Regardless of whether we have data to prepend, a yield MUST be called here.
+    -- Note that only output filters can prepend data. Input filters must use the 
+    -- final stage to append data to the content.
+    coroutine.yield([optional header to be prepended to the content])
+    
+    -- After we have yielded, buckets will be sent to us, one by one, and we can 
+    -- do whatever we want with them and then pass on the result.
+    -- Buckets are stored in the global variable 'bucket', so we create a loop
+    -- that checks if 'bucket' is not nil:
+    while bucket ~= nil do
+        local output = mangle(bucket) -- Do some stuff to the content
+        coroutine.yield(output) -- Return our new content to the filter chain
+    end
+
+    -- Once the buckets are gone, 'bucket' is set to nil, which will exit the 
+    -- loop and land us here. Anything extra we want to append to the content
+    -- can be done by doing a final yield here. Both input and output filters 
+    -- can append data to the content in this phase.
+    coroutine.yield([optional footer to be appended to the content])
+end
+    </highlight>
+</section>
+
 <section id="databases">
     <title>Database connectivity</title>
     <p>
@@ -489,11 +1009,13 @@ r:dbacquire(dbType[, dbParams]) -- Acqui
     on the most popular database engines (mySQL, PostgreSQL, FreeTDS, ODBC, SQLite, Oracle)
     as well as mod_dbd.
     </p>
-    <p>Connecting and firing off queries is as easy as:</p>
+    <p>The example below shows how to acquire a database handle and return information from a table:</p>
     <highlight language="lua">
-function handler(r)
-    local database, err = r:dbacquire("mysql", "server=localhost&amp;user=root&amp;database=mydb")
+function handle(r)
+    -- Acquire a database handle
+    local database, err = r:dbacquire("mysql", "server=localhost,user=root,dbname=mydb")
     if not err then
+        -- Select some information from it
         local results, err = database:select(r, "SELECT `name`, `age` FROM `people` WHERE 1")
         if not err then
             local rows = results(0) -- fetch all rows synchronously
@@ -510,7 +1032,7 @@ function handler(r)
 end
     </highlight>
     <p>
-    To utilize <module>mod_dbd</module>, simply specify <code>mod_dbd</code>
+    To utilize <module>mod_dbd</module>, specify <code>mod_dbd</code>
     as the database type, or leave the field blank:
     </p>
     <highlight language="lua">
@@ -532,7 +1054,7 @@ local result, errmsg = database:select(r
 -- Create and run a prepared statement:
 local statement, errmsg = database:prepare(r, "DELETE FROM `tbl` WHERE `age` > %u")
 if not errmsg then
-    local result, errmsg = statement:query(20) -- run the statement with age >20
+    local result, errmsg = statement:query(20) -- run the statement with age &gt; 20
 end
 
 -- Fetch a prepared statement from a DBDPrepareSQL directive:
@@ -662,7 +1184,7 @@ collectgarbage() -- close the handle via
 <directivesynopsis>
 <name>LuaScope</name>
 <description>One of once, request, conn, thread -- default is once</description>
-<syntax>LuaScope once|request|conn|thread</syntax>
+<syntax>LuaScope once|request|conn|thread|server [min] [max]</syntax>
 <default>LuaScope once</default>
 <contextlist><context>server config</context><context>virtual host</context>
 <context>directory</context><context>.htaccess</context>
@@ -670,7 +1192,7 @@ collectgarbage() -- close the handle via
 <override>All</override>
 
 <usage>
-    <p>Specify the lifecycle scope of the Lua interpreter which will
+    <p>Specify the life cycle scope of the Lua interpreter which will
     be used by handlers in this "Directory." The default is "once"</p>
 
    <dl>
@@ -681,22 +1203,33 @@ collectgarbage() -- close the handle via
              request scoped.</dd>
 
     <dt>conn:</dt> <dd>Same as request but attached to the connection_rec</dd>
+
     <dt>thread:</dt> <dd>Use the interpreter for the lifetime of the thread 
             handling the request (only available with threaded MPMs).</dd>
-<!-- not implemented
+
     <dt>server:</dt>  <dd>This one is different than others because the
             server scope is quite long lived, and multiple threads
-            will have the same server_rec. To accommodate this
-            server scoped interpreter are stored in an apr
-            resource list. The min and max arguments are intended
-            to specify the pool size, but are unused at this time.</dd>
--->
+            will have the same server_rec. To accommodate this,
+            server scoped Lua states are stored in an apr
+            resource list. The <code>min</code> and <code>max</code> arguments 
+            specify the minimum and maximum number of Lua states to keep in the 
+            pool.</dd>
    </dl>
+    <p>
+    Generally speaking, the <code>thread</code> and <code>server</code> scopes 
+    execute roughly 2-3 times faster than the rest, because they don't have to 
+    spawn new Lua states on every request (especially with the event MPM, as 
+    even keepalive requests will use a new thread for each request). If you are 
+    satisfied that your scripts will not have problems reusing a state, then 
+    the <code>thread</code> or <code>server</code> scopes should be used for 
+    maximum performance. While the <code>thread</code> scope will provide the 
+    fastest responses, the <code>server</code> scope will use less memory, as 
+    states are pooled, allowing f.x. 1000 threads to share only 100 Lua states, 
+    thus using only 10% of the memory required by the <code>thread</code> scope.
+    </p>
 </usage>
 </directivesynopsis>
 
-<!--
-/* Not implemented in 2.4.x yet */
 <directivesynopsis>
 <name>LuaMapHandler</name>
 <description>Map a path to a lua handler</description>
@@ -709,8 +1242,8 @@ collectgarbage() -- close the handle via
     <p>This directive matches a uri pattern to invoke a specific
     handler function in a specific file. It uses PCRE regular
     expressions to match the uri, and supports interpolating
-    match groups into both the file path and the function name
-    be careful writing your regular expressions to avoid security
+    match groups into both the file path and the function name. 
+    Be careful writing your regular expressions to avoid security
     issues.</p>
    <example><title>Examples:</title>
    <highlight language="config">
@@ -730,7 +1263,6 @@ collectgarbage() -- close the handle via
         provided.</p>
 </usage>
 </directivesynopsis>
--->
 
 <directivesynopsis>
 <name>LuaPackagePath</name>
@@ -770,13 +1302,13 @@ LuaPackagePath /scripts/lib/?/init.lua
 </usage>
 </directivesynopsis>
 
-<!-- Not implemented yet
 <directivesynopsis>
 <name>LuaCodeCache</name>
 <description>Configure the compiled code cache.</description>
 <syntax>LuaCodeCache stat|forever|never</syntax>
 <default>LuaCodeCache stat</default>
-<contextlist><context>server config</context><context>virtual host</context>
+<contextlist>
+<context>server config</context><context>virtual host</context>
 <context>directory</context><context>.htaccess</context>
 </contextlist>
 <override>All</override>
@@ -803,7 +1335,6 @@ LuaCodeCache never
 
 </usage>
 </directivesynopsis>
--->
 
 <directivesynopsis>
 <name>LuaHookTranslateName</name>
@@ -861,7 +1392,7 @@ end
 
 <directivesynopsis>
 <name>LuaHookFixups</name>
-<description>Provide a hook for the fixups phase of request
+<description>Provide a hook for the fixups phase of a request
 processing</description>
 <syntax>LuaHookFixups  /path/to/lua/script.lua hook_function_name</syntax>
 <contextlist><context>server config</context><context>virtual host</context>
@@ -883,7 +1414,46 @@ processing</description>
 <context>directory</context><context>.htaccess</context>
 </contextlist>
 <override>All</override>
-    <usage><p>...</p></usage>
+    <usage>
+    <p>Like <directive>LuaHookTranslateName</directive> but executed at the 
+    map-to-storage phase of a request. Modules like mod_cache run at this phase,
+    which makes for an interesting example on what to do here:</p>
+    <highlight language="config">
+    LuaHookMapToStorage /path/to/lua/script.lua check_cache
+    </highlight>
+    <highlight language="lua">
+require"apache2"
+cached_files = {}
+
+function read_file(filename) 
+    local input = io.open(filename, "r")
+    if input then
+        local data = input:read("*a")
+        cached_files[filename] = data
+        file = cached_files[filename]
+        input:close()
+    end
+    return cached_files[filename]
+end
+
+function check_cache(r)
+    if r.filename:match("%.png$") then -- Only match PNG files
+        local file = cached_files[r.filename] -- Check cache entries
+        if not file then
+            file = read_file(r.filename)  -- Read file into cache
+        end
+        if file then -- If file exists, write it out
+            r.status = 200
+            r:write(file)
+            r:info(("Sent %s to client from cache"):format(r.filename))
+            return apache2.DONE -- skip default handler for PNG files
+        end
+    end
+    return apache2.DECLINED -- If we had nothing to do, let others serve this.
+end
+    </highlight>
+
+    </usage>
 </directivesynopsis>
 
 <directivesynopsis>
@@ -909,7 +1479,27 @@ processing</description>
 <context>directory</context><context>.htaccess</context>
 </contextlist>
 <override>All</override>
-    <usage><p>...</p></usage>
+    <usage><p>
+    This directive provides a hook for the type_checker phase of the request processing. 
+    This phase is where requests are assigned a content type and a handler, and thus can 
+    be used to modify the type and handler based on input:
+    </p>
+    <highlight language="config">
+    LuaHookTypeChecker /path/to/lua/script.lua type_checker
+    </highlight>
+    <highlight language="lua">
+    function type_checker(r)
+        if r.uri:match("%.to_gif$") then -- match foo.png.to_gif
+            r.content_type = "image/gif" -- assign it the image/gif type
+            r.handler = "gifWizard"      -- tell the gifWizard module to handle this
+            r.filename = r.uri:gsub("%.to_gif$", "") -- fix the filename requested
+            return apache2.OK
+        end
+
+        return apache2.DECLINED
+    end
+    </highlight>
+</usage>
 </directivesynopsis>
 
 <directivesynopsis>
@@ -1018,7 +1608,16 @@ hook function usually returns OK, DECLIN
 <contextlist><context>server config</context><context>virtual host</context>
 </contextlist>
 <override>All</override>
-<usage><p>...</p>
+<usage>
+    <p>
+    This phase is run immediately after the request has been mapped to a virtal host, 
+    and can be used to either do some request processing before the other phases kick 
+    in, or to serve a request without the need to translate, map to storage et cetera. 
+    As this phase is run before anything else, directives such as <directive
+   type="section" module="core">Location</directive> or <directive
+   type="section" module="core">Directory</directive> are void in this phase, just as 
+    URIs have not been properly parsed yet.
+    </p>
    <note><title>Context</title><p>This directive is not valid in <directive
    type="section" module="core">Directory</directive>, <directive
    type="section" module="core">Files</directive>, or htaccess
@@ -1038,18 +1637,140 @@ hook function usually returns OK, DECLIN
 <p>After a lua function has been registered as authorization provider, it can be used
 with the <directive module="mod_authz_core">Require</directive> directive:</p>
 
-<example>
 <highlight language="config">
 LuaRoot /usr/local/apache2/lua
 LuaAuthzProvider foo authz.lua authz_check_foo
 &lt;Location /&gt;
-  Require foo bar
+  Require foo johndoe
 &lt;/Location&gt;
 </highlight>
-</example>
+<highlight language="lua">
+require "apache2"
+function authz_check_foo(r, who)
+    if r.user ~= who then return apache2.AUTHZ_DENIED
+    return apache2.AUTHZ_GRANTED
+end
+</highlight>
+
+
+</usage>
+</directivesynopsis>
+
+
+<directivesynopsis>
+<name>LuaInputFilter</name>
+<description>Provide a Lua function for content input filtering</description>
+<syntax>LuaInputFilter filter_name /path/to/lua/script.lua function_name</syntax>
+<contextlist><context>server config</context> </contextlist>
+<compatibility>2.5.0 and later</compatibility>
+
+<usage>
+<p>Provides a means of adding a Lua function as an input filter. 
+As with output filters, input filters work as coroutines, 
+first yielding before buffers are sent, then yielding whenever 
+a bucket needs to be passed down the chain, and finally (optionally) 
+yielding anything that needs to be appended to the input data. The 
+global variable <code>bucket</code> holds the buckets as they are passed 
+onto the Lua script:
+</p>
+
+<highlight language="config">
+LuaInputFilter myInputFilter /www/filter.lua input_filter
+&lt;FilesMatch "\.lua&gt;
+  SetInputFilter myInputFilter
+&lt;/FilesMatch&gt;
+</highlight>
+<highlight language="lua">
+--[[
+    Example input filter that converts all POST data to uppercase.
+]]--
+function input_filter(r)
+    print("luaInputFilter called") -- debug print
+    coroutine.yield() -- Yield and wait for buckets
+    while bucket do -- For each bucket, do...
+        local output = string.upper(bucket) -- Convert all POST data to uppercase
+        coroutine.yield(output) -- Send converted data down the chain
+    end
+    -- No more buckets available.
+    coroutine.yield("&amp;filterSignature=1234") -- Append signature at the end
+end
+</highlight>
+<p>
+The input filter supports denying/skipping a filter if it is deemed unwanted:
+</p>
+<highlight language="lua">
+function input_filter(r)
+    if not good then
+        return -- Simply deny filtering, passing on the original content instead
+    end
+    coroutine.yield() -- wait for buckets
+    ... -- insert filter stuff here
+end
+</highlight>
+<p>
+See "<a href="#modifying_buckets">Modifying contents with Lua 
+filters</a>" for more information.
+</p>
+</usage>
+</directivesynopsis>
 
+<directivesynopsis>
+<name>LuaOutputFilter</name>
+<description>Provide a Lua function for content output filtering</description>
+<syntax>LuaOutputFilter filter_name /path/to/lua/script.lua function_name</syntax>
+<contextlist><context>server config</context> </contextlist>
+<compatibility>2.5.0 and later</compatibility>
+
+<usage>
+<p>Provides a means of adding a Lua function as an output filter. 
+As with input filters, output filters work as coroutines, 
+first yielding before buffers are sent, then yielding whenever 
+a bucket needs to be passed down the chain, and finally (optionally) 
+yielding anything that needs to be appended to the input data. The 
+global variable <code>bucket</code> holds the buckets as they are passed 
+onto the Lua script:
+</p>
+
+<highlight language="config">
+LuaOutputFilter myOutputFilter /www/filter.lua output_filter
+&lt;FilesMatch "\.lua&gt;
+  SetOutputFilter myOutputFilter
+&lt;/FilesMatch&gt;
+</highlight>
+<highlight language="lua">
+--[[
+    Example output filter that escapes all HTML entities in the output
+]]--
+function output_filter(r)
+    coroutine.yield("(Handled by myOutputFilter)&lt;br/&gt;\n") -- Prepend some data to the output,
+                                                          -- yield and wait for buckets.
+    while bucket do -- For each bucket, do...
+        local output = r:escape_html(bucket) -- Escape all output
+        coroutine.yield(output) -- Send converted data down the chain
+    end
+    -- No more buckets available.
+end
+</highlight>
+<p>
+As with the input filter, the output filter supports denying/skipping a filter 
+if it is deemed unwanted:
+</p>
+<highlight language="lua">
+function output_filter(r)
+    if not r.content_type:match("text/html") then
+        return -- Simply deny filtering, passing on the original content instead
+    end
+    coroutine.yield() -- wait for buckets
+    ... -- insert filter stuff here
+end
+</highlight>
+<p>
+See "<a href="#modifying_buckets">Modifying contents with Lua filters</a>" for more 
+information.
+</p>
 </usage>
 </directivesynopsis>
 
 
+
 </modulesynopsis>

Modified: httpd/httpd/branches/2.4.x/modules/lua/README
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/lua/README?rev=1491468&r1=1491467&r2=1491468&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/lua/README (original)
+++ httpd/httpd/branches/2.4.x/modules/lua/README Mon Jun 10 14:36:56 2013
@@ -38,13 +38,10 @@
 
 * Task List
 ** TODO Use r->file to determine file, doing rewriting in translate_name   
-** TODO Change to controlling lifecycle by passing in a pool?
-   Need to determine how to handle server scoped then!
 ** TODO Provide means to get useful output from lua errors in response body
    Probably have to put it on the vm spec for pre-handler errors, as
    it is pre-handler, will prolly be on the request_config somewhere,
    but sometimes cannot put there, so... fun
-** TODO Filters
 ** TODO Mapping in the server_rec
 ** TODO Connection scoped vms
 ** TODO Figure out how reentrancy works regarding filter chain stuff. 
@@ -52,14 +49,10 @@
 ** TODO Flesh out apw_*getvm for each flavor we allow
 ** TODO Rework apw_sgetvm to use the create_vm stuff like apw_rgetvm
 ** TODO apw_rgetvm needs to handle connection scoped vms     
-** TODO options in server scoped vms (ie, min and max vm counts)
 ** TODO provide means to implement authn and authz providers
 ** TODO: Flatten LuaHook* to LuaHook phase file fn ?
-** TODO: Lua and ap_expr integration in one or both directions
 ** TODO: document or remove block sections
 ** TODO: test per-dir behavior of block sections
-** TODO: Catch-up documentation on r: methods
-** TODO: 500 errors instead of 404 with AddHandler lua-script
 ** TODO: Suppress internal details (fs path to scripts, etc) in error responses
     
 * License
@@ -82,3 +75,6 @@
 ** Brian Akins
 ** Justin Erenkrantz
 ** Philip M. Gollucci
+** Stefan Fritsch
+** Eric Covener
+** Daniel Gruno

Modified: httpd/httpd/branches/2.4.x/modules/lua/config.m4
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/lua/config.m4?rev=1491468&r1=1491467&r2=1491468&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/lua/config.m4 (original)
+++ httpd/httpd/branches/2.4.x/modules/lua/config.m4 Mon Jun 10 14:36:56 2013
@@ -136,7 +136,7 @@ else
 fi 
 ])
 
-lua_objects="lua_apr.lo lua_config.lo mod_lua.lo lua_request.lo lua_vmprep.lo lua_dbd.lo"
+lua_objects="lua_apr.lo lua_config.lo mod_lua.lo lua_request.lo lua_vmprep.lo lua_dbd.lo lua_passwd.lo"
 
 APACHE_MODULE(lua, Apache Lua Framework, $lua_objects, , , [
   CHECK_LUA()

Modified: httpd/httpd/branches/2.4.x/modules/lua/lua_apr.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/lua/lua_apr.c?rev=1491468&r1=1491467&r2=1491468&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/lua/lua_apr.c (original)
+++ httpd/httpd/branches/2.4.x/modules/lua/lua_apr.c Mon Jun 10 14:36:56 2013
@@ -18,17 +18,7 @@
 #include "mod_lua.h"
 #include "lua_apr.h"
 
-/**
- * make a userdata out of a C pointer, and vice versa
- * instead of using lightuserdata
- */
-#ifndef lua_boxpointer
-#define lua_boxpointer(L,u) (*(void **)(lua_newuserdata(L, sizeof(void *))) = (u))
-#define lua_unboxpointer(L,i)   (*(void **)(lua_touserdata(L, i)))
-#endif
-
-
-AP_LUA_DECLARE(apr_table_t *) ap_lua_check_apr_table(lua_State *L, int index)
+apr_table_t *ap_lua_check_apr_table(lua_State *L, int index)
 {
     apr_table_t *t;
     luaL_checkudata(L, index, "Apr.Table");
@@ -37,7 +27,7 @@ AP_LUA_DECLARE(apr_table_t *) ap_lua_che
 }
 
 
-AP_LUA_DECLARE(void) ap_lua_push_apr_table(lua_State *L, apr_table_t *t)
+void ap_lua_push_apr_table(lua_State *L, apr_table_t *t)
 {
     lua_boxpointer(L, t);
     luaL_getmetatable(L, "Apr.Table");
@@ -70,7 +60,7 @@ static const luaL_Reg lua_table_methods[
 };
 
 
-AP_LUA_DECLARE(int) ap_lua_init(lua_State *L, apr_pool_t *p)
+int ap_lua_init(lua_State *L, apr_pool_t *p)
 {
     luaL_newmetatable(L, "Apr.Table");
     luaL_register(L, "apr_table", lua_table_methods);

Modified: httpd/httpd/branches/2.4.x/modules/lua/lua_apr.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/lua/lua_apr.h?rev=1491468&r1=1491467&r2=1491468&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/lua/lua_apr.h (original)
+++ httpd/httpd/branches/2.4.x/modules/lua/lua_apr.h Mon Jun 10 14:36:56 2013
@@ -29,9 +29,8 @@
 #include "apr_base64.h"
 
 
-AP_LUA_DECLARE(int) ap_lua_init(lua_State *L, apr_pool_t * p);
-AP_LUA_DECLARE(apr_table_t*) ap_lua_check_apr_table(lua_State *L, int index);
-AP_LUA_DECLARE(void) ap_lua_push_apr_table(lua_State *L, apr_table_t *t);
-AP_LUA_DECLARE(int) ap_lua_load_httpd_functions(lua_State *L);
+int ap_lua_init(lua_State *L, apr_pool_t * p);
+apr_table_t *ap_lua_check_apr_table(lua_State *L, int index);
+void ap_lua_push_apr_table(lua_State *L, apr_table_t *t);
 
 #endif /* !_LUA_APR_H_ */

Modified: httpd/httpd/branches/2.4.x/modules/lua/lua_config.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/lua/lua_config.c?rev=1491468&r1=1491467&r2=1491468&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/lua/lua_config.c (original)
+++ httpd/httpd/branches/2.4.x/modules/lua/lua_config.c Mon Jun 10 14:36:56 2013
@@ -51,7 +51,7 @@ static int apl_toscope(const char *name)
     return AP_LUA_SCOPE_ONCE;
 }
 
-AP_LUA_DECLARE(apr_status_t) ap_lua_map_handler(ap_lua_dir_cfg *cfg,
+apr_status_t ap_lua_map_handler(ap_lua_dir_cfg *cfg,
                                                  const char *file,
                                                  const char *function,
                                                  const char *pattern,
@@ -257,7 +257,7 @@ static const struct luaL_Reg cmd_methods
     {NULL, NULL}
 };
 
-AP_LUA_DECLARE(void) ap_lua_load_config_lmodule(lua_State *L)
+void ap_lua_load_config_lmodule(lua_State *L)
 {
     luaL_newmetatable(L, "Apache2.DirConfig");  /* [metatable] */
     lua_pushvalue(L, -1);

Modified: httpd/httpd/branches/2.4.x/modules/lua/lua_config.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/lua/lua_config.h?rev=1491468&r1=1491467&r2=1491468&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/lua/lua_config.h (original)
+++ httpd/httpd/branches/2.4.x/modules/lua/lua_config.h Mon Jun 10 14:36:56 2013
@@ -20,9 +20,9 @@
 #ifndef _APL_CONFIG_H_
 #define _APL_CONFIG_H_
 
-AP_LUA_DECLARE(void) ap_lua_load_config_lmodule(lua_State *L);
+void ap_lua_load_config_lmodule(lua_State *L);
 
-AP_LUA_DECLARE(apr_status_t) ap_lua_map_handler(ap_lua_dir_cfg *cfg,
+apr_status_t ap_lua_map_handler(ap_lua_dir_cfg *cfg,
                                                 const char *file,
                                                 const char *function,
                                                 const char *pattern,

Modified: httpd/httpd/branches/2.4.x/modules/lua/lua_dbd.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/lua/lua_dbd.c?rev=1491468&r1=1491467&r2=1491468&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/lua/lua_dbd.c (original)
+++ httpd/httpd/branches/2.4.x/modules/lua/lua_dbd.c Mon Jun 10 14:36:56 2013
@@ -16,7 +16,6 @@
  */
 
 #include "mod_lua.h"
-#include "lua_apr.h"
 #include "lua_dbd.h"
 
 APLOG_USE_MODULE(lua);
@@ -377,7 +376,7 @@ int lua_db_prepared_select(lua_State *L)
     st = (lua_db_prepared_statement*) lua_topointer(L, -1);
     
     /* Check if we got enough variables passed on to us.
-     * This, of course, only works for prepped statements made through lua. */
+     * This, of course, only works for prepared statements made through lua. */
     have = lua_gettop(L) - 2;
     if (st->variables != -1 && have < st->variables ) {
         lua_pushboolean(L, 0);
@@ -468,7 +467,7 @@ int lua_db_prepared_query(lua_State *L)
     st = (lua_db_prepared_statement*) lua_topointer(L, -1);
     
     /* Check if we got enough variables passed on to us.
-     * This, of course, only works for prepped statements made through lua. */
+     * This, of course, only works for prepared statements made through lua. */
     have = lua_gettop(L) - 2;
     if (st->variables != -1 && have < st->variables ) {
         lua_pushboolean(L, 0);
@@ -704,7 +703,7 @@ static lua_db_handle* lua_push_db_handle
     supported.
    =============================================================================
  */
-AP_LUA_DECLARE(int) lua_db_acquire(lua_State *L)
+int lua_db_acquire(lua_State *L)
 {
     /*~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
     const char      *type;

Modified: httpd/httpd/branches/2.4.x/modules/lua/lua_dbd.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/lua/lua_dbd.h?rev=1491468&r1=1491467&r2=1491468&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/lua/lua_dbd.h (original)
+++ httpd/httpd/branches/2.4.x/modules/lua/lua_dbd.h Mon Jun 10 14:36:56 2013
@@ -50,7 +50,7 @@ typedef struct {
     lua_db_handle           *db;
 } lua_db_prepared_statement;
 
-AP_LUA_DECLARE(int) lua_db_acquire(lua_State* L);
+int lua_db_acquire(lua_State* L);
 int lua_db_escape(lua_State* L);
 int lua_db_close(lua_State* L);
 int lua_db_prepare(lua_State* L);

Modified: httpd/httpd/branches/2.4.x/modules/lua/lua_request.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/lua/lua_request.c?rev=1491468&r1=1491467&r2=1491468&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/lua/lua_request.c (original)
+++ httpd/httpd/branches/2.4.x/modules/lua/lua_request.c Mon Jun 10 14:36:56 2013
@@ -16,19 +16,33 @@
  */
 
 #include "mod_lua.h"
-#include "util_script.h"
 #include "lua_apr.h"
-#include "scoreboard.h"
 #include "lua_dbd.h"
+#include "lua_passwd.h"
+#include "scoreboard.h"
 #include "util_md5.h"
+#include "util_script.h"
+#include "util_varbuf.h"
+#include "apr_date.h"
+#include "apr_pools.h"
+#include "apr_thread_mutex.h"
+
+#include <lua.h>
+
+extern apr_thread_mutex_t* lua_ivm_mutex;
 
 APLOG_USE_MODULE(lua);
 #define POST_MAX_VARS 500
 
+#ifndef MODLUA_MAX_REG_MATCH
+#define MODLUA_MAX_REG_MATCH 25
+#endif
+
 typedef char *(*req_field_string_f) (request_rec * r);
 typedef int (*req_field_int_f) (request_rec * r);
 typedef apr_table_t *(*req_field_apr_table_f) (request_rec * r);
 
+
 void ap_lua_rstack_dump(lua_State *L, request_rec *r, const char *msg)
 {
     int i;
@@ -431,6 +445,7 @@ static int req_escape_html(lua_State *L)
     lua_pushstring(L, ap_escape_html(r->pool, s));
     return 1;
 }
+
 /* wrap optional ssl_var_lookup as  r:ssl_var_lookup(String) */
 static int req_ssl_var_lookup(lua_State *L)
 {
@@ -441,6 +456,7 @@ static int req_ssl_var_lookup(lua_State 
     lua_pushstring(L, res);
     return 1;
 }
+
 /* BEGIN dispatch mathods for request_rec fields */
 
 /* not really a field, but we treat it like one */
@@ -602,6 +618,11 @@ static int req_ssl_is_https_field(reques
     return ap_lua_ssl_is_https(r->connection);
 }
 
+static int req_ap_get_server_port(request_rec *r)
+{
+    return (int) ap_get_server_port(r);
+}
+
 static int lua_ap_rflush (lua_State *L) {
 
     int returnValue;
@@ -613,10 +634,6 @@ static int lua_ap_rflush (lua_State *L) 
     return 1;
 }
 
-static int lua_ap_port(request_rec* r) 
-{
-    return (int) ap_get_server_port(r);
-}
 
 static const char* lua_ap_options(request_rec* r) 
 {
@@ -634,7 +651,7 @@ static const char* lua_ap_allowoverrides
 
 static int lua_ap_started(request_rec* r) 
 {
-    return ap_scoreboard_image->global->restart_time;
+    return (int)(ap_scoreboard_image->global->restart_time / 1000000);
 }
 
 static const char* lua_ap_basic_auth_pw(request_rec* r) 
@@ -670,7 +687,7 @@ static int lua_ap_sendfile(lua_State *L)
     luaL_checktype(L, 2, LUA_TSTRING);
     r = ap_lua_check_request_rec(L, 1);
     filename = lua_tostring(L, 2);
-    apr_stat(&file_info, filename, APR_FINFO_NORM, r->pool);
+    apr_stat(&file_info, filename, APR_FINFO_MIN, r->pool);
     if (file_info.filetype == APR_NOFILE || file_info.filetype == APR_DIR) {
         lua_pushboolean(L, 0);
     }
@@ -682,7 +699,7 @@ static int lua_ap_sendfile(lua_State *L)
         rc = apr_file_open(&file, filename, APR_READ, APR_OS_DEFAULT,
                             r->pool);
         if (rc == APR_SUCCESS) {
-            ap_send_fd(file, r, 0, file_info.size, &sent);
+            ap_send_fd(file, r, 0, (apr_size_t)file_info.size, &sent);
             apr_file_close(file);
             lua_pushinteger(L, sent);
         }
@@ -709,10 +726,12 @@ static int lua_apr_b64encode(lua_State *
     r = ap_lua_check_request_rec(L, 1);
     luaL_checktype(L, 2, LUA_TSTRING);
     plain = lua_tolstring(L, 2, &plain_len);
-    encoded_len = apr_base64_encode_len(plain_len) + 1;
+    encoded_len = apr_base64_encode_len(plain_len);
     if (encoded_len) {
         encoded = apr_palloc(r->pool, encoded_len);
-        apr_base64_encode(encoded, plain, plain_len);
+        encoded_len = apr_base64_encode(encoded, plain, plain_len);
+        if (encoded_len > 0 && encoded[encoded_len - 1] == '\0')
+            encoded_len--; 
         lua_pushlstring(L, encoded, encoded_len);
         return 1;
     }
@@ -728,13 +747,16 @@ static int lua_apr_b64decode(lua_State *
     char           *plain;
     size_t          encoded_len, decoded_len;
     request_rec    *r;
+
     r = ap_lua_check_request_rec(L, 1);
     luaL_checktype(L, 2, LUA_TSTRING);
     encoded = lua_tolstring(L, 2, &encoded_len);
-    decoded_len = apr_base64_decode_len(encoded) + 1;
+    decoded_len = apr_base64_decode_len(encoded);
     if (decoded_len) {
         plain = apr_palloc(r->pool, decoded_len);
-        apr_base64_decode(plain, encoded);
+        decoded_len = apr_base64_decode(plain, encoded);
+        if (decoded_len > 0 && plain[decoded_len - 1] == '\0')
+            decoded_len--; 
         lua_pushlstring(L, plain, decoded_len);
         return 1;
     }
@@ -822,14 +844,103 @@ static int lua_apr_sha1(lua_State *L)
     return 1;
 }
 
+/*
+ * lua_apr_htpassword; r:htpassword(string [, algorithm [, cost]]) - Creates
+ * a htpassword hash from a string
+ */
+static int lua_apr_htpassword(lua_State *L)
+{
+    passwd_ctx     ctx = { 0 };
+    request_rec    *r;
+
+    r = ap_lua_check_request_rec(L, 1);
+    luaL_checktype(L, 2, LUA_TSTRING);
+    ctx.passwd = apr_pstrdup(r->pool, lua_tostring(L, 2));
+    ctx.alg = luaL_optinteger(L, 3, ALG_APMD5);
+    ctx.cost = luaL_optinteger(L, 4, 0);
+    ctx.pool = r->pool;
+    ctx.out = apr_pcalloc(r->pool, MAX_PASSWD_LEN);
+    ctx.out_len = MAX_PASSWD_LEN;
+    if (mk_password_hash(&ctx)) {
+        lua_pushboolean(L, 0);
+        lua_pushstring(L, ctx.errstr);
+        return 2;
+    } else {
+        lua_pushstring(L, ctx.out);
+    }
+    return 1;
+}
+
+/*
+ * lua_apr_mkdir; r:mkdir(string [, permissions]) - Creates a directory
+ */
+static int lua_apr_mkdir(lua_State *L)
+{
+    request_rec     *r;
+    const char      *path;
+    apr_status_t    status;
+    apr_fileperms_t perms;
+
+    r = ap_lua_check_request_rec(L, 1);
+    luaL_checktype(L, 2, LUA_TSTRING);
+    path = lua_tostring(L, 2);
+    perms = luaL_optinteger(L, 3, APR_OS_DEFAULT);
+    status = apr_dir_make(path, perms, r->pool);
+    lua_pushboolean(L, (status == 0));
+    return 1;
+}
+
+/*
+ * lua_apr_mkrdir; r:mkrdir(string [, permissions]) - Creates directories
+ * recursive
+ */
+static int lua_apr_mkrdir(lua_State *L)
+{
+    request_rec     *r;
+    const char      *path;
+    apr_status_t    status;
+    apr_fileperms_t perms;
 
+    r = ap_lua_check_request_rec(L, 1);
+    luaL_checktype(L, 2, LUA_TSTRING);
+    path = lua_tostring(L, 2);
+    perms = luaL_optinteger(L, 3, APR_OS_DEFAULT);
+    status = apr_dir_make_recursive(path, perms, r->pool);
+    lua_pushboolean(L, (status == 0));
+    return 1;
+}
 
 /*
- * lua_ap_banner; r:banner() - Returns the current server banner
+ * lua_apr_rmdir; r:rmdir(string) - Removes a directory
  */
-static int lua_ap_banner(lua_State *L)
+static int lua_apr_rmdir(lua_State *L)
 {
-    lua_pushstring(L, ap_get_server_banner());
+    request_rec     *r;
+    const char      *path;
+    apr_status_t    status;
+
+    r = ap_lua_check_request_rec(L, 1);
+    luaL_checktype(L, 2, LUA_TSTRING);
+    path = lua_tostring(L, 2);
+    status = apr_dir_remove(path, r->pool);
+    lua_pushboolean(L, (status == 0));
+    return 1;
+}
+
+/*
+ * lua_apr_date_parse_rfc; r.date_parse_rfc(string) - Parses a DateTime string
+ */
+static int lua_apr_date_parse_rfc(lua_State *L)
+{
+    const char *input;
+    apr_time_t result;
+
+    luaL_checktype(L, 1, LUA_TSTRING);
+    input = lua_tostring(L, 1);
+    result = apr_date_parse_rfc(input);
+    if (result == 0)
+        return 0;
+    lua_pushnumber(L, (lua_Number)(result / APR_USEC_PER_SEC));
     return 1;
 }
 
@@ -841,9 +952,9 @@ static int lua_ap_mpm_query(lua_State *L
     int x,
         y;
 
-    x = lua_tonumber(L, 1);
+    x = lua_tointeger(L, 1);
     ap_mpm_query(x, &y);
-    lua_pushnumber(L, y);
+    lua_pushinteger(L, y);
     return 1;
 }
 
@@ -889,28 +1000,30 @@ static int lua_ap_expr(lua_State *L)
 
 
 /*
- * lua_ap_regex; r:regex(string, pattern) - Evaluates a regex and returns
- * captures if matched
+ * lua_ap_regex; r:regex(string, pattern [, flags])
+ * - Evaluates a regex and returns captures if matched
  */
 static int lua_ap_regex(lua_State *L)
 {
     request_rec    *r;
     int i,
-        rv;
+        rv,
+        flags;
     const char     *pattern,
     *source;
     char           *err;
     ap_regex_t regex;
-    ap_regmatch_t matches[AP_MAX_REG_MATCH+1];
+    ap_regmatch_t matches[MODLUA_MAX_REG_MATCH+1];
 
     luaL_checktype(L, 1, LUA_TUSERDATA);
     luaL_checktype(L, 2, LUA_TSTRING);
     luaL_checktype(L, 3, LUA_TSTRING);
     r = ap_lua_check_request_rec(L, 1);
-    pattern = lua_tostring(L, 2);
-    source = lua_tostring(L, 3);
+    source = lua_tostring(L, 2);
+    pattern = lua_tostring(L, 3);
+    flags = luaL_optinteger(L, 4, 0);
 
-    rv = ap_regcomp(&regex, pattern, 0);
+    rv = ap_regcomp(&regex, pattern, flags);
     if (rv) {
         lua_pushboolean(L, 0);
         err = apr_palloc(r->pool, 256);
@@ -919,7 +1032,17 @@ static int lua_ap_regex(lua_State *L)
         return 2;
     }
 
-    rv = ap_regexec(&regex, source, AP_MAX_REG_MATCH, matches, 0);
+    if (regex.re_nsub > MODLUA_MAX_REG_MATCH) {
+        lua_pushboolean(L, 0);
+        err = apr_palloc(r->pool, 64);
+        apr_snprintf(err, 64,
+                     "regcomp found %d matches; only %d allowed.",
+                     regex.re_nsub, MODLUA_MAX_REG_MATCH);
+        lua_pushstring(L, err);
+        return 2;
+    }
+
+    rv = ap_regexec(&regex, source, MODLUA_MAX_REG_MATCH, matches, 0);
     if (rv == AP_REG_NOMATCH) {
         lua_pushboolean(L, 0);
         return 1;
@@ -953,7 +1076,7 @@ static int lua_ap_scoreboard_process(lua
 
     luaL_checktype(L, 1, LUA_TUSERDATA);
     luaL_checktype(L, 2, LUA_TNUMBER);
-    i = lua_tonumber(L, 2);
+    i = lua_tointeger(L, 2);
     ps_record = ap_get_scoreboard_process(i);
     if (ps_record) {
         lua_newtable(L);
@@ -1008,8 +1131,8 @@ static int lua_ap_scoreboard_worker(lua_
     luaL_checktype(L, 1, LUA_TUSERDATA);
     luaL_checktype(L, 2, LUA_TNUMBER);
     luaL_checktype(L, 3, LUA_TNUMBER);
-    i = lua_tonumber(L, 2);
-    j = lua_tonumber(L, 3);
+    i = lua_tointeger(L, 2);
+    j = lua_tointeger(L, 3);
     ws_record = ap_get_scoreboard_worker_from_indexes(i, j);
     if (ws_record) {
         lua_newtable(L);
@@ -1019,7 +1142,7 @@ static int lua_ap_scoreboard_worker(lua_
         lua_settable(L, -3);
 
         lua_pushstring(L, "bytes_served");
-        lua_pushnumber(L, ws_record->bytes_served);
+        lua_pushnumber(L, (lua_Number) ws_record->bytes_served);
         lua_settable(L, -3);
 
         lua_pushstring(L, "client");
@@ -1027,7 +1150,7 @@ static int lua_ap_scoreboard_worker(lua_
         lua_settable(L, -3);
 
         lua_pushstring(L, "conn_bytes");
-        lua_pushnumber(L, ws_record->conn_bytes);
+        lua_pushnumber(L, (lua_Number) ws_record->conn_bytes);
         lua_settable(L, -3);
 
         lua_pushstring(L, "conn_count");
@@ -1039,7 +1162,7 @@ static int lua_ap_scoreboard_worker(lua_
         lua_settable(L, -3);
 
         lua_pushstring(L, "last_used");
-        lua_pushnumber(L, ws_record->last_used);
+        lua_pushnumber(L, (lua_Number) ws_record->last_used);
         lua_settable(L, -3);
 
         lua_pushstring(L, "pid");
@@ -1051,7 +1174,7 @@ static int lua_ap_scoreboard_worker(lua_
         lua_settable(L, -3);
 
         lua_pushstring(L, "start_time");
-        lua_pushnumber(L, ws_record->start_time);
+        lua_pushnumber(L, (lua_Number) ws_record->start_time);
         lua_settable(L, -3);
 
         lua_pushstring(L, "status");
@@ -1059,7 +1182,7 @@ static int lua_ap_scoreboard_worker(lua_
         lua_settable(L, -3);
 
         lua_pushstring(L, "stop_time");
-        lua_pushnumber(L, ws_record->stop_time);
+        lua_pushnumber(L, (lua_Number) ws_record->stop_time);
         lua_settable(L, -3);
 
         lua_pushstring(L, "tid");
@@ -1085,23 +1208,13 @@ static int lua_ap_scoreboard_worker(lua_
 }
 
 /*
- * lua_ap_restarted; r:started() - Returns the timestamp of last server
- * (re)start
- */
-static int lua_ap_restarted(lua_State *L)
-{
-    lua_pushnumber(L, ap_scoreboard_image->global->restart_time);
-    return 1;
-}
-
-/*
  * lua_ap_clock; r:clock() - Returns timestamp with microsecond precision
  */
 static int lua_ap_clock(lua_State *L)
 {
     apr_time_t now;
     now = apr_time_now();
-    lua_pushnumber(L, now);
+    lua_pushnumber(L, (lua_Number) now);
     return 1;
 }
 
@@ -1141,7 +1254,7 @@ static int lua_ap_module_info(lua_State 
     luaL_checktype(L, 1, LUA_TSTRING);
     moduleName = lua_tostring(L, 1);
     mod = ap_find_linked_module(moduleName);
-    if (mod) {
+    if (mod && mod->cmds) {
         const command_rec *cmd;
         lua_newtable(L);
         lua_pushstring(L, "commands");
@@ -1191,42 +1304,93 @@ static int lua_ap_set_document_root(lua_
 }
 
 /*
- * lua_ap_stat; r:stat(filename) - Runs stat on a file and returns the file
- * info as a table
+ * lua_ap_getdir; r:get_direntries(directory) - Gets all entries of a
+ * directory and returns the directory info as a table
+ */
+static int lua_ap_getdir(lua_State *L)
+{
+    request_rec    *r;
+    apr_dir_t      *thedir;
+    apr_finfo_t    file_info;
+    apr_status_t   status;
+    const char     *directory;
+
+    luaL_checktype(L, 1, LUA_TUSERDATA);
+    luaL_checktype(L, 2, LUA_TSTRING);
+    r = ap_lua_check_request_rec(L, 1);
+    directory = lua_tostring(L, 2);
+    if (apr_dir_open(&thedir, directory, r->pool) == APR_SUCCESS) {
+        int i = 0;
+        lua_newtable(L);
+        do {
+            status = apr_dir_read(&file_info, APR_FINFO_NAME, thedir);
+            if (APR_STATUS_IS_INCOMPLETE(status)) {
+                continue; /* ignore un-stat()able files */
+            }
+            else if (status != APR_SUCCESS) {
+                break;
+            }
+            lua_pushinteger(L, ++i);
+            lua_pushstring(L, file_info.name);
+            lua_settable(L, -3);
+
+        } while (1);
+        apr_dir_close(thedir);
+        return 1;
+    }
+    else {
+        return 0;
+    }
+}
+
+/*
+ * lua_ap_stat; r:stat(filename [, wanted]) - Runs stat on a file and
+ * returns the file info as a table
  */
 static int lua_ap_stat(lua_State *L)
 {
     request_rec    *r;
     const char     *filename;
     apr_finfo_t file_info;
+    apr_int32_t wanted;
 
     luaL_checktype(L, 1, LUA_TUSERDATA);
     luaL_checktype(L, 2, LUA_TSTRING);
     r = ap_lua_check_request_rec(L, 1);
     filename = lua_tostring(L, 2);
-    if (apr_stat(&file_info, filename, APR_FINFO_NORM, r->pool) == OK) {
+    wanted = luaL_optinteger(L, 3, APR_FINFO_MIN);
+    if (apr_stat(&file_info, filename, wanted, r->pool) == OK) {
         lua_newtable(L);
-
-        lua_pushstring(L, "mtime");
-        lua_pushinteger(L, file_info.mtime);
-        lua_settable(L, -3);
-
-        lua_pushstring(L, "atime");
-        lua_pushinteger(L, file_info.atime);
-        lua_settable(L, -3);
-
-        lua_pushstring(L, "ctime");
-        lua_pushinteger(L, file_info.ctime);
-        lua_settable(L, -3);
-
-        lua_pushstring(L, "size");
-        lua_pushinteger(L, file_info.size);
-        lua_settable(L, -3);
-
-        lua_pushstring(L, "filetype");
-        lua_pushinteger(L, file_info.filetype);
-        lua_settable(L, -3);
-
+        if (wanted & APR_FINFO_MTIME) {
+            lua_pushstring(L, "mtime");
+            lua_pushnumber(L, (lua_Number) file_info.mtime);
+            lua_settable(L, -3);
+        }
+        if (wanted & APR_FINFO_ATIME) {
+            lua_pushstring(L, "atime");
+            lua_pushnumber(L, (lua_Number) file_info.atime);
+            lua_settable(L, -3);
+        }
+        if (wanted & APR_FINFO_CTIME) {
+            lua_pushstring(L, "ctime");
+            lua_pushnumber(L, (lua_Number) file_info.ctime);
+            lua_settable(L, -3);
+        }
+        if (wanted & APR_FINFO_SIZE) {
+            lua_pushstring(L, "size");
+            lua_pushnumber(L, (lua_Number) file_info.size);
+            lua_settable(L, -3);
+        }
+        if (wanted & APR_FINFO_TYPE) {
+            lua_pushstring(L, "filetype");
+            lua_pushinteger(L, file_info.filetype);
+            lua_settable(L, -3);
+        }
+        if (wanted & APR_FINFO_PROT) {
+            lua_pushstring(L, "protection");
+            lua_pushinteger(L, file_info.protection);
+            lua_settable(L, -3);
+        }
         return 1;
     }
     else {
@@ -1293,7 +1457,6 @@ static int lua_ap_server_info(lua_State 
  */
 static int lua_ap_set_context_info(lua_State *L)
 {
-
     request_rec    *r;
     const char     *prefix;
     const char     *document_root;
@@ -1319,7 +1482,6 @@ static int lua_ap_set_context_info(lua_S
  */
 static int lua_ap_os_escape_path(lua_State *L)
 {
-
     char           *returnValue;
     request_rec    *r;
     const char     *path;
@@ -1345,7 +1507,6 @@ static int lua_ap_os_escape_path(lua_Sta
  */
 static int lua_ap_escape_logitem(lua_State *L)
 {
-
     char           *returnValue;
     request_rec    *r;
     const char     *str;
@@ -1368,7 +1529,6 @@ static int lua_ap_escape_logitem(lua_Sta
  */
 static int lua_ap_strcmp_match(lua_State *L)
 {
-
     int returnValue;
     const char     *str;
     const char     *expected;
@@ -1396,7 +1556,6 @@ static int lua_ap_strcmp_match(lua_State
  */
 static int lua_ap_set_keepalive(lua_State *L)
 {
-
     int returnValue;
     request_rec    *r;
     luaL_checktype(L, 1, LUA_TUSERDATA);
@@ -1417,7 +1576,6 @@ static int lua_ap_set_keepalive(lua_Stat
  */
 static int lua_ap_make_etag(lua_State *L)
 {
-
     char           *returnValue;
     request_rec    *r;
     int force_weak;
@@ -1440,7 +1598,6 @@ static int lua_ap_make_etag(lua_State *L
  */
 static int lua_ap_send_interim_response(lua_State *L)
 {
-
     request_rec    *r;
     int send_headers = 0;
     luaL_checktype(L, 1, LUA_TUSERDATA);
@@ -1462,7 +1619,6 @@ static int lua_ap_send_interim_response(
  */
 static int lua_ap_custom_response(lua_State *L)
 {
-
     request_rec    *r;
     int status;
     const char     *string;
@@ -1485,19 +1641,17 @@ static int lua_ap_custom_response(lua_St
  */
 static int lua_ap_exists_config_define(lua_State *L)
 {
-
     int returnValue;
     const char     *name;
     luaL_checktype(L, 1, LUA_TSTRING);
     name = lua_tostring(L, 1);
     returnValue = ap_exists_config_define(name);
-    lua_pushinteger(L, returnValue);
+    lua_pushboolean(L, returnValue);
     return 1;
 }
 
 static int lua_ap_get_server_name_for_url(lua_State *L)
 {
-
     const char     *servername;
     request_rec    *r;
     luaL_checktype(L, 1, LUA_TUSERDATA);
@@ -1507,10 +1661,7 @@ static int lua_ap_get_server_name_for_ur
     return 1;
 }
 
-
-
-/**
- * ap_state_query (int query_code) item starts a new field  */
+/* ap_state_query (int query_code) item starts a new field  */
 static int lua_ap_state_query(lua_State *L)
 {
 
@@ -1523,12 +1674,15 @@ static int lua_ap_state_query(lua_State 
     return 1;
 }
 
-static int lua_ap_sleep(lua_State *L)
+/*
+ * lua_ap_usleep; r:usleep(microseconds)
+ * - Sleep for the specified number of microseconds.
+ */
+static int lua_ap_usleep(lua_State *L)
 {
-
-    int msec;
+    apr_interval_time_t msec;
     luaL_checktype(L, 1, LUA_TNUMBER);
-    msec = (lua_tonumber(L, 1) * 1000000);
+    msec = (apr_interval_time_t)lua_tonumber(L, 1);
     apr_sleep(msec);
     return 0;
 }
@@ -1584,7 +1738,7 @@ static int req_dispatch(lua_State *L)
                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01489)
                               "request_rec->dispatching %s -> int", name);
                 rs = (*func) (r);
-                lua_pushnumber(L, rs);
+                lua_pushinteger(L, rs);
                 return 1;
             }
         case APL_REQ_FUNTYPE_BOOLEAN:{
@@ -1653,6 +1807,67 @@ static int req_debug(lua_State *L)
     return req_log_at(L, APLOG_DEBUG);
 }
 
+static int lua_ivm_get(lua_State *L) 
+{
+    const char *key, *raw_key;
+    lua_ivm_object *object = NULL;
+    request_rec *r = ap_lua_check_request_rec(L, 1);
+    key = luaL_checkstring(L, 2);
+    raw_key = apr_pstrcat(r->pool, "lua_ivm_", key, NULL);
+    apr_thread_mutex_lock(lua_ivm_mutex);
+    apr_pool_userdata_get((void **)&object, raw_key, r->server->process->pool);
+    if (object) {
+        if (object->type == LUA_TBOOLEAN) lua_pushboolean(L, (int) object->number);
+        else if (object->type == LUA_TNUMBER) lua_pushnumber(L, object->number);
+        else if (object->type == LUA_TSTRING) lua_pushlstring(L, object->vb.buf, object->size);
+        apr_thread_mutex_unlock(lua_ivm_mutex);
+        return 1;
+    }
+    else {
+        apr_thread_mutex_unlock(lua_ivm_mutex);
+        return 0;
+    }
+}
+
+
+static int lua_ivm_set(lua_State *L) 
+{
+    const char *key, *raw_key;
+    const char *value = NULL;
+    size_t str_len;
+    lua_ivm_object *object = NULL;
+    request_rec *r = ap_lua_check_request_rec(L, 1);
+    key = luaL_checkstring(L, 2);
+    luaL_checkany(L, 3);
+    raw_key = apr_pstrcat(r->pool, "lua_ivm_", key, NULL);
+    
+    apr_thread_mutex_lock(lua_ivm_mutex);
+    apr_pool_userdata_get((void **)&object, raw_key, r->server->process->pool);
+    if (!object) {
+        object = apr_pcalloc(r->server->process->pool, sizeof(lua_ivm_object));
+        ap_varbuf_init(r->server->process->pool, &object->vb, 2);
+        object->size = 1;
+        object->vb_size = 1;
+    }
+    object->type = lua_type(L, 3);
+    if (object->type == LUA_TNUMBER) object->number = lua_tonumber(L, 3);
+    else if (object->type == LUA_TBOOLEAN) object->number = lua_tonumber(L, 3);
+    else if (object->type == LUA_TSTRING) {
+        value = lua_tolstring(L, 3, &str_len);
+        str_len++; /* add trailing \0 */
+        if ( str_len > object->vb_size) {
+            ap_varbuf_grow(&object->vb, str_len);
+            object->vb_size = str_len;
+        }
+        object->size = str_len-1;
+        memset(object->vb.buf, 0, str_len);
+        memcpy(object->vb.buf, value, str_len-1);
+    }
+    apr_pool_userdata_set(object, raw_key, NULL, r->server->process->pool);
+    apr_thread_mutex_unlock(lua_ivm_mutex);
+    return 0;
+}
+
 #define APLUA_REQ_TRACE(lev) static int req_trace##lev(lua_State *L)  \
 {                                                               \
     return req_log_at(L, APLOG_TRACE##lev);                     \
@@ -1744,6 +1959,21 @@ static const struct luaL_Reg connection_
     {NULL, NULL}
 };
 
+static const char* lua_ap_auth_name(request_rec* r)
+{
+    const char *name;
+    name = ap_auth_name(r);
+    return name ? name : "";
+}
+
+static const char* lua_ap_get_server_name(request_rec* r)
+{
+    const char *name;
+    name = ap_get_server_name(r);
+    return name ? name : "localhost";
+}
+
+
 
 static const struct luaL_Reg server_methods[] = {
     {NULL, NULL}
@@ -1758,7 +1988,7 @@ static req_fun_t *makefun(const void *fu
     return rft;
 }
 
-AP_LUA_DECLARE(void) ap_lua_load_request_lmodule(lua_State *L, apr_pool_t *p)
+void ap_lua_load_request_lmodule(lua_State *L, apr_pool_t *p)
 {
 
     apr_hash_t *dispatch = apr_hash_make(p);
@@ -1876,7 +2106,7 @@ AP_LUA_DECLARE(void) ap_lua_load_request
     apr_hash_set(dispatch, "flush", APR_HASH_KEY_STRING,
                  makefun(&lua_ap_rflush, APL_REQ_FUNTYPE_LUACFUN, p));
     apr_hash_set(dispatch, "port", APR_HASH_KEY_STRING,
-                 makefun(&lua_ap_port, APL_REQ_FUNTYPE_INT, p));
+                 makefun(&req_ap_get_server_port, APL_REQ_FUNTYPE_INT, p));
     apr_hash_set(dispatch, "banner", APR_HASH_KEY_STRING,
                  makefun(&ap_get_server_banner, APL_REQ_FUNTYPE_STRING, p));
     apr_hash_set(dispatch, "options", APR_HASH_KEY_STRING,
@@ -1898,19 +2128,21 @@ AP_LUA_DECLARE(void) ap_lua_load_request
     apr_hash_set(dispatch, "some_auth_required", APR_HASH_KEY_STRING,
                  makefun(&lua_ap_some_auth_required, APL_REQ_FUNTYPE_BOOLEAN, p));
     apr_hash_set(dispatch, "server_name", APR_HASH_KEY_STRING,
-                 makefun(&ap_get_server_name, APL_REQ_FUNTYPE_STRING, p));
+                 makefun(&lua_ap_get_server_name, APL_REQ_FUNTYPE_STRING, p));
     apr_hash_set(dispatch, "auth_name", APR_HASH_KEY_STRING,
-                 makefun(&ap_auth_name, APL_REQ_FUNTYPE_STRING, p));
+                 makefun(&lua_ap_auth_name, APL_REQ_FUNTYPE_STRING, p));
     apr_hash_set(dispatch, "sendfile", APR_HASH_KEY_STRING,
                  makefun(&lua_ap_sendfile, APL_REQ_FUNTYPE_LUACFUN, p));
     apr_hash_set(dispatch, "dbacquire", APR_HASH_KEY_STRING,
                  makefun(&lua_db_acquire, APL_REQ_FUNTYPE_LUACFUN, p));
     apr_hash_set(dispatch, "stat", APR_HASH_KEY_STRING,
                  makefun(&lua_ap_stat, APL_REQ_FUNTYPE_LUACFUN, p));
+    apr_hash_set(dispatch, "get_direntries", APR_HASH_KEY_STRING,
+                 makefun(&lua_ap_getdir, APL_REQ_FUNTYPE_LUACFUN, p));
     apr_hash_set(dispatch, "regex", APR_HASH_KEY_STRING,
                  makefun(&lua_ap_regex, APL_REQ_FUNTYPE_LUACFUN, p));
-    apr_hash_set(dispatch, "sleep", APR_HASH_KEY_STRING,
-                 makefun(&lua_ap_sleep, APL_REQ_FUNTYPE_LUACFUN, p));
+    apr_hash_set(dispatch, "usleep", APR_HASH_KEY_STRING,
+                 makefun(&lua_ap_usleep, APL_REQ_FUNTYPE_LUACFUN, p));
     apr_hash_set(dispatch, "base64_encode", APR_HASH_KEY_STRING,
                  makefun(&lua_apr_b64encode, APL_REQ_FUNTYPE_LUACFUN, p));
     apr_hash_set(dispatch, "base64_decode", APR_HASH_KEY_STRING,
@@ -1919,14 +2151,20 @@ AP_LUA_DECLARE(void) ap_lua_load_request
                  makefun(&lua_apr_md5, APL_REQ_FUNTYPE_LUACFUN, p));
     apr_hash_set(dispatch, "sha1", APR_HASH_KEY_STRING,
                  makefun(&lua_apr_sha1, APL_REQ_FUNTYPE_LUACFUN, p));
+    apr_hash_set(dispatch, "htpassword", APR_HASH_KEY_STRING,
+                 makefun(&lua_apr_htpassword, APL_REQ_FUNTYPE_LUACFUN, p));
+    apr_hash_set(dispatch, "mkdir", APR_HASH_KEY_STRING,
+                 makefun(&lua_apr_mkdir, APL_REQ_FUNTYPE_LUACFUN, p));
+    apr_hash_set(dispatch, "mkrdir", APR_HASH_KEY_STRING,
+                 makefun(&lua_apr_mkrdir, APL_REQ_FUNTYPE_LUACFUN, p));
+    apr_hash_set(dispatch, "rmdir", APR_HASH_KEY_STRING,
+                 makefun(&lua_apr_rmdir, APL_REQ_FUNTYPE_LUACFUN, p));
+    apr_hash_set(dispatch, "date_parse_rfc", APR_HASH_KEY_STRING,
+                 makefun(&lua_apr_date_parse_rfc, APL_REQ_FUNTYPE_LUACFUN, p));
     apr_hash_set(dispatch, "escape", APR_HASH_KEY_STRING,
                  makefun(&lua_ap_escape, APL_REQ_FUNTYPE_LUACFUN, p));
     apr_hash_set(dispatch, "unescape", APR_HASH_KEY_STRING,
                  makefun(&lua_ap_unescape, APL_REQ_FUNTYPE_LUACFUN, p));
-    apr_hash_set(dispatch, "banner", APR_HASH_KEY_STRING,
-                 makefun(&lua_ap_banner, APL_REQ_FUNTYPE_LUACFUN, p));
-    apr_hash_set(dispatch, "port", APR_HASH_KEY_STRING,
-                 makefun(&lua_ap_port, APL_REQ_FUNTYPE_LUACFUN, p));
     apr_hash_set(dispatch, "mpm_query", APR_HASH_KEY_STRING,
                  makefun(&lua_ap_mpm_query, APL_REQ_FUNTYPE_LUACFUN, p));
     apr_hash_set(dispatch, "expr", APR_HASH_KEY_STRING,
@@ -1935,8 +2173,6 @@ AP_LUA_DECLARE(void) ap_lua_load_request
                  makefun(&lua_ap_scoreboard_process, APL_REQ_FUNTYPE_LUACFUN, p));
     apr_hash_set(dispatch, "scoreboard_worker", APR_HASH_KEY_STRING,
                  makefun(&lua_ap_scoreboard_worker, APL_REQ_FUNTYPE_LUACFUN, p));
-    apr_hash_set(dispatch, "started", APR_HASH_KEY_STRING,
-                 makefun(&lua_ap_restarted, APL_REQ_FUNTYPE_LUACFUN, p));
     apr_hash_set(dispatch, "clock", APR_HASH_KEY_STRING,
                  makefun(&lua_ap_clock, APL_REQ_FUNTYPE_LUACFUN, p));
     apr_hash_set(dispatch, "requestbody", APR_HASH_KEY_STRING,
@@ -1975,6 +2211,10 @@ AP_LUA_DECLARE(void) ap_lua_load_request
                  makefun(&lua_ap_state_query, APL_REQ_FUNTYPE_LUACFUN, p));
     apr_hash_set(dispatch, "get_server_name_for_url", APR_HASH_KEY_STRING,
                  makefun(&lua_ap_get_server_name_for_url, APL_REQ_FUNTYPE_LUACFUN, p));
+    apr_hash_set(dispatch, "ivm_get", APR_HASH_KEY_STRING,
+                 makefun(&lua_ivm_get, APL_REQ_FUNTYPE_LUACFUN, p));
+    apr_hash_set(dispatch, "ivm_set", APR_HASH_KEY_STRING,
+                 makefun(&lua_ivm_set, APL_REQ_FUNTYPE_LUACFUN, p));
     
     lua_pushlightuserdata(L, dispatch);
     lua_setfield(L, LUA_REGISTRYINDEX, "Apache2.Request.dispatch");
@@ -2005,7 +2245,7 @@ AP_LUA_DECLARE(void) ap_lua_load_request
 
 }
 
-AP_LUA_DECLARE(void) ap_lua_push_connection(lua_State *L, conn_rec *c)
+void ap_lua_push_connection(lua_State *L, conn_rec *c)
 {
     lua_boxpointer(L, c);
     luaL_getmetatable(L, "Apache2.Connection");
@@ -2022,7 +2262,7 @@ AP_LUA_DECLARE(void) ap_lua_push_connect
 }
 
 
-AP_LUA_DECLARE(void) ap_lua_push_server(lua_State *L, server_rec *s)
+void ap_lua_push_server(lua_State *L, server_rec *s)
 {
     lua_boxpointer(L, s);
     luaL_getmetatable(L, "Apache2.Server");
@@ -2035,7 +2275,7 @@ AP_LUA_DECLARE(void) ap_lua_push_server(
     lua_pop(L, 1);
 }
 
-AP_LUA_DECLARE(void) ap_lua_push_request(lua_State *L, request_rec *r)
+void ap_lua_push_request(lua_State *L, request_rec *r)
 {
     lua_boxpointer(L, r);
     luaL_getmetatable(L, "Apache2.Request");

Modified: httpd/httpd/branches/2.4.x/modules/lua/lua_request.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/lua/lua_request.h?rev=1491468&r1=1491467&r2=1491468&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/lua/lua_request.h (original)
+++ httpd/httpd/branches/2.4.x/modules/lua/lua_request.h Mon Jun 10 14:36:56 2013
@@ -15,21 +15,23 @@
  * limitations under the License.
  */
 
-#include "mod_lua.h"
-
 #ifndef _LUA_REQUEST_H_
 #define _LUA_REQUEST_H_
 
-AP_LUA_DECLARE(void) ap_lua_load_request_lmodule(lua_State *L, apr_pool_t *p);
-AP_LUA_DECLARE(void) ap_lua_push_connection(lua_State *L, conn_rec *r);
-AP_LUA_DECLARE(void) ap_lua_push_server(lua_State *L, server_rec *r);
-AP_LUA_DECLARE(void) ap_lua_push_request(lua_State *L, request_rec *r);
+#include "mod_lua.h"
+#include "util_varbuf.h"
+
+void ap_lua_load_request_lmodule(lua_State *L, apr_pool_t *p);
+void ap_lua_push_connection(lua_State *L, conn_rec *r);
+void ap_lua_push_server(lua_State *L, server_rec *r);
+void ap_lua_push_request(lua_State *L, request_rec *r);
 
 #define APL_REQ_FUNTYPE_STRING      1
 #define APL_REQ_FUNTYPE_INT         2
 #define APL_REQ_FUNTYPE_TABLE       3
 #define APL_REQ_FUNTYPE_LUACFUN     4
 #define APL_REQ_FUNTYPE_BOOLEAN     5
+#define APL_REQ_FUNTYPE_INT64       6
 
 typedef struct
 {
@@ -37,5 +39,12 @@ typedef struct
     int type;
 } req_fun_t;
 
+typedef struct {
+    int type;
+    size_t size;
+    size_t vb_size;
+    lua_Number number;
+    struct ap_varbuf vb;
+} lua_ivm_object;
 
 #endif /* !_LUA_REQUEST_H_ */



Mime
View raw message