В одном из наших проектов существует возможность написания плагинов для расширения функционала сервиса.
Пользователи создают плагины-приложения в нашем интерфейсе и описывают их логику на PHP.
Необходимо было ограничить возможности PHP, чтобы никто нам случайно не нашкодил.
Существует некоторое количество инструментов для исполнения кода PHP в защищенной среде: выполнение в отдельном процессе, сохранение кода в файле и вызов через cli с урезанными возможностями или использование специализированных расширений для PHP.
В силу специфики сервиса и приложений а так же для возможности использования песочницы на всех ОС (процессы и расширения для sandbox не работают в Windows) с базовыми настройками PHP был написан небольшой класс: Ext_Sandbox_PHPValidator.
Небольшое описание класса
Внутри всего две функции:
- static function php_syntax_error($code, $tokens = null)
- static function validatePHPCode($source, $functions = array(), $enable = true)
php_syntax_error
Функция проверяет, правилен ли синтаксис PHP кода (не пропущены ли скобки и т.д.)
$code — php код (без <?php )
$tokens — необязательный параметр, вы можете передать его если вы уже распарсили код на токены (распарсить можно используя функцию token_get_all).
Функция возвращает ошибку в формате: array( Error Mesage, Error Line # )
Если ошибки нет — функция возвратит false.
validatePHPCode
Функция проверяет php-код и возвращает результат проверки (true или false).
$source — php-код без <?php в начале
$functions — разрешенные/запрещенные функции
$enable — boolean, если true, то $functions будут содержать список разрешенных функций, если false — список запрещенных функций.
Пример:
<?php
require 'PHPValidator.php';
$code = <<<PHP
$b = 1;
$c = 2;
$a = $b + $c;
echo $a;
class test {
public function __construct() {
echo 'construct';
}
public function foo($num) {
var_dump($num);
}
}
$test = new test();
$test->foo($a);
PHP;
// validate the code
$validator = new Ext_Sandbox_PHPValidator();
try
{
// we enable only one function - echo, all others will throw error
$validator->validatePHPCode( $code, array('echo'), true);
$status = 'passed';
}
catch(Exception $ex)
{
$status = $ex->getMessage();
}
echo 'Status of validation is: ' . $status;
Попробовать онлайн: http://ideone.com/e1qx28
Автор: xytop