Песочница для PHP

В одном из наших проектов существует возможность написания плагинов для расширения функционала сервиса.
Пользователи создают плагины-приложения в нашем интерфейсе и описывают их логику на 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

Класс находится на GitHub.