Prechádzať zdrojové kódy

Merge pull request #45 from bel2125/master

Support <?= in LSP
sunsetbrew 11 rokov pred
rodič
commit
448dad5fd2
4 zmenil súbory, kde vykonal 119 pridanie a 36 odobranie
  1. 5 3
      docs/Installing.md
  2. 37 21
      docs/UserManual.md
  3. 56 3
      src/mod_lua.inl
  4. 21 9
      test/page.lp

+ 5 - 3
docs/Installing.md

@@ -1,13 +1,15 @@
 Civetweb Install Guide
 ====
 
-This guide covers the distributions for CivetWeb.  The latest source code is available at https://github.com/sunsetbrew/civetweb.
+This guide covers the distributions for CivetWeb.  The latest source code is available at [https://github.com/sunsetbrew/civetweb](https://github.com/sunsetbrew/civetweb).
 
 Windows
 ---
 
-This pre-built version comes pre-built wit Lua support.  There is no SSL support included due to licensing restrictions; however, users can build Civetwab SSL themselves.
- 
+This pre-built version comes pre-built wit Lua support. Libraries for SSL support are not included due to licensing restrictions;
+however, users may add an SSL library themselves.
+Instructions for adding SSL support can be found in [https://github.com/sunsetbrew/civetweb/tree/master/docs](https://github.com/sunsetbrew/civetweb/tree/master/docs)
+
 1. Install the [Visual C++ Redistributable for Visual Studio 2012](http://www.microsoft.com/en-us/download/details.aspx?id=30679)
 2. Download latest *civetweb-win.zip* from [SourceForge](https://sourceforge.net/projects/civetweb/files/)
 3. When started, Civetweb puts itself into the tray.

+ 37 - 21
docs/UserManual.md

@@ -338,40 +338,56 @@ websockets may also be served from a different directory. By default,
 the document_root is used as websocket_root as well.
 
 
-# Lua Server Pages
-Pre-built Windows and Mac civetweb binaries have built-in Lua Server Pages
-support. That means it is possible to write PHP-like scripts with civetweb,
-using Lua programming language instead of PHP. Lua is known
-for it's speed and small size. Civetweb uses Lua version 5.2.2, the
-documentation for it can be found at
-[Lua 5.2 reference manual](http://www.lua.org/manual/5.2/).
+# Lua Scripts and Lua Server Pages
+Pre-built Windows and Mac civetweb binaries have built-in Lua scripting
+support as well as support for Lua Server Pages.
+
+Lua scripts (default extension: *.lua) use plain Lua syntax.
+The body of the script file is not sent directly to the client,
+the Lua script must send header and content of the web page by calling
+the function mg.write(text).
 
-To create a Lua Page, make sure a file has `.lp` extension. For example,
-let's say it is going to be `my_page.lp`. The contents of the file, just like
-with PHP, is HTML with embedded Lua code. Lua code must be enclosed in
-`<?  ?>` blocks, and can appear anywhere on the page. For example, to
-print current weekday name, one can write:
+Lua Server Pages (default extensions: *.lsp, *.lp) are html pages containing
+script elements similar to PHP, using the Lua programming language instead of
+PHP. Lua script elements must be enclosed in `<?  ?>` blocks, and can appear
+anywhere on the page. For example, to print current weekday name, one can
+write:
 
     <p>
       <span>Today is:</span>
       <? mg.write(os.date("%A")) ?>
     </p>
 
+Lua is known for it's speed and small size. Civetweb uses Lua version 5.2.2,
+the documentation for it can be found at
+[Lua 5.2 reference manual](http://www.lua.org/manual/5.2/).
+
+
 Note that this example uses function `mg.write()`, which prints data to the
 web page. Using function `mg.write()` is the way to generate web content from
 inside Lua code. In addition to `mg.write()`, all standard library functions
 are accessible from the Lua code (please check reference manual for details),
-and also information about the request is available in `mg.request_info` object,
-like request method, all headers, etcetera. Please refer to
-`struct mg_request_info` definition in
+and also information about the request is available in `mg.request_info`
+object, like request method, all headers, etcetera.
+
+[page2.lua](https://github.com/sunsetbrew/civetweb/blob/master/test/page2.lua)
+is an example for a plain Lua script.
+
+[page2.lp](https://github.com/sunsetbrew/civetweb/blob/master/test/page2.lp)
+is an example for a Lua Server Page.
+
+Both examples show the content of the `mg.request_info` object as the page
+content. Please refer to `struct mg_request_info` definition in
 [civetweb.h](https://github.com/sunsetbrew/civetweb/blob/master/include/civetweb.h)
-to see what kind of information is present in `mg.request_info` object. Also,
-[page.lp](https://github.com/sunsetbrew/civetweb/blob/master/test/page.lp) and
-[prime_numbers.lp](https://github.com/sunsetbrew/civetweb/blob/master/examples/docroot/prime_numbers.lp)
-contains some example code that uses `request_info` and other functions (form
-submitting for example).
+to see additional information on the elements of the `mg.request_info` object.
+
+Civetweb also provides access to the [SQlite3 database](http://www.sqlite.org/)
+through the [LuaSQLite3 interface](http://lua.sqlite.org/index.cgi/doc/tip/doc/lsqlite3.wiki)
+in Lua. An example is given in
+[page.lp](https://github.com/sunsetbrew/civetweb/blob/master/test/page.lp).
+
 
-Civetweb exports the following to the Lua server page:
+Civetweb exports the following functions to Lua:
 
     mg.read()         -- reads a chunk from POST data, returns it as a string
     mg.write(str)     -- writes string to the client

+ 56 - 3
src/mod_lua.inl

@@ -174,16 +174,57 @@ static void lsp_abort(lua_State *L)
     lua_error(L);
 }
 
+struct lsp_var_reader_data
+{
+    const char * begin;
+    unsigned len;
+    unsigned state;
+};
+
+static const char * lsp_var_reader(lua_State *L, void *ud, size_t *sz)
+{
+    struct lsp_var_reader_data * reader = (struct lsp_var_reader_data *)ud;
+    const char * ret;
+
+    switch (reader->state) {
+        case 0:
+            ret = "mg.write(";
+            *sz = strlen(ret);
+            break;
+        case 1:
+            ret = reader->begin;
+            *sz = reader->len;
+            break;
+        case 2:
+            ret = ")";
+            *sz = strlen(ret);
+            break;
+        default:
+            ret = 0;
+            *sz = 0;
+    }
+
+    reader->state++;
+    return ret;
+}
+
 static int lsp(struct mg_connection *conn, const char *path,
     const char *p, int64_t len, lua_State *L)
 {
-    int i, j, pos = 0, lines = 1, lualines = 0;
+    int i, j, pos = 0, lines = 1, lualines = 0, is_var, lua_ok;
     char chunkname[MG_BUF_LEN];
+    struct lsp_var_reader_data data;
 
     for (i = 0; i < len; i++) {
         if (p[i] == '\n') lines++;
         if ((i + 1) < len && p[i] == '<' && p[i + 1] == '?') {
-            for (j = i + 1; j < len ; j++) {
+
+            is_var = ((i + 2) < len && p[i + 2] == '=');
+
+            if (is_var) j = i + 2;
+            else j = i + 1;
+
+            while (j < len) {
                 if (p[j] == '\n') lualines++;
                 if ((j + 1) < len && p[j] == '?' && p[j + 1] == '>') {
                     mg_write(conn, p + pos, i - pos);
@@ -191,7 +232,17 @@ static int lsp(struct mg_connection *conn, const char *path,
                     snprintf(chunkname, sizeof(chunkname), "@%s+%i", path, lines);
                     lua_pushlightuserdata(L, conn);
                     lua_pushcclosure(L, lsp_error, 1);
-                    if (luaL_loadbuffer(L, p + (i + 2), j - (i + 2), chunkname)) {
+
+                    if (is_var) {
+                        data.begin = p + (i + 3);
+                        data.len = j - (i + 3);
+                        data.state = 0;
+                        lua_ok = lua_load(L, lsp_var_reader, &data, chunkname, NULL);
+                    } else {
+                        lua_ok = luaL_loadbuffer(L, p + (i + 2), j - (i + 2), chunkname);
+                    }
+
+                    if (lua_ok) {
                         /* Syntax error or OOM. Error message is pushed on stack. */
                         lua_pcall(L, 1, 0, 0);
                     } else {
@@ -203,7 +254,9 @@ static int lsp(struct mg_connection *conn, const char *path,
                     i = pos - 1;
                     break;
                 }
+                j++;
             }
+
             if (lualines > 0) {
                 lines += lualines;
                 lualines = 0;

+ 21 - 9
test/page.lp

@@ -4,17 +4,28 @@ Content-Type: text/html
 <html><body>
 
 
-<p>This is an example Lua server page served by
+<p>This is another example of a Lua server page, served by
 <a href="http://code.google.com/p/civetweb">Civetweb web server</a>.
-Civetweb has Lua, Sqlite, and other functionality built in the binary.
-This example page stores the request in the Sqlite database, and shows
-all requests done previously.</p>
-<p> Today is <? mg.write(os.date("%A")) ?>
+</p><p>
+The following features are available:
+<ul>
+<?
+  mg.write("<li>" .. _VERSION .. " server pages</li>")
+  if sqlite3 then
+    mg.write("<li>sqlite3 binding</li>")
+  end
+  if lfs then
+    mg.write("<li>lua file system</li>")
+  end
+?>
+</ul></p>
+<p> Today is <? mg.write(os.date("%A")) ?></p>
+<p> URI is <? mg.write(mg.request_info.uri) ?></p>
+<p> URI is <?=mg.request_info.uri?></p>
 
+<p>Database example:
 <pre>
 <?
-  -- for k,v in pairs(_G) do mg.write(k, '\n') end
-
   -- Open database
   local db = sqlite3.open('requests.db')
 
@@ -32,7 +43,6 @@ all requests done previously.</p>
     );
   ]])
 
-
   -- Add entry about this request
   local stmt = db:prepare(
     'INSERT INTO requests VALUES(NULL, datetime("now"), ?, ?, ?);');
@@ -54,4 +64,6 @@ all requests done previously.</p>
   -- Close database
   db:close()
 ?>
-</pre></body></html>
+</pre></p>
+
+</body></html>