<?xml version="1.0" encoding="UTF-8"?>
<feed
  xmlns="http://www.w3.org/2005/Atom"
  xmlns:thr="http://purl.org/syndication/thread/1.0"
  xml:lang="en"
   >
  <title type="text">All Unkept</title>
  <subtitle type="text"></subtitle>

  <updated>2013-05-24T11:16:23Z</updated>
  <generator uri="http://blogofile.com/">Blogofile</generator>

  <link rel="alternate" type="text/html" href="http://lukeplant.me.uk/blog" />
  <id>http://lukeplant.me.uk/blog/feed/atom/</id>
  <link rel="self" type="application/atom+xml" href="http://lukeplant.me.uk/blog/feed/atom/" />
  <entry>
    <author>
      <name></name>
      <uri>http://lukeplant.me.uk/blog</uri>
    </author>
    <title type="html"><![CDATA[Why escape-on-input is a bad idea]]></title>
    <link rel="alternate" type="text/html" href="http://lukeplant.me.uk/blog/posts/why-escape-on-input-is-a-bad-idea" />
    <id>http://lukeplant.me.uk/blog/posts/why-escape-on-input-is-a-bad-idea</id>
    <updated>2012-08-06T20:59:01Z</updated>
    <published>2012-08-06T20:59:01Z</published>
    <category scheme="http://lukeplant.me.uk/blog" term="Python" />
    <category scheme="http://lukeplant.me.uk/blog" term="Security" />
    <category scheme="http://lukeplant.me.uk/blog" term="PHP" />
    <category scheme="http://lukeplant.me.uk/blog" term="Web development" />
    <category scheme="http://lukeplant.me.uk/blog" term="Django" />
    <summary type="html"><![CDATA[Why escape-on-input is a bad idea]]></summary>
    <content type="html" xml:base="http://lukeplant.me.uk/blog/posts/why-escape-on-input-is-a-bad-idea"><![CDATA[<div class="document">
<p>The right way to handle issues with untrusted data is:</p>
<blockquote>
Filter on input, escape on output</blockquote>
<p>This means that you validate or limit data that comes in (filter), but only
transform (escape or encode) it at the point you are sending it as output to
another system that requires the encoding. It has been standard best practice
since just about forever <sup>[citation required]</sup>.</p>
<p>An alternative is “escape on input”: at the point that data enters your system,
you apply a transformation to it to avoid a problem further down the line when
the data is used.</p>
<p>It's come to my attention that some serious web developers (or at least, they
take themselves seriously and are taken seriously by others) are <strong>still</strong>
suggesting the practice of escape-on-input.</p>
<p>For example, with escape-on-input, to avoid XSS any data that enters your system
has HTML escaping applied to it <em>immediately</em>, before your application code
touches it.</p>
<p>I chose that example deliberately, because people are actually recommending it:</p>
<ul>
<li><p class="first"><a class="reference external" href="http://nikic.github.com/2012/06/29/PHP-solves-problems-Oh-and-you-can-program-with-it-too.html#comment-572962448">in some recent “PHP sucks” debate</a>.</p>
</li>
<li><p class="first">which, in turn, linked to a <a class="reference external" href="http://toys.lerdorf.com/archives/38-The-no-framework-PHP-MVC-framework.html">page by Rasmus Lerdorf recommending
escape-on-input as a sensible way to deal with XSS</a>.
The page, admittedly, is describing a ‘toy’, a ‘no-framework PHP framework’,
yet he does seem to be serious about the usefulness of escape-on-input.</p>
<p>The page is from 2006, and uses the pecl/filter extension, but the extension
has since made it into core (PHP 5.2), and the <a class="reference external" href="http://www.php.net/manual/en/filter.configuration.php">docs for it</a> suggest a
configuration that is clearly intended for XSS prevention. As recently as
2008, and probably to this day, Lerdorf is <a class="reference external" href="http://grokbase.com/p/php/php-internals/083qakz7wj/php-dev-short-open-tag">still defending and recommending
this approach</a>,
and it appears to be part of his reason for thinking that PHP templating
doesn't need an autoescape mechanism.</p>
</li>
<li><p class="first">Just as significantly, <a class="reference external" href="http://www.slideshare.net/zanelackey/effective-approaches-to-web-application-security">Etsy are using and recommending escape-on-input</a> (slide
18 onward). As a very successful modern company using PHP, people will look
up to them and copy them.</p>
</li>
</ul>
<p>So, this approach, unfortunately, is popular amongst some, and I can't find a
decent post explaining why it's such a terrible idea both in theory and
practice. Here is my attempt. It should be applicable to almost any system and
any language, although I'll mainly be using examples from web development.</p>
<div class="section" id="in-theory">
<h1>In theory</h1>
<ul>
<li><p class="first">First of all, escape-on-input <strong>is just wrong</strong> — you've taken some input and
applied some transformation that is totally irrelevant to that data. If,
taking our example, you have some data collected by HTTP POST or GET
parameters, applying HTML escaping to it is a layering violation — it mixes an
output formatting concern into input handling. Layering violations make your
code much harder to understand and maintain, because you have to take into
account other layers instead of letting each component and layer do its own
job.</p>
<p>Doing things ‘right’ is very important, even if doing them ‘wrong’ seems to
work and you are tempted to be dismissive of ‘theoretical’ concerns about
purity etc. When you have to maintain code, you will be very glad if things
are in the right place, and not full of hacks and surprises.</p>
</li>
<li><p class="first">You have corrupted your data by default. The system (or the most convenient
API) is now lying about what data has come in. As you have applied a
transformation to the <strong>data itself</strong>, the layering violation is not an
isolated problem in one part of the code, but infects every part of your code,
especially if you store the corrupted data in a database.</p>
<p>Your data is <strong>everything</strong>. As I read recently, <a class="reference external" href="http://blog.datamarket.com/2012/07/08/the-11-best-data-quotes/">“data matures like wine,
applications like fish”</a>. You can
always rewrite your application, but if you corrupt your data, you've done the
worst thing you can to your system.</p>
</li>
<li><p class="first">This is exacerbated by the fact that many encodings are one-way — you cannot
losslessly or unambiguously convert them back. If at a later point you need
the original data, you might be in a pickle.</p>
</li>
<li><p class="first">Escaping your data for one output backend will only deal with <strong>that</strong>
output. A typical web app might deal with at least the following backends,
which have different characters that are dangerous, and have different
requirements for dealing with them:</p>
<ul class="simple">
<li>HTML: ' &lt; &gt; &quot; &amp;</li>
<li>SMTP and HTTP: ; : newlines</li>
<li>SQL: '</li>
<li>JSON: &quot;</li>
<li>Shell - space, quotes and various other characters</li>
</ul>
<p>Any number of others could be added, and all could have security
implications. Using escape-on-input will only fix one of these (apart from
happy coincidences where it might fix more than one), but for the others you
will still need a sensible solution to the problem. Why not have a sensible
solution for all of them?</p>
</li>
<li><p class="first">Escaping on input will not only fail to deal with the problems of more than
one output, it will actually make your data <strong>incorrect</strong> for many outputs.</p>
<p>Suppose you decide to do HTML escaping, and someone enters <em>Jack &amp; Jill</em> as a
title for something. Your escape-on-input turns this to <em>Jack &amp;amp; Jill</em> and
that goes in the DB. Suppose you want to email people and put this title in
the subject line. You now have to apply the reverse transformation to get a
sensible subject line in the email, and you have to <strong>remember</strong> to do this
for every output that is not HTML.</p>
<p>Sometimes, the bug is <a class="reference external" href="http://instagram.com/p/SVfQruppEE/">significantly more annoying</a> than an email with an incorrect title.</p>
<p>You also have daft bugs like the fact that doing a search on that field for
the string ‘amp’ (or ‘quot’, ‘apos’, ‘lt’, ‘gt’ etc. or any substrings) will get
various false matches.</p>
<p>I have seen some people respond to this by saying “it's better to have the
occasional double-encoding bug or incorrect query result than an XSS
exploit&quot;. Well, first, that depends on your business. XSS is a problem because
it costs time and money, and so does corrupting your data. Many people have
data that actually matters, and corrupt data is a big deal, and much harder to
cope with than an XSS bug, because data lives on and on, while your code can
get replaced easily.</p>
<p>Second, this decision affects <strong>frameworks</strong> that are used to handle data of
<strong>all kinds</strong>, and the decision affects the entire code base of your
application and beyond, as described below. Data-handling frameworks that work
on the assumption that your data is not important are insanity. <a class="reference external" href="http://www.biblegateway.com/passage/?search=Psalm%2011:3&amp;version=KJV">If the
foundations be destroyed, what can the righteous do?</a></p>
<p>Third, it's entirely unnecessary. XSS is not hard to fix given decent
programming tools.</p>
</li>
<li><p class="first">At what point does data ‘enter’ your system?</p>
<p>It might sound like a simple question, but it's tricky in reality, and I'll
illustrate using an HTTP request.</p>
<p>In most web apps, the GET and POST parameters are your ‘raw input’. However,
using most normal web framework APIs, data in GET and POST parameters has
already been interpreted. The ‘raw’ data is really the bytes that make up the
HTTP request, which typically will use URL encoding for GET query parameters
and a choice of encodings for POST data (URL encoding or MIME multipart
attachment format).</p>
<p>The framework may also do another level of decoding — interpreting the
series of bytes as a series of unicode code points.</p>
<p>Both parts of this initial transformation makes sense and are appropriate,
because they are reversing the encoding already applied to the data by the
protocol involved. The web browser takes the data you type in — unicode code
points — and applies a series of transformations to it, according to the HTTP
protocol, and your web framework reverses these to get the data back.</p>
<p>Now, if you want to avoid XSS problems, you have to apply the escaping
<strong>after</strong> this initial decoding has been done. But this highlights another
possibility. What if the data requires <em>further</em> decoding before you get the
‘real’ raw data? For example, some data might be sent base64 encoded for a
variety of reasons, or any other type of encoding.</p>
<p>This extra level of encoding gives two problems:</p>
<ul>
<li><p class="first">your automatic HTML escaping may have corrupted the encoded data so that it
now cannot be decoded. For example, you had a GET parameter that held a URL,
which itself had parameters in the query string:</p>
<pre class="literal-block">
GET /foo?bar=1&amp;url=http%3A%2F%2Fexample.com%2F%3Fx%3D1%26y%3D2 HTTP/1.1
</pre>
<p>Your framework's HTTP handling will produce a query dictionary that looks
something like the following:</p>
<pre class="literal-block">
{&quot;bar&quot;: 1,
 &quot;url&quot;: &quot;http://example.com/?x=1&amp;y=2&quot;
 }
</pre>
<p>But your automatic escaping turns that into:</p>
<pre class="literal-block">
{&quot;bar&quot;: 1,
 &quot;url&quot;: &quot;http://example.com/?x=1&amp;amp;y=2&quot;
 }
</pre>
<p>If you want to extract the 'y' parameter from 'url', you are stuck. You
can't correctly interpret the data in the 'url' parameter, because it has
been corrupted. You're going to have to re-decode the input, and you might
not even notice this problem.</p>
</li>
<li><p class="first">Even if the data comes through your automatic escaping unscathed
(e.g. base64 under HTML escaping), or you can undo the corruption and get it
properly decoded, after decoding you will have to <strong>manually apply</strong> HTML
escaping to make it match all the other automatically escaped data. If you
don't, you've potentially got a bug and an XSS exploit.</p>
<p>So your automatic escape-on-input has <strong>missed</strong> data, and this happens
because you can't really define the point at which the data has ‘entered’
your system and needs the escaping applied.</p>
</li>
</ul>
<p>This problem means that the escape-on-input approach is inherently flawed and
<strong>cannot</strong> be fixed. <strong>You just have to patch it up on a case-by-case basis,
which is exactly what escape-on-input is supposed to avoid.</strong></p>
<p>And then, what about other sources of data — data on the file system, in a
cache etc. Are these entry points? Well, it depends on how the data was put
there. You have to manually follow this all the way through your app; get it
wrong and you've got double escaping bugs or security flaws.</p>
<p>(By contrast, escape on output always works, because you apply it at the point
where you know it is needed — in the backend that knows the escaping rules.)</p>
</li>
<li><p class="first">Other systems putting data into your database, or getting data out, have to
abide by your data transformation rules.</p>
<p>These systems might have nothing to do with your primary domain (e.g. a web
site). Making them understand and obey rules that have nothing to do with the
data itself is insanity and extremely short sighted.</p>
<p>You can't deal with this problem when you come to it, because you don't have
to just fix your code, you've got to fix all your data too, and by the time
you cross this bridge you might have a lot of data and might need a very
delicate database migration to get it right. The data may even have escaped
your control (e.g. been copied into other systems), or backwards compatibility
concerns might stop you from making the change you need to make.</p>
</li>
<li><p class="first">Within your main application, the decision to escape on input affects your
whole code base.</p>
<p>If you want to use any libraries, you need to make sure that they are using
all the same assumptions that you have in your main code base.</p>
<p>For example, if you've got a form/widget library in your web app, it will very
often need to echo user input back to them in the case of a form that has
validation errors. This library has to know if you already escaped the input.</p>
<p>Writing the library to work in two modes is asking for trouble. Rather, you
need it to have been written from the beginning to assume the same escaping
rules.</p>
<p>This kills code re-use — you can only use code that assumes the same input
escaping — or it means that you will end up with tons of bugs due to
incompatibilities between the assumptions made in your application code and
the library.</p>
<p>Essentially, this is the problem of a global configuration setting, but worse
since it affects the <em>operand</em> of your entire application (the data going
through it), not just the functionality of various <em>operators</em>.</p>
</li>
<li><p class="first">The confusion caused by the above is likely to <em>increase</em> security
problems. “Keep It Simple, Stupid” remains a very good maxim for developers.</p>
<p>To continue an example used above: you want to send an email with some data
that has already been HTML escaped, and so you need to unescape the data to
avoid emails with the subject &quot;Jack &amp;amp; Jill&quot; when the user entered &quot;Jack &amp;
Jill&quot;. You decide it's not sensible for the mail sending functions to do this
internally, (or maybe they're provided by a 3rd party who made that decision
for you), so the calling code does the unescaping.</p>
<p>You later decide to switch to HTML emails, and the developer who implements it
thinks that since data is already escaped, there is no problem including it
without extra escaping in the body of the HTML email, leading to a
vulnerability (not classic XSS in this case, but still a problem).</p>
<p>There is also the example I gave above where an extra layer of
encoding/decoding in the raw data makes it likely you'll forget to apply the
escaping.</p>
<p>The confusion caused by escape-on-input means your entire code base becomes a
potential source not only of double-escaping bugs but of security problems as
well.</p>
</li>
</ul>
</div>
<div class="section" id="in-practice">
<h1>In practice</h1>
<p>Thankfully, we don't just have to rely on the above analysis to conclude that
escape-on-input is a terrible idea. PHP, always willing to help when it comes to
“examples of how not to do it”, provides us with a perfect case study.</p>
<div class="section" id="magic-quotes">
<h2>Magic quotes</h2>
<p>PHP used to have a feature called magic quotes. It was an escape-on-input
feature that escaped single quotes (<strong>'</strong>) with backslashes. This was to protect
you from SQL injection attacks, by making the data safe for interpolation into a
SQL query.</p>
<p>This caused all kinds of problems.</p>
<p>First, if you are not first passing something through a database, and using
string interpolation to build up SQL queries, you have to remember to strip
those slashes using the function <tt class="docutils literal">stripslashes()</tt>.</p>
<p>If you don't, you get double encoding. It looks like \'this\', you\'ve
almost certainly seen it across the web, though it seems we\'re thankfully
past the worst of it.</p>
<p>Second, even if you remember, you've added some hideous cruft to your code. In
the bit of code which is handling form validation (and is therefore echoing user
input back to the user without the database being involved), you've got these
bizarre <tt class="docutils literal">stripslashes()</tt> calls. What on earth does ‘reverse transforming a
string for SQL statement preparation’ have to do with the task of input
validation?</p>
<p>Third, it turns out that different databases need different escaping mechanisms
to do things fully correctly. So you now have to do <tt class="docutils literal">stripslashes()</tt> on data
even if you are passing it to a database using string-interpolated queries!</p>
<p>Then, since the above problems are common (building up SQL queries by string
interpolation was always a bad idea, and very often you pass on the data to
outputs that don't want SQL escaping at all), it's desirable to have a way to
turn this behaviour off completely.</p>
<p>To handle this, there is a php.ini setting to turn it on/off.</p>
<p>And there were more complications, for example:</p>
<ul class="simple">
<li>do you apply magic quotes to ‘all input’ (<tt class="docutils literal">magic_quotes_runtime</tt>) or just to
GET/POST/COOKIE data (<tt class="docutils literal">magic_quotes_gpc</tt>)? (This is the problem of defining
what exactly is ‘input’)</li>
<li>attempts to fix some of the above with yet more configuration options like
<tt class="docutils literal">magic_quotes_sybase</tt>.</li>
</ul>
<p>And so now you've got even more problems. Since these are global settings, you
can't have library code mess with them, since other code might set the global to
a different value or assume a certain value.</p>
<p>You could try making all code detect the current setting and have different code
paths depending on the result. This works very badly — having multiple code
paths is a recipe for code duplication and bug proliferation. It's extremely
easy to forget to do it, or get one of the paths wrong, since you will likely
only test one configuration value and one set of code paths in reality.</p>
<p>Alternatively, you can make one bit of code responsible for fixing the setting
to a sensible value (the only one being 'off'), and then make all code assume
that from then on. (If you can't turn it off, you can use the code included
<a class="reference external" href="http://www.php.net/manual/en/security.magicquotes.disabling.php">here</a> as a
horrible kludge to reverse it's behaviour).</p>
<p>Eventually, this final approach was the one taken by all significant
projects. <strong>Turn the whole feature off, and assume it is off from then
on</strong>. (Which means the feature is useless, of course).</p>
<p>And of course, thankfully, the PHP developers realised that this entire thing
was a <strong>huge mistake</strong> that caused nothing but a vast amount of confusion and
bugs, and <strong>removed the whole thing</strong> for good in PHP 5.4.</p>
<p>Magic quotes, <a class="reference external" href="http://me.veekun.com/blog/2012/04/09/php-a-fractal-of-bad-design/">as eevee put it</a>, were “so
close to secure-by-default, and yet so far from understanding the concept at
all.”</p>
<p>To digress for a moment: we keep getting told that PHP is improving, and the
community has learnt from its mistakes. Unfortunately it seems the leaders in
the community are bent on <strong>recreating</strong> old mistakes.</p>
<p>According to Lerdorf, the much newer PHP 'filter' extension is <a class="reference external" href="http://grokbase.com/t/php/php-internals/08373a1vvf/short-open-tag/083qakz7wj#20080323qvterw1df6a006qxyg83z9qsb8">“magic_quotes
done right”</a>. But
it still suffers from almost all the problems described here, for all the
reasons described. Global HTML escaping on input is essentially the same as
magic quotes, and just as tragically bad.</p>
</div>
<div class="section" id="elgg">
<h2>Elgg</h2>
<p>In researching for this post, I came across <a class="reference external" href="http://trac.elgg.org/ticket/561">this ticket for Elgg</a>, an open source social networking engine.
Just read through the ticket and see the mess they are in. It's clear they
strongly regret the decision they made to escape-on-input, and, in their own
words, have created “horrendous” problems for themselves, especially as their
application has grown to include other interfaces such as JSON REST APIs.</p>
<p>However, fixing it is very hard. They have to coordinate many changes across
their code base with a big database migration. If data has leaked from the
databases and tables they control into other systems, such as denormalised
tables, other databases, caches etc., or if there is other code by third parties
that makes the old assumptions about encoded data, they are in even more of a
pickle. And both of those things are probably inevitable in something like an
open source framework, which is designed for other people to build on and
extend.</p>
<p>This is the pain that comes from mixing input handling and output encoding,
and from corrupting the data in your database.</p>
</div>
<div class="section" id="etsy">
<h2>Etsy</h2>
<p>According to <a class="reference external" href="http://www.slideshare.net/zanelackey/effective-approaches-to-web-application-security">their security presentation</a>,
Etsy are using escape-on-input for XSS protection.</p>
<p>They claim that this is a much more secure option, as it is secure by
default. (They do note, however, the problem with input that is encoded in some
other way, like base64, so they are aware of the problems.)</p>
<p>Their presentation goes on to describe an elaborate system for detecting and
fixing XSS attacks (the slides don't give enough detail for me to understand
what exactly they are doing, but it's clearly a lot of work).</p>
<p>And <a class="reference external" href="http://www.nzinfosec.com/etsy-has-been-one-of-the-best-companies-ive-reported-holes-to/">their system does indeed catch XSS bugs in the wild and allow them to fix
them within hours</a>.</p>
<p>Wait, what?</p>
<p>They've corrupted their database by doing escape-on-input, they've inflicted
themselves with all the development pain described above, and they've <strong>still</strong>
got XSS bugs?</p>
<p>Granted, they've got impressive ways of dealing with these problems. But it's
like <a class="reference external" href="http://xkcd.com/463/">virus checkers on voting machines</a>. Advanced ways
of dealing with problems that shouldn't even be possible tells you that you are
doing it wrong. They've become very fast at <a class="reference external" href="http://www.red-sweater.com/blog/125/easy-programming">re-tying their shoelaces, instead
of working out how to tie shoelaces so they don't come undone</a>.</p>
<p>They claim that with escape-on-input, XSS problems are now greppable, but it
doesn't sound like it. If they were, code audits would be a massively more
efficient way to find XSS problems than the methods they are using.</p>
<p>The main problem is almost certainly that they are using an output system for
HTML that doesn't do HTML escaping by default (I'm guessing they are using PHP
as their template language). If the backend that deals with HTML <strong>actually
deals with HTML</strong> then you eliminate the vast majority of these problems
overnight.</p>
<p>I'm willing to bet that large sites that use Django (or other frameworks that
have basically solved the XSS problem by HTML escaping on output <strong>by default</strong>)
don't have teams and automated systems dedicated to this problem, and don't need
them. In Django apps, XSS problems <strong>are</strong> greppable - you grep for
<tt class="docutils literal">mark_safe</tt> in Python and the <tt class="docutils literal">|safe</tt> filter in templates (and then,
obviously, you may have to recursively grep for any functions that call
<tt class="docutils literal">mark_safe</tt> on inputs). Since all data which isn't ‘mark_safe()’d gets escaped
by the templating engine, and all HTML comes out of the template engine, that's
basically all you need to do.</p>
</div>
</div>
<div class="section" id="now-for-some-flame-bait">
<h1>Now for some flame bait</h1>
<p>How did this happen to Etsy?</p>
<p>Are the Etsy devs stupid? I suspect not. Etsy is clearly doing well, and I
imagine they have enough money to hire top-notch developers. Some of their
<a class="reference external" href="http://www.etsy.com/careers/job_description.php?job_id=ozhhVfwM">careers pages</a> show they
are happy using a variety of languages and technologies, and their <a class="reference external" href="http://codeascraft.etsy.com/">engineering
blog</a> seems to be sane and competent. Even their
security presentation showed considerable ingenuity and technical ability in
dealing with security problems (in entirely the wrong way, unfortunately, but
still impressive).</p>
<p>I doubt they are low quality developers. Rather, I suspect that use of PHP has
addled their brains. They have become far too accustomed to working in an
environment in which insanity reigns — an environment in which <a class="reference external" href="/blogmedia/php_less_than.txt">the less than
operator pretends to work correctly with strings but it's just a trap</a>.</p>
<p>When I programmed in a Windows environment, I theorised that use of Windows
itself contributed to the poor quality of the programming in the code base, and
the fact that developers thought nothing or writing tons of tedious
code. Because Windows was so unscriptable, I imagined that Windows programmers
developed a high tolerance for tedium and repetition, which is exactly the
opposite of qualities needed by a programmer to make a computer do everything
efficiently and reliably. (Since then, I've found that Sturgeon's law was
probably a better explanation for the quality of the code, but I still think the
fundamental idea applies).</p>
<p>With PHP, the fact that it comes with a template language that is simply not fit
for purpose — because it doesn't do HTML escaping by default, or even easily —
has somehow made the Etsy developers believe that it is normal to struggle with
XSS, that it is perfectly reasonable that even after taking the drastic action
of corrupting their entire database by HTML escaping it, they should <strong>still</strong>
need elaborate XSS-catching systems.</p>
<p>Instead of <a class="reference external" href="http://www.youtube.com/watch?v=5mdy8bFiyzY">trying</a> to fix XSS,
they should just fix it. Like <a class="reference external" href="https://docs.djangoproject.com/en/dev/topics/templates/#automatic-html-escaping">this in Django</a>. Or
<a class="reference external" href="http://pypi.python.org/pypi/MarkupSafe/">this in Turbogears and Jinja</a>. Or
<a class="reference external" href="http://www.yesodweb.com/book/shakespearean-templates#types-33">this in Yesod</a>. Or even <a class="reference external" href="http://twig.sensiolabs.org/doc/templates.html#html-escaping">this
in PHP</a> (though
due to limitations of the language you won't be able to have the convenience of
things like <a class="reference external" href="https://docs.djangoproject.com/en/dev/ref/utils/#django.utils.safestring.mark_safe">mark_safe</a>
in Django). But living with an environment of pain and madness makes you think
that it ought to be hard.</p>
<p>Right the way up to Rasmus Lerdorf at the top, many people in the PHP community
live with the insanity of their tools, and add more insanity to cope with it,
rather than fix their tools or choose better ones.</p>
</div>
<div class="section" id="a-lesson-for-pythonistas">
<h1>A lesson for Pythonistas</h1>
<p>Bashing other people is fun, but when I do so I always try to get something more
valuable out of it by using the opportunity to examine myself. The problem I
discussed in the last section (which is just a manifestation of the <a class="reference external" href="http://en.wikipedia.org/wiki/Broken_windows_theory">broken
windows theory</a>) applies
to other communities, and I'll attempt to apply it to the Python community.</p>
<p>Refusing to live with stupidity is one of the reasons that Python 3 is really
important.</p>
<p>Python 3 does not represent a massive leap forward in terms of additions to the
language. Mainly it just fixes a bunch of mistakes in Python 2, and introduces a
whole lot of backwards incompatibilities in the process. One of the biggest is
unicode/bytes. Python 2 was stupid here — it went directly against the Zen of
Python, and said “in the face of ambiguity about what encoding to use, guess.”
This caused a world of pain.</p>
<p>Now, you can work around it in most cases by some sensible conventions and a
certain amount of discipline. You can also cope with the fact the <tt class="docutils literal">&quot;a&quot; &lt; 1</tt>
doesn't raise an exception. You can live with <tt class="docutils literal">next()</tt> being a method in the
iterator protocol, when it should be a method called <tt class="docutils literal">__next__()</tt> and a builtin
<strong>function</strong> <tt class="docutils literal">next()</tt>. You can live with the fact that <tt class="docutils literal">print</tt> is a totally
unnecessary keyword, since it should just be a builtin function. You can get
used to the fact that <cite>class Foo:</cite> means something subtly but significantly
different from <cite>class Foo(object):</cite>. You can work around or ignore dozens of
other little niggles, gotchas and inconsistencies.</p>
<p>But all the while, you are training yourself to tolerate stupidity,
inconsistency and brokenness. Removing these warts is really important, and
worth all the pain of the migration. The alternative is for Python to become the
next PHP.</p>
<p>On top of these things, there are other types of brokenness in Python that
people in the community seem less willing to acknowledge or tackle. For some of
these I think we need exposure to completely different languages — languages
where you can spawn thousands of ‘threads’ easily and get performance benefits,
for example, or languages where you can write code that is both very high level
<strong>and</strong> extremely fast. If we live entirely with Python and its set of
limitations, we'll think that those problems are normal and unavoidable.</p>
<hr class="docutils" />
<p>Updates:</p>
<ul class="simple">
<li>2012/08/07 - corrections about turning magic_quotes_gpc off at runtime.</li>
<li>2012/10/08 - noted bug with queries returning false matches.</li>
</ul>
</div>
</div>
]]></content>
  </entry>
  <entry>
    <author>
      <name></name>
      <uri>http://lukeplant.me.uk/blog</uri>
    </author>
    <title type="html"><![CDATA[PHP, Python and Persuasion]]></title>
    <link rel="alternate" type="text/html" href="http://lukeplant.me.uk/blog/posts/php,-python-and-persuasion" />
    <id>http://lukeplant.me.uk/blog/posts/php,-python-and-persuasion</id>
    <updated>2012-07-04T22:22:29Z</updated>
    <published>2012-07-04T22:22:29Z</published>
    <category scheme="http://lukeplant.me.uk/blog" term="Python" />
    <category scheme="http://lukeplant.me.uk/blog" term="PHP" />
    <category scheme="http://lukeplant.me.uk/blog" term="Django" />
    <summary type="html"><![CDATA[PHP, Python and Persuasion]]></summary>
    <content type="html" xml:base="http://lukeplant.me.uk/blog/posts/php,-python-and-persuasion"><![CDATA[<div class="document">
<p>I always find it fascinating to observe conversations in which people's
arguments fail to convince each other. A few days ago we witnessed some PHP
debates, kicked off by <a class="reference external" href="http://www.codinghorror.com/blog/2012/06/the-php-singularity.html">Jeff Attwood</a>.</p>
<p>I foolishly got slightly involved on one ‘<a class="reference external" href="http://nikic.github.com/2012/06/29/PHP-solves-problems-Oh-and-you-can-program-with-it-too.html">rebuttal</a>’. At
church last Sunday I also chatted with a friend who has used PHP and likes it,
and this time I tried to put myself in his shoes. It is often much more helpful
talking to people in the flesh, and I think it is always enlightening to look at
why we fail to convince.</p>
<p>One reason we can't rule out is simple irrationality. All of us are vulnerable
to <a class="reference external" href="http://en.wikipedia.org/wiki/Confirmation_bias">confirmation bias</a>, and
people will often go to great lengths to convince themselves that they are doing
the right thing and do not need to change their views or practices. You see this
all the time when two groups of people share experiences after having made
different decisions about how to spend some leisure time. Both groups are often
desperate to believe that they haven't missed out, and will seek to persuade
each other (but in reality, persuade themselves) that they were in the group
that had the most fun.</p>
<p>However, just assuming the other person is being irrational doesn't really help
you, and can in fact hinder communication. Below I will attempt to be more
constructive in looking at the ways we can fail to convince people. I'll try not
to turn it into a rebuttal to the “PHP isn't so bad” posts!</p>
<p>In his great rant <a class="reference external" href="http://me.veekun.com/blog/2012/04/09/php-a-fractal-of-bad-design/">PHP: a fractal of bad design</a>, ‘Eevee’
has lots of great arguments against PHP, and there were others in different
posts. But there are reasons why some will fail to hit home. (This is not a
criticism, by the way — many of these problems are unavoidable if you are
addressing an audience as mixed as “all the PHP developers in the world”).</p>
<ol class="arabic">
<li><p class="first">Expert understanding.</p>
<p>Eevee writes:</p>
<blockquote>
<p>empty($var) is so extremely not-a-function that anything but a variable,
e.g. empty($var || $var2), is a parse error. Why on Earth does the parser
need to know about empty?</p>
</blockquote>
<p>To an experienced programmer, <tt class="docutils literal">empty()</tt> is rather surprising. If you know —
or at least have some idea — about how to implement a programming language,
you'll understand terminology like lexer, parser, interpreter etc. So when
you try <tt class="docutils literal"><span class="pre">empty($var</span> || $var2)</tt>, and it returns a <strong>parse</strong> error, even
though it looks like a function, you think “this programming language must
have been designed by complete amateurs — I don't want anything to do with
it”.  [ <em>EDIT: changed this paragraph, previously I was gettting mixed up
between isset() and empty()</em> ]</p>
<p>For a less experienced or able programmer, however, none of this is a problem.
Programming languages are entirely magic, and one type of magic is no more
surprising than another.</p>
<p>Talking about what the parser is doing is completely incomprehensible to such a
developer. You cannot communicate the reaction you feel, because it requires a
deeper level of understanding of how things are supposed to work. Less able or
experienced developers are simply unable to assess the quality of the tools they
work with.</p>
</li>
<li><p class="first">Craftsmanship</p>
<p>For many coders, the <strong>only</strong> thing that matters is whether PHP allows them to
get something done. The quality of the tools or materials being used does not
matter.</p>
<p>Not only are many coders <strong>unable</strong> to assess the quality of the tools they
using, they wouldn't care even if they could, because programming is simply
about getting something done. Any thought of taking pride in your work is
absent. Such a person will never be convinced by arguments that talk about the
quality of tools.</p>
</li>
<li><p class="first">Amateur vs professional</p>
<p>Eevee accused the PHP world of being created by and filled with amateurs. I
suspect that to many PHP developers, that has the same effect as Java people
saying to Pythonistas that Python is not ‘enterprise ready’. Many Python
developers don't care about “the Enterprise” in the first place, and the word
may even have negative conatations — associations of massively overengineered
and poorly written bloatware written in Java or C#, which could be replaced by a
Python project 10 times smaller.</p>
<p>Many PHP users simply do not aspire to be professional, because they are happy to be
called amateurs — they <strong>are</strong> amateurs, doing stuff just for fun, pure
hobbyists who are not making money out of what they are doing, nor relying on
PHP to behave in a sane manner with important data. PHP has brought joy to their
life. Does it matter to them that PHP doesn't live up to some standard they
don't need?</p>
<p>Many developers simply do not care that much about the data that goes through
their website. “So what if PHP doesn't have any decent way of handling decimal
values?  It's close enough for my needs.” For these people not only is the
quality of the <strong>tool</strong> unimportant, the quality of the <strong>result</strong> is of
little consequence. No-one will die or sue them even if it has major bugs.</p>
<p>Also, professionals often have (or feel) obligations to support the code they
write, whereas amateurs do not. Therefore amateurs will always trade
long-term maintainability for initial deployment speed.</p>
</li>
<li><p class="first">Defending your day job</p>
<p>The previous argument doesn't cover a lot of users, however. Many are using PHP
‘professionally’, and even have customers who may demand that work is done with
PHP. (It is perhaps the essential problem of PHP that a language that was
designed to be a simple template language for non-programmers has turned into
the work-horse of the web, and the network effects caused by adoption amongst
amateurs have made it a language for professionals.)</p>
<p>Now, most people want to feel good about the work they are doing. And most
people are not in a position to have much influence on whether or not they
use PHP. If you tell someone “the tool you are using is Bad For The World”,
they will get defensive, even if they would rather be using something else.</p>
<p>I'm extremely fortunate in the work I do that I get to choose my projects
carefully, and then charge a high rate for work that I can take real pride
in. It's actually fairly unkind of me to berate people for using a language that
they didn't really choose — even if they think they are choosing it and will
defend it to the death. They are only doing so because the alternative is to say
“yes it sucks, and yes I'm doing the world a disservice by continuing to promote
it, but it pays the bills”. I've occasionally been in a similar situation in the
past, and know how demoralising and depressing it is, and it is more comforting
to rationalise your current situation.</p>
<p>In fact, when I was last in a situation like this, I did come up with a whole
bunch of rationalisations, which I still think are valid to some degree.</p>
<ul>
<li><p class="first">Engineers must be pragmatists at some level. You're paid to achieve things,
not for the internal beauty of your code.</p>
</li>
<li><p class="first">I should take pride in customer satisfaction, because that is what matters.</p>
</li>
<li><p class="first">The language itself is not the only factor. You also must consider:</p>
<ul class="simple">
<li>development tools</li>
<li>the availability and quality of libraries</li>
<li>documentation and support for such libraries</li>
<li>availability of people to maintain the software in the future.</li>
</ul>
<p>All of these things depend on human factors and network effects, and can be
used to justify a choice on the basis that “lots of other people are choosing
this”.</p>
</li>
</ul>
<p>(If you are a “PHP developer” reading this, I apologise for being patronising —
this post is not meant to insult, and is not aimed at you but at others).</p>
</li>
<li><p class="first">Experience</p>
<p>The vast majority of PHP developers that I've come across have not used any
other serious web frameworks. That is why they can say things like <a class="reference external" href="http://fabien.potencier.org/article/64/php-is-much-better-than-what-you-think">“PHP is the
best web platform... ever.”</a></p>
<p>To make such a statement, you need to have <strong>in-depth</strong> knowledge of a <strong>large</strong>
number of alternative web platforms — if not <strong>all</strong> the web platforms in
existence. However, the author did not demonstrate <strong>any</strong> knowledge of <strong>any</strong>
alternatives. You are never going to persuade anyone that way. Rather, it will
lead people simply to dismiss your opinions entirely. Being ready to make
pronouncements on subjects for which you clearly don't have a fraction of the
required knowledge is a sign that nothing you say is trustworthy.</p>
<p>However, the problem goes both ways. Eevee's rant, and Jeff's, both contain
statements that are to some degree out of date (or appear out of date to someone
on the other side who knows the 'standard solution' for the problems
highlighted). The reason for this is obvious. If you feel passionately about how
bad something is, you will stop using it, and your level of knowledge of the
technology will go down. This does lead to a bit of a problem. Those who are
unwilling to work with technology X because of how bad it is can always be
dismissed as being ignorant of it.</p>
<p>A facet of this problem is that it is extremely easy to <strong>underestimate</strong>
something that you don't have knowledge of — for instance, you can simply
underestimate the <strong>size</strong> of a competing community.</p>
<p>I'll admit I was surprised to learn that PHP has a package manager with <a class="reference external" href="http://packagist.org/statistics">1900
packages in its main repository</a>. However,
the <a class="reference external" href="http://fabien.potencier.org/article/64/php-is-much-better-than-what-you-think">author</a>
who pointed that out might be more surprised to know some of the following
figures:</p>
<p><strong>Python</strong>:</p>
<ul class="simple">
<li>PyPI has 20,000 packages<ul>
<li>over 2,400 are Django related</li>
<li>over 2,000 are Plone related</li>
<li>over 800 are Zope3 related</li>
<li>over 800 are Zope2 related</li>
<li>over 130 are Turbogears related</li>
</ul>
</li>
</ul>
<p><strong>Perl</strong>:</p>
<ul class="simple">
<li>CPAN has:<ul>
<li>107,764 Perl modules</li>
<li>9,827 authors</li>
</ul>
</li>
</ul>
<p>Let's add <strong>Haskell</strong>, as an example of a minority language if ever there was
one, and not the first language you'd think of for building web sites:</p>
<ul class="simple">
<li>Hackage has 5376 packages:<ul>
<li>350 in the 'Web' category</li>
<li>55 for ‘Yesod’ (one web framework)</li>
</ul>
</li>
</ul>
<p>I'm sure other languages can boast similar or much better figures. I don't even
know where to look with Java — it's quite possibly so large that the idea of a
central repository doesn't even make sense.</p>
<p>PHP, despite having huge numbers of developers, looks rather small in
comparison. Now, all of these statistics are flawed in a variety of ways, PHP's
included, and the bigger a community is, the more they will be flawed — for
example, PyPI download stats will often be way out because people are using
mirrors etc — but this doesn't affect the point I'm making.</p>
<p>The point is that all the communities are large, and these figures are just the
tip of the iceberg in terms of how much is going on in each and every
community. And from within a community, you can see some big figures and think
“well I doubt anyone could seriously be competing with <strong>that</strong>!”. This is true
no matter what community you belong to. And it makes it difficult to communicate
in a meaningful way. Very few can honestly say that they've evaluated the
alternatives in a fair way, because the alternatives are so huge.</p>
</li>
</ol>
<div class="section" id="conclusion">
<h1>Conclusion</h1>
<p>I'm not sure I have a conclusion actually. These are just some of the pitfalls
we face in communicating across different technology communities. I often forget
these things, especially when communicating on the internet, and this post is
here mainly to help me remember!</p>
<p>Because of the broad spectrum of PHP users, I do think that arguments against
PHP are going to have to be more <strong>individual</strong> to be effective.</p>
<p>For example, suppose you have a customer that wants PHP for a website that deals
with money in some way e.g. a shop. I might attempt to shock them by using
<a class="reference external" href="http://www.phpsh.org/">phpsh</a> to demonstrate <a class="reference external" href="http://marc.info/?l=php-internals&amp;m=109057070829170">PHP's inability to get some
basic arithmetic questions correct</a>. I would explain that
all languages have problems with floating point arithmetic, which is why other
languages have good solutions to this problem e.g. <a class="reference external" href="http://docs.python.org/library/decimal.html">Python's decimal module</a>, which makes it easy to get
things right.  PHP has nothing approaching this (and yes I know about BCMath and
GNU Multiple Precision bindings). Rather, PHP's fundamental attitude is to 1)
silently ignore errors, 2) attempt to paper over errors and 3) silently convert
your data even if that means losing information. Is this the langauge you want to
handle your data?</p>
<p>For a different situation, I think you'll need a completely different
argument. And for many situations, don't even try if you think your words are
going to come over as insulting, since that will be counter-productive. That
often applies to the internet, and I need to remember that!</p>
</div>
</div>
]]></content>
  </entry>
</feed>
