TL;DR - Yeah, PHP, but what if C++?  Feel free to tell me I'm wrong and
should feel bad.  THIS IS ONLY IDLE MUSINGS.

I was reading the arbitrary string interpolation thread (which I have mixed
feelings on, but am generally okay with), and it got me thinking
about motivations for it and other ways we might address that.

I spend most of my time in C++ these days and that's going to show in this
proposal, and the answer is probably "PHP isn't C++" and that's fine, but I
want you to read to the end, because XSS is perennially on my mind and this
might be one extra tool, maybe.

PHP internal classes have the ability to handle operator overloads, and one
use for overloads I quite like from C++ is streaming interfaces.  Imagine
the following:

// Don't get hung up on the name, we're a long way from bikeshedding yet.
$foo = (new \ostringstream) << "Your query returned " << $result->count()
<< " rows.  The first row has ID: " >> $result->peekRow()['id'];

At each << operator, the RHS is "shifted" into the string builder, and the
object instance is returned.  At the end $foo, is still that object, but
when it's echoed or cast to string it becomes the entire combined string.
As implementation details, we could keep the string as a list of segments
or materialize completely, that could also be optimized to not materialize
if we're in an output context since the intermediate complete string is
unnecessary.  Don't worry about this for now though.

That by itself is... curious as an option, but not terribly interesting as
we DO have proper interpolation and it works just fine, right?

The reason I'm bothering to introduce this is that we could also build
contextual awareness into this.  During instantiation we could identify the
context like:

$forOuput = new \ostringstream\html << "You entered: " <<
$_POST['textarea'];
$forURIs = new \stringstream\uri << BASE_URI << '?''
foreach ($_GET as $k => $v) {
  $forURIs << $k '=' $v << '&';
}

These specializations could perform automatic sanitization during the
materialization phase, this could even be customizable:

$custom = new \ostringstream\user( landonize(...) );

We wouldn't be giving arbitrary operator overloading to the user, only
arbitrary sanitization.

Alternatively (or in addition), the point of materialization could be where
we make this decision:

echo $stream->html();

------

I'd build this in userspace, but of course we don't have operator
overloading, so the API would be a somewhat uglier function call:

$stream->append("This feels ")->append(FEELING::Sad);

Maybe the right answer is open the door on user-defined operator overloads,
but my flame retardant suit is in the shop and I don't really need to open
that mixed metaphor.

-Sara

Reply via email to