Ne pas Essayez d'écrire cette fonction en PHP. Vous allez inévitablement vous tromper et votre application aura inévitablement un exploit d'exécution à distance arbitraire.
D'abord, réfléchissez au problème que vous résolvez réellement. Je suppose que vous essayez simplement d'obtenir des données de PHP vers Python. Vous pouvez essayer d'écrire un fichier .ini plutôt qu'un fichier .py. Python a un excellent parser de syntaxe ini, ConfigParser. Vous pouvez écrire la fonction de citation la plus évidente et potentiellement incorrecte en PHP et rien de grave ne se produira si (lire: quand) vous vous trompez.
Vous pouvez également écrire un fichier XML. Il y a trop de parseurs et d'émetteurs XML pour PHP et Python pour que je les liste même ici.
Si je vraiment ne peux pas vous convaincre que c'est un terrible, terrible idée, vous pouvez au moins utiliser la fonction pré-existante que Python a pour faire une telle chose: repr()
.
Voici une fonction PHP pratique qui exécuter un script Python pour le faire pour vous:
<?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);
Le chunk_size
chèque est destiné à empêcher une attaque par laquelle se termine votre entrée par être deux chaînes très longues, qui ont l'air comme ("hello " + ("." * chunk_size))
et '; os.system("do bad stuff")
respectivement. Maintenant, cette attaque naïve ne fonctionnera pas exactement, car Python ne laissera pas une chaîne entre guillemets se terminer au milieu d'une ligne, et ces guillemets dans l'appel system()
seront eux-mêmes cités, mais si l'attaquant réussit à obtenir un ligne continuation ("\") dans le bon endroit et utiliser quelque chose comme os.system(map(chr, ...))
puis ils peuvent injecter du code qui va fonctionner. J'ai opté pour simplement lire un morceau et abandonner s'il y avait plus de sortie, plutôt que de continuer à lire et à accumuler, car il y a aussi des limites sur la longueur de la ligne du fichier source Python; pour tout ce que je sais, ça pourrait être un autre vecteur d'attaque. Python n'est pas destiné à être sécurisé contre les personnes arbitraires qui écrivent du code source arbitraire sur votre système, il est donc peu probable que cette zone soit auditée.
Le fait que j'ai dû penser à tout cela pour cet exemple trivial est juste un autre exemple de pourquoi vous ne devriez pas utiliser le code source python comme format d'échange de données.
Nono, tu m'as convaincu. :) Cette approche devrait avoir soulevé toutes sortes de drapeaux rouges dans ma tête quand j'ai d'abord pensé à cela. Je suis curieux de savoir pourquoi la fonction ci-dessus vérifie que la taille du segment est égale à la longueur de la chaîne; pourriez-vous expliquer cette partie un peu plus loin? –
Je l'ai édité pour ajouter une belle explication longue; J'espère que cela pourra aider. – Glyph