Re: New escaped output operator

From: Date: Mon, 20 Jun 2016 16:07:42 +0000
Subject: Re: New escaped output operator
References: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15  Groups: php.internals 
Request: Send a blank email to internals+get-94153@lists.php.net to get a copy of this message
On 06/20/2016 10:24 AM, Rasmus Schultz wrote:
<ul> <?php foreach ( $things as $thing ) { ?> <li><a href="/things/<?= $thing['name'] ?>" onclick="show_popup('<?= $thing['name'] ?>');"><?= $thing['name'] ?></a> <?php } ?> </ul> There are three different escape mechanism needed there; if there is a shorthand for one, do you think it will be more likely or less that people will get the other two right?
I have to agree with that - assigning special syntax to one kind of escape-function gives that function an elevated status, which could easily encourage neglect and oversight. I do wish that we had an obvious, consistently-named set of web-related escape/encode functions for use in plain PHP templates, like html(), attr(), js(), etc... having to type and read htmlspecialchars() and json_encode() while you're trying to visually parse a template is really inconvenient. That's all it is though, inconvenience. Nice to have, not must have. I'd be much more interested in a general solution to the problem of being unable to (or at least strongly demotivated from) using actual namespaced functions in this and many other cases - that's a missing feature and a more general problem, whereas in my opinion an operator or shorter function-names are just a work-around... (and please, nobody say "use a template engine" - I *am* using a template engine, it's called PHP!)
In many of the PHP template engines, there are multiple "filters" available with a specific syntax, and a way to add more. You have to specify which one you want, because only you know the context. Twig (and possibly others?) lets you set a default escaper that can be overridden case by case as needed, including by a "none" option. Rather than try to make print statements themselves into a more secure template layer (Sorry, Rasmus, that ship has long since sailed, even Drupal gave up on PHPTemplate), perhaps it would be more useful to look at the needs of the various template engines (Twig, Smarty, Blade, etc.) and see what the language can/should do to make it easier for those engines to be made secure. That same underlying tooling, then, can be exposed in a way that those still using PHP itself as a template engine can leverage it more easily. I'm not 100% certain what that would look like. My initial thought (which is potentially a terrible idea), is some sort of callable registration, akin to stream wrappers or autoloaders, where you could do something vaguely like this: register_escaper('html', function($var) { return htmlentities($var, ENT_QUOTES | ENT_HTML5); }); register_escaper('html_attrib', function($var) { ... }); register_escaper('raw', function($var) { return $var;}); set_default_escaper('html'); // I dislike a global flag like this, but it works for this demonstration. <?php print $foo; // no escaping, because BC. printe $foo; // Run through html escaper printe($foo, 'html_attrib'); // Run through html_attrib escaper ?> <?= $foo; ?> // No escaping <?~ $foo ?> // Run through html escaper <?~html_attrib $foo ?> // Run through html_attrib escaper And then Twig, Smarty, etc. can also leverage the registered escapers, and add their own as appropriate. That's off-the-cuff syntax that may be terrible, but the goal here is to better enable template engines (whether thick ones like Twig or thin ones like *.view.php) to do security better, rather than trying to Solve It For All The Things(tm), which for security is a very dangerous dead-end approach. --Larry Garfield

« previous php.internals (#94153) next »