Updated all dependencies and prepared for PHP 8
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
vendor
|
vendor
|
||||||
build
|
build
|
||||||
cache
|
cache
|
||||||
|
stacks
|
||||||
|
config.php
|
||||||
.cache
|
.cache
|
||||||
.config
|
.config
|
||||||
.local
|
.local
|
||||||
|
|||||||
+4
-7
@@ -1,13 +1,10 @@
|
|||||||
FROM cloudobjects/php-app-base:latest
|
FROM cloudobjects/php-app-base:8.4
|
||||||
|
|
||||||
# Add application code
|
# Add application code
|
||||||
ADD / /var/www/app/
|
ADD / /www/
|
||||||
|
|
||||||
# Add an executable to the Docker container for CLI use
|
# Add an executable to the Docker container for CLI use
|
||||||
RUN mv /var/www/app/phpmae.docker /usr/local/bin/phpmae && chmod +x /usr/local/bin/phpmae
|
RUN mv /www/phpmae.docker /usr/local/bin/phpmae && chmod +x /usr/local/bin/phpmae
|
||||||
|
|
||||||
# Have default config.php ready for CLI where init may not run
|
# Have default config.php ready for CLI where init may not run
|
||||||
RUN cp /var/www/app/config.php.default /var/www/app/config.php
|
RUN cp /www/config.php.default /www/config.php
|
||||||
|
|
||||||
# Launch init script
|
|
||||||
CMD ["/bin/sh", "/var/www/app/init.sh"]
|
|
||||||
|
|||||||
+3
-2
@@ -1,7 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Symfony\Component\Finder\Finder;
|
use Symfony\Component\Finder\Finder;
|
||||||
use CloudObjects\SDK\COIDParser, CloudObjects\SDK\ObjectRetriever;
|
use CloudObjects\SDK\COIDParser, CloudObjects\SDK\ObjectRetriever,
|
||||||
|
CloudObjects\SDK\Constants;
|
||||||
use Webmozart\Assert\Assert;
|
use Webmozart\Assert\Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -182,7 +183,7 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
|
|
||||||
$this->taskWriteToFile($stackDir.'/meta.json')
|
$this->taskWriteToFile($stackDir.'/meta.json')
|
||||||
->text(json_encode([
|
->text(json_encode([
|
||||||
'rev' => $stackObject->getProperty(ObjectRetriever::REVISION_PROPERTY)->getValue(),
|
'rev' => $stackObject->getProperty(Constants::PROPERTY_REVISION)->getValue(),
|
||||||
'whitelisted_classes' => $whitelistedClasses
|
'whitelisted_classes' => $whitelistedClasses
|
||||||
]))
|
]))
|
||||||
->run();
|
->run();
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use DI\Container, DI\FactoryInterface, Invoker\InvokerInterface;
|
|||||||
use DI\Definition\Source\DefinitionArray, DI\Definition\Source\SourceChain;
|
use DI\Definition\Source\DefinitionArray, DI\Definition\Source\SourceChain;
|
||||||
use Psr\Http\Message\RequestInterface;
|
use Psr\Http\Message\RequestInterface;
|
||||||
use CloudObjects\SDK\ObjectRetriever, CloudObjects\SDK\COIDParser,
|
use CloudObjects\SDK\ObjectRetriever, CloudObjects\SDK\COIDParser,
|
||||||
CloudObjects\SDK\NodeReader;
|
CloudObjects\SDK\NodeReader, CloudObjects\SDK\Constants;
|
||||||
use CloudObjects\PhpMAE\Exceptions\PhpMAEException;
|
use CloudObjects\PhpMAE\Exceptions\PhpMAEException;
|
||||||
|
|
||||||
class ClassRepository {
|
class ClassRepository {
|
||||||
@@ -147,8 +147,8 @@ class ClassRepository {
|
|||||||
$objectRetriever = $this->container->get(ObjectRetriever::class);
|
$objectRetriever = $this->container->get(ObjectRetriever::class);
|
||||||
|
|
||||||
// Get revision
|
// Get revision
|
||||||
$revision = $object->getProperty(ObjectRetriever::REVISION_PROPERTY)
|
$revision = $object->getProperty(Constants::PROPERTY_REVISION)
|
||||||
? $object->getProperty(ObjectRetriever::REVISION_PROPERTY)->getValue()
|
? $object->getProperty(Constants::PROPERTY_REVISION)->getValue()
|
||||||
: 'LocalConfig';
|
: 'LocalConfig';
|
||||||
|
|
||||||
// Build filename where cached version should exist
|
// Build filename where cached version should exist
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace CloudObjects\PhpMAE;
|
|||||||
|
|
||||||
use CloudObjects\PhpMAE\Sandbox\CustomizedSandbox;
|
use CloudObjects\PhpMAE\Sandbox\CustomizedSandbox;
|
||||||
use PHPSandbox\SandboxWhitelistVisitor, PHPSandbox\ValidatorVisitor;
|
use PHPSandbox\SandboxWhitelistVisitor, PHPSandbox\ValidatorVisitor;
|
||||||
use PhpParser\ParserFactory, PhpParser\NodeTraverser;
|
use PhpParser\ParserFactory, PhpParser\PhpVersion, PhpParser\NodeTraverser;
|
||||||
use ML\IRI\IRI;
|
use ML\IRI\IRI;
|
||||||
use CloudObjects\SDK\COIDParser;
|
use CloudObjects\SDK\COIDParser;
|
||||||
use CloudObjects\PhpMAE\Exceptions\PhpMAEException;
|
use CloudObjects\PhpMAE\Exceptions\PhpMAEException;
|
||||||
@@ -43,7 +43,6 @@ class ClassValidator {
|
|||||||
'GuzzleHttp\Client',
|
'GuzzleHttp\Client',
|
||||||
'GuzzleHttp\HandlerStack', 'GuzzleHttp\Middleware',
|
'GuzzleHttp\HandlerStack', 'GuzzleHttp\Middleware',
|
||||||
'GuzzleHttp\Handler\CurlHandler',
|
'GuzzleHttp\Handler\CurlHandler',
|
||||||
'GuzzleHttp\Subscriber\Oauth\Oauth1',
|
|
||||||
'GuzzleHttp\Promise',
|
'GuzzleHttp\Promise',
|
||||||
'Dflydev\FigCookies\SetCookie',
|
'Dflydev\FigCookies\SetCookie',
|
||||||
'Symfony\Component\Mime\Email',
|
'Symfony\Component\Mime\Email',
|
||||||
@@ -105,7 +104,7 @@ class ClassValidator {
|
|||||||
$stack = ClassRepository::DEFAULT_STACK) {
|
$stack = ClassRepository::DEFAULT_STACK) {
|
||||||
|
|
||||||
// Initialize parser and parse source code
|
// Initialize parser and parse source code
|
||||||
$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
|
$parser = (new ParserFactory)->createForVersion(PhpVersion::getHostVersion());
|
||||||
$ast = $parser->parse($sourceCode);
|
$ast = $parser->parse($sourceCode);
|
||||||
|
|
||||||
// Parse and dump use statements
|
// Parse and dump use statements
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use Psr\Http\Message\RequestInterface, Psr\Http\Message\ResponseInterface;
|
|||||||
use DI\ContainerBuilder;
|
use DI\ContainerBuilder;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\Common\Cache\FilesystemCache;
|
use Doctrine\Common\Cache\FilesystemCache;
|
||||||
use Slim\Http\Response;
|
use Slim\Psr7\Response;
|
||||||
use Symfony\Component\Mailer\MailerInterface,
|
use Symfony\Component\Mailer\MailerInterface,
|
||||||
Symfony\Component\Mailer\Transport, Symfony\Component\Mailer\Mailer;
|
Symfony\Component\Mailer\Transport, Symfony\Component\Mailer\Mailer;
|
||||||
use CloudObjects\SDK\ObjectRetriever, CloudObjects\SDK\NodeReader, CloudObjects\SDK\COIDParser;
|
use CloudObjects\SDK\ObjectRetriever, CloudObjects\SDK\NodeReader, CloudObjects\SDK\COIDParser;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class SandboxedContainer implements ContainerInterface {
|
|||||||
$this->container = $container;
|
$this->container = $container;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function has($id) {
|
public function has($id) : bool {
|
||||||
return $this->container->has($id);
|
return $this->container->has($id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use DI\Definition\Source\DefinitionSource, DI\Definition\Source\Autowiring,
|
|||||||
*/
|
*/
|
||||||
class WhitelistReflectionBasedAutowiring extends ReflectionBasedAutowiring implements DefinitionSource, Autowiring {
|
class WhitelistReflectionBasedAutowiring extends ReflectionBasedAutowiring implements DefinitionSource, Autowiring {
|
||||||
|
|
||||||
public function autowire(string $name, ObjectDefinition $definition = null) {
|
public function autowire(string $name, ?ObjectDefinition $definition = null) : ?ObjectDefinition {
|
||||||
return isset($definition) ? parent::autowire($name, $definition) : null;
|
return isset($definition) ? parent::autowire($name, $definition) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+30
-26
@@ -10,8 +10,9 @@ use Psr\Http\Message\RequestInterface, Psr\Http\Message\ResponseInterface,
|
|||||||
Psr\Http\Message\ServerRequestInterface;
|
Psr\Http\Message\ServerRequestInterface;
|
||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
use Psr\Http\Server\RequestHandlerInterface;
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
use Slim\App;
|
use Slim\Psr7\Response;
|
||||||
use Slim\Http\Headers, Slim\Http\Request, Slim\Http\Response, Slim\Http\Environment;
|
use Slim\Factory\ServerRequestCreatorFactory;
|
||||||
|
use Slim\ResponseEmitter;
|
||||||
use ML\IRI\IRI;
|
use ML\IRI\IRI;
|
||||||
use ML\JsonLD\Node;
|
use ML\JsonLD\Node;
|
||||||
use Tuupola\Middleware\HttpBasicAuthentication,
|
use Tuupola\Middleware\HttpBasicAuthentication,
|
||||||
@@ -35,7 +36,6 @@ class Engine implements RequestHandlerInterface {
|
|||||||
|
|
||||||
private $objectRetriever;
|
private $objectRetriever;
|
||||||
private $classRepository;
|
private $classRepository;
|
||||||
private $slim;
|
|
||||||
private $container;
|
private $container;
|
||||||
private $reader;
|
private $reader;
|
||||||
|
|
||||||
@@ -43,12 +43,11 @@ class Engine implements RequestHandlerInterface {
|
|||||||
private $runClass;
|
private $runClass;
|
||||||
|
|
||||||
public function __construct(ObjectRetriever $objectRetriever,
|
public function __construct(ObjectRetriever $objectRetriever,
|
||||||
ClassRepository $classRepository, App $slim,
|
ClassRepository $classRepository,
|
||||||
ErrorHandler $errorHandler, ContainerInterface $container) {
|
ErrorHandler $errorHandler, ContainerInterface $container) {
|
||||||
|
|
||||||
$this->objectRetriever = $objectRetriever;
|
$this->objectRetriever = $objectRetriever;
|
||||||
$this->classRepository = $classRepository;
|
$this->classRepository = $classRepository;
|
||||||
$this->slim = $slim;
|
|
||||||
$this->container = $container;
|
$this->container = $container;
|
||||||
$this->reader = new NodeReader([
|
$this->reader = new NodeReader([
|
||||||
'prefixes' => [
|
'prefixes' => [
|
||||||
@@ -149,14 +148,14 @@ class Engine implements RequestHandlerInterface {
|
|||||||
if ($this->reader->getFirstValueBool($this->object, 'phpmae:allowsGETRequests'))
|
if ($this->reader->getFirstValueBool($this->object, 'phpmae:allowsGETRequests'))
|
||||||
$input = $request->getQueryParams();
|
$input = $request->getQueryParams();
|
||||||
else
|
else
|
||||||
return (new Response(405));
|
return new Response(405);
|
||||||
} elseif ($request->getMethod() == 'POST') {
|
} elseif ($request->getMethod() == 'POST') {
|
||||||
// POST is always allowed
|
// POST is always allowed
|
||||||
$input = $request->getParsedBody();
|
$input = $request->getParsedBody();
|
||||||
if (!is_array($input))
|
if (!is_array($input))
|
||||||
$input = [];
|
$input = [];
|
||||||
} else
|
} else
|
||||||
return (new Response(405));
|
return new Response(405);
|
||||||
|
|
||||||
set_time_limit($this->container->has('execution_time_limit')
|
set_time_limit($this->container->has('execution_time_limit')
|
||||||
? $this->container->get('execution_time_limit') : self::CLASS_TIME_LIMIT);
|
? $this->container->get('execution_time_limit') : self::CLASS_TIME_LIMIT);
|
||||||
@@ -171,24 +170,28 @@ class Engine implements RequestHandlerInterface {
|
|||||||
*/
|
*/
|
||||||
public function generateResponse($content) {
|
public function generateResponse($content) {
|
||||||
$lowercaseContent = is_string($content) ? strtolower($content) : '';
|
$lowercaseContent = is_string($content) ? strtolower($content) : '';
|
||||||
if (!isset($content))
|
if (!isset($content)) {
|
||||||
// Empty response
|
// Empty response
|
||||||
$response = new Response(204);
|
$response = new Response(204);
|
||||||
elseif (is_string($content) && (substr($lowercaseContent, 0, 5) == '<html' || substr($lowercaseContent, 0, 14) == '<!doctype html'))
|
} elseif (is_string($content) && (substr($lowercaseContent, 0, 5) == '<html' || substr($lowercaseContent, 0, 14) == '<!doctype html')) {
|
||||||
// HTML response
|
// HTML response
|
||||||
$response = (new Response)->write($content);
|
$response = new Response(200);
|
||||||
elseif (is_string($content) && (substr($lowercaseContent, 0, 7) == 'http://' || substr($lowercaseContent, 0, 8) == 'https://'))
|
$response->getBody()->write($content);
|
||||||
|
} elseif (is_string($content) && (substr($lowercaseContent, 0, 7) == 'http://' || substr($lowercaseContent, 0, 8) == 'https://')) {
|
||||||
// Redirect response
|
// Redirect response
|
||||||
$response = (new Response)->withRedirect($content);
|
$response = (new Response(302))->withHeader('Location', $content);
|
||||||
elseif (is_string($content) || is_numeric($content))
|
} elseif (is_string($content) || is_numeric($content)) {
|
||||||
// Plain text response
|
// Plain text response
|
||||||
$response = (new Response)->withHeader('Content-Type', 'text/plain')->write($content);
|
$response = (new Response(200))->withHeader('Content-Type', 'text/plain');
|
||||||
elseif (is_object($content) && in_array(ResponseInterface::class, class_implements($content)))
|
$response->getBody()->write((string)$content);
|
||||||
|
} elseif (is_object($content) && in_array(ResponseInterface::class, class_implements($content))) {
|
||||||
// Existing response to pass through
|
// Existing response to pass through
|
||||||
$response = $content;
|
$response = $content;
|
||||||
else
|
} else {
|
||||||
// JSON response (default)
|
// JSON response (default)
|
||||||
$response = (new Response)->withJson($content);
|
$response = (new Response(200))->withHeader('Content-Type', 'application/json');
|
||||||
|
$response->getBody()->write(json_encode($content));
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: add support for XML
|
// TODO: add support for XML
|
||||||
|
|
||||||
@@ -219,7 +222,8 @@ class Engine implements RequestHandlerInterface {
|
|||||||
* Start execution of a request.
|
* Start execution of a request.
|
||||||
*/
|
*/
|
||||||
public function execute(RequestInterface $request) {
|
public function execute(RequestInterface $request) {
|
||||||
$path = rtrim($request->getUri()->getBasePath().$request->getUri()->getPath(), '/');
|
$path = $request->getUri()->getPath();
|
||||||
|
|
||||||
switch ($path) {
|
switch ($path) {
|
||||||
case "":
|
case "":
|
||||||
case "/":
|
case "/":
|
||||||
@@ -243,7 +247,8 @@ class Engine implements RequestHandlerInterface {
|
|||||||
if (file_exists(__DIR__.'/../static'.$path)) {
|
if (file_exists(__DIR__.'/../static'.$path)) {
|
||||||
// Proxy for static files
|
// Proxy for static files
|
||||||
$filename = realpath(__DIR__.'/../static'.$path);
|
$filename = realpath(__DIR__.'/../static'.$path);
|
||||||
$response = (new Response)->write(file_get_contents($filename));
|
$response = new Response(200);
|
||||||
|
$response->getBody()->write(file_get_contents($filename));
|
||||||
switch (pathinfo($filename, PATHINFO_EXTENSION)) {
|
switch (pathinfo($filename, PATHINFO_EXTENSION)) {
|
||||||
case "css":
|
case "css":
|
||||||
return $response->withHeader('Content-Type', 'text/css');
|
return $response->withHeader('Content-Type', 'text/css');
|
||||||
@@ -278,7 +283,7 @@ class Engine implements RequestHandlerInterface {
|
|||||||
*/
|
*/
|
||||||
public function loadRunClass(IRI $coid, RequestInterface $request = null) {
|
public function loadRunClass(IRI $coid, RequestInterface $request = null) {
|
||||||
if (COIDParser::isValidCOID($coid) && COIDParser::getType($coid) != COIDParser::COID_ROOT) {
|
if (COIDParser::isValidCOID($coid) && COIDParser::getType($coid) != COIDParser::COID_ROOT) {
|
||||||
$this->object = $this->objectRetriever->get($coid);
|
$this->object = $this->objectRetriever->getObjectNode($coid);
|
||||||
if (!isset($this->object))
|
if (!isset($this->object))
|
||||||
throw new PhpMAEException("The object <" . (string)$coid . "> does not exist or this phpMAE instance is not allowed to access it.");
|
throw new PhpMAEException("The object <" . (string)$coid . "> does not exist or this phpMAE instance is not allowed to access it.");
|
||||||
$this->runClass = $this->classRepository->createInstance($this->object, $request);
|
$this->runClass = $this->classRepository->createInstance($this->object, $request);
|
||||||
@@ -315,18 +320,17 @@ class Engine implements RequestHandlerInterface {
|
|||||||
public function run() {
|
public function run() {
|
||||||
set_time_limit(self::PREPARE_TIME_LIMIT);
|
set_time_limit(self::PREPARE_TIME_LIMIT);
|
||||||
|
|
||||||
$env = new Environment($_SERVER);
|
$request = ServerRequestCreatorFactory::create()->createServerRequestFromGlobals();
|
||||||
$request = Request::createFromEnvironment($env);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$response = $this->execute($request);
|
$response = $this->execute($request);
|
||||||
|
|
||||||
} catch (PhpMAEException $e) {
|
} catch (PhpMAEException $e) {
|
||||||
// Create plain-text error response
|
// Create plain-text error response
|
||||||
$response = (new Response(500))
|
$response = (new Response(500))->withHeader('Content-Type', 'text/plain');
|
||||||
->withHeader('Content-Type', 'text/plain')
|
$response->getBody()->write($e->getMessage());
|
||||||
->write($e->getMessage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->slim->respond($response);
|
(new ResponseEmitter())->emit($response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,27 +6,25 @@
|
|||||||
|
|
||||||
namespace CloudObjects\PhpMAE;
|
namespace CloudObjects\PhpMAE;
|
||||||
|
|
||||||
use Slim\App;
|
use Slim\Psr7\Response;
|
||||||
use Slim\Http\Response;
|
use Slim\ResponseEmitter;
|
||||||
use ML\JsonLD\Node;
|
use ML\JsonLD\Node;
|
||||||
use CloudObjects\SDK\ObjectRetriever;
|
use CloudObjects\SDK\ObjectRetriever;
|
||||||
|
|
||||||
class ErrorHandler {
|
class ErrorHandler {
|
||||||
|
|
||||||
private $classMap = [];
|
private $classMap = [];
|
||||||
private $slim;
|
|
||||||
private $responseGenerator;
|
private $responseGenerator;
|
||||||
|
|
||||||
public function __construct(App $slim) {
|
public function __construct() {
|
||||||
$this->slim = $slim;
|
// ini_set("display_errors", 0);
|
||||||
ini_set("display_errors", 0);
|
|
||||||
$this->setResponseGenerator(function($error, $object) {
|
$this->setResponseGenerator(function($error, $object) {
|
||||||
$message = substr($error['message'], 0, strpos($error['message'], ' in /'));
|
$message = substr($error['message'], 0, strpos($error['message'], ' in /'));
|
||||||
return (new Response(500))
|
$response = (new Response(500))->withHeader('Content-Type', 'text/plain');
|
||||||
->withHeader('Content-Type', 'text/plain')
|
$response->getBody()->write("Error in implementation of <".$object->getId()."> at revision "
|
||||||
->write("Error in implementation of <".$object->getId()."> at revision "
|
|
||||||
. $object->getProperty(ObjectRetriever::REVISION_PROPERTY)->getValue()
|
. $object->getProperty(ObjectRetriever::REVISION_PROPERTY)->getValue()
|
||||||
. ":\n".$message);
|
. ":\n".$message);
|
||||||
|
return $response;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +42,7 @@ class ErrorHandler {
|
|||||||
&& isset($this->classMap[$error['file']])) {
|
&& isset($this->classMap[$error['file']])) {
|
||||||
|
|
||||||
$response = call_user_func($this->responseGenerator, $error, $this->classMap[$error['file']]);
|
$response = call_user_func($this->responseGenerator, $error, $this->classMap[$error['file']]);
|
||||||
$this->slim->respond($response);
|
(new ResponseEmitter())->emit($response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
namespace CloudObjects\PhpMAE;
|
namespace CloudObjects\PhpMAE;
|
||||||
|
|
||||||
use Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Slim\Http\Response;
|
use Slim\Psr7\Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The JsonRPCTransport writes JsonRPC output into a Slim response.
|
* The JsonRPCTransport writes JsonRPC output into a Slim response.
|
||||||
@@ -19,10 +19,11 @@ class JsonRPCTransport {
|
|||||||
public function reply($data) {
|
public function reply($data) {
|
||||||
if (is_a($data, ResponseInterface::class))
|
if (is_a($data, ResponseInterface::class))
|
||||||
$this->response = $data->withHeader('C-PhpMae-Passthru', '1');
|
$this->response = $data->withHeader('C-PhpMae-Passthru', '1');
|
||||||
else
|
else {
|
||||||
$this->response = (new Response(200))
|
$this->response = (new Response(200))
|
||||||
->withHeader('Content-Type', 'application/json')
|
->withHeader('Content-Type', 'application/json');
|
||||||
->write($data);
|
$this->response->getBody()->write($data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function receive() {
|
public function receive() {
|
||||||
|
|||||||
+39
-33
@@ -10,9 +10,11 @@ use InvalidArgumentException;
|
|||||||
use Psr\Http\Message\RequestInterface, Psr\Http\Message\ResponseInterface;
|
use Psr\Http\Message\RequestInterface, Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
use Slim\App;
|
use Slim\App;
|
||||||
use Tuupola\Middleware\CorsMiddleware;;
|
use Slim\Factory\AppFactory;
|
||||||
use Slim\Http\Environment, Slim\Http\Uri, Slim\Http\Response,
|
use Slim\Factory\ServerRequestCreatorFactory;
|
||||||
Slim\Http\Request, Slim\Http\Headers;
|
use Slim\ResponseEmitter;
|
||||||
|
use Slim\Psr7\Response;
|
||||||
|
use Tuupola\Middleware\CorsMiddleware;
|
||||||
use GuzzleHttp\Client;
|
use GuzzleHttp\Client;
|
||||||
use GuzzleHttp\Exception\BadResponseException;
|
use GuzzleHttp\Exception\BadResponseException;
|
||||||
use GuzzleHttp\Psr7\ServerRequest;
|
use GuzzleHttp\Psr7\ServerRequest;
|
||||||
@@ -40,11 +42,10 @@ class Router {
|
|||||||
$this->container = $container;
|
$this->container = $container;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getRequestHeaders(Request $request) {
|
private function getRequestHeaders(RequestInterface $request) {
|
||||||
$headers = new Headers; // this instance is required to access the "normalizeKey" method
|
|
||||||
$output = [];
|
$output = [];
|
||||||
foreach (array_keys($request->getHeaders()) as $key) {
|
foreach (array_keys($request->getHeaders()) as $key) {
|
||||||
$key = $headers->normalizeKey($key);
|
$key = strtolower($key);
|
||||||
if (substr($key, 0, 9) == 'c-phpmae-' || $key == 'host') {
|
if (substr($key, 0, 9) == 'c-phpmae-' || $key == 'host') {
|
||||||
// do not forward "Host" header or custom phpMAE headers
|
// do not forward "Host" header or custom phpMAE headers
|
||||||
continue;
|
continue;
|
||||||
@@ -112,10 +113,13 @@ class Router {
|
|||||||
$params = $request->getQueryParams();
|
$params = $request->getQueryParams();
|
||||||
}
|
}
|
||||||
} catch (InvalidArgumentException $e) {
|
} catch (InvalidArgumentException $e) {
|
||||||
return (new Response(400))->withJson([
|
$errorResponse = (new Response(400))
|
||||||
|
->withHeader('Content-Type', 'application/json');
|
||||||
|
$errorResponse->getBody()->write(json_encode([
|
||||||
'error' => 'InputValidationFailed',
|
'error' => 'InputValidationFailed',
|
||||||
'message' => $e->getMessage()
|
'message' => $e->getMessage()
|
||||||
]);
|
]));
|
||||||
|
return $errorResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add static parameters from Router
|
// Add static parameters from Router
|
||||||
@@ -158,7 +162,10 @@ class Router {
|
|||||||
if (isset($rpcResponse['result'])) {
|
if (isset($rpcResponse['result'])) {
|
||||||
return $engine->generateResponse($rpcResponse['result']);
|
return $engine->generateResponse($rpcResponse['result']);
|
||||||
} else {
|
} else {
|
||||||
return (new Response(500))->withJson($rpcResponse);
|
$errResponse = (new Response(500))
|
||||||
|
->withHeader('Content-Type', 'application/json');
|
||||||
|
$errResponse->getBody()->write(json_encode($rpcResponse));
|
||||||
|
return $errResponse;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Generic class execution (invokable)
|
// Generic class execution (invokable)
|
||||||
@@ -167,7 +174,8 @@ class Router {
|
|||||||
|
|
||||||
} elseif ($reader->hasProperty($r, 'phpmae:redirectsToURL')) {
|
} elseif ($reader->hasProperty($r, 'phpmae:redirectsToURL')) {
|
||||||
// Route to redirect to a specific external URL
|
// Route to redirect to a specific external URL
|
||||||
return (new Response)->withRedirect($reader->getFirstValueString($r, 'phpmae:redirectsToURL'));
|
return (new Response(302))
|
||||||
|
->withHeader('Location', $reader->getFirstValueString($r, 'phpmae:redirectsToURL'));
|
||||||
|
|
||||||
} elseif ($reader->hasProperty($r, 'phpmae:redirectsToBaseURL')) {
|
} elseif ($reader->hasProperty($r, 'phpmae:redirectsToBaseURL')) {
|
||||||
// Route to redirect to an external base URL
|
// Route to redirect to an external base URL
|
||||||
@@ -175,7 +183,7 @@ class Router {
|
|||||||
$uri = $request->getUri();
|
$uri = $request->getUri();
|
||||||
$targetUrl = (string)$baseUrl->resolve(substr($uri->getPath(), 1) . ($uri->getQuery() != '' ? '?'.$uri->getQuery() : ''));
|
$targetUrl = (string)$baseUrl->resolve(substr($uri->getPath(), 1) . ($uri->getQuery() != '' ? '?'.$uri->getQuery() : ''));
|
||||||
|
|
||||||
return (new Response)->withRedirect($targetUrl);
|
return (new Response(302))->withHeader('Location', $targetUrl);
|
||||||
|
|
||||||
} elseif ($reader->hasProperty($r, 'phpmae:proxiesRequestsToBaseURL')) {
|
} elseif ($reader->hasProperty($r, 'phpmae:proxiesRequestsToBaseURL')) {
|
||||||
// Route to proxy requests to an external URL
|
// Route to proxy requests to an external URL
|
||||||
@@ -200,22 +208,28 @@ class Router {
|
|||||||
|
|
||||||
if ($request->hasHeader('If-None-Match') && strpos($request->getHeaderLine('If-None-Match'), $etag) > -1) {
|
if ($request->hasHeader('If-None-Match') && strpos($request->getHeaderLine('If-None-Match'), $etag) > -1) {
|
||||||
// Can use cached version
|
// Can use cached version
|
||||||
return (new Response(304))->withHeader('ETag', $etag)
|
return (new Response(304))
|
||||||
|
->withHeader('ETag', $etag)
|
||||||
->withHeader('Cache-Control', 'max-age='.self::STATIC_CACHE_TTL.', public');
|
->withHeader('Cache-Control', 'max-age='.self::STATIC_CACHE_TTL.', public');
|
||||||
}
|
}
|
||||||
|
|
||||||
$attachmentContent = $retriever->getAttachment(new IRI($object->getId()),
|
$attachmentContent = $retriever->getAttachment(new IRI($object->getId()),
|
||||||
$reader->getFirstValueString($r, 'phpmae:servesStaticFileAttachment'));
|
$reader->getFirstValueString($r, 'phpmae:servesStaticFileAttachment'));
|
||||||
|
|
||||||
if (!isset($attachmentContent))
|
if (!isset($attachmentContent)) {
|
||||||
return (new Response(501))->write("Requested static file attachment cannot be found.");
|
$notFoundResponse = new Response(501);
|
||||||
|
$notFoundResponse->getBody()->write("Requested static file attachment cannot be found.");
|
||||||
|
return $notFoundResponse;
|
||||||
|
}
|
||||||
|
|
||||||
return $engine->generateResponse($attachmentContent)
|
return $engine->generateResponse($attachmentContent)
|
||||||
->withHeader('ETag', $etag)
|
->withHeader('ETag', $etag)
|
||||||
->withHeader('Cache-Control', 'max-age='.self::STATIC_CACHE_TTL.', public');
|
->withHeader('Cache-Control', 'max-age='.self::STATIC_CACHE_TTL.', public');
|
||||||
} else {
|
} else {
|
||||||
// Route has no implementation
|
// Route has no implementation
|
||||||
return (new Response(501))->write("Route implementation not available or no access granted.");
|
$notImplResponse = new Response(501);
|
||||||
|
$notImplResponse->getBody()->write("Route implementation not available or no access granted.");
|
||||||
|
return $notImplResponse;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -239,22 +253,16 @@ class Router {
|
|||||||
$modes = explode('|', $this->container->get('mode'));
|
$modes = explode('|', $this->container->get('mode'));
|
||||||
$fallback = false;
|
$fallback = false;
|
||||||
|
|
||||||
$configuration = [
|
$app = AppFactory::create();
|
||||||
'settings' => [
|
$serverRequest = ServerRequestCreatorFactory::create()->createServerRequestFromGlobals();
|
||||||
'displayErrorDetails' => true,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
$c = new \Slim\Container($configuration);
|
|
||||||
$app = new App($c);
|
|
||||||
|
|
||||||
$router = null;
|
$router = null;
|
||||||
$env = new Environment($_SERVER);
|
|
||||||
foreach ($modes as $m) {
|
foreach ($modes as $m) {
|
||||||
switch ($m) {
|
switch ($m) {
|
||||||
case 'router:vhost':
|
case 'router:vhost':
|
||||||
if ($router == null) {
|
if ($router == null) {
|
||||||
$uri = Uri::createFromEnvironment($env);
|
$uri = $serverRequest->getUri();
|
||||||
if ($uri->getHost() == 'localhost' || filter_var($uri->getHost(), FILTER_VALIDATE_IP) !== false) continue;
|
if ($uri->getHost() == 'localhost' || filter_var($uri->getHost(), FILTER_VALIDATE_IP) !== false) break;
|
||||||
|
|
||||||
$namespace = $this->objectRetriever->get('coid://'.$uri->getHost());
|
$namespace = $this->objectRetriever->get('coid://'.$uri->getHost());
|
||||||
if (isset($namespace) && $routerCoid = $namespace->getProperty('coid://phpmae.dev/hasRouter'))
|
if (isset($namespace) && $routerCoid = $namespace->getProperty('coid://phpmae.dev/hasRouter'))
|
||||||
@@ -263,9 +271,8 @@ class Router {
|
|||||||
break;
|
break;
|
||||||
case 'router:header':
|
case 'router:header':
|
||||||
if ($router == null) {
|
if ($router == null) {
|
||||||
$request = Request::createFromEnvironment($env);
|
if ($serverRequest->hasHeader('C-PhpMae-Router-COID'))
|
||||||
if ($request->hasHeader('C-PhpMae-Router-COID'))
|
$router = $this->getRouter(new IRI($serverRequest->getHeaderLine('C-PhpMae-Router-COID')));
|
||||||
$router = $this->getRouter(new IRI($request->getHeaderLine('C-PhpMae-Router-COID')));
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'default':
|
case 'default':
|
||||||
@@ -281,7 +288,7 @@ class Router {
|
|||||||
|
|
||||||
if (isset($router)) {
|
if (isset($router)) {
|
||||||
$this->configure($app, $router);
|
$this->configure($app, $router);
|
||||||
$response = $app->run(true);
|
$response = $app->handle($serverRequest);
|
||||||
} elseif ($fallback) {
|
} elseif ($fallback) {
|
||||||
$this->container->get(Engine::class)
|
$this->container->get(Engine::class)
|
||||||
->run();
|
->run();
|
||||||
@@ -292,11 +299,10 @@ class Router {
|
|||||||
|
|
||||||
} catch (PhpMAEException $e) {
|
} catch (PhpMAEException $e) {
|
||||||
// Create plain-text error response
|
// Create plain-text error response
|
||||||
$response = (new Response(500))
|
$response = (new Response(500))->withHeader('Content-Type', 'text/plain');
|
||||||
->withHeader('Content-Type', 'text/plain')
|
$response->getBody()->write($e->getMessage());
|
||||||
->write($e->getMessage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$app->respond($response);
|
(new ResponseEmitter())->emit($response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@ namespace CloudObjects\PhpMAE\Sandbox;
|
|||||||
|
|
||||||
use PHPSandbox\PHPSandbox, PHPSandbox\SandboxWhitelistVisitor,
|
use PHPSandbox\PHPSandbox, PHPSandbox\SandboxWhitelistVisitor,
|
||||||
PHPSandbox\Error;
|
PHPSandbox\Error;
|
||||||
use PhpParser\NodeTraverser, PhpParser\ParserFactory;
|
use PhpParser\NodeTraverser, PhpParser\PhpVersion, PhpParser\ParserFactory;
|
||||||
use PhpParser\PrettyPrinter\Standard;
|
use PhpParser\PrettyPrinter\Standard;
|
||||||
use PhpParser\Error as ParserError;
|
use PhpParser\Error as ParserError;
|
||||||
|
|
||||||
@@ -38,10 +38,10 @@ class CustomizedSandbox extends PHPSandbox {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function validate($code) {
|
public function validate($code) : self {
|
||||||
$this->preparsed_code = $this->disassemble($code);
|
$this->preparsed_code = $this->disassemble($code);
|
||||||
$factory = new ParserFactory;
|
$factory = new ParserFactory;
|
||||||
$parser = $factory->create(ParserFactory::PREFER_PHP7);
|
$parser = $factory->createForVersion(PhpVersion::getHostVersion());
|
||||||
try {
|
try {
|
||||||
$this->parsed_ast = $parser->parse($this->preparsed_code);
|
$this->parsed_ast = $parser->parse($this->preparsed_code);
|
||||||
} catch (ParserError $error) {
|
} catch (ParserError $error) {
|
||||||
@@ -55,13 +55,11 @@ class CustomizedSandbox extends PHPSandbox {
|
|||||||
($this->allow_traits && $this->auto_whitelist_traits) ||
|
($this->allow_traits && $this->auto_whitelist_traits) ||
|
||||||
($this->allow_globals && $this->auto_whitelist_globals)){
|
($this->allow_globals && $this->auto_whitelist_globals)){
|
||||||
$traverser = new NodeTraverser;
|
$traverser = new NodeTraverser;
|
||||||
$whitelister = new SandboxWhitelistVisitor($this);
|
$traverser->addVisitor(new SandboxWhitelistVisitor($this));
|
||||||
$traverser->addVisitor($whitelister);
|
|
||||||
$traverser->traverse($this->parsed_ast);
|
$traverser->traverse($this->parsed_ast);
|
||||||
}
|
}
|
||||||
$traverser = new NodeTraverser;
|
$traverser = new NodeTraverser;
|
||||||
$validator = new CustomizedValidatorVisitor($this);
|
$traverser->addVisitor(new CustomizedValidatorVisitor($this));
|
||||||
$traverser->addVisitor($validator);
|
|
||||||
$this->prepared_ast = $traverser->traverse($this->parsed_ast);
|
$this->prepared_ast = $traverser->traverse($this->parsed_ast);
|
||||||
$this->prepared_code = $prettyPrinter->prettyPrint($this->prepared_ast);
|
$this->prepared_code = $prettyPrinter->prettyPrint($this->prepared_ast);
|
||||||
return $this;
|
return $this;
|
||||||
|
|||||||
@@ -6,15 +6,50 @@
|
|||||||
|
|
||||||
namespace CloudObjects\PhpMAE\Sandbox;
|
namespace CloudObjects\PhpMAE\Sandbox;
|
||||||
|
|
||||||
use PhpParser\Node, PhpParser\NodeVisitorAbstract;
|
use PhpParser\Node,
|
||||||
use PHPSandbox\PHPSandbox, PHPSandbox\ValidatorVisitor,
|
PhpParser\NodeTraverser,
|
||||||
PHPSandbox\Error;
|
PhpParser\NodeVisitorAbstract,
|
||||||
|
Throwable;
|
||||||
|
|
||||||
class CustomizedValidatorVisitor extends ValidatorVisitor {
|
/**
|
||||||
|
* Validator class for PHP Sandboxes.
|
||||||
|
*
|
||||||
|
* This class takes parsed AST code and checks it against the passed PHPSandbox instance
|
||||||
|
* configuration for errors, and throws exceptions if they are found
|
||||||
|
*
|
||||||
|
* @namespace PHPSandbox
|
||||||
|
*
|
||||||
|
* @author Elijah Horton <elijah@corveda.com>
|
||||||
|
* @version 3.0
|
||||||
|
*/
|
||||||
|
class CustomizedValidatorVisitor extends NodeVisitorAbstract {
|
||||||
|
|
||||||
|
/** The PHPSandbox instance to check against
|
||||||
|
* @var PHPSandbox
|
||||||
|
*/
|
||||||
|
protected CustomizedSandbox $sandbox;
|
||||||
|
|
||||||
|
/** ValidatorVisitor class constructor
|
||||||
|
*
|
||||||
|
* This constructor takes a passed PHPSandbox instance to check against for validating sandboxed code.
|
||||||
|
*
|
||||||
|
* @param CustomizedSandbox $sandbox The PHPSandbox instance to check against
|
||||||
|
*/
|
||||||
|
public function __construct(CustomizedSandbox $sandbox){
|
||||||
|
$this->sandbox = $sandbox;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Examine the current PhpParser_Node node against the PHPSandbox configuration for validating sandboxed code
|
||||||
|
*
|
||||||
|
* @param Node $node The sandboxed $node to validate
|
||||||
|
*
|
||||||
|
* @throws Throwable Throws an exception if validation fails
|
||||||
|
*
|
||||||
|
* @return Node|bool|null Return rewritten node, false if node must be removed, or null if no changes to the node are made
|
||||||
|
*/
|
||||||
public function leaveNode(Node $node){
|
public function leaveNode(Node $node){
|
||||||
if($node instanceof Node\Arg){
|
if($node instanceof Node\Arg && $this->sandbox->sandbox_strings){
|
||||||
return new Node\Expr\FuncCall(new Node\Name\FullyQualified(($node->value instanceof Node\Expr\Variable) ? 'PHPSandbox\\wrapByRef' : 'PHPSandbox\\wrap'), [$node, new Node\Expr\StaticCall(new Node\Name\FullyQualified("CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox"), 'getGlobalSandbox')], $node->getAttributes());
|
return new Node\Expr\FuncCall(new Node\Name\FullyQualified(($node->value instanceof Node\Expr\Variable) ? 'PHPSandbox\\wrapByRef' : 'PHPSandbox\\wrap'), [$node, new Node\Expr\StaticCall(new Node\Name\FullyQualified("PHPSandbox\\PHPSandbox"), 'getSandbox', [new Node\Arg(new Node\Scalar\String_($this->sandbox->name))])], $node->getAttributes());
|
||||||
} else if($node instanceof Node\Stmt\InlineHTML){
|
} else if($node instanceof Node\Stmt\InlineHTML){
|
||||||
if(!$this->sandbox->allow_escaping){
|
if(!$this->sandbox->allow_escaping){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to escape to HTML!", Error::ESCAPE_ERROR, $node);
|
$this->sandbox->validationError("Sandboxed code attempted to escape to HTML!", Error::ESCAPE_ERROR, $node);
|
||||||
@@ -24,140 +59,140 @@ class CustomizedValidatorVisitor extends ValidatorVisitor {
|
|||||||
$this->sandbox->validationError("Sandboxed code attempted to cast!", Error::CAST_ERROR, $node);
|
$this->sandbox->validationError("Sandboxed code attempted to cast!", Error::CAST_ERROR, $node);
|
||||||
}
|
}
|
||||||
if($node instanceof Node\Expr\Cast\Int_){
|
if($node instanceof Node\Expr\Cast\Int_){
|
||||||
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified("CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox"), 'getGlobalSandbox'), '_intval', [new Node\Arg($node->expr)], $node->getAttributes());
|
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified('CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox'), 'getGlobalSandbox'), '_intval', [new Node\Arg($node->expr)], $node->getAttributes());
|
||||||
} else if($node instanceof Node\Expr\Cast\Double){
|
} else if($node instanceof Node\Expr\Cast\Double){
|
||||||
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified("CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox"), 'getGlobalSandbox'), '_floatval', [new Node\Arg($node->expr)], $node->getAttributes());
|
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified('CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox'), 'getGlobalSandbox'), '_floatval', [new Node\Arg($node->expr)], $node->getAttributes());
|
||||||
} else if($node instanceof Node\Expr\Cast\Bool_){
|
} else if($node instanceof Node\Expr\Cast\Bool_){
|
||||||
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified("CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox"), 'getGlobalSandbox'), '_boolval', [new Node\Arg($node->expr)], $node->getAttributes());
|
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified('CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox'), 'getGlobalSandbox'), '_boolval', [new Node\Arg($node->expr)], $node->getAttributes());
|
||||||
} else if($node instanceof Node\Expr\Cast\Array_){
|
} else if($node instanceof Node\Expr\Cast\Array_){
|
||||||
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified("CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox"), 'getGlobalSandbox'), '_arrayval', [new Node\Arg($node->expr)], $node->getAttributes());
|
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified('CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox'), 'getGlobalSandbox'), '_arrayval', [new Node\Arg($node->expr)], $node->getAttributes());
|
||||||
} else if($node instanceof Node\Expr\Cast\Object_){
|
} else if($node instanceof Node\Expr\Cast\Object_){
|
||||||
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified("CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox"), 'getGlobalSandbox'), '_objectval', [new Node\Arg($node->expr)], $node->getAttributes());
|
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified('CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox'), 'getGlobalSandbox'), '_objectval', [new Node\Arg($node->expr)], $node->getAttributes());
|
||||||
}
|
}
|
||||||
} else if($node instanceof Node\Expr\FuncCall){
|
} else if($node instanceof Node\Expr\FuncCall){
|
||||||
if($node->name instanceof Node\Name){
|
if($node->name instanceof Node\Name){
|
||||||
$name = strtolower($node->name->toString());
|
$name = strtolower($node->name->toString());
|
||||||
if(!$this->sandbox->checkFunc($name)){
|
if(!$this->sandbox->checkFunc($name)){
|
||||||
$this->sandbox->validationError("Function failed custom validation!", Error::VALID_FUNC_ERROR, $node);
|
$this->sandbox->validationError('Function failed custom validation!', Error::VALID_FUNC_ERROR, $node);
|
||||||
}
|
}
|
||||||
if($this->sandbox->isDefinedFunc($name)){
|
if($this->sandbox->isDefinedFunc($name)){
|
||||||
$args = $node->args;
|
$args = $node->args;
|
||||||
array_unshift($args, new Node\Arg(new Node\Scalar\String_($name)));
|
array_unshift($args, new Node\Arg(new Node\Scalar\String_($name)));
|
||||||
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified("CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox"), 'getGlobalSandbox'), 'call_func', $args, $node->getAttributes());
|
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified('CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox'), 'getGlobalSandbox'), 'call_func', $args, $node->getAttributes());
|
||||||
}
|
}
|
||||||
if($this->sandbox->overwrite_defined_funcs && in_array($name, PHPSandbox::$defined_funcs)){
|
if($this->sandbox->overwrite_defined_funcs && in_array($name, CustomizedSandbox::$defined_funcs)){
|
||||||
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified("CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox"), 'getGlobalSandbox'), '_' . $name, [new Node\Arg(new Node\Expr\FuncCall(new Node\Name([$name])))], $node->getAttributes());
|
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified('CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox'), 'getGlobalSandbox'), '_' . $name, [new Node\Arg(new Node\Expr\FuncCall(new Node\Name([$name])))], $node->getAttributes());
|
||||||
}
|
}
|
||||||
if($this->sandbox->overwrite_sandboxed_string_funcs && in_array($name, PHPSandbox::$sandboxed_string_funcs)){
|
if($this->sandbox->overwrite_sandboxed_string_funcs && in_array($name, CustomizedSandbox::$sandboxed_string_funcs)){
|
||||||
$args = $node->args;
|
$args = $node->args;
|
||||||
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified("CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox"), 'getGlobalSandbox'), '_' . $name, $args, $node->getAttributes());
|
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified('CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox'), 'getGlobalSandbox'), '_' . $name, $args, $node->getAttributes());
|
||||||
}
|
}
|
||||||
if($this->sandbox->overwrite_func_get_args && in_array($name, PHPSandbox::$arg_funcs)){
|
if($this->sandbox->overwrite_func_get_args && in_array($name, CustomizedSandbox::$arg_funcs)){
|
||||||
if($name == 'func_get_arg'){
|
if($name === 'func_get_arg'){
|
||||||
$index = new Node\Arg(new Node\Scalar\LNumber(0));
|
$index = new Node\Arg(new Node\Scalar\LNumber(0));
|
||||||
if(isset($node->args[0]) && $node->args[0] instanceof Node\Arg){
|
if(isset($node->args[0]) && $node->args[0] instanceof Node\Arg){
|
||||||
$index = $node->args[0];
|
$index = $node->args[0];
|
||||||
}
|
}
|
||||||
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified("CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox"), 'getGlobalSandbox'), '_' . $name, [new Node\Arg(new Node\Expr\FuncCall(new Node\Name(['func_get_args']))), $index], $node->getAttributes());
|
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified('CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox'), 'getGlobalSandbox'), '_' . $name, [new Node\Arg(new Node\Expr\FuncCall(new Node\Name(['func_get_args']))), $index], $node->getAttributes());
|
||||||
}
|
}
|
||||||
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified("CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox"), 'getGlobalSandbox'), '_' . $name, [new Node\Arg(new Node\Expr\FuncCall(new Node\Name(['func_get_args'])))], $node->getAttributes());
|
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified('CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox'), 'getGlobalSandbox'), '_' . $name, [new Node\Arg(new Node\Expr\FuncCall(new Node\Name(['func_get_args'])))], $node->getAttributes());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return new Node\Expr\Ternary(
|
return new Node\Expr\Ternary(
|
||||||
new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified("CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox"), 'getGlobalSandbox'), 'check_func', [new Node\Arg($node->name)], $node->getAttributes()),
|
new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified('CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox'), 'getGlobalSandbox'), 'checkFunc', [new Node\Arg($node->name)], $node->getAttributes()),
|
||||||
$node,
|
$node,
|
||||||
new Node\Expr\ConstFetch(new Node\Name('null'))
|
new Node\Expr\ConstFetch(new Node\Name('null'))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if($node instanceof Node\Stmt\Function_){
|
} else if($node instanceof Node\Stmt\Function_){
|
||||||
if(!$this->sandbox->allow_functions){
|
if(!$this->sandbox->allow_functions){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to define function!", Error::DEFINE_FUNC_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted to define function!', Error::DEFINE_FUNC_ERROR, $node);
|
||||||
}
|
}
|
||||||
if(!$this->sandbox->checkKeyword('function')){
|
if(!$this->sandbox->checkKeyword('function')){
|
||||||
$this->sandbox->validationError("Keyword failed custom validation!", Error::VALID_KEYWORD_ERROR, $node, 'function');
|
$this->sandbox->validationError('Keyword failed custom validation!', Error::VALID_KEYWORD_ERROR, $node, 'function');
|
||||||
}
|
}
|
||||||
if(!$node->name){
|
if(!$node->name){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to define unnamed function!", Error::DEFINE_FUNC_ERROR, $node, '');
|
$this->sandbox->validationError('Sandboxed code attempted to define unnamed function!', Error::DEFINE_FUNC_ERROR, $node, '');
|
||||||
}
|
}
|
||||||
if($this->sandbox->isDefinedFunc($node->name)){
|
if($this->sandbox->isDefinedFunc($node->name)){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to redefine function!", Error::DEFINE_FUNC_ERROR, $node, $node->name);
|
$this->sandbox->validationError('Sandboxed code attempted to redefine function!', Error::DEFINE_FUNC_ERROR, $node, $node->name);
|
||||||
}
|
}
|
||||||
if($node->byRef && !$this->sandbox->allow_references){
|
if($node->byRef && !$this->sandbox->allow_references){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to define function return by reference!", Error::BYREF_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted to define function return by reference!', Error::BYREF_ERROR, $node);
|
||||||
}
|
}
|
||||||
} else if($node instanceof Node\Expr\Closure){
|
} else if($node instanceof Node\Expr\Closure){
|
||||||
if(!$this->sandbox->allow_closures){
|
if(!$this->sandbox->allow_closures){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to create a closure!", Error::CLOSURE_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted to create a closure!', Error::CLOSURE_ERROR, $node);
|
||||||
}
|
}
|
||||||
} else if($node instanceof Node\Stmt\Class_){
|
} else if($node instanceof Node\Stmt\Class_){
|
||||||
if(!$this->sandbox->allow_classes){
|
if(!$this->sandbox->allow_classes){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to define class!", Error::DEFINE_CLASS_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted to define class!', Error::DEFINE_CLASS_ERROR, $node);
|
||||||
}
|
}
|
||||||
if(!$this->sandbox->checkKeyword('class')){
|
if(!$this->sandbox->checkKeyword('class')){
|
||||||
$this->sandbox->validationError("Keyword failed custom validation!", Error::VALID_KEYWORD_ERROR, $node, 'class');
|
$this->sandbox->validationError('Keyword failed custom validation!', Error::VALID_KEYWORD_ERROR, $node, 'class');
|
||||||
}
|
}
|
||||||
if(!$node->name){
|
if(!$node->name){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to define unnamed class!", Error::DEFINE_CLASS_ERROR, $node, '');
|
$this->sandbox->validationError('Sandboxed code attempted to define unnamed class!', Error::DEFINE_CLASS_ERROR, $node, '');
|
||||||
}
|
}
|
||||||
if(!$this->sandbox->checkClass($node->name)){
|
if(!$this->sandbox->checkClass($node->name)){
|
||||||
$this->sandbox->validationError("Class failed custom validation!", Error::VALID_CLASS_ERROR, $node, $node->name);
|
$this->sandbox->validationError('Class failed custom validation!', Error::VALID_CLASS_ERROR, $node, $node->name);
|
||||||
}
|
}
|
||||||
if($node->extends instanceof Node\Name){
|
if($node->extends instanceof Node\Name){
|
||||||
if(!$this->sandbox->checkKeyword('extends')){
|
if(!$this->sandbox->checkKeyword('extends')){
|
||||||
$this->sandbox->validationError("Keyword failed custom validation!", Error::VALID_KEYWORD_ERROR, $node, 'extends');
|
$this->sandbox->validationError('Keyword failed custom validation!', Error::VALID_KEYWORD_ERROR, $node, 'extends');
|
||||||
}
|
}
|
||||||
if(!$node->extends->toString()){
|
if(!$node->extends->toString()){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to extend unnamed class!", Error::DEFINE_CLASS_ERROR, $node, '');
|
$this->sandbox->validationError('Sandboxed code attempted to extend unnamed class!', Error::DEFINE_CLASS_ERROR, $node, '');
|
||||||
}
|
}
|
||||||
if(!$this->sandbox->checkClass($node->extends->toString(), true)){
|
if(!$this->sandbox->checkClass($node->extends->toString(), true)){
|
||||||
$this->sandbox->validationError("Class extension failed custom validation!", Error::VALID_CLASS_ERROR, $node, $node->extends->toString());
|
$this->sandbox->validationError('Class extension failed custom validation!', Error::VALID_CLASS_ERROR, $node, $node->extends->toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(is_array($node->implements)){
|
if(is_array($node->implements)){
|
||||||
if(!$this->sandbox->checkKeyword('implements')){
|
if(!$this->sandbox->checkKeyword('implements')){
|
||||||
$this->sandbox->validationError("Keyword failed custom validation!", Error::VALID_KEYWORD_ERROR, $node, 'implements');
|
$this->sandbox->validationError('Keyword failed custom validation!', Error::VALID_KEYWORD_ERROR, $node, 'implements');
|
||||||
}
|
}
|
||||||
foreach($node->implements as $implement){
|
foreach($node->implements as $implement){
|
||||||
/**
|
/**
|
||||||
* @var Node\Name $implement
|
* @var Node\Name $implement
|
||||||
*/
|
*/
|
||||||
if(!$implement->toString()){
|
if(!$implement->toString()){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to implement unnamed interface!", Error::DEFINE_INTERFACE_ERROR, $node, '');
|
$this->sandbox->validationError('Sandboxed code attempted to implement unnamed interface!', Error::DEFINE_INTERFACE_ERROR, $node, '');
|
||||||
}
|
}
|
||||||
if(!$this->sandbox->checkInterface($implement->toString())){
|
if(!$this->sandbox->checkInterface($implement->toString())){
|
||||||
$this->sandbox->validationError("Interface failed custom validation!", Error::VALID_INTERFACE_ERROR, $node, $implement->toString());
|
$this->sandbox->validationError('Interface failed custom validation!', Error::VALID_INTERFACE_ERROR, $node, $implement->toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if($node instanceof Node\Stmt\Interface_){
|
} else if($node instanceof Node\Stmt\Interface_){
|
||||||
if(!$this->sandbox->allow_interfaces){
|
if(!$this->sandbox->allow_interfaces){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to define interface!", Error::DEFINE_INTERFACE_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted to define interface!', Error::DEFINE_INTERFACE_ERROR, $node);
|
||||||
}
|
}
|
||||||
if(!$this->sandbox->checkKeyword('interface')){
|
if(!$this->sandbox->checkKeyword('interface')){
|
||||||
$this->sandbox->validationError("Keyword failed custom validation!", Error::VALID_KEYWORD_ERROR, $node, 'interface');
|
$this->sandbox->validationError('Keyword failed custom validation!', Error::VALID_KEYWORD_ERROR, $node, 'interface');
|
||||||
}
|
}
|
||||||
if(!$node->name){
|
if(!$node->name){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to define unnamed interface!", Error::DEFINE_INTERFACE_ERROR, $node, '');
|
$this->sandbox->validationError('Sandboxed code attempted to define unnamed interface!', Error::DEFINE_INTERFACE_ERROR, $node, '');
|
||||||
}
|
}
|
||||||
if(!$this->sandbox->checkInterface($node->name)){
|
if(!$this->sandbox->checkInterface($node->name)){
|
||||||
$this->sandbox->validationError("Interface failed custom validation!", Error::VALID_INTERFACE_ERROR, $node, $node->name);
|
$this->sandbox->validationError('Interface failed custom validation!', Error::VALID_INTERFACE_ERROR, $node, $node->name);
|
||||||
}
|
}
|
||||||
} else if($node instanceof Node\Stmt\Trait_){
|
} else if($node instanceof Node\Stmt\Trait_){
|
||||||
if(!$this->sandbox->allow_traits){
|
if(!$this->sandbox->allow_traits){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to define trait!", Error::DEFINE_TRAIT_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted to define trait!', Error::DEFINE_TRAIT_ERROR, $node);
|
||||||
}
|
}
|
||||||
if(!$this->sandbox->checkKeyword('trait')){
|
if(!$this->sandbox->checkKeyword('trait')){
|
||||||
$this->sandbox->validationError("Keyword failed custom validation!", Error::VALID_KEYWORD_ERROR, $node, 'trait');
|
$this->sandbox->validationError('Keyword failed custom validation!', Error::VALID_KEYWORD_ERROR, $node, 'trait');
|
||||||
}
|
}
|
||||||
if(!$node->name){
|
if(!$node->name){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to define unnamed trait!", Error::DEFINE_TRAIT_ERROR, $node, '');
|
$this->sandbox->validationError('Sandboxed code attempted to define unnamed trait!', Error::DEFINE_TRAIT_ERROR, $node, '');
|
||||||
}
|
}
|
||||||
if(!$this->sandbox->checkTrait($node->name)){
|
if(!$this->sandbox->checkTrait($node->name)){
|
||||||
$this->sandbox->validationError("Trait failed custom validation!", Error::VALID_TRAIT_ERROR, $node, $node->name);
|
$this->sandbox->validationError('Trait failed custom validation!', Error::VALID_TRAIT_ERROR, $node, $node->name);
|
||||||
}
|
}
|
||||||
} else if($node instanceof Node\Stmt\TraitUse){
|
} else if($node instanceof Node\Stmt\TraitUse){
|
||||||
if(!$this->sandbox->checkKeyword('use')){
|
if(!$this->sandbox->checkKeyword('use')){
|
||||||
$this->sandbox->validationError("Keyword failed custom validation!", Error::VALID_KEYWORD_ERROR, $node, 'use');
|
$this->sandbox->validationError('Keyword failed custom validation!', Error::VALID_KEYWORD_ERROR, $node, 'use');
|
||||||
}
|
}
|
||||||
if(is_array($node->traits)){
|
if(is_array($node->traits)){
|
||||||
foreach($node->traits as $trait){
|
foreach($node->traits as $trait){
|
||||||
@@ -165,26 +200,26 @@ class CustomizedValidatorVisitor extends ValidatorVisitor {
|
|||||||
* @var Node\Name $trait
|
* @var Node\Name $trait
|
||||||
*/
|
*/
|
||||||
if(!$trait->toString()){
|
if(!$trait->toString()){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to use unnamed trait!", Error::DEFINE_TRAIT_ERROR, $node, '');
|
$this->sandbox->validationError('Sandboxed code attempted to use unnamed trait!', Error::DEFINE_TRAIT_ERROR, $node, '');
|
||||||
}
|
}
|
||||||
if(!$this->sandbox->checkTrait($trait->toString())){
|
if(!$this->sandbox->checkTrait($trait->toString())){
|
||||||
$this->sandbox->validationError("Trait failed custom validation!", Error::VALID_TRAIT_ERROR, $node, $trait->toString());
|
$this->sandbox->validationError('Trait failed custom validation!', Error::VALID_TRAIT_ERROR, $node, $trait->toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if($node instanceof Node\Expr\Yield_){
|
} else if($node instanceof Node\Expr\Yield_){
|
||||||
if(!$this->sandbox->allow_generators){
|
if(!$this->sandbox->allow_generators){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to create a generator!", Error::GENERATOR_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted to create a generator!', Error::GENERATOR_ERROR, $node);
|
||||||
}
|
}
|
||||||
if(!$this->sandbox->checkKeyword('yield')){
|
if(!$this->sandbox->checkKeyword('yield')){
|
||||||
$this->sandbox->validationError("Keyword failed custom validation!", Error::VALID_KEYWORD_ERROR, $node, 'yield');
|
$this->sandbox->validationError('Keyword failed custom validation!', Error::VALID_KEYWORD_ERROR, $node, 'yield');
|
||||||
}
|
}
|
||||||
} else if($node instanceof Node\Stmt\Global_){
|
} else if($node instanceof Node\Stmt\Global_){
|
||||||
if(!$this->sandbox->allow_globals){
|
if(!$this->sandbox->allow_globals){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to use global keyword!", Error::GLOBALS_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted to use global keyword!', Error::GLOBALS_ERROR, $node);
|
||||||
}
|
}
|
||||||
if(!$this->sandbox->checkKeyword('global')){
|
if(!$this->sandbox->checkKeyword('global')){
|
||||||
$this->sandbox->validationError("Keyword failed custom validation!", Error::VALID_KEYWORD_ERROR, $node, 'global');
|
$this->sandbox->validationError('Keyword failed custom validation!', Error::VALID_KEYWORD_ERROR, $node, 'global');
|
||||||
}
|
}
|
||||||
foreach($node->vars as $var){
|
foreach($node->vars as $var){
|
||||||
/**
|
/**
|
||||||
@@ -192,57 +227,57 @@ class CustomizedValidatorVisitor extends ValidatorVisitor {
|
|||||||
*/
|
*/
|
||||||
if($var instanceof Node\Expr\Variable){
|
if($var instanceof Node\Expr\Variable){
|
||||||
if(!$this->sandbox->checkGlobal($var->name)){
|
if(!$this->sandbox->checkGlobal($var->name)){
|
||||||
$this->sandbox->validationError("Global failed custom validation!", Error::VALID_GLOBAL_ERROR, $node, $var->name);
|
$this->sandbox->validationError('Global failed custom validation!', Error::VALID_GLOBAL_ERROR, $node, $var->name);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to pass non-variable to global keyword!", Error::DEFINE_GLOBAL_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted to pass non-variable to global keyword!', Error::DEFINE_GLOBAL_ERROR, $node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if($node instanceof Node\Expr\Variable){
|
} else if($node instanceof Node\Expr\Variable){
|
||||||
if(!is_string($node->name)){
|
if(!is_string($node->name)){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted dynamically-named variable call!", Error::DYNAMIC_VAR_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted dynamically-named variable call!', Error::DYNAMIC_VAR_ERROR, $node);
|
||||||
}
|
}
|
||||||
if($node->name == $this->sandbox->name){
|
if($node->name == $this->sandbox->name){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to access the PHPSandbox instance!", Error::SANDBOX_ACCESS_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted to access the PHPSandbox instance!', Error::SANDBOX_ACCESS_ERROR, $node);
|
||||||
}
|
}
|
||||||
if(in_array($node->name, PHPSandbox::$superglobals)){
|
if(in_array($node->name, CustomizedSandbox::$superglobals)){
|
||||||
if(!$this->sandbox->checkSuperglobal($node->name)){
|
if(!$this->sandbox->checkSuperglobal($node->name)){
|
||||||
$this->sandbox->validationError("Superglobal failed custom validation!", Error::VALID_SUPERGLOBAL_ERROR, $node, $node->name);
|
$this->sandbox->validationError('Superglobal failed custom validation!', Error::VALID_SUPERGLOBAL_ERROR, $node, $node->name);
|
||||||
}
|
}
|
||||||
if($this->sandbox->overwrite_superglobals){
|
if($this->sandbox->overwrite_superglobals){
|
||||||
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified("CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox"), 'getGlobalSandbox'), '_get_superglobal', [new Node\Arg(new Node\Scalar\String_($node->name))], $node->getAttributes());
|
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified('CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox'), 'getGlobalSandbox'), '_get_superglobal', [new Node\Arg(new Node\Scalar\String_($node->name))], $node->getAttributes());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(!$this->sandbox->checkVar($node->name)){
|
if(!$this->sandbox->checkVar($node->name)){
|
||||||
$this->sandbox->validationError("Variable failed custom validation!", Error::VALID_VAR_ERROR, $node, $node->name);
|
$this->sandbox->validationError('Variable failed custom validation!', Error::VALID_VAR_ERROR, $node, $node->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if($node instanceof Node\Stmt\StaticVar){
|
} else if($node instanceof Node\Stmt\StaticVar){
|
||||||
if(!$this->sandbox->allow_static_variables){
|
if(!$this->sandbox->allow_static_variables){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to create static variable!", Error::STATIC_VAR_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted to create static variable!', Error::STATIC_VAR_ERROR, $node);
|
||||||
}
|
}
|
||||||
if(!is_string($node->name)){
|
if(!is_string($node->var->name)){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted dynamically-named static variable call!", Error::DYNAMIC_STATIC_VAR_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted dynamically-named static variable call!', Error::DYNAMIC_STATIC_VAR_ERROR, $node);
|
||||||
}
|
}
|
||||||
if(!$this->sandbox->checkVar($node->name)){
|
if(!$this->sandbox->checkVar($node->var->name)){
|
||||||
$this->sandbox->validationError("Variable failed custom validation!", Error::VALID_VAR_ERROR, $node, $node->name);
|
$this->sandbox->validationError('Variable failed custom validation!', Error::VALID_VAR_ERROR, $node, $node->var->name);
|
||||||
}
|
}
|
||||||
if($node->default instanceof Node\Expr\New_){
|
if($node->default instanceof Node\Expr\New_){
|
||||||
$node->default = $node->default->args[0];
|
$node->default = $node->default->args[0];
|
||||||
}
|
}
|
||||||
} else if($node instanceof Node\Stmt\Const_){
|
} else if($node instanceof Node\Stmt\Const_){
|
||||||
$this->sandbox->validationError("Sandboxed code cannot use const keyword in the global scope!", Error::GLOBAL_CONST_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code cannot use const keyword in the global scope!', Error::GLOBAL_CONST_ERROR, $node);
|
||||||
} else if($node instanceof Node\Expr\ConstFetch){
|
} else if($node instanceof Node\Expr\ConstFetch){
|
||||||
if(!$node->name instanceof Node\Name){
|
if(!$node->name instanceof Node\Name){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted dynamically-named constant call!", Error::DYNAMIC_CONST_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted dynamically-named constant call!', Error::DYNAMIC_CONST_ERROR, $node);
|
||||||
}
|
}
|
||||||
if(!$this->sandbox->checkConst($node->name->toString())){
|
if(!$this->sandbox->checkConst($node->name->toString())){
|
||||||
$this->sandbox->validationError("Constant failed custom validation!", Error::VALID_CONST_ERROR, $node, $node->name->toString());
|
$this->sandbox->validationError('Constant failed custom validation!', Error::VALID_CONST_ERROR, $node, $node->name->toString());
|
||||||
}
|
}
|
||||||
} else if($node instanceof Node\Expr\ClassConstFetch || $node instanceof Node\Expr\StaticCall || $node instanceof Node\Expr\StaticPropertyFetch){
|
} else if($node instanceof Node\Expr\ClassConstFetch || $node instanceof Node\Expr\StaticCall || $node instanceof Node\Expr\StaticPropertyFetch){
|
||||||
$class = $node->class;
|
$class = $node->class;
|
||||||
if(!$class instanceof Node\Name){
|
if(!$class instanceof Node\Name){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted dynamically-named class call!", Error::DYNAMIC_CLASS_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted dynamically-named class call!', Error::DYNAMIC_CLASS_ERROR, $node);
|
||||||
}
|
}
|
||||||
if($this->sandbox->isDefinedClass($class)){
|
if($this->sandbox->isDefinedClass($class)){
|
||||||
$node->class = new Node\Name($this->sandbox->getDefinedClass($class));
|
$node->class = new Node\Name($this->sandbox->getDefinedClass($class));
|
||||||
@@ -251,7 +286,7 @@ class CustomizedValidatorVisitor extends ValidatorVisitor {
|
|||||||
* @var Node\Name $class
|
* @var Node\Name $class
|
||||||
*/
|
*/
|
||||||
if(!$this->sandbox->checkClass($class->toString())){
|
if(!$this->sandbox->checkClass($class->toString())){
|
||||||
$this->sandbox->validationError("Class constant failed custom validation!", Error::VALID_CLASS_ERROR, $node, $class->toString());
|
$this->sandbox->validationError('Class constant failed custom validation!', Error::VALID_CLASS_ERROR, $node, $class->toString());
|
||||||
}
|
}
|
||||||
return $node;
|
return $node;
|
||||||
} else if($node instanceof Node\Param && $node->type instanceof Node\Name){
|
} else if($node instanceof Node\Param && $node->type instanceof Node\Name){
|
||||||
@@ -262,13 +297,13 @@ class CustomizedValidatorVisitor extends ValidatorVisitor {
|
|||||||
return $node;
|
return $node;
|
||||||
} else if($node instanceof Node\Expr\New_){
|
} else if($node instanceof Node\Expr\New_){
|
||||||
if(!$this->sandbox->allow_objects){
|
if(!$this->sandbox->allow_objects){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to create object!", Error::CREATE_OBJECT_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted to create object!', Error::CREATE_OBJECT_ERROR, $node);
|
||||||
}
|
}
|
||||||
if(!$this->sandbox->checkKeyword('new')){
|
if(!$this->sandbox->checkKeyword('new')){
|
||||||
$this->sandbox->validationError("Keyword failed custom validation!", Error::VALID_KEYWORD_ERROR, $node, 'new');
|
$this->sandbox->validationError('Keyword failed custom validation!', Error::VALID_KEYWORD_ERROR, $node, 'new');
|
||||||
}
|
}
|
||||||
if(!$node->class instanceof Node\Name){
|
if(!$node->class instanceof Node\Name){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted dynamically-named class call!", Error::DYNAMIC_CLASS_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted dynamically-named class call!', Error::DYNAMIC_CLASS_ERROR, $node);
|
||||||
}
|
}
|
||||||
$class = $node->class->toString();
|
$class = $node->class->toString();
|
||||||
if($this->sandbox->isDefinedClass($class)){
|
if($this->sandbox->isDefinedClass($class)){
|
||||||
@@ -278,25 +313,25 @@ class CustomizedValidatorVisitor extends ValidatorVisitor {
|
|||||||
return $node;
|
return $node;
|
||||||
} else if($node instanceof Node\Expr\ErrorSuppress){
|
} else if($node instanceof Node\Expr\ErrorSuppress){
|
||||||
if(!$this->sandbox->allow_error_suppressing){
|
if(!$this->sandbox->allow_error_suppressing){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to suppress error!", Error::ERROR_SUPPRESS_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted to suppress error!', Error::ERROR_SUPPRESS_ERROR, $node);
|
||||||
}
|
}
|
||||||
} else if($node instanceof Node\Expr\AssignRef){
|
} else if($node instanceof Node\Expr\AssignRef){
|
||||||
if(!$this->sandbox->allow_references){
|
if(!$this->sandbox->allow_references){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to assign by reference!", Error::BYREF_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted to assign by reference!', Error::BYREF_ERROR, $node);
|
||||||
}
|
}
|
||||||
} else if($node instanceof Node\Stmt\HaltCompiler){
|
} else if($node instanceof Node\Stmt\HaltCompiler){
|
||||||
if(!$this->sandbox->allow_halting){
|
if(!$this->sandbox->allow_halting){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to halt compiler!", Error::HALT_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted to halt compiler!', Error::HALT_ERROR, $node);
|
||||||
}
|
}
|
||||||
if(!$this->sandbox->checkKeyword('halt')){
|
if(!$this->sandbox->checkKeyword('halt')){
|
||||||
$this->sandbox->validationError("Keyword failed custom validation!", Error::VALID_KEYWORD_ERROR, $node, 'halt');
|
$this->sandbox->validationError('Keyword failed custom validation!', Error::VALID_KEYWORD_ERROR, $node, 'halt');
|
||||||
}
|
}
|
||||||
} else if($node instanceof Node\Stmt\Namespace_){
|
} else if($node instanceof Node\Stmt\Namespace_){
|
||||||
if(!$this->sandbox->allow_namespaces){
|
if(!$this->sandbox->allow_namespaces){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to define namespace!", Error::DEFINE_NAMESPACE_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted to define namespace!', Error::DEFINE_NAMESPACE_ERROR, $node);
|
||||||
}
|
}
|
||||||
if(!$this->sandbox->checkKeyword('namespace')){
|
if(!$this->sandbox->checkKeyword('namespace')){
|
||||||
$this->sandbox->validationError("Keyword failed custom validation!", Error::VALID_KEYWORD_ERROR, $node, 'namespace');
|
$this->sandbox->validationError('Keyword failed custom validation!', Error::VALID_KEYWORD_ERROR, $node, 'namespace');
|
||||||
}
|
}
|
||||||
if($node->name instanceof Node\Name){
|
if($node->name instanceof Node\Name){
|
||||||
$namespace = $node->name->toString();
|
$namespace = $node->name->toString();
|
||||||
@@ -305,99 +340,305 @@ class CustomizedValidatorVisitor extends ValidatorVisitor {
|
|||||||
$this->sandbox->defineNamespace($namespace);
|
$this->sandbox->defineNamespace($namespace);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->sandbox->validationError("Sandboxed code attempted use invalid namespace!", Error::DEFINE_NAMESPACE_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted use invalid namespace!', Error::DEFINE_NAMESPACE_ERROR, $node);
|
||||||
}
|
}
|
||||||
return $node->stmts;
|
return $node->stmts;
|
||||||
} else if($node instanceof Node\Stmt\Use_){
|
} else if($node instanceof Node\Stmt\Use_){
|
||||||
if(!$this->sandbox->allow_aliases){
|
if(!$this->sandbox->allow_aliases){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to use namespace and/or alias!", Error::DEFINE_ALIAS_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted to use namespace and/or alias!', Error::DEFINE_ALIAS_ERROR, $node);
|
||||||
}
|
}
|
||||||
if(!$this->sandbox->checkKeyword('use')){
|
if(!$this->sandbox->checkKeyword('use')){
|
||||||
$this->sandbox->validationError("Keyword failed custom validation!", Error::VALID_KEYWORD_ERROR, $node, 'use');
|
$this->sandbox->validationError('Keyword failed custom validation!', Error::VALID_KEYWORD_ERROR, $node, 'use');
|
||||||
}
|
}
|
||||||
foreach($node->uses as $use){
|
foreach($node->uses as $use){
|
||||||
/**
|
/**
|
||||||
* @var Node\Stmt\UseUse $use
|
* @var Node\Stmt\UseUse $use
|
||||||
*/
|
*/
|
||||||
if($use instanceof Node\Stmt\UseUse && $use->name instanceof Node\Name && (is_string($use->alias) || is_null($use->alias))){
|
if($use instanceof Node\Stmt\UseUse && $use->name instanceof Node\Name && (is_string($use->alias) || $use->alias instanceof Node\Identifier || is_null($use->alias))){
|
||||||
$this->sandbox->checkAlias($use->name->toString());
|
$this->sandbox->checkAlias($use->name->toString());
|
||||||
if($use->alias){
|
if($use->alias){
|
||||||
if(!$this->sandbox->checkKeyword('as')){
|
if(!$this->sandbox->checkKeyword('as')){
|
||||||
$this->sandbox->validationError("Keyword failed custom validation!", Error::VALID_KEYWORD_ERROR, $node, 'as');
|
$this->sandbox->validationError('Keyword failed custom validation!', Error::VALID_KEYWORD_ERROR, $node, 'as');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->sandbox->defineAlias($use->name->toString(), $use->alias);
|
$this->sandbox->whitelistClass($use->getAlias());
|
||||||
|
$this->sandbox->whitelistType($use->getAlias());
|
||||||
|
$this->sandbox->defineAlias($use->name->toString(), $use->getAlias());
|
||||||
} else {
|
} else {
|
||||||
$this->sandbox->validationError("Sandboxed code attempted use invalid namespace or alias!", Error::DEFINE_ALIAS_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted use invalid namespace or alias!', Error::DEFINE_ALIAS_ERROR, $node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return NodeTraverser::REMOVE_NODE;
|
||||||
} else if($node instanceof Node\Expr\ShellExec){
|
} else if($node instanceof Node\Expr\ShellExec){
|
||||||
if($this->sandbox->isDefinedFunc('shell_exec')){
|
if($this->sandbox->isDefinedFunc('shell_exec')){
|
||||||
$args = [
|
$args = [
|
||||||
new Node\Arg(new Node\Scalar\String_('shell_exec')),
|
new Node\Arg(new Node\Scalar\String_('shell_exec')),
|
||||||
new Node\Arg(new Node\Scalar\String_(implode('', $node->parts)))
|
new Node\Arg(new Node\Scalar\String_(implode('', $node->parts)))
|
||||||
];
|
];
|
||||||
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified("CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox"), 'getGlobalSandbox'), 'call_func', $args, $node->getAttributes());
|
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified('CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox'), 'getGlobalSandbox'), 'call_func', $args, $node->getAttributes());
|
||||||
}
|
}
|
||||||
if($this->sandbox->hasWhitelistedFuncs()){
|
if($this->sandbox->hasWhitelistedFuncs()){
|
||||||
if(!$this->sandbox->isWhitelistedFunc('shell_exec')){
|
if(!$this->sandbox->isWhitelistedFunc('shell_exec')){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to use shell execution backticks when the shell_exec function is not whitelisted!", Error::BACKTICKS_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted to use shell execution backticks when the shell_exec function is not whitelisted!', Error::BACKTICKS_ERROR, $node);
|
||||||
}
|
}
|
||||||
} else if($this->sandbox->hasBlacklistedFuncs() && $this->sandbox->isBlacklistedFunc('shell_exec')){
|
} else if($this->sandbox->hasBlacklistedFuncs() && $this->sandbox->isBlacklistedFunc('shell_exec')){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to use shell execution backticks when the shell_exec function is blacklisted!", Error::BACKTICKS_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted to use shell execution backticks when the shell_exec function is blacklisted!', Error::BACKTICKS_ERROR, $node);
|
||||||
}
|
}
|
||||||
if(!$this->sandbox->allow_backticks){
|
if(!$this->sandbox->allow_backticks){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to use shell execution backticks!", Error::BACKTICKS_ERROR, $node);
|
$this->sandbox->validationError('Sandboxed code attempted to use shell execution backticks!', Error::BACKTICKS_ERROR, $node);
|
||||||
}
|
}
|
||||||
} else if($name = $this->isMagicConst($node)){
|
} else if($name = $this->isMagicConst($node)){
|
||||||
if(!$this->sandbox->checkMagicConst($name)){
|
if(!$this->sandbox->checkMagicConst($name)){
|
||||||
$this->sandbox->validationError("Magic constant failed custom validation!", Error::VALID_MAGIC_CONST_ERROR, $node, $name);
|
$this->sandbox->validationError('Magic constant failed custom validation!', Error::VALID_MAGIC_CONST_ERROR, $node, $name);
|
||||||
}
|
}
|
||||||
if($this->sandbox->isDefinedMagicConst($name)){
|
if($this->sandbox->isDefinedMagicConst($name)){
|
||||||
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified("CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox"), 'getGlobalSandbox'), '_get_magic_const', [new Node\Arg(new Node\Scalar\String_($name))], $node->getAttributes());
|
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified('CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox'), 'getGlobalSandbox'), '_get_magic_const', [new Node\Arg(new Node\Scalar\String_($name))], $node->getAttributes());
|
||||||
|
} else if(($filepath = $this->sandbox->getExecutingFile()) && in_array($name, ['__DIR__', '__FILE__'], true)){
|
||||||
|
return new Node\Scalar\String_($name === '__DIR__' ? dirname($filepath) : $filepath);
|
||||||
}
|
}
|
||||||
} else if($name = $this->isKeyword($node)){
|
} else if($name = $this->isKeyword($node)){
|
||||||
if(!$this->sandbox->checkKeyword($name)){
|
if(!$this->sandbox->checkKeyword($name)){
|
||||||
$this->sandbox->validationError("Keyword failed custom validation!", Error::VALID_KEYWORD_ERROR, $node, $name);
|
$this->sandbox->validationError('Keyword failed custom validation!', Error::VALID_KEYWORD_ERROR, $node, $name);
|
||||||
}
|
}
|
||||||
if($node instanceof Node\Expr\Include_ && !$this->sandbox->allow_includes){
|
if($node instanceof Node\Expr\Include_ && !$this->sandbox->allow_includes){
|
||||||
$this->sandbox->validationError("Sandboxed code attempted to include files!", Error::INCLUDE_ERROR, $node, $name);
|
$this->sandbox->validationError('Sandboxed code attempted to include files!', Error::INCLUDE_ERROR, $node, $name);
|
||||||
} else if($node instanceof Node\Expr\Include_ &&
|
} else if($node instanceof Node\Expr\Include_ &&
|
||||||
(
|
(
|
||||||
($node->type == Node\Expr\Include_::TYPE_INCLUDE && $this->sandbox->isDefinedFunc('include'))
|
($node->type == Node\Expr\Include_::TYPE_INCLUDE && $this->sandbox->isDefinedFunc('include'))
|
||||||
|| ($node->type == Node\Expr\Include_::TYPE_INCLUDE_ONCE && $this->sandbox->isDefinedFunc('include_once'))
|
|| ($node->type == Node\Expr\Include_::TYPE_INCLUDE_ONCE && $this->sandbox->isDefinedFunc('include_once'))
|
||||||
|| ($node->type == Node\Expr\Include_::TYPE_REQUIRE && $this->sandbox->isDefinedFunc('require'))
|
|| ($node->type == Node\Expr\Include_::TYPE_REQUIRE && $this->sandbox->isDefinedFunc('require'))
|
||||||
|| ($node->type == Node\Expr\Include_::TYPE_REQUIRE_ONCE && $this->sandbox->isDefinedFunc('require_once'))
|
|| ($node->type == Node\Expr\Include_::TYPE_REQUIRE_ONCE && $this->sandbox->isDefinedFunc('require_once'))
|
||||||
)){
|
)
|
||||||
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified("CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox"), 'getGlobalSandbox'), 'call_func', [new Node\Arg(new Node\Scalar\String_($name)), new Node\Arg($node->expr)], $node->getAttributes());
|
){
|
||||||
|
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified('CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox'), 'getGlobalSandbox'), 'call_func', [new Node\Arg(new Node\Scalar\String_($name)), new Node\Arg($node->expr)], $node->getAttributes());
|
||||||
} else if($node instanceof Node\Expr\Include_ && $this->sandbox->sandbox_includes){
|
} else if($node instanceof Node\Expr\Include_ && $this->sandbox->sandbox_includes){
|
||||||
switch($node->type){
|
switch($node->type){
|
||||||
case Node\Expr\Include_::TYPE_INCLUDE_ONCE:
|
case Node\Expr\Include_::TYPE_INCLUDE_ONCE:
|
||||||
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified("CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox"), 'getGlobalSandbox'), '_include_once', [new Node\Arg($node->expr)], $node->getAttributes());
|
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified('CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox'), 'getGlobalSandbox'), '_include_once', [new Node\Arg($node->expr)], $node->getAttributes());
|
||||||
break;
|
|
||||||
case Node\Expr\Include_::TYPE_REQUIRE:
|
case Node\Expr\Include_::TYPE_REQUIRE:
|
||||||
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified("CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox"), 'getGlobalSandbox'), '_require', [new Node\Arg($node->expr)], $node->getAttributes());
|
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified('CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox'), 'getGlobalSandbox'), '_require', [new Node\Arg($node->expr)], $node->getAttributes());
|
||||||
break;
|
|
||||||
case Node\Expr\Include_::TYPE_REQUIRE_ONCE:
|
case Node\Expr\Include_::TYPE_REQUIRE_ONCE:
|
||||||
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified("CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox"), 'getGlobalSandbox'), '_require_once', [new Node\Arg($node->expr)], $node->getAttributes());
|
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified('CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox'), 'getGlobalSandbox'), '_require_once', [new Node\Arg($node->expr)], $node->getAttributes());
|
||||||
break;
|
|
||||||
case Node\Expr\Include_::TYPE_INCLUDE:
|
case Node\Expr\Include_::TYPE_INCLUDE:
|
||||||
default:
|
default:
|
||||||
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified("CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox"), 'getGlobalSandbox'), '_include', [new Node\Arg($node->expr)], $node->getAttributes());
|
return new Node\Expr\MethodCall(new Node\Expr\StaticCall(new Node\Name\FullyQualified('CloudObjects\\PhpMAE\\Sandbox\\CustomizedSandbox'), 'getGlobalSandbox'), '_include', [new Node\Arg($node->expr)], $node->getAttributes());
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if($name = $this->isOperator($node)){
|
} else if($name = $this->isOperator($node)){
|
||||||
if(!$this->sandbox->checkOperator($name)){
|
if(!$this->sandbox->checkOperator($name)){
|
||||||
$this->sandbox->validationError("Operator failed custom validation!", Error::VALID_OPERATOR_ERROR, $node, $name);
|
$this->sandbox->validationError('Operator failed custom validation!', Error::VALID_OPERATOR_ERROR, $node, $name);
|
||||||
}
|
}
|
||||||
} else if($name = $this->isPrimitive($node)){
|
} else if($name = $this->isPrimitive($node)){
|
||||||
if(!$this->sandbox->checkPrimitive($name)){
|
if(!$this->sandbox->checkPrimitive($name)){
|
||||||
$this->sandbox->validationError("Primitive failed custom validation!", Error::VALID_PRIMITIVE_ERROR, $node, $name);
|
$this->sandbox->validationError('Primitive failed custom validation!', Error::VALID_PRIMITIVE_ERROR, $node, $name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
/** Test the current PhpParser_Node node to see if it is a magic constant, and return the name if it is and null if it is not
|
||||||
|
*
|
||||||
|
* @param Node $node The sandboxed $node to test
|
||||||
|
*
|
||||||
|
* @return string|null Return string name of node, or null if it is not a magic constant
|
||||||
|
*/
|
||||||
|
protected function isMagicConst(Node $node) : ?string {
|
||||||
|
return ($node instanceof Node\Scalar\MagicConst) ? $node->getName() : null;
|
||||||
|
}
|
||||||
|
/** Test the current PhpParser_Node node to see if it is a keyword, and return the name if it is and null if it is not
|
||||||
|
*
|
||||||
|
* @param Node $node The sandboxed $node to test
|
||||||
|
*
|
||||||
|
* @return string|null Return string name of node, or null if it is not a keyword
|
||||||
|
*/
|
||||||
|
protected function isKeyword(Node $node) : ?string {
|
||||||
|
switch($node->getType()){
|
||||||
|
case 'Expr_Eval':
|
||||||
|
return 'eval';
|
||||||
|
case 'Expr_Exit':
|
||||||
|
return 'exit';
|
||||||
|
case 'Expr_Include':
|
||||||
|
return 'include';
|
||||||
|
case 'Stmt_Echo':
|
||||||
|
case 'Expr_Print': //for our purposes print is treated as functionally equivalent to echo
|
||||||
|
return 'echo';
|
||||||
|
case 'Expr_Clone':
|
||||||
|
return 'clone';
|
||||||
|
case 'Expr_Empty':
|
||||||
|
return 'empty';
|
||||||
|
case 'Expr_Yield':
|
||||||
|
return 'yield';
|
||||||
|
case 'Stmt_Goto':
|
||||||
|
case 'Stmt_Label': //no point in using labels without goto
|
||||||
|
return 'goto';
|
||||||
|
case 'Stmt_If':
|
||||||
|
case 'Stmt_Else': //no point in using ifs without else
|
||||||
|
case 'Stmt_ElseIf': //no point in using ifs without elseif
|
||||||
|
return 'if';
|
||||||
|
case 'Stmt_Break':
|
||||||
|
return 'break';
|
||||||
|
case 'Stmt_Switch':
|
||||||
|
case 'Stmt_Case': //no point in using cases without switch
|
||||||
|
return 'switch';
|
||||||
|
case 'Stmt_Try':
|
||||||
|
case 'Stmt_Catch': //no point in using catch without try
|
||||||
|
case 'Stmt_TryCatch': //no point in using try, catch or finally without try
|
||||||
|
return 'try';
|
||||||
|
case 'Stmt_Throw':
|
||||||
|
return 'throw';
|
||||||
|
case 'Stmt_Unset':
|
||||||
|
return 'unset';
|
||||||
|
case 'Stmt_Return':
|
||||||
|
return 'return';
|
||||||
|
case 'Stmt_Static':
|
||||||
|
return 'static';
|
||||||
|
case 'Stmt_While':
|
||||||
|
case 'Stmt_Do': //no point in using do without while
|
||||||
|
return 'while';
|
||||||
|
case 'Stmt_Declare':
|
||||||
|
case 'Stmt_DeclareDeclare': //no point in using declare key=>value without declare
|
||||||
|
return 'declare';
|
||||||
|
case 'Stmt_For':
|
||||||
|
case 'Stmt_Foreach': //no point in using foreach without for
|
||||||
|
return 'for';
|
||||||
|
case 'Expr_Instanceof':
|
||||||
|
return 'instanceof';
|
||||||
|
case 'Expr_Isset':
|
||||||
|
return 'isset';
|
||||||
|
case 'Expr_List':
|
||||||
|
return 'list';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
/** Test the current PhpParser_Node node to see if it is an operator, and return the name if it is and null if it is not
|
||||||
|
*
|
||||||
|
* @param Node $node The sandboxed $node to test
|
||||||
|
*
|
||||||
|
* @return string|null Return string name of node, or null if it is not an operator
|
||||||
|
*/
|
||||||
|
protected function isOperator(Node $node) : ?string {
|
||||||
|
switch($node->getType()){
|
||||||
|
case 'Expr_Assign':
|
||||||
|
return '=';
|
||||||
|
case 'Expr_AssignBitwiseAnd':
|
||||||
|
return '&=';
|
||||||
|
case 'Expr_AssignBitwiseOr':
|
||||||
|
return '|=';
|
||||||
|
case 'Expr_AssignBitwiseXor':
|
||||||
|
return '^=';
|
||||||
|
case 'Expr_AssignConcat':
|
||||||
|
return '.=';
|
||||||
|
case 'Expr_AssignDiv':
|
||||||
|
return '/=';
|
||||||
|
case 'Expr_AssignMinus':
|
||||||
|
return '-=';
|
||||||
|
case 'Expr_AssignMod':
|
||||||
|
return '%=';
|
||||||
|
case 'Expr_AssignMul':
|
||||||
|
return '*=';
|
||||||
|
case 'Expr_AssignPlus':
|
||||||
|
return '+=';
|
||||||
|
case 'Expr_AssignRef':
|
||||||
|
return '=&';
|
||||||
|
case 'Expr_AssignShiftLeft':
|
||||||
|
return '<<=';
|
||||||
|
case 'Expr_AssignShiftRight':
|
||||||
|
return '>>=';
|
||||||
|
case 'Expr_BitwiseAnd':
|
||||||
|
return '&';
|
||||||
|
case 'Expr_BitwiseNot':
|
||||||
|
return '~';
|
||||||
|
case 'Expr_BitwiseOr':
|
||||||
|
return '|';
|
||||||
|
case 'Expr_BitwiseXor':
|
||||||
|
return '^';
|
||||||
|
case 'Expr_BooleanAnd':
|
||||||
|
return '&&';
|
||||||
|
case 'Expr_BooleanNot':
|
||||||
|
return '!';
|
||||||
|
case 'Expr_BooleanOr':
|
||||||
|
return '||';
|
||||||
|
case 'Expr_Concat':
|
||||||
|
return '.';
|
||||||
|
case 'Expr_Div':
|
||||||
|
return '/';
|
||||||
|
case 'Expr_Equal':
|
||||||
|
return '==';
|
||||||
|
case 'Expr_Greater':
|
||||||
|
return '>';
|
||||||
|
case 'Expr_GreaterOrEqual':
|
||||||
|
return '>=';
|
||||||
|
case 'Expr_Identical':
|
||||||
|
return '===';
|
||||||
|
case 'Expr_LogicalAnd':
|
||||||
|
return 'and';
|
||||||
|
case 'Expr_LogicalOr':
|
||||||
|
return 'or';
|
||||||
|
case 'Expr_LogicalXor':
|
||||||
|
return 'xor';
|
||||||
|
case 'Expr_Minus':
|
||||||
|
return '-';
|
||||||
|
case 'Expr_Mod':
|
||||||
|
return '%';
|
||||||
|
case 'Expr_Mul':
|
||||||
|
return '*';
|
||||||
|
case 'Expr_NotEqual':
|
||||||
|
return '!=';
|
||||||
|
case 'Expr_NotIdentical':
|
||||||
|
return '!==';
|
||||||
|
case 'Expr_Plus':
|
||||||
|
return '+';
|
||||||
|
case 'Expr_PostDec':
|
||||||
|
return 'n--';
|
||||||
|
case 'Expr_PostInc':
|
||||||
|
return 'n++';
|
||||||
|
case 'Expr_PreDec':
|
||||||
|
return '--n';
|
||||||
|
case 'Expr_PreInc':
|
||||||
|
return '++n';
|
||||||
|
case 'Expr_ShiftLeft':
|
||||||
|
return '<<';
|
||||||
|
case 'Expr_ShiftRight':
|
||||||
|
return '>>';
|
||||||
|
case 'Expr_Smaller':
|
||||||
|
return '<';
|
||||||
|
case 'Expr_SmallerOrEqual':
|
||||||
|
return '<=';
|
||||||
|
case 'Expr_Ternary':
|
||||||
|
return '?';
|
||||||
|
case 'Expr_UnaryMinus':
|
||||||
|
return '-n';
|
||||||
|
case 'Expr_UnaryPlus':
|
||||||
|
return '+n';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
/** Test the current PhpParser_Node node to see if it is a primitive, and return the name if it is and null if it is not
|
||||||
|
*
|
||||||
|
* @param Node $node The sandboxed $node to test
|
||||||
|
*
|
||||||
|
* @return string|null Return string name of node, or null if it is not a primitive
|
||||||
|
*/
|
||||||
|
protected function isPrimitive(Node $node) : ?string {
|
||||||
|
switch($node->getType()){
|
||||||
|
case 'Expr_Cast_Array':
|
||||||
|
case 'Expr_Array':
|
||||||
|
return 'array';
|
||||||
|
case 'Expr_Cast_Bool': //booleans are treated as constants otherwise. . .
|
||||||
|
return 'bool';
|
||||||
|
case 'Expr_Cast_String':
|
||||||
|
case 'Scalar_String':
|
||||||
|
case 'Scalar_Encapsed':
|
||||||
|
return 'string';
|
||||||
|
case 'Expr_Cast_Double':
|
||||||
|
case 'Scalar_DNumber':
|
||||||
|
return 'float';
|
||||||
|
case 'Expr_Cast_Int':
|
||||||
|
case 'Scalar_LNumber':
|
||||||
|
return 'int';
|
||||||
|
case 'Expr_Cast_Object':
|
||||||
|
return 'object';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -13,8 +13,8 @@ class TwigTemplate {
|
|||||||
|
|
||||||
public function __construct($key, $content, $cachePath) {
|
public function __construct($key, $content, $cachePath) {
|
||||||
$this->key = $key;
|
$this->key = $key;
|
||||||
$this->environment = new \Twig_Environment(
|
$this->environment = new \Twig\Environment(
|
||||||
new \Twig_Loader_Array([ $key => $content ]),
|
new \Twig\Loader\ArrayLoader([ $key => $content ]),
|
||||||
[ 'cache' => $cachePath ]
|
[ 'cache' => $cachePath ]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace CloudObjects\PhpMAE;
|
|||||||
|
|
||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
use Psr\Http\Message\RequestInterface;
|
use Psr\Http\Message\RequestInterface;
|
||||||
use Slim\Http\Response;
|
use Slim\Psr7\Response;
|
||||||
use ML\IRI\IRI;
|
use ML\IRI\IRI;
|
||||||
use ML\JsonLD\JsonLD;
|
use ML\JsonLD\JsonLD;
|
||||||
use CloudObjects\Utilities\RDF\Arc2JsonLdConverter;
|
use CloudObjects\Utilities\RDF\Arc2JsonLdConverter;
|
||||||
@@ -30,7 +30,7 @@ class UploadController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function uploadSource(RequestInterface $request) {
|
private function uploadSource(RequestInterface $request) {
|
||||||
$object = $this->objectRetriever->get($request->getQueryParam('coid'));
|
$object = $this->objectRetriever->get($request->getQueryParams()['coid'] ?? null);
|
||||||
if (!$object)
|
if (!$object)
|
||||||
throw new PhpMAEException("Unable to retrieve object.");
|
throw new PhpMAEException("Unable to retrieve object.");
|
||||||
|
|
||||||
@@ -42,10 +42,11 @@ class UploadController {
|
|||||||
new IRI($object->getId()),
|
new IRI($object->getId()),
|
||||||
TypeChecker::getAdditionalTypes($object));
|
TypeChecker::getAdditionalTypes($object));
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$response = (new Response(400))->withJson([
|
$response = (new Response(400))->withHeader('Content-Type', 'application/json');
|
||||||
|
$response->getBody()->write(json_encode([
|
||||||
'error_code' => get_class($e),
|
'error_code' => get_class($e),
|
||||||
'error_message' => $e->getMessage()
|
'error_message' => $e->getMessage()
|
||||||
]);
|
]));
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,12 +68,12 @@ class UploadController {
|
|||||||
|
|
||||||
// Validate config
|
// Validate config
|
||||||
if (!isset($jsonLdConfig->{'@id'})
|
if (!isset($jsonLdConfig->{'@id'})
|
||||||
|| $jsonLdConfig->{'@id'} != $request->getQueryParam('coid')) {
|
|| $jsonLdConfig->{'@id'} != ($request->getQueryParams()['coid'] ?? null)) {
|
||||||
throw new PhpMAEException("Uploaded configuration does not correspond to object.");
|
throw new PhpMAEException("Uploaded configuration does not correspond to object.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store configuration
|
// Store configuration
|
||||||
$iri = new IRI($request->getQueryParam('coid'));
|
$iri = new IRI($request->getQueryParams()['coid'] ?? null);
|
||||||
$path = $this->container->get('uploads_dir')
|
$path = $this->container->get('uploads_dir')
|
||||||
.DIRECTORY_SEPARATOR.'config'
|
.DIRECTORY_SEPARATOR.'config'
|
||||||
.DIRECTORY_SEPARATOR.$iri->getHost()
|
.DIRECTORY_SEPARATOR.$iri->getHost()
|
||||||
@@ -91,7 +92,7 @@ class UploadController {
|
|||||||
if ($request->getMethod() != 'PUT')
|
if ($request->getMethod() != 'PUT')
|
||||||
throw new PhpMAEException("Must use PUT for uploading to test environment.");
|
throw new PhpMAEException("Must use PUT for uploading to test environment.");
|
||||||
|
|
||||||
switch ($request->getQueryParam('type')) {
|
switch ($request->getQueryParams()['type'] ?? null) {
|
||||||
case "source":
|
case "source":
|
||||||
return $this->uploadSource($request);
|
return $this->uploadSource($request);
|
||||||
break;
|
break;
|
||||||
|
|||||||
+21
-24
@@ -5,38 +5,35 @@
|
|||||||
"homepage": "https://github.com/CloudObjects/phpMAE",
|
"homepage": "https://github.com/CloudObjects/phpMAE",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"require": {
|
"require": {
|
||||||
"symfony/console" : "^4.2.1",
|
"symfony/console" : "^7",
|
||||||
"corveda/php-sandbox": "^2.0.1",
|
"corveda/php-sandbox": "^3.1",
|
||||||
"cloudobjects/sdk" : "dev-main",
|
"cloudobjects/sdk" : "dev-main",
|
||||||
"php-di/php-di": "^6.0",
|
"php-di/php-di": "^7.1.1",
|
||||||
"slim/slim" : "^3.0",
|
"slim/slim" : "^4.0",
|
||||||
|
"slim/psr7" : "^1.6",
|
||||||
|
"slim/http" : "^1.3",
|
||||||
"jsonrpc/jsonrpc": "^1.0",
|
"jsonrpc/jsonrpc": "^1.0",
|
||||||
"vlucas/phpdotenv" : "^2.4.0",
|
"vlucas/phpdotenv" : "^5.6.3",
|
||||||
"semsol/arc2" : "~2.3.1",
|
"semsol/arc2" : "~3.0.0",
|
||||||
"cloudobjects/rdfutilities" : "dev-main",
|
"cloudobjects/rdfutilities" : "dev-main",
|
||||||
"tuupola/slim-basic-auth": "^3.2",
|
"jimtools/basic-auth": "^1.0",
|
||||||
"dflydev/fig-cookies": "^1.0",
|
"dflydev/fig-cookies": "^3.2.0",
|
||||||
"doctrine/collections": "^1.5",
|
"doctrine/collections": "^3.0.0",
|
||||||
"twig/twig": "^2.5",
|
"twig/twig": "^3.27.0",
|
||||||
"monolog/monolog": "^1.24",
|
"monolog/monolog": "^3.10.0",
|
||||||
"guzzlehttp/oauth-subscriber": "^0.3.0",
|
"webmozart/assert": "^1.6",
|
||||||
"webmozart/assert": "^1.3",
|
"psr/simple-cache": "^3.0",
|
||||||
"psr/simple-cache": "^1.0",
|
"tuupola/cors-middleware": "^1.5",
|
||||||
"tuupola/cors-middleware": "^1.1",
|
"relay/relay": "^3.0",
|
||||||
"relay/relay": "^2.1",
|
"symfony/mailer": "^8.1.0"
|
||||||
"symfony/mailer": "^5.3"
|
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"CloudObjects\\PhpMAE\\" : "classes"
|
"CloudObjects\\PhpMAE\\" : "classes"
|
||||||
},
|
}
|
||||||
"files" : [
|
|
||||||
"vendor/semsol/arc2/ARC2_getFormat.php",
|
|
||||||
"vendor/semsol/arc2/ARC2_getPreferredFormat.php"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"require-dev" : {
|
"require-dev" : {
|
||||||
"phpunit/phpunit": "~5.7",
|
"phpunit/phpunit": "~8.5",
|
||||||
"consolidation/robo": "~1"
|
"consolidation/robo": "^5.1.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+2779
-2329
File diff suppressed because it is too large
Load Diff
@@ -19,12 +19,8 @@ echo "<?php return array(" \
|
|||||||
" 'agws.data_cache' => 'file', " \
|
" 'agws.data_cache' => 'file', " \
|
||||||
" 'log.target' => 'errorlog', " \
|
" 'log.target' => 'errorlog', " \
|
||||||
" 'log.level' => Monolog\Logger::INFO, " \
|
" 'log.level' => Monolog\Logger::INFO, " \
|
||||||
" ); " > /var/www/app/config.php
|
" ); " > config.php
|
||||||
|
|
||||||
# Make cache folder
|
# Make cache folder
|
||||||
mkdir /var/www/app/cache
|
mkdir cache
|
||||||
chown lighttpd:lighttpd /var/www/app/cache
|
chown www-data:www-data cache
|
||||||
|
|
||||||
# Run start script from parent container
|
|
||||||
|
|
||||||
sh /tmp/start.sh
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ vendor: composer.lock
|
|||||||
|
|
||||||
robo.phar:
|
robo.phar:
|
||||||
# Get a copy of robo
|
# Get a copy of robo
|
||||||
curl -L -o robo.phar http://robo.li/robo.phar
|
curl -L -o robo.phar https://github.com/consolidation/robo/releases/download/4.0.4/robo.phar
|
||||||
|
|
||||||
config.php: config.php.default
|
config.php: config.php.default
|
||||||
# Use .default if no other config provided
|
# Use .default if no other config provided
|
||||||
|
|||||||
Reference in New Issue
Block a user