Не попробуйте написать эту функцию на PHP. Вы неизбежно ошибетесь, и ваше приложение неизбежно будет иметь произвольный эксплойт для удаленного выполнения.
Во-первых, подумайте, какую проблему вы на самом деле решаете. Я полагаю, вы просто пытаетесь получить данные из PHP в Python. Вы можете попытаться написать файл .ini, а не файл .py. Python имеет отличный синтаксический анализатор ini, ConfigParser . Вы можете написать очевидную и потенциально неверную функцию цитирования в PHP, и ничего серьезного не произойдет, если (читай: когда) вы ошибетесь.
Вы также можете написать файл XML. Слишком много парсеров и эмиттеров XML для PHP и Python, чтобы я мог перечислить их здесь.
Если я действительно не смогу убедить вас в том, что это ужасная, ужасная идея, то вы можете по крайней мере использовать уже существующую функцию, которая есть в Python для такой вещь: repr()
.
Вот удобная функция PHP, которая запустит скрипт Python, чтобы сделать это для вас:
<?php
function py_escape($input) {
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w")
);
$process = proc_open(
"python -c 'import sys; sys.stdout.write(repr(sys.stdin.read()))'",
$descriptorspec, $pipes);
fwrite($pipes[0], $input);
fclose($pipes[0]);
$chunk_size = 8192;
$escaped = fread($pipes[1], $chunk_size);
if (strlen($escaped) == $chunk_size) {
// This is important for security.
die("That string's too big.\n");
}
proc_close($process);
return $escaped;
}
// Example usage:
$x = "string \rfull \nof\t crappy stuff";
print py_escape($x);
Проверка chunk_size
предназначена для предотвращения атаки, в результате которой ваши входные данные заканчиваются двумя действительно длинными строками, которые выглядят как ("hello " + ("." * chunk_size))
и '; os.system("do bad stuff")
соответственно. Теперь эта наивная атака не будет работать точно, потому что Python не допустит, чтобы строка в одинарных кавычках заканчивалась в середине строки, и эти кавычки в вызове system()
сами будут заключены в кавычки, но если злоумышленнику удастся получить продолжение строки ("\") в нужном месте и использовать что-то вроде os.system(map(chr, ...))
, тогда они могут внедрить некоторый код, который будет выполняться.
Я решил просто прочитать один блок и сдаться, если было больше вывода, чем продолжать читать и накапливать, потому что есть также ограничения на длину строки исходного файла Python; насколько я знаю, это может быть еще одним вектором атаки. Python не предназначен для защиты от произвольных людей, пишущих произвольный исходный код в вашей системе, поэтому вряд ли эта область будет проверена.
Тот факт, что мне пришлось подумать обо всем этом для этого тривиального примера, является еще одним примером того, почему вы не должны использовать исходный код Python в качестве формата обмена данными.