On Aug 30, 7:23*pm, Christopher Vogt <christopher.v...@rwth-aachen.de>
wrote:
Quote:
Hej everybody,
>
I built something for myself that might help some of you as well.
Looking at a couple of PHP template engines made me think.
>
I have two main requirements for a presentation layer framework:
*- use PHP as the template language
*- effective XSS prevention without betting on discipline
>
Plain PHP only satisfies the first. I could not find a PHP template
engine that satisfies both. (Savant doesn't.)
>
So here is my own minimal solution and I would like to know your
opinion. Also, if anybody has seen something like it out there, please
point me to it.
>
The Idea:
Automatically wrap every string meant for output into an object, which
offers filtering methods like htmlentities. This also means intercepting
access to strings contained in Arrays and Objects. This can be done
using the Decorator pattern.
>
The code:
http://code.google.com/p/cvphplib/so...runk/cvphplib/
svn checkouthttp://cvphplib.googlecode.com/svn/trunk/cvphplib/
>
Example usage:
// first a simple string
<? $string = CV_OutputFilter::filter( '<marquee>evil</marquee>' ); ?>
<?=$string?triggers an error
<?=$string->htmlentities()?works fine
<?=$string->urlencode()?* *works fine
<?=$string->raw()?outputs the unfiltered value
>
// extracting a bunch of filtered variables into the local scope
<?php
$vars = array( 'x'=>5, 'o'=>new O(), 'array' =array('<i>'=>'<b>') );
extract( CV_OutputFilter::filter($vars)->toArray() );
?>
>
// access to object members
<?=$o->var?triggers an error
<?=$o->method()?triggers an error
<?=$o->var->htmlentities()?works fine
<?=$o->method()->htmlentities()?works fine
>
// access to array elements
<?=$array['<i>']?triggers an error
<?=$array['<i>']->htmlentities()?works fine
>
// Iterating over an array
<? foreach( $array as $value ){} ?works fine
<? foreach( $array as $key =$value ){} ?throws an exception, because
$key would not be filtered in this case
>
// decorating array keys requires some iterator magic
<? foreach( $array->key_as($key) as $value ): ?>
* * * * <?=$key->htmlentities()?>: <?=$value->htmlentities()?<br/>
<? endforeach; ?>
>
Potential problem:
*- potentially slow (due to many object instantiations and reflection)
>
Benefits:
*- effective XSS prevention without betting on discipline
*- template-engine-like variable extraction into local scope
*- clean and short syntax
*- very little to learn
>
Functionality already implemented, but not shown in the example:
*- register custom filter methods
*- enable __toString() with custom default filter
*- use tuple array(key,value) for $value instead of 'key_as'-magic
*- register custom filter applied on keys in ->toArray()
*- decoration of multidimensional arrays and webs of object references
>
More example code:
http://code.google.com/p/cvphplib/so...vphplib/tests/...
>
So, what do you think?
Haven't checked out any code other than the stuff you posted here, but
I like it.
I like how just trying to display a variable triggers an error,
forcing the author to think. Additionally, I like how you're not
trying to add any framework-ish features, but leave it up to the
framework coders to maybe automatically do a CV_OutputFilter::filter()
on all variables sent to the view (assuming an MVC setup).
I see only one downside, and that is that IMHO the position where
things are done is slightly architecturally incorrect: you typically
want to do htmlentities() as the last operation, or second last
sometimes (before an nl2br/bbcode formatter or so). This means that if
there are operations performed on the variable that require it
unmangled, the author needs to do a workaround:
<?= htmlentities(parse_important_stuff_using_html_char s($var->raw())) ?
Naturally, if parse_important_stuff_using_html_chars is common, this
can be solved by registering it as a custom filter, of course.
Another worry: did you test the speed of your approach? I haven't
looked into the source, but it appears quite some magic requires
__get, __set and __call, which may slow down the view element of the
page a bit.
(btw, as another (on topic) shameless plug, my home cooked compiling
template engine does htmlentities or htmlspecial chars by default when
echoing expressions, and allows pure PHP code,
http://e.teeselink.nl/mplate..
if you're cool with that, I may want to add your filter class thingy
as an extention to it, though, for more fine grained control)
Egbert