J'ai passé du temps sur ce problème récemment. Voici le contour de ma solution.
J'ai créé une nouvelle classe appelée HtmlSafe qui contient des chaînes pouvant être écrites en toute sécurité sur le client WWW sans faille de sécurité. L'idée était que les fonctions qui génèrent des balises HTML retournent des objets HtmlSafe, et les variables qui sortent de la boîte ne sont pas HtmlSafe. Tout ce qui crée un HtmlSafe s'est également porté garant de la sécurité de la chaîne en question. La concaténation d'une chaîne non sécurisée au format HTML avec une chaîne sécurisée au format HTML entraîne l'échappement de la chaîne non protégée par HTML via CGI :: escapeHTML, puis sa jointure avec la chaîne HTML-safe. Concaténant une autre instance de HtmlSafe à HtmlSafe simplement joint les chaînes en question sans s'échapper. J'ai fini par utiliser une surcharge pour pouvoir redéfinir le. opérateur pour la classe HtmlSafe.
Armé avec cette chose, je donnai un processus template- $>() fonctionner une variable de sortie de $ qui était en fait un sous-marin qui a invoqué une concaténation avec HtmlSafe, comme ceci:
my $output = HtmlSafe->new("");
$template->process($vars, sub { $output .= $_[0]; });
return $output->unwrap(); # remove HtmlSafe and return underlying string
Nous sommes presque prêts avec le HtmlSafe TT2. Le gros changement que j'ai dû faire était de changer la fonction textblock() dans Template :: Directive, qui est utilisée par Template :: Parser pour générer des instances HtmlSafe de n'importe quel bloc de texte qu'il a essayé d'émettre. Ceux-ci semblent correspondre avec le texte des noeuds du modèle analysé, si juste faire
package MyDirective;
use base "Template::Directive";
sub textblock { my $self = shift; return "$Template::Directive::OUTPUT HtmlSafe->new(" . $self->text(@_) . ")"; }
que j'ai donné à parser comme ceci:
my $parser = Template::Parser->new({
FACTORY => "MyDirective",
});
En plus de cela, je défini un filtre « none » pour TT2 qui enveloppe simplement tout ce qui est défini comme HtmlSafe, ainsi vous pouvez produire du HTML brut si vous devez. Cela évite d'échapper aux choses. Le filtre "html" par défaut est no-op, car tout ce qui est concaténé à HtmlSafe est maintenant échappé.
Un modèle personnalisé :: Stash ne serait probablement pas suffisant.Les deux '[% x%]' et '[% y = x%]' appellent la méthode 'get()' de la mémoire pour rechercher 'x' mais seule la première produit une sortie, la mémoire ne sera probablement pas capable de dites la différence entre "get and print" et simplement "get" pour que vous finissiez avec beaucoup de choses codées en double/triple/... HTML. Probablement le mieux de ne pas déranger. –
La philosophie de conception de TT est de permettre par défaut des attaques de script intersite et de n'autoriser la sécurité que par une quantité abondante de rasage yak. – geira
Oui, ce serait beaucoup trop pratique pour entrer dans la philosophie TT. – jeje