Я хотел бы знать, был ли безопасный способ оценить математику, как
2+2 10000+12000 10000-20 2 + 2 40 - 20 + 23 - 12
Без использования eval()
поскольку входные данные могут поступать от любых пользователей. То, что мне нужно реализовать, это только добавления и вычитания целых чисел.
Есть ли какие-либо фрагменты, которые уже существуют для этого, или любые функции PHP, с которыми я не сталкивался?
Я бы спросил, используя eval
, учитывая разнообразие математических функций, доступных в PHP. Вы сказали, что хотите сделать просто математику – единственная причина использования eval
состоит в том, чтобы выполнять более сложные операции или принимать уравнения цельной ткани от пользователя.
Если вы просто хотите добавить или вычесть, дезинформировать ввод с помощью intval
и перейти в город:
$number1 = '100'; $number2 = 'shell_exec(\'rm -rf *\')'; echo intval($number1) + intval($number2); // 100
Попробуйте: http://codepad.org/LSUDUw1M
Это работает, потому что intval
игнорирует что-либо нечисловое.
Если вы действительно получаете все уравнение от ввода пользователя (т.е. 100 - 20
), вы можете использовать preg_replace
для удаления чего-либо, кроме разрешенных операторов и номеров:
$input = '20 + 4; shell_exec(\'rm *\')'; $input = preg_replace( '/[^0-9+-]/', '', $input ); eval('$result = '.$input.';'); echo 'result: '.$result; // 24
Попробуйте: http://codepad.org/tnISDPJ3
Здесь мы используем регулярное выражение /[^0-9+-]/
, которое соответствует чему-либо NOT 0-9 OR + OR – и заменяет его пустой строкой.
Если вы хотите получить больше на глубину с помощью разрешенных уравнений, взятых прямо с страницы руководства eval
:
// credit for code to bohwaz (http://www.php.net/manual/en/function.eval.php#107377) $test = '2+3*pi'; // Remove whitespaces $test = preg_replace('/\s+/', '', $test); $number = '(?:\d+(?:[,.]\d+)?|pi|π)'; // What is a number $functions = '(?:abs|a?cosh?|a?sinh?|a?tanh?|exp|log10|deg2rad|rad2deg|sqrt|ceil|floor|round)'; // Allowed PHP functions $operators = '[+\/*^%-]'; // Allowed math operators $regexp = '/^(('.$number.'|'.$functions.'\s*\((?1)+\)|\((?1)+\))(?:'.$operators.'(?2))?)+$/'; // Final regexp, heavily using recursive patterns if (preg_match($regexp, $q)) { $test = preg_replace('!pi|π!', 'pi()', $test); // Replace pi with pi function eval('$result = '.$test.';'); } else { $result = false; }
Документация
preg_replace
– http://php.net/manual/en/function.preg-replace.php intval
– http://php.net/manual/en/function.intval.php eval
– http://php.net/manual/en/function.eval.php Вы можете сами разобрать выражения.
Что-то вроде этого:
// Minus is the same as plus a negative // Also remove spaces after minus signs $str = preg_replace('/-\s*(\d+)/', '+-$1', $str); // Split on plusses $nums = explode('+', $str); // Trim values $nums = array_map('trim', $nums); // Add 'em up echo array_sum($nums);
Я использовал этот метод в калькуляторе калькулятора.
$field1 = $_GET["field1"]; $field2 = $_GET["field2"]; $answer = $field1 + $field2; echo "$field1 + $field2 = $answer";