Skip to content

Commit

Permalink
feat: initial checkin
Browse files Browse the repository at this point in the history
  • Loading branch information
joostfaassen committed Jul 23, 2020
0 parents commit 585c539
Show file tree
Hide file tree
Showing 11 changed files with 360 additions and 0 deletions.
13 changes: 13 additions & 0 deletions .editorconfig
@@ -0,0 +1,13 @@
root = true

[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

[*.php]
indent_style = space
indent_size = 4
32 changes: 32 additions & 0 deletions .gitignore
@@ -0,0 +1,32 @@
tmp/
.env
*.tmp
*.bak
*.swp
*~.nib
data/
local.properties
.settings/
composer.lock

### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
nbactions.xml
nb-configuration.xml


### vim ###
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
*.un~
Session.vim
.netrwhist
*~

### Composer ###
vendor/
autotune.json
19 changes: 19 additions & 0 deletions LICENSE.md
@@ -0,0 +1,19 @@
# The MIT License

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

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

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
57 changes: 57 additions & 0 deletions README.md
@@ -0,0 +1,57 @@
Lua PHP
=======

This library enables you to add Lua scripting support to your PHP applications.

## LuaSandbox

The LuaSandbox class allows you to easily run user-supplied Lua scripts in an empty sandbox environment.
This means that dangerous functions (i.e. for file and network IO) are unavailable by default.
To make the sandbox useful, you register your own PHP-implemented functions that you allow the chunks to execute.

## Use-cases

* Support user-supplied scripts to respond to events in your application
* Advanced expressions, filters, segments
* Customizable routing
* ... and many more :)

## Usage

Check the `example/` directory for a well-documented example.

## About Lua

* Website: http://www.lua.org/
* Wikipedia: https://en.wikipedia.org/wiki/Lua_(programming_language)

## Requirements

This library requires that the [PHP Lua extension](https://www.php.net/manual/en/book.lua.php) is installed.

A quick install guide for Ubuntu:

```sh
# Install lua library
apt-get install -y --no-install-recommends lua5.3 liblua5.3-dev
# pecl expects liblua and includes in specific locations, so move them around a bit:
cp /usr/lib/x86_64-linux-gnu/liblua5.3.a /usr/lib/liblua.a
cp /usr/lib/x86_64-linux-gnu/liblua5.3.so /usr/lib/liblua.so
ln -s /usr/include/lua5.3 /usr/include/lua
# Install the lua extension through pecl
pecl install lua
# Activate the lua extension in your PHP config
php --ini # find out where your PHP config files are located
echo "extension=lua.so" > /path/to/my/php/conf.d/lua.ini
```

## License

MIT. Please refer to the [license file](LICENSE) for details.

## Brought to you by the LinkORB Engineering team

<img src="http://www.linkorb.com/d/meta/tier1/images/linkorbengineering-logo.png" width="200px" /><br />
Check out our other projects at [linkorb.com/engineering](http://www.linkorb.com/engineering).

Btw, we're hiring!
23 changes: 23 additions & 0 deletions composer.json
@@ -0,0 +1,23 @@
{
"name": "linkorb/lua",
"description": "Lua PHP: Library for extending your application with lua scripts",
"homepage": "http://www.github.com/linkorb/lua-php",
"keywords": ["php", "lua", "scripting", "sandbox", "linkorb"],
"type": "library",
"authors": [
{
"name": "LinkORB Engineering",
"email": "engineering@linkorb.com",
"role": "Development"
}
],
"require": {
"php": ">=7.2.0"
},
"autoload": {
"psr-4": {
"LinkORB\\Lua\\": "src/"
}
},
"license": "MIT"
}
13 changes: 13 additions & 0 deletions example/example-advanced.lua
@@ -0,0 +1,13 @@
local function on_click(data)
-- error("BWAM")
print("On click!!")
end

return {
name = "My advanced chunk",
description = "This is an example structure",
on_click = on_click,
on_exit = function(data)
print("I'll be back")
end,
}
9 changes: 9 additions & 0 deletions example/example-simple.lua
@@ -0,0 +1,9 @@
-- This is an example lua file to load into the sandbox

return function(foo, bar)
print(reverse(foo) .. ", " .. bar)
-- local f = io.open('/etc/hostname', "rb")
-- local content = f:read "*a"
-- print(content)
return "This is returned from Lua"
end
42 changes: 42 additions & 0 deletions example/example.php
@@ -0,0 +1,42 @@
<?php

require __DIR__ . '/../vendor/autoload.php';

use LinkORB\Lua\LuaSandbox;

// Instantiate a Lua sandbox
$sandbox = LuaSandbox::build();

// A new sandbox has a completely clean environment
// This means you'll have to register your own functions/callbacks
// to make it useful
$sandbox->registerCallback('print', function($text) {
echo "PRINT: " . $text . PHP_EOL;
});

$sandbox->registerCallback('reverse', function($text) {
return strrev($text);
});

// Let's register some callable Lua chunks:
$code = file_get_contents(__DIR__ . '/example-simple.lua');
$sandbox->registerChunk('example-simple', $code);

$code = file_get_contents(__DIR__ . '/example-advanced.lua');
$sandbox->registerChunk('example-advanced', $code);


// You can now call a chunk (assuming it is a function) with arguments:
$res = $sandbox->callChunk('example-simple', ['hello', 'world']);
echo "RETURN VALUE: " . $res . PHP_EOL;

// You can also retrieve a chunk by name:
$chunk = $sandbox->getChunk('example-advanced');
print_r($chunk);
$chunk['on_click']('Click test');

// You can retrieve the environment for inspection:
$e = $sandbox->getEnvironment();
print_r($e);

echo "Done\n";
43 changes: 43 additions & 0 deletions lua/sandbox.lua
@@ -0,0 +1,43 @@
local sandbox_env = {
-- start with an empty environment
}

-- array of registered chunks
local chunks = {}

function registerChunk(chunk_name, code)
local chunk, message = load(code, 'sandbox:' .. chunk_name, 't', sandbox_env)
if not chunk then
error("Failed to register chunk: " .. chunk_name)
end
chunks[chunk_name] = chunk()
end

-- promote an item in the global _ENV to the sandbox env
function registerCallback(name)
sandbox_env[name] = _ENV[name]
end

-- call a chunk by name as a function with parameters
function callChunk(chunk_name, ...)
local chunk = getChunk(chunk_name)
local status, res = pcall(chunk, ...)
if (not status) then
error(res)
end
return res
end

-- retrieve a chunk by name
function getChunk(chunk_name)
local chunk = chunks[chunk_name]
if (not chunk) then
error("Getting unregistered chunk: " .. chunk_name)
end
return chunk
end

-- retrieve the sandbox environment for inspection
function getEnvironment()
return sandbox_env
end
10 changes: 10 additions & 0 deletions src/LuaException.php
@@ -0,0 +1,10 @@
<?php

namespace LinkORB\Lua;

use RuntimeException;

class LuaException extends RuntimeException
{

}
99 changes: 99 additions & 0 deletions src/LuaSandbox.php
@@ -0,0 +1,99 @@
<?php

namespace LinkORB\Lua;

use Lua;

class LuaSandbox
{

protected $lua;

public static function build()
{
$lua = new Lua();
$sandbox = new self($lua);
return $sandbox;
}

protected function error(string $message)
{
throw new LuaException($message);
}

public function __construct(Lua $lua)
{
$this->lua = $lua;

$this->lua->registerCallback("error", function($message) {
$this->error($message);
});

$this->lua->registerCallback("cool", function($message) {
echo "COOL: $message\n";
});

$this->lua->registerCallback("print", function($message, $a = null, $b = null, $c = null) {
echo "PRINT: $message $a $b $c\n";
});

$sandboxCode = file_get_contents(__DIR__ . '/../lua/sandbox.lua');
$this->lua->eval($sandboxCode);
}

public function registerChunk(string $name, string $code): void
{
$res = $this->lua->call("registerChunk", array($name, $code));
if ($res) {
throw new LuaException("Failed to register chunk " . $name);
}
}

public function registerCallback(string $name, callable $cb)
{
$this->lua->registerCallback($name, $cb);
$res = $this->lua->call("registerCallback", array($name));
}


public function getChunk(string $name)
{
$res = $this->lua->call("getChunk", array($name));
return $res;
}


public function callChunk(string $name, $arguments)
{
array_unshift($arguments, $name);
$res = $this->lua->call("callChunk", $arguments);
return $res;
}

public function getEnvironment()
{
$res = $this->lua->call("getEnvironment", []);
return $res;
}



// $x = $lua->call("getChunk", array('demo-advanced'));
// if (!$x) {
// echo "PHP: That failed\n";
// }
// print_r($x);
// $f = $x['onFrame'];
// try {
// $f('ahaha');
// } catch (\Exception $e) {
// print_r($e);
// }
// $f = ($x['onTerminate'] ?? null);
// $f("bye", "x");

// echo "Done\n";

// }

}

0 comments on commit 585c539

Please sign in to comment.