<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Acko.net]]></title>
  <link href="https://acko.net/atom.xml" rel="self"/>
  <link href="https://acko.net/"/>
  <updated>2026-03-05T12:10:39+01:00</updated>
  <id>https://acko.net</id>
  <author>
    <name><![CDATA[Steven Wittens]]></name>
    
  </author>

  
  <entry>
    <title type="html"><![CDATA[Safe String Theory for the Web]]></title>
    <link href="https://acko.net/blog/safe-string-theory-for-the-web/"/>
    <updated>2008-04-03T00:00:00+02:00</updated>
    <id>https://acko.net/blog/safe-string-theory-for-the-web</id>
    <content type="html"><![CDATA[<div class="g8 i2 first"><div class="pad"><p>One of the major things that really bugs me about the web is how poor the average web programmer handles strings. Here we are, changing the way the world works on top of text based protocols and languages like HTTP, MIME, JavaScript and CSS, yet some of the biggest issues that <a href="http://drupal.org/security">still plague us</a> are cross-site scripting and mangled text due to aggressive filtering, mismatched encodings or overzealous escaping.
</p>

<p>
Almost <a href="http://acko.net/blog/xss-friends-text-handling-in-php-applications">two years ago</a> I said I'd write down some formal notes on how to avoid issues like XSS, but I never actually posted anything. See, once I sat down to actually try and untangle the do's and don'ts, I found it extremely hard to build up a big coherent picture.
</p>

<p>
But I'm going to try anyway. The text is aimed at people who have had to deal with these issues, who are looking for a bit of formalism to frame their own solutions in.
</p>

<style type="text/css">
p.string {
  text-align: center;
  margin-top: 0.5em;
  margin-bottom: 0.5em;
}
span.letter {
  padding: 0.125em 0.25em;
  border: 1px solid #ccc;
  margin-right: -1px;
  background: #eee;
}
span.marked {
  background: #ffc;
}
div.context {
  font-size: 0.8em;
  margin-top: -0.5em;
  margin-bottom: 0.625em;
}
span.ugc {
  color: #34a;
}
div.code {
  padding: 0.5em;
  border: 1px solid #ccc;
  background: #eee;
}
table {
  margin: 0.5em auto;
}
</style>

<h2>The Problem</h2>

<p>
At the most fundamental level, all the issues mentioned above come down to this: you are building a string for output to a client of some sort, and one or more pieces of data you are using is triggering unknown effects, because it has an unexpected meaning to the client.
</p>

<p>
For example this little PHP snippet, repeated in variations across the web:
</p>

<p class="codeblock">
<code>&lt;?php&nbsp;print&nbsp;$user-&gt;name&nbsp;?&gt;'s&nbsp;profile</code>
</p>

<p>
If <code>$user-&gt;name</code> contains malicious JavaScript, your users are screwed.
</p>

<p>
What this really comes down is concatenation of data, or more literally, strings. So with that in mind, let's take a closer look at...
</p>

<h2>The Humble String</h2>

<p>
What exactly is a string? It seems like a trivial question, but I really think a lot of people don't really know a good answer to this. Here's mine:
</p>

<p class="textblock">
A string is an <strong>arbitrary sequence</strong> (1) of characters composed from a <strong>given character set</strong> (2), which acquires meaning when placed in an <strong>appropriate context</strong> (3).
</p>

<p>
This definition covers three important aspects of strings:
</p>

<ol>
  <li>They have no intrinsic restrictions on their content.</li>
  <li>They are useless blobs of data unless you know which symbols it represents.</li>
  <li>The represented symbols are meaningless unless you know the context to interpret them in.</li>
</ol>

<p>
This is a much more high-level concept than what you encounter in e.g. C++, where the definition is more akin to:
</p>

<p class="textblock">
A string is an arbitrary sequence of bytes/words/dwords, in most cases terminated by a null byte/word/dword.
</p>

<p>
This latter definition is mostly useless for learning how to deal with strings, because it only describes their form, not their function.
</p>

<p>
So let's take a closer look at the three points above.
</p>

<h2>1. Representation of Symbols</h2>

<p class="textblock">
They are useless blobs of data unless you know which symbols it represents.
</p>

<p>
This issue is relatively well known these days and is commonly described as <em>encodings</em> and <em>character sets</em>. A character set is simply a huge, numbered list of characters to draw from; an 'alphabet' like ASCII or Unicode. An encoding is a mechanism for turning characters—i.e. numbers— into sequences of bits. For example, Latin-1 uses one byte per character, and UTF-8 uses 1-4 bytes per character. Theoretically encodings and character sets are independent of each other, but in practice the two terms are used interchangeably to describe one particular pair.
</p>

<p>
You can't say much about them these days without delving into Unicode. Fortunately, Joel Spolski has already written up a great <a href="http://www.joelonsoftware.com/articles/Unicode.html">crash course on Unicode</a>, which explains much better than I could. The main thing to take away is that every legacy character set in use can be converted to Unicode and back again without loss. That makes Unicode the only sensible choice as the internal character set of a program, and on the web.
</p>

<p>
For the purposes of security though, encodings and character sets are mostly irrelevant, as the problems occur regardless of which you use. All you need to do is be consistent, making sure your code can't get confused about which encoding it's working with. So below, we'll talk about strings above the encoding level, as sequences of known characters. Like so:
</p>

<p class="string"><span class="letter">S</span><span class="letter">t</span><span class="letter">r</span><span class="letter">i</span><span class="letter">n</span><span class="letter">g</span><span class="letter">&nbsp;</span><span class="letter">T</span><span class="letter">h</span><span class="letter">e</span><span class="letter">o</span><span class="letter">r</span><span class="letter">y</span>
</p>

<h2>2. Arbitrary Content</h2>

<p class="textblock">
They have no intrinsic restrictions on their content.
</p>

<p>
The second point seems self-evident, but can be rephrased into an important mantra for coding practices: there are no restrictions on a string's contents except those you enforce yourself. This makes strings fast and efficient, but also a possible carrier of unexpected data.
</p>

<p>
The typical response to this danger is to apply a strict filtering to any textual inputs your program has and before doing anything else to the data. The idea is to remove anything that may be interpreted later as unwanted mark-up or dangerous code. On the web, this usually means stripping out anything that looks like an HTML tag, doing funky things with ampersands and getting rid of quotes. While this is an approach that is often advocated as an effective and bulletproof solution, it is rather short-sighted and limited in scope, and I strongly oppose it.
</p>

<p>
This is of course very different from regular input validation, like ensuring a selected value is one of a given list of options, or checking if a given input is numeric and in the accepted range. These are different from regular textual inputs, because the desired result is in fact not a string, but either a more restricted data type (like an integer) or a more abstract reference to an existing, internal object.
</p>

<p>
To understand why textual strings are such poor candidates for input validation, we need to look at the third point.
</p>

<h2>3. Different Contexts</h2>

<p class="textblock">
The represented symbols are meaningless unless you know the context to interpret them in.
</p>

<p>
Context, or the lack of it, is essentially the cause of issues such as SQL injection, XSS and HTTP hijacking. And, I think it is exactly because it is so essential to processing strings, that it is often taken as self-evident and forgotten.
</p>

<p>
Let's go back to our example string:
</p>

<p class="string"><span class="letter">S</span><span class="letter">t</span><span class="letter">r</span><span class="letter">i</span><span class="letter">n</span><span class="letter">g</span><span class="letter">&nbsp;</span><span class="letter">T</span><span class="letter">h</span><span class="letter">e</span><span class="letter">o</span><span class="letter">r</span><span class="letter">y</span>
</p>

<p>
Everyone will see this string represents two English words. That's because people are great at deriving context from free floating pieces of data. However even with natural languages, confusion can arise. Take for example this string:
</p>

<p class="string"><span class="letter">B</span><span class="letter">o</span><span class="letter">n</span><span class="letter">j</span><span class="letter">o</span><span class="letter">u</span><span class="letter">r</span>
</p>

<p>
Is it a French greeting? Sure. But it is also the name used by Apple for its zero-configuration network stack. We can only know which one is meant, by knowing more about the <em>context it is used in</em>.
</p>

<p>
Now why bother with this trivial exercise? Because the web is all about textual protocols and languages. While people are great at deriving contexts automatically, computers aren't, and generally rely on strict semantics.
</p>

<p>
Imagine a discussion forum, and people post topics with the following subjects:
</p>

<p class="string"><span class="letter">&lt;</span><span class="letter">b</span><span class="letter">&gt;</span><span class="letter">O</span><span class="letter">M</span><span class="letter">G</span><span class="letter">!</span><span class="letter">!</span><span class="letter">!</span><span class="letter">&lt;</span><span class="letter">/</span><span class="letter">b</span><span class="letter">&gt;</span>
</p>

<p class="string"><span class="letter">&lt;</span><span class="letter">b</span><span class="letter">&gt;</span><span class="letter">&nbsp;</span><span class="letter">i</span><span class="letter">s</span><span class="letter">&nbsp;</span><span class="letter">d</span><span class="letter">e</span><span class="letter">p</span><span class="letter">r</span><span class="letter">e</span><span class="letter">c</span><span class="letter">a</span><span class="letter">t</span><span class="letter">e</span><span class="letter">d</span>
</p>

<p>
Each string contains the character <span class="letter">&lt;</span> in a slightly different context. The first uses it as part of intended bold tags. The second seems to use the same bold tag, but is actually just talking <em>about</em> the tag instead of using it for markup. More formally, we can say the first string is written in an <em>HTML context</em>, the second in a <em>plain-text context</em>.
</p>

<p>
If we were to try and display these strings in the wrong context, we'd see tags printed when they should be interpreted, or text marked up when it should be shown as is.
</p>

<h3>Context Conversion</h3>

<p>
To unify the two strings above, we can convert the plain-text string to HTML without loss of meaning, like so:
</p>

<p class="string"><span class="letter marked">&lt;</span><span class="letter">b</span><span class="letter marked">&gt;</span><span class="letter">&nbsp;</span><span class="letter">i</span><span class="letter">s</span><span class="letter">&nbsp;</span><span class="letter">d</span><span class="letter">e</span><span class="letter">p</span><span class="letter">r</span><span class="letter">e</span><span class="letter">c</span><span class="letter">a</span><span class="letter">t</span><span class="letter">e</span><span class="letter">d</span>
</p>

<p class="string"><span class="letter marked">&amp;</span><span class="letter marked">l</span><span class="letter marked">t</span><span class="letter marked">;</span><span class="letter">b</span><span class="letter marked">&amp;</span><span class="letter marked">g</span><span class="letter marked">t</span><span class="letter marked">;</span><span class="letter">&nbsp;</span><span class="letter">i</span><span class="letter">s</span><span class="letter">&nbsp;</span><span class="letter">d</span><span class="letter">e</span><span class="letter">p</span><span class="letter">r</span><span class="letter">e</span><span class="letter">c</span><span class="letter">a</span><span class="letter">t</span><span class="letter">e</span><span class="letter">d</span>
</p>

<p>
This kind of context conversion is commonplace under the term <em>escaping</em> and in this case, will replace any character that has a special meaning in HTML with its escaped equivalent. This ensures the resulting string still means the same thing in the new context.
</p>

<h2>On the Web, Contexts Happen</h2>

<p>
Usually, the lesson above of escaping input to HTML-safe text is where the discussion about XSS ends. However, armed with only the knowledge that <em>HTML-special characters must be escaped</em> to be safe, it can be hard to see why in fact you should not just filter all your data on input to ensure it contains none of these pesky characters in the first place. After all, how many people really need to use angle brackets and ampersands anyway?
</p>

<p>
Well, first of all, I think that's underestimating certain users. The following subject might not be so rare on a message board, yet would be mangled by typical aggressive character stripping:
</p>

<p class="string"><span class="letter">&lt;</span><span class="letter">_</span><span class="letter">&lt;</span><span class="letter">&nbsp;</span><span class="letter">s</span><span class="letter">o</span><span class="letter">&nbsp;</span><span class="letter">s</span><span class="letter">a</span><span class="letter">d</span>
</p>

<p>
More fundamentally though, it implies that there is only one kind of string context used on the web. Nothing could be further from the truth. Let's look at three different, common contexts.
</p>

<h3>HTML</h3>

<p>
We take a simple snippet of HTML by itself with some assumed user-generated text in it:
</p>

<p class="codeblock">
<code>  &lt;span title=&quot;<span class="ugc">attribute text</span>&quot;&gt;<span class="ugc">inline text</span>&lt;/span&gt;
</code>
</p>

<p>
We look at some different segments of the snippet, and look at what 'forbidden characters' would break or change the semantics of each.
</p>

<p>
<table>
  <thead>
    <tr>
      <th>Snippet</th>
      <th>Forbidden</th>
      <th>Escaped as</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><span style="color: #34a;">attribute text</span></td>
      <td><span class="letter">"</span><span class="letter">&amp;</span></td>
      <td>&amp;quot; &amp;amp;</td>
    </tr>
    <tr>
      <td><span class="ugc">inline text</span></td>
      <td><span class="letter">&lt;</span><span class="letter">&amp;</span></td>
      <td>&amp;lt; &amp;amp;</td>
    </tr>
  </tbody>
</table>
</p>

<p>
For example, quotes are disallowed in attribute text values, because otherwise a string with a quote could alter the meaning of the HTML snippet considerably:
</p>

<p class="codeblock">
<code>  &lt;span title=&quot;<span class="ugc">attribute with injected&quot; property=&quot;doEvil() </span>&quot;&gt;<span class="ugc">inline text</span>&lt;/a&gt;
</code>
</p>

<p>
Note:
</p>

<ul>
<li>All ampersands need to be escaped (including those in URLs) for it to validate. HTML's stricter cousin XML will refuse to parse unescaped ampersands as well, and even requires that apostrophes be escaped too.</li>
<li>XSS attacks do not necessarily involve angle-brackets. In the attribute context, all you need is a <span class="letter">"</span> to wreak havoc.</li>
</ul>

<h3>URLs</h3>

<p>
The situation is more complicated with URLs. The common HTTP URL for example:
</p>

<p class="codeblock">
<code>  http://<span class="ugc">user</span>:<span class="ugc">password</span>@<span class="ugc">host.com</span>/<span class="ugc">path/</span>?<span class="ugc">variable</span>=<span class="ugc">value</span>&amp;<span class="ugc">foo</span>=<span class="ugc">bar</span>#
  </code>
</p>

<p>
<table>
  <thead>
    <tr>
      <th>Snippet</th>
      <th>Forbidden</th>
      <th>Escaped as</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>(all)</td>
      <td><span class="letter">&lt;</span><span class="letter">&gt;</span><span class="letter">"</span><span class="letter">#</span><span class="letter">%</span><span class="letter">{</span><span class="letter">}</span><span class="letter">|</span><span class="letter">\</span><span class="letter">^</span><span class="letter">~</span><span class="letter">[</span><span class="letter">]</span><span class="letter">`</span><span class="letter"> </span> (and non-printables)</td>
      <td>%3C %3E %22 %23 ...</td>
    </tr>
    <tr>
      <td><span class="ugc">user</span></td>
      <td><span class="letter">@</span><span class="letter">:</span></td>
      <td>%40 %3A</td>
    </tr>
    <tr>
      <td><span class="ugc">password</span></td>
      <td><span class="letter">:</span></td>
      <td>%3A</td>
    </tr>
    <tr>
      <td><span class="ugc">host.com</span></td>
      <td><span class="letter">/</span><span class="letter">@</span></td>
      <td>disallowed</td>
    </tr>
    <tr>
      <td><span class="ugc">path</span></td>
      <td><span class="letter">?</span></td>
      <td>%3F</td>
    </tr>
    <tr>
      <td><span class="ugc">variable</span></td>
      <td><span class="letter">&amp;</span><span class="letter">=</span></td>
      <td>%26 %3D</td>
    </tr>
    <tr>
      <td><span class="ugc">value</span></td>
      <td><span class="letter">&amp;</span><span class="letter">+</span></td>
      <td>%26 %2B</td>
    </tr>
  </tbody>
</table>
</p>

<p>
Note:
</p>

<ul>
  <li>Many forget that a <span class="letter">+</span> in a query value actually means a space, not a plus.</li>
  <li>Even completely valid URLs can still be malicious, through the <code>javascript://</code> protocol.</li>
  <li>Defined by <a href="http://www.faqs.org/rfcs/rfc1738.html">RFC 1738</a> and <a href="http://www.faqs.org/rfcs/rfc2616.html">RFC 2616</a>.</li>
</ul>

<h3>MIME Headers</h3>

<p>
Several protocols such as HTTP and SMTP employ the same mechanism of providing metadata for pieces of content. This includes data such as e-mail subjects, senders, cookie headers or HTTP redirects, likely to contain user-generated data.
</p>

<p class="codeblock">
<code>  Subject: <span class="ugc">message subject</span><br />
  Content-Type: text/html; charset=utf-8
  </code>
</p>

<p>
<table>
  <thead>
    <tr>
      <th>Snippet</th>
      <th>Forbidden</th>
      <th>Escaped as</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><span class="ugc">message subject</span></td>
      <td><span class="letter"><em style="opacity: 0.7">CR</em></span><span class="letter"><em style="opacity: 0.7">LF</em></span> (if not followed by space), <span class="letter">(</span><span class="letter">)</span><span class="letter">&lt;</span><span class="letter">&gt;</span><span class="letter">@</span><span class="letter">,</span><span class="letter">;</span><span class="letter">:</span><span class="letter">\</span><span class="letter">"</span><span class="letter">/</span><span class="letter">[</span><span class="letter">]</span><span class="letter">?</span><span class="letter">=</span>
       + any non-printable</td>
      <td><span style="white-space: nowrap">=?UTF-8?B?...?=</span></td>
    </tr>
  </tbody>
</table>
</p>

<p>Note:</p>

<ul>
  <li>CRLF sequences without trailing space start a new field and can be used for header injection.</li>
  <li>Lines should be wrapped at 80 columns with CRLF + space.</li>
  <li>Defined by <a href="http://www.faqs.org/rfcs/rfc2045.html">RFC 2045</a>.</li>
</ul>

<h2>Lolwut?</h2>

<p>
If the above three tables seem complicated and confusing, that's normal. It should be obvious that each of the three contexts is unique and has its own special range of 'forbidden characters' for user input (and even some sub-contexts). From this perspective, it would be impossible to define a safe <em>input</em> filtering mechanism for text on the web that didn't destroy almost all legitimate content.
</p>

<p>
You would have to filter or escape only for a single context, which would create a situation where the exact same approach to a problem can be safe in some cases, but unsafe in others, thus promoting bad coding practices. In particular, any framework that has a concept of <em>tainted</em> strings that are auto-escaped has it wrong: it's marking strings as safe/unsafe, when it should be treating them as <em>plain text</em>, <em>unsafe HTML</em>, <em>filtered HTML</em>, <em>MIME value</em>, etc. Whether that happens implicitly through data flow, or explicitly through typing depends on the architecture.
</p>

<p>
With the selection above, I also ignored other important contexts (notably JS / JSON or SQL). However, the fact that I was able to make my point using only old school Web 1.0 techniques should show how this problem becomes even hairier in today's Web 2.0.
</p>

<h2>So What Then?</h2>

<p>
The right way around string incompatibilities is to use appropriate conversions to change content from one context to another without changing its meaning, and do so when <em>outputting</em> text in a particular instance. We already did it above for the plain-text example, but similar conversions can be made in almost every other instance. Most web languages (like PHP) contain pre-built and tested functions for doing this.
</p>

<p>
Whenever you put strings together, you need to ask yourself what context the strings are in. If they are not the same, an appropriate conversion needs to be made, or you can run into bugs or worse, exploits.
</p>

<p>
The best way is to mentally color in all your variables by their type: text, HTML, SQL, JS, MIME, etc. You should aim to keep data in the most natural form possible, until right before output. Storing possible XSS code in your database might seem like it's tempting fate, but if you apply proper escaping on the way out, you can be sure that it's safe, no matter where the data comes from or what protocol it's being sent on. It turns out to be a far more paranoid approach than input filtering, because you don't have to trust anything you didn't hardcode.
</p>

<p>
So, use prepared SQL statements to leave the escaping to your database interface. Make your HTML templates escape dynamic variables implicitly if possible. Never compose JSON manually. Finally, be careful when tying web code into other systems: a Bash command containing a user-supplied filename is a exploit waiting to happen.
</p>

<p>
For the example snippet at the very beginning, the appropriate fix is:
</p>

<p class="codeblock">
<code>&lt;?php&nbsp;print&nbsp;htmlspecialchars($user-&gt;name)&nbsp;?&gt;'s&nbsp;profile</code>
</p>

<p>
The trick is in understanding why that call goes <em>there</em>, and not somewhere else. Ideally however, the framework has been constructed so that context issues simply cannot happen, by passing data through interfaces, and letting well-tested code handle the concatenation for you.
</p>

<p>
<em>Update: Google's DocType wiki has an excellent section with instructions for <a href="http://code.google.com/p/doctype-mirror/wiki/ArticleXSS">escaping for various contexts</a></em>.
</p>

</div></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Because there are too many serious websites around]]></title>
    <link href="https://acko.net/blog/because-there-are-too-many-serious-websites-around/"/>
    <updated>2008-02-07T00:00:00+01:00</updated>
    <id>https://acko.net/blog/because-there-are-too-many-serious-websites-around</id>
    <content type="html"><![CDATA[<div class="g8 i2 first"><div class="pad"><p>I finished designing and building this year's edition of <a href="http://www.leuvenspeelt.be/">LeuvenSpeelt.be</a>, a site that promotes student theater at my old university. You can <a href="/tag/theater">read about the background</a> in my previous blog posts.
</p>

<p>
<a href="http://www.leuvenspeelt.be/"><img class="natural" src="/files/leuvenspeelt/leuvenspeelt2008.jpg" alt="LeuvenSpeelt.be 2008 screenshot" title="LeuvenSpeelt.be - Promoting amateur theater by students" /></a>
</p>

<p>
The site is a simple Drupal installation with heavy content and theme work. The design is heavy on graphics and built as an experimental semi-fluid layout that adapts to different screen resolutions. Peripheral design elements are shifted in or out of the browser frame to make more space for content as needed.
</p>

<p>
Tools used: Photoshop, Illustrator, 3D Studio Max, TextMate. Uses the beautiful Fontin font available freely from Jos Buivenga's <a href="http://www.josbuivenga.demon.nl/index.html">exljbris</a> foundry.
</p>

<p>
And no, no easter eggs this year.</p></div></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[On not doing Drupal anymore]]></title>
    <link href="https://acko.net/blog/on-not-doing-drupal-anymore/"/>
    <updated>2008-01-17T00:00:00+01:00</updated>
    <id>https://acko.net/blog/on-not-doing-drupal-anymore</id>
    <content type="html"><![CDATA[<div class="g8 i2 first"><div class="pad"><p>Various people have prodded me to explain my recent involvement in Drupal, or rather the lack of it. Unfortunately, I haven't found a way to do so in a way that is constructive and tactful, especially not when it comes to other contributors. Like Soylent Green, Open Source is made of people, and it's these people who are at the basis of a mountain of frustration that has driven me off.
<!--break-->
At the end of the day, I feel that the vast majority of contributors is not willing or not able to apply the level of diligence that I apply to my own Drupal work. This is both in terms of technical background and research, as well as in the actual execution and quality assurance. I find that too little effort is spent on polishing things so they really shine, e.g. in the actual development (back-end <em>and</em> UI), but equally in, say, outreach and marketing. It also seems that any exceptional efforts that go beyond this typical fare are often wasted, because the author invariably has to fight a prolonged (and sometimes never-ending) battle to keep the polish from being obliterated by someone else's refactoring.
</p>

<p>
This is further aggravated by the fact that a certain group of people always seems ready to chime in their two cents (or more) in long, repetitive e-mail threads or project issues, while not actually contributing to the end result or even bringing solid, technical arguments to the table. Said persons seem more interested in maintaining the business revenue that Drupal provides to them, rather than producing a better CMS.
</p>

<p>
This leads to a culture where actual expertise becomes a burden rather than a benefit, because whoever does something first is often expected to keep doing it indefinitely, for the benefit of everyone else. Rather than contributors having a symbiotic relationship with each other, it becomes more and more parasitic and unidirectional.
</p>

<p>
After many years in this environment, I find myself utterly drained and unmotivated to participate in that sort of charade anymore.
</p></div></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Ensuring your contributed code gathers dust]]></title>
    <link href="https://acko.net/blog/ensuring-your-contributed-code-gathers-dust/"/>
    <updated>2007-05-01T00:00:00+02:00</updated>
    <id>https://acko.net/blog/ensuring-your-contributed-code-gathers-dust</id>
    <content type="html"><![CDATA[<div class="g8 i2 first"><div class="pad"><h2>8 tips for the aspiring Drupal developer</h2>

<p>
Open source is really great. You get to cherry pick from some of the <a href="http://drupal.org">best software out there</a> and build <a href="http://comicjuice.com">neat stuff</a> with it, fast. Most open source projects will also encourage you to contribute your own work back to the project. Supposedly, so others can benefit from your work.
</p>

<p>
While that's often an easy, karma-scoring move, it can have some unintended, annoying consequences. For example, people might start sending in bug reports for your code or may offer suggestions on how to improve it. Even worse, meddling know-it-alls may even offer to 'help' with development and do things with it that you never intended. Some projects, like Drupal, even trick you into such forced participation, by automatically supplying issue trackers, RSS feeds, revision control and other, undesirable community interaction.
</p>

<p>
Luckily, there are several things you can do to keep those pesky contributors away altogether. You can participate in open source without suffering any of its extended effects. Here are some concrete tips for the aspiring Drupal developer. Of course, a true creative will find novel ways of keeping their open source involvement to an absolute minimum!
</p>

<ol>
  <li><strong>Using an existing platform can be daunting.</strong> If it does something weird that you really can't explain, just work around it. You have better things to do. Warn others away with a comment that explains that you "Don't know why, but with this, the problem goes away." Avoid getting help from the original coders: they were the ones that broke it, remember?</li>
  <li><strong>Lift pieces from the core and change them.</strong> Drupal core provides a rich platform, but the core developers are often short-sighted. For example, several key API functions contain so-called 'security measures' that often just get in your way. Feel free to copy code from core and tweak as needed. Slap a <code>mymodule_</code> prefix on the function name and you're good to go. Comments about what you tweaked are unnecessary—people can just use diff. And, unlike core, your copy will never be broken by 'fixes' from the community.</li>
  <li><strong>Include everything but the kitchen sink.</strong> If your project needs several related features, group them together into one big module. This ensures that others will always see something they don't need and can't easily get rid of. The idea of serious remodeling in foreign code is an easy turn-off.</li>
  <li><strong>Forget about backwards compatibility and upgrade paths.</strong> If it works for you, that's good enough. Besides, if someone else needs to keep their data, they can still figure out the changes on their own if they're determined. Extra points scored for ensuring that your module can only be installed correctly on a blank site, as this ensures low uptake.</li>
  <li><strong>Avoid conforming to coding conventions.</strong> There's nothing like non-standard names and confusing syntax to make that first read through of the code just that little bit more annoying. And really, why should you conform to the whims of a bunch of like-minded zombies?</li>
  <li><strong>Skip code comments when possible.</strong> As the original author, you already know what the code does. Plus, leaving out Doxygen sections for functions is a great way to make it harder for someone to 'get the big picture' and see how your code fits together. If you must leave a comment as a reminder, don't use sentences, but just slap some related keywords together. Avoid verbs, as they easily expose data relationships and control logic.</li>
  <li><strong>Don't make it localizable.</strong> If you don't speak English, you can even code directly in your native language, and save yourself a lot of trouble translating later. This means you also don't have to deal with those annoying Localization APIs that are over-engineered only to handle the moon language of some godforsaken mountain pygmies anyway.</li>
  <li><p><strong>If you must, obfuscate and bloat.</strong> Some projects are just too large, trendy or otherwise high-profile to not attract a crowd. In this case, going through the trouble of making your code more verbose and complicated is often needed to keep these nosy people at bay. Go through the extra effort—it's worth it. </p>

<p>
Some of the better methods include:
</p>
    <ul>
      <li>Clustering pieces of your code together in large mega-functions with no clear delimiters.</li>
      <li>Writing out all your control flow in long, repeated logic structures that contain as many squares from the truth table as possible.</li>
      <li>Keeping local data in static and global variables, for much longer than needed.</li>
      <li>Subtly misnaming functions, methods and variables for maximum effect: a <code>_check()</code> that doesn't, a <code>_save()</code> that deletes or a <code>_form()</code> that returns a table can wreak havoc in the most unexpected places.</li>
      <li>Creatively using APIs for accessing internal or otherwise unrelated data. The <a href="http://api.drupal.org">API reference</a> is a great resource for finding such useful backdoors.</li>
    </ul>
    
  </li>
</ol>

<p>
With these simple guidelines, you'll keep even the most seasoned contributor far away before they ever think of submitting a patch!
</p></div></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[jQuery OSCMS presentation slides]]></title>
    <link href="https://acko.net/blog/jquery-oscms-presentation-slides/"/>
    <updated>2007-03-23T00:00:00+01:00</updated>
    <id>https://acko.net/blog/jquery-oscms-presentation-slides</id>
    <content type="html"><![CDATA[<div class="g8 i2 first"><div class="pad"><p><em><strong>Update</strong>: a raw <a href="http://video.google.com/videoplay?docid=8359290939840291444&amp;hl=en">video</a> is now available of (almost) the entire session. Thanks to Jon F Hancock for recording it.</em>
</p>

<p>
Today I did my second session at OSCMS, which was basically a repeat of the <a href="/blog/jquery-drupalcon-talk">jQuery talk</a> I did at DrupalCon Brussels.
</p>

<p>
You can <a href="/files/drupalcon-jquery/jQuery - 23 March 2007.pdf">download a PDF</a> (2.2MB) of the (slightly tweaked) presentation slides.</p></div></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Design presentation slides]]></title>
    <link href="https://acko.net/blog/design-presentation-slides/"/>
    <updated>2007-03-22T00:00:00+01:00</updated>
    <id>https://acko.net/blog/design-presentation-slides</id>
    <content type="html"><![CDATA[<div class="g8 i2 first"><div class="pad"><p>I did my OSCMS talk <a href="/blog/oscms-talk-designer-eye-for-the-geek-guy-gal">Designer eye for the geek guy</a> today. My main plan for this talk was to blast as much basic graphical design concepts into people's heads as possible and sort of teach some of the principles, vocabulary and methods that a lot of designers take for granted.
</p>

<p>
The response was great as far as I could tell. I also got the inevitable "How do we deal with Internet Explorer?" spin-off discussion in the questions round at the end ;).
</p>

<p>
<a href="http://www.blkmtn.org/">Steven Peck</a> <a href="http://video.google.com/videoplay?docid=4892104132825691414&amp;hl=en">recorded my session</a> on video.
</p>

<p>
You can <a href="http://acko.net/files/design-eye/Design%20Eye%20for%20the%20Geek%20Guy-Gal%20-%2022%20March%202007.pdf">download the slides as PDF</a> (36.5 MB), though because of all the graphics it's quite large. I think some sections will not be clear at all without the spoken explanation to go along with it though.
</p></div></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Going to the US sucks]]></title>
    <link href="https://acko.net/blog/going-to-the-us-sucks/"/>
    <updated>2007-03-17T00:00:00+01:00</updated>
    <id>https://acko.net/blog/going-to-the-us-sucks</id>
    <content type="html"><![CDATA[<div class="g8 i2 first"><div class="pad"><p>Ugh. So, I just found out that I will be fingerprinted and photographed when I go to the United States next week for the OSCMS conference. For some reason, I was under the impression that visitors with a visa waiver (like EU citizens) were not subject to this rule, and this was why I was still going. Perhaps they changed it recently.
</p>

<p>
Today was the first time I heard this issue mentioned, so I want to give a clear signal to the US members of the Drupal community: this is unacceptable and hinders development and business. For sure, it's the last time I'll be going into the United States while this continues, and if this trip wasn't so important to me I'd have cancelled my flight already.
</p>

<p>
Your country's government is messed up beyond belief, and its policies scares away the entire world. It wouldn't be so bad if the US didn't perpetually tout its everlasting respect for personal rights and freedom. As a European who has just moved to North America, I can say for sure that I constantly feel as though my privacy is under assault, because corporate interests, advertising and other annoyances take precedence over the right to be left alone here. It's a huge cultural difference.
</p>

<p>
This news immediately set in motion plans for subverting the system. I'd be having a little kitchen vegetable slicing accident if it were to help. Unfortunately, my prior experience with US customs a couple years back leads me to believe that any sort of irregularity would only lead to hours of delay and a much more thorough printing and photographing.
</p>

<p>
For now, the US is reduced to a bizarre, quirky, sad laughing stock for me. My visit will be bathed in the surreal air of stepping into an asylum.<!--break--></p></div></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Drupal.org Explosion and Trends]]></title>
    <link href="https://acko.net/blog/drupal-org-explosion-and-trends/"/>
    <updated>2007-03-11T00:00:00+01:00</updated>
    <id>https://acko.net/blog/drupal-org-explosion-and-trends</id>
    <content type="html"><![CDATA[<div class="g8 i2 first"><div class="pad"><p>One of the things I do occasionally is collect some of my own statistics on Drupal.org. An interesting one is to look at the size, expressed in <em>nodes</em>, and the growth rate of Drupal.org, expressed as <em>nodes per hour</em>.
</p>

<p>
Just like rings on a tree trunk, you can see Drupal.org evolve.
</p>

<p>
<div style="margin: 1em 0; text-align: center;"><a href="/files/drupal-trends/drupal.org stats - march 2007.pdf" title="Click for a scalable PDF version"><img class="natural" style="display: inline" src="/files/drupal-trends/drupal.org stats - march 2007.png" alt="Drupal.org growth doubles every major release." /></a></div>
</p>

<p>
Now while the nodes graph (red, left axis) looks exponential at first, it turns out that its growth (blue, right axis) is actually quite stair-stepped. In fact, a remarkable trend can be observed: <em>with every major release of Drupal, Drupal.org's growth rate doubles nearly instantly</em>.
</p>

<p>
This has been true mostly since Drupal 4.5 and happened recently again with Drupal 5.0. The only exception was a relatively unexpected, but sustained linear growth burst throughout the fall of 2005 and the spring of 2006. There were many high profile projects at that time as well as a lot of anxious waiting for 4.7 (with a long train of betas and release candidates), so it is possible our unnaturally long dev cycle for 4.7 smeared out the growth to a more regular line.
</p>

<p>
Note that the first year of Drupal is missing, as the statistics were too small to show up.
</p>

<p>
What's also interesting is that you can clearly see the times when project.module has changed. The first tiny bump is the conversion of projects to nodes, while the other two spikes are the recent conversion of project releases to nodes. For some reason, a huge amount of existing releases got a creation timestamp a while ago, possibly due to some change in project.module housekeeping at that time.
</p>

<p>
Other noticeable events include the holidays (when activity slows down a lot) as well as the server crash of July 2005, and the subsequent move to OSUOSL.
</p>

<p>
I've attached the raw Excel Spreadsheet for anyone interested. See if you can match up any other events to the graph.<!--break--></p></div></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[ComicJuice gets even better]]></title>
    <link href="https://acko.net/blog/comicjuice-gets-even-better/"/>
    <updated>2007-03-09T00:00:00+01:00</updated>
    <id>https://acko.net/blog/comicjuice-gets-even-better</id>
    <content type="html"><![CDATA[<div class="g8 i2 first"><div class="pad"><p>I finished some more tweaks to ComicJuice:
</p>

<ul>
<li>
<p>IE6 and 7 are now supported, thanks to the amazing <a href="http://excanvas.sourceforge.net/">ExplorerCanvas</a> by Google. It emulates the <a href="http://developer.mozilla.org/en/docs/Drawing_Graphics_with_Canvas">&lt;canvas&gt; tag</a> in IE, meaning that client-side scriptable vector graphics are now available on all the major browsers (IE, Firefox, Safari, Opera). I doubt Konqueror will be far behind.
</p>

<p>
This opens up some cool abilities, like dynamic in-page graphs, mini-widgets (sliders, dials, maps, ...) and even pure JS games. There's a bunch of examples linked on <a href="http://en.wikipedia.org/wiki/Canvas_(HTML_element)">Wikipedia</a> (though most don't use ExplorerCanvas yet).</p>
</li>
<li>
<p>I added support for uploading your own images rather than using pictures on the web. It uses a customized and themed version of core's JS uploader.
</p>
<p class="tc"><img class="natural" src="/files/comicjuice/comicjuice.png" alt="comic juice" /></p>
</li>
<li>I improved the clipping of speech bubbles so there should be less useless whitespace around comics, especially when embedding them.</li>
</ul>

</div></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Announcing.... ComicJuice!]]></title>
    <link href="https://acko.net/blog/announcing-comicjuice/"/>
    <updated>2007-03-06T00:00:00+01:00</updated>
    <id>https://acko.net/blog/announcing-comicjuice</id>
    <content type="html"><![CDATA[<div class="g8 i2 first"><div class="pad">
  
<h1>Announcing.... ComicJuice!</h1>
  
<p>I'm proud to announce the start of ComicJuice, a web 2.0 social mashup tool that lets you create comics in your browser and share them with others.
</p>

<p>
<em>Update: Now with Internet Explorer support! Thanks to <a href="http://code.google.com/p/explorercanvas/">Google's ExplorerCanvas</a>. Viewing comics works in IE6 and 7, while editing still requires IE7.</em>
</p>

<p>
<iframe style="margin: 0 auto;" width="425" height="349" src="http://www.youtube.com/embed/qhVMU48GfvE" frameborder="0" allowfullscreen="allowfullscreen"></iframe>
</p>

<p>
The crazy part is that I started working on this only friday evening (that's 4 days ago). Once I had the initial idea and a rough plan, I simply couldn't not code it.
</p>

<p>
A lot of jQuery and JavaScript later, with some &lt;canvas&gt; wizardry (boy is that thing inconsistent across browsers), we have a fully-fledged comic creator. The best part is that all of it is rendered client-side, so no actual images need to be generated. To display a comic, we use the same code as the editing interface. The down-side is that it doesn't work in IE, but I've been thinking about maybe doing a rough canvas emulation. We'll see. For now, the latest versions of Safari, Firefox and Opera have been tested and work well.
</p>

<p>
You can also embed comics with iframes, and copy/pastable code is provided. Like this lame example:
</p>

<p><em>(No longer available)</em></p>

<p>
I figured a Web 2.0 mash-up would not be complete without a fitting design to go in, so I designed icons, sliders and toolbars for the editor, as well as a theme for the website. The theme is a Garland knock-off: I guess I'm proving myself wrong that it's a bad base theme. It's actually quite good as it has fluid/fixed 1-3 column layouts in it.
</p>

<p>
I'm curious to see if ComicJuice takes off and what people do with it. It was a blast to code in any case. Check it out.</p></div></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Drupal's Designer Future]]></title>
    <link href="https://acko.net/blog/drupals-designer-future/"/>
    <updated>2007-03-01T00:00:00+01:00</updated>
    <id>https://acko.net/blog/drupals-designer-future</id>
    <content type="html"><![CDATA[<div class="g8 i2 first"><div class="pad"><p>In the past months I've been doing a lot more graphical design, and it's caused me to think about how it relates to Drupal. This prompted me to write a rather long blog piece with some insights and a call to action. If you are interested in the future of Drupal, please read on.<!--break-->
</p>

<p>
The trigger was that I noticed that I'm getting less and less motivated to do graphics work for Drupal. It's not that I don't like design... I loved designing and building that LeuvenSpeelt.be site last month for example. But when it comes to Drupal graphics, the personal reward that I feel from doing it doesn't seem proportional to the effort I put in. This includes designing little banners for the Drupal.org spotlight, doing a t-shirt, making ad buttons, doing the association theme and more.
</p>

<p>
The most recent big example was the Garland theme. When Stefan Nagtegaal showed a work-in-progress version of his 'Themetastic' theme (as it was then called) in September, I was instantly charmed and knew that this was our new default theme in the making and said so clearly.
</p>

<p>
Many others were not convinced though and hammered on details, even though the basic design for the theme was rock solid. Some were not convinced of the theme's potential, or simply didn't see that we needed a theme that was graphically smashing rather than a good base to develop on.
</p>

<p>
At that point, I essentially said "screw the community, this is going to be our default theme" and started refining the theme so it was perfect for core. This took several weeks.
</p>

<p>
Until then, the rest of the community put its eggs in the wrong baskets and got a lot of useless design-by-committee done. These designs, which were in my opinion mediocre at best, were being pushed for inclusion. This may sound a bit harsh, but I honestly believe that if the most popular candidate theme, Deliciously Zen, had become the new default core theme, we'd have been ridiculed for still not 'getting' design after 6 years and Drupal 5 would not have been such a big release. Just like 4.7, most people would not stick to Drupal long enough to discover how good it is.
</p>

<p>
Now, when the Garland theme was finally done, everyone suddenly changed their opinion and congratulated <em>the community</em> on its excellent work. I have to admit this hit a nerve, especially after I'd been spending countless days and nights the two weeks before fixing annoying IE rendering bugs, redoing the CSS layout and adding a whole new layer of Glitz und Glanz to Drupal core.
</p>

<p>
Only three people did serious work on what became the Garland theme: Stefan Nagtegaal did the original design from scratch and worked with Adrian Rossouw to come up with a proof-of-concept of the recolorable theme. I wrote the color picker, improved the theme and coded what became the color.module based on Adrian's stuff.
</p>

<p>
Only a handful of people helped with testing of the theme during its development and only after the main theme was finished — most of the bugs were in the recoloring mechanism. How can such a vital piece of Drupal 5 have only have 3 serious contributors, when the whole release had almost 500 people submitting <em>patches</em>?
</p>

<p>
To me, this shows that we have a problem in the Drupal community, or rather a knowledge void. Not enough Drupal people are savvy enough about theming and design to help out with even small tasks (like a banner) or even give quality tips and feedback on other work.  The result is that theming and design receives little attention. Most contributed themes and sites could look a lot better, if they just themed it some more. And getting patches into core that give the defaults a little more oomph is tough, as they are often considered to be useless embellishments.
</p>

<p>
Still, ever since Drupal started, there has been the recurring cry of doing more to attract great designers to the platform. The overall effects of this have been minimal. However, something similar did happen before.
</p>

<p>
Before Drupal 4.0 was released, the focus was mainly on features and Drupal was a highly experimental project. After a while, as more people started using it, many users complained that Drupal was too hard or confusing to use. Because of this, 4.0 was the first of many releases that contained significant usability improvements, in this case in the administration area. Many small and large usability features were added. With the menu system and tabs having been added to core by Drupal 4.5, even contributed modules started using the same UI concepts as core. Drupal's UI ended up much more consistent across configurations and it became easier to learn and document. Now with Drupal 5.0, we have undoubtedly produced the most usable release yet.
</p>

<p>
How did this happen? Over the years, the idea has popped up many times to bring usability experts on board to do a review, and the hope has lived that a usability expert or two will magically pop up in the community and solve all our problems (sound familiar?). Neither has happened so far.
</p>

<p>
What did happen is that usability became a big priority for the project, and as a result, many people started educating themselves about it. The community quickly identified those in its ranks knowledgable about usability and listened to their advice. Soon, big UI gurus were being quoted on the mailing lists and "-1 isn't usable" became a valid reason to dismiss a feature. Sure, this process took time, but it definitely happened. Plus, the combined usability knowledge and effort of the community, though individually not at expert level, had a much larger effect in the long run than any single expert could have.
</p>

<p>
The same needs to happen for design. For years now, the Drupal community has been hoping for a group of prodigy designers to magically appear and design a set of jaw dropping themes and UI. They have not shown up. Talking and maintaining a high quality of design across Drupal still often feels like swimming upstream, because most community members don't care much for design unless it is delivered in front of their noses on a silver platter. For many, design is still something to only be enjoyed, not something to be created.
</p>

<p>
Now, I really want to see this change. For one thing, the shortage of design talent means Drupal is generally perceived to be ugly. It's quite demotivating, because we put a lot of time into it. Unfortunately people illogically, but consistently, assume a relation between how something looks and how good it is built. With Drupal 5 we've done a lot to improve this, but we could still do a lot better. Drupal is no OS X (yet).
</p>

<p>
For another, when only a handful people are always doing the same jobs, the passion tends to slip out and the challenge becomes a chore. I honestly have no ideas left for a spotlight banner at the moment. That's why the <a href="http://drupal.org/themes/bluebeach/spotlight/performance-scalability.png">scalability banner</a> is so mind-numbingly boring, though I made <a href="http://drupal.org/node/15209">plenty of cool ones</a> before.
</p>

<p>
This is also why I'm holding that <a href="http://acko.net/blog/oscms-talk-designer-eye-for-the-geek-guy-gal">OSCMS talk about design</a> this month: I want more people to realize that if your site and/or module is ugly, people aren't going to like it or use it. It's as simple as that. If you mess up something as basic as text formatting, your message simply doesn't get through (hello MySpace users). The only way to change that is to put in the effort to make things look clean and nice. Nice products and nice sites tend to cause happy, dedicated and long-term users.
</p>

<p>
The community not only needs to realize this, but also needs to teach itself the knowledge and skill to do something about it. Drupal has infinite potential, but it only goes where the community takes it. If the majority remains allergic to design and graphics, very little will change and only at a glacial pace.</p></div></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[LeuvenSpeelt another year]]></title>
    <link href="https://acko.net/blog/leuvenspeelt-another-year/"/>
    <updated>2007-02-15T00:00:00+01:00</updated>
    <id>https://acko.net/blog/leuvenspeelt-another-year</id>
    <content type="html"><![CDATA[<div class="g8 i2 first"><div class="pad"><p><em>Update: check out the <a href="http://acko.net/blog/poster-for-interfacultair-theaterfestival-done">poster</a> I did for the event as well.</em>
</p>

<p>
<a href="/blog/leuvenspeelt-theater-and-drupal">Just like last year</a>, my (now) ex-university, the Catholic University of Leuven, still has a theaterfestival for and by students. Friends of mine organise it and I'm the resident web monkey and designer for their site and poster. The site's domain name means "Leuven plays" and is a pun on theater and plays (it works in english too). So, every year we try to base ourself on some playful theme when coming up with the promotional material.
</p>

<p>
In the past, there's been <a href="http://www.leuvenspeelt.be/2005/">blackjack</a> and <a href="http://www.leuvenspeelt.be/2006/">chess</a>. Last year's design came out really well, so I posed myself the challenge of doing even better.
</p>

<p>
I redesigned the site from scratch, this time using a <em>1930's carnival/fair</em> as the theme.<!--break--> A lot of Google Image researching by the organisers found lots of tents, wagons, clowns, snake ladies, acrobats and bearded women. I modelled the carnival setting in 3D Studio Max entirely from scratch, using free textures found on the web as well as custom painted textures. We also found some very nice ticket designs, which lead to the typography and framing of the page.
</p>

<p>
<div style="margin: 0.5em auto; width: 454px;"><img class="natural" src="/files/leuvenspeelt/itf-kaartjes.jpg" alt="" /></div>
</p>

<p>
<div style="margin: 0.5em auto; width: 454px;"><img class="natural" src="/files/leuvenspeelt/itf3d.jpg" alt="" /></div>
</p>

<p>
The renders were cut up into layers and composed into a semi-fluid CSS-based layout (no flash). Then I turned that into a Drupal theme and installed it on the site. The result is very heavy on images (with several hundred of KB's of PNGs/JPEGs), but in this case it's acceptable as the site's audience will consist 99% of students browsing through the university network or someplace close.
</p>

<p>
<div style="margin: 0.5em auto; width: 454px;"><a href="http://www.leuvenspeelt.be"><img class="natural" src="/files/leuvenspeelt/leuvenspeelt-2007.jpg" alt="" /></a></div>
</p>

<p>
To make the ticket metaphor even better, I used some JavaScript and cookie magic to issue each visitor a unique ticket with a printed serial number. Each page you visit punches a hole in the paper, though of course you can still browse the site as much as you want. If you wait an hour or more and come back to the site, you'll get a fresh ticket with a new number. The serial number is in fact just a hit counter in disguise.
</p>

<p>
Just like the previous years, there are two easter eggs hidden around the site. You'll know when you've found them.
</p>

<p>
The only hiccup was getting IE6 and IE7 to play nice. In the end, there are only a few minor issues that don't damage the design overall, except for one IE7 issue left to solve. All other browsers played nice from the start.
</p>

<p>
The site can be found at <a href="http://www.leuvenspeelt.be/">LeuvenSpeelt.be</a> (Dutch).
</p>

<p>
Next up is finishing the work on this year's poster, which uses the same overall setting.</p></div></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[OSCMS Talk: Designer Eye for the Geek Guy/Gal]]></title>
    <link href="https://acko.net/blog/oscms-talk-designer-eye-for-the-geek-guy-gal/"/>
    <updated>2007-02-14T00:00:00+01:00</updated>
    <id>https://acko.net/blog/oscms-talk-designer-eye-for-the-geek-guy-gal</id>
    <content type="html"><![CDATA[<div class="g8 i2 first"><div class="pad"><p><em>Update: I've posted the <a href="/blog/design-presentation-slides">presentation slides and a video</a> is available as well.</em>
</p>

<p>
I'll be attending the <a href="http://www.oscms-summit.org">OSCMS conference</a> in Sunnyvale CA at Yahoo next month. Aside from a repeat of my DrupalCon jQuery talk, (though with a bit more examples) I just submitted another proposal for a talk. It's something that I've wanted to do for a while now:
</p>

<blockquote>
<p>
In meetings and lectures across the globe, people are made to endure hideous presentation slides featuring some of the wildest colors, clip art and typography. Many websites are so confusingly laid out, that you get dizzy from the overload of boxes, images or links. And every day, people receive resumés, invoices and ads ... <em>*cue lightning and thunder*</em> set in the Comic Sans font.
</p>

<p>
It's enough to make the average designer's hair turn blue, fall out, morph into a ninja and stab him/her in the eyes.
</p>

<p>
But, all hope is not lost! Contrary to popular belief, graphical design is not some arcane voodoo magic, but a straightforward discipline that values experience, reusability, elegance and good tools just like programming. Just like code, there are plenty of objective ways to measure the quality of a design. However, just like art is subjective, so may two programmers disagree on which implementation is the best. No designer is born with a genetic sense of proportion... it's just that while you were busy writing BASIC code on your C64, they were busy drawing superheroes.
</p>

<p>
I myself am an engineering geek who's never had any sort of formal design or art training, but has earned the title of "design nazi" on numerous occasions.
</p>

<p>
This session will teach geeks some basic principles about graphical design (especially on the web), from a geek perspective. This means we won't talk about "visually balanced design" but "here's a good approach to spacing". Soon, you'll be hearing the oooh's and aaah's when you don your designer hat.
</p>
</blockquote>

<p>
You can vote on the <a href="http://2007.oscms-summit.org/node/340">session page</a> if you're interested.</p></div></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Vancouver PHP Conference]]></title>
    <link href="https://acko.net/blog/vancouver-php-conference/"/>
    <updated>2007-02-12T00:00:00+01:00</updated>
    <id>https://acko.net/blog/vancouver-php-conference</id>
    <content type="html"><![CDATA[<div class="g8 i2 first"><div class="pad"><p>Ahoy from the <a href="http//vancouver.php.net/">Vancouver PHP</a> conference. I gave a talk titled "A Closer Look at Drupal 5" earlier. Overall response was positive, although according to Boris I wouldn't have managed to squeeze everything in 1 hour if I hadn't put on my zippy fast presentation speaking voice, so there might have been some information overload at times.
</p>

<p>
Oh well.. I figure anyone generally only remembers at most 50% of a talk, so I might as well blast you with a bunch of things and hope some of it sticks ;).
</p>

<p>
Thanks to <a href="http://buytaert.net/">Dries</a> and <a href="http://walkah.net">James</a> for letting me use their earlier presentations as a base.
</p>

<p>
<em>The slides are no longer available by Dries' request, as he has had problems with people stealing slides without permission before. Sorry.</em></p></div></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Authenticated Distributed Search (OpenSearch, OpenID)]]></title>
    <link href="https://acko.net/blog/authenticated-distributed-search-opensearch-openid/"/>
    <updated>2007-02-06T00:00:00+01:00</updated>
    <id>https://acko.net/blog/authenticated-distributed-search-opensearch-openid</id>
    <content type="html"><![CDATA[<div class="g8 i2 first"><div class="pad"><p>I've been working on Drupal distributed search for a while now, releasing a beta of the <a href="http://drupal.org/project/opensearch_aggregator">OpenSearch Aggregator</a> as well as a release of the <a href="http://drupal.org/project/opensearch">OpenSearch feed</a> module. The aggregator has a friendly UI for setting up any number of sources and the feed contains relevance information from the Drupal search system. Results are also cached on the aggregator for performance reasons.
</p>

<p>
More information about these modules can be found in my <a href="http://acko.net/tag/opensearch">earlier blog posts</a> about OpenSearch.
</p>

<p>
The ultimate goal however is to set up distributed search for a <a href="http://bryght.com/">Bryght</a> client between a network of secure Drupal sites. The searches for logged-in users should include content that is visible to them across all the different Drupal sites.
</p>

<p>
OpenID is the obvious choice as an identity mechanism for the users, but it does not immediately help us with the authentication. I've written a document after some research that details possible approaches and solutions. Because we're talking about frontier technology here, it seemed best to repost it publicly to sollicit feedback from anyone interested. I could certainly use some extra opinions on this, as it is all very new to me.
</p>

<h2>Essential requirements</h2>

<p>
The most basic requirement can be summed up as follows:
</p>

<p>
Given the search aggregator (master) and a group of sites that return results (slaves). Whenever a search is performed by a user logged in on the master, the master contacts all the slaves and passes along the identity of the user making the request. This information needs to be unambiguous and secure. Slaves will then return results respecting the user's access permissions back to the master, who aggregates and caches the results for browsing.
</p>

<p>
All communication to the slaves is done by the master. For practical and performance reasons, none of this can be implemented on the browser/client-side (other than maybe a trivial form/redirect to log-in once).
</p>

<h2>1. Naive implementation</h2>

<p>
A very simple implementation could use each user's e-mail address as the global identifier for identity, and map it to the local Drupal uid on each site. The request could be signed using a simple keyed hash (HMAC) with a shared secret key that is set on all the participating sites (thus encoding trust). A query from the server to a slave might look like:
</p>

<p class="codeblock">
<code>GET&nbsp;http://example.com/opensearch/node/keywords?user=name@example.com&amp;hmac=123456789abcdef
</code>
</p>

<p>
There are several problems with this:
</p>

<ul>
<li>The user needs to register manually on each of the participating sites using the same e-mail address.</li>
<li>A shared secret needs to be manually set on each of the participating sites.</li>
<li>All participating sites must be part of a completely trusted, closed network.</li>
</ul>

<h2>2. Improvements: OpenID log-in</h2>

<p>
Some first low-hanging fruit is using distributed OpenID for the end users. This avoids explicit registering on each of the participating sites, as the Drupal OpenID module does this for us when you log-in the first time. It also gives us a globally unique identifier (the user's OpenID) which is verified (by DNS), to cross reference the local numeric uid's with.
</p>

<p>
However, OpenID is distributed in nature, and does not immediately help us when we want to have the master prove to the slave that it is allowed to fetch content for a certain user. The only entity that knows and holds the keys/cookies to which sites a user is logged in to is the user's browser (User-Agent), while the home site knows only which sites are allowed and have been logged in to in the past.
</p>

<p>
The trust between master and slave would still have to be implemented through some other means, for example again using a shared secret key and HMAC verification:
</p>

<p class="codeblock">
<code>GET&nbsp;http://example.com/opensearch/node/keywords?user=user.openid.com&amp;hmac=123456789abcdef
</code>
</p>

<p>
Instead of authenticating every request, we could also implement an authenticated 'back door' through which the master can force log-ins on the slaves without doing actual OpenID authentication with the home server. The result would be a session cookie for each slave that can be used normally by the master:
</p>

<p class="codeblock">
<code>POST&nbsp;http://example.com/trust/?user=user.openid.com&amp;hmac=123456789abcdef<br />
=&gt;&nbsp;Cookie&nbsp;is&nbsp;set<br />
<br />
GET&nbsp;http://example.com/opensearch/node/keywords<br />
Cookie:&nbsp;PHPSESSID=123456789abcdef123456789abcdef
</code>
</p>

<p>
This backdoor login would be provided by another module, and would have to rely on e.g. a DNS or IP-based whitelist of allowed hosts, optionally with SSL to ensure confidentiality.
</p>

<p>
Access control would be respected by Drupal using the normal session mechanism and the OpenSearch client module would not need to be altered. The cookies can be stored along with the local user account on the master, and aggregated OpenSearch data would be cached on the master per user.
</p>

<h2>3. Search master as home server</h2>

<p>
A possible solution is to restrict the OpenID home server to be the search master.
</p>

<p>
This would allow the master to log-in to the slaves directly, as it can produce all the necessary cryptographic tokens without needing user action. No modifications are needed to the slaves. Once the master has logged in once to each site, it has a valid session cookie for each (like in (2)).
</p>

<h2>4. Multi-login extension to OpenID</h2>

<p>
Another solution would require an extension to OpenID, both to the client module for Drupal and the code that runs the home server. Still, it would allow the home server to be any other server (or even a set of servers), provided the home server supports the custom extension.
</p>

<p>
When the user logs in to the search master, the module would know that it will need access to each of the search slaves. When it sends a request to the home server, it would not only ask for a log-in to itself, but also for each of the slaves. The user would get a single screen on the home site to log-in to (with correct notification that this is a multi-login), and is returned to the search master.
</p>

<p>
The search master logs in the user locally, and uses the cryptographic tokens for each of the slaves to log into them. The slaves can verify the log-in tokens using direct communication with the OpenID provider. Like in (3), normal Drupal cookies are returned to the master and used to perform the searches.
</p>

<h2>5. Other ideas</h2>

<p>
Of the above methods, only (2) is really immediately practical. Using OpenID at the base does not help if you still need proprietary extensions, or if you take away the ability to choose a home site. And if we do want to do (4) properly, then we need to develop an actual spec that respects the principles and security of OpenID. Not an easy job.
</p>

<p>
The downside of (2) is that there is no actual proof that the log-in took place, and that we rely on the shared key to ensure trust.
</p>

<p>
However, because the whole Identity 2.0 space is still developing, I think it would be silly to try and build something elaborate that implements some sort of utopian federation/whatchamacallit model. It would be an insane amount of work and would not be future proof or even useful today as very few real-world services would support it. I think we just have to wait here to see what develops, once OpenID gains some more widespread use and people get more comfortable with these concepts (which should happen in 2007).
</p>

<h2>5.1. SAML</h2>

<p>
SAML has been suggested as a standardized way of passing along security assertions. However, SAML is really a competitor to OpenID and started as a way of doing single sign-on between trusted sites.
</p>

<p>
The main difference is that OpenID is tied to a particular HTTP exchange pattern, while SAML better separates the message from the delivery method. Still, SAML is based on exactly the same principles, so assertions have to be generated and signed by the home server. So, they are still useless if we want the master to securely prove the log-in of a certain OpenID. Of course, we could encapsulate the message from master to slave in an unsigned SAML message, but that would really defeat the point of using SAML in the first place.
</p>

<p>
SAML itself doesn't do trust either. The slaves would still have to have a whitelist that includes only the master and which would be verified again by DNS/IP or SSL.
</p>

<h2>5.2. OpenID Proof-of-login token</h2>

<p>
The big functionality hole in OpenID is that the only one who can verify the cryptographic tokens for a log-in is the intended recipient (the relying party). There is no way in the specs to 'forward' the assertion by the home server that the user logged in to the relying party in a way that makes the information verifiable for everyone.
</p>

<p>
An extension to OpenID for this would be good. It's essentially a variant on the multi-login idea, where, instead of asking the user to log-in to the cloud of sites, the user only logs in to the master, and the master sends proof of this log-in to the slaves:
</p>

<p class="codeblock">
<code>POST&nbsp;http://example.com/trust/?user=user.openid.com&amp;....crypto-here....<br />
=&gt;&nbsp;Cookie&nbsp;is&nbsp;set
</code>
</p>

<p>
The slaves would again have a whitelist based on IP/DNS or SSL. The main difference with (4) is that here, trust is again set by the administrator rather than explicitly given by the user through OpenID.
</p>

<h2>Conclusion</h2>

<p>
(4) sounds like the cleanest solution, as it does not rely on explicit whitelisting for trust. The user simply has to check that the master is not asking for a log-in to an external site. However, it would require an extension to the OpenID log-in process on the home server, including the UI (as the extra log-ins have to be communicated somehow), so it is unlikely that it would be implemented easily.
</p>

<p>
(5.2) sounds better in this light, because only changes under the hood need to be made. The home server would simply send along extra cryptographic tokens that can be forwarded to other parties. Depending on security issues, these tokens could be requested in general (by amount) or for specific recipients (for each specific slave).
</p>

<p>
Both solutions require serious crypto and spec work to do properly.
</p>

</div></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Expanding Textareas]]></title>
    <link href="https://acko.net/blog/expanding-textareas/"/>
    <updated>2007-01-20T00:00:00+01:00</updated>
    <id>https://acko.net/blog/expanding-textareas</id>
    <content type="html"><![CDATA[<div class="g8 i2 first"><div class="pad"><p>See the <a href="http://drupal.org/node/111308">Drupal.org issue</a>.
</p>

<p>
<div style="padding-bottom: 2em;">
<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab" width="478" height="344">
 <param name="src" value="/files/drupal-expand/jQuery-expand.mov" />
 <param name="controller" value="true" />
 <param name="autostart" value="false" />
 <object type="video/quicktime" data="/files/drupal-expand/jQuery-expand.mov" width="478" height="344" class="mov">
  <param name="controller" value="true" />
  <param name="autostart" value="false" />
  Quicktime embedding doesn't seem to be working. Try <a href="/files/drupal-expand/jQuery-expand.mov">downloading the file.</a>
 </object>
</object>
</div></p></div></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Making Drupal smarter]]></title>
    <link href="https://acko.net/blog/making-drupal-smarter/"/>
    <updated>2007-01-19T00:00:00+01:00</updated>
    <id>https://acko.net/blog/making-drupal-smarter</id>
    <content type="html"><![CDATA[<div class="g8 i2 first"><div class="pad"><p>One of the things I worked on for Drupal 5 was to make Drupal smarter about itself. For example, the new status report tells you about security or maintenance problems, and can alert you if you need to run update.php after updating a module. These warnings are also pushed out to the main administration page.
</p>

<p>
This is a significant improvement in usability, as we try to make site set up and maintenance as painless as possible. The user can focus on the things they care about. If there is something that needs the admin's attention, it is clearly indicated.
</p>

<p>
The inspiration for this came from OS X. There are some really great examples of this in both Apple and third-party applications.
<!--break-->
For example, Mail.app automatically figures out if your mail server requires SSL or not: it simply tries both and sees which works when you set up the account. It happens transparently.
</p>

<p>
NewsFire does something similar. When you click the "Add feed" button, it automatically takes any URL on the clipboard, pings it and fetches the feed title (provided it points to a valid feed). All you need to do is press ok on the pre-filled form. If there is no URL on the clipboard, you get a blank form.
</p>

<p>
With our new _install and _enable hooks, and _requirements to examine the server environment, Drupal 5 modules have a lot of more opportunities to 'do the right thing' transparently. 
</p>

<p>
We should encourage this practice as much as possible. Modules that require Drupal's configuration to match certain settings should make sure they are set correctly. If the setting is relatively benign and related to the module's purpose, it can be set automatically. Otherwise, it can be a requirement for the module to be installed/enabled.
</p>

<p>
We do need to walk a fine line between information overload and too much magic. But I think we've managed to do fine so far.
</p></div></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Updated Drupal TextMate Bundle]]></title>
    <link href="https://acko.net/blog/updated-drupal-textmate-bundle/"/>
    <updated>2007-01-14T00:00:00+01:00</updated>
    <id>https://acko.net/blog/updated-drupal-textmate-bundle</id>
    <content type="html"><![CDATA[<div class="g8 i2 first"><div class="pad"><p>I've updated my Drupal TextMate bundle script to also generate snippets for all PHP internal functions, including correct placeholders for the function arguments. It's a lifesaver when navigating PHP's bizarre Array or String APIs.
</p>

<p>
The script fetches the PHP function list straight from PHP CVS, but it still needs a Drupal tree to work. You can also copy in the contrib documentation to get snippets for hooks too (which even auto-fill in the module name). All PHP files within the given path are parsed.
</p>

<p>
To use it, place it in <code>~/Library/Application&nbsp;Support/TextMate/Bundles</code> and run it:
</p>

<p>
<code><br />
php&nbsp;generate.php.txt&nbsp;[path&nbsp;to&nbsp;drupal]<br />
</code>
</p>

<p>
In TextMate, go to Bundles › Bundle Editor › Reload Bundles to activate it. 
</p>

<p>
  <a href="/files/drupal-textmate/generate.php.txt">Download</a>
</p>

<p>
 (License: <a href="http://www.gnu.org/copyleft/gpl.html">GPL</a>)
</p></div></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[On Breaking Things]]></title>
    <link href="https://acko.net/blog/on-breaking-things/"/>
    <updated>2007-01-05T00:00:00+01:00</updated>
    <id>https://acko.net/blog/on-breaking-things</id>
    <content type="html"><![CDATA[<div class="g8 i2 first"><div class="pad"><p>See the <a href="http://drupal.org/node/107061">Drupal.org issue</a>.
</p>

<p>
<div style="padding-bottom: 2em;">
<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab" width="478" height="394">
 <param name="src" value="/files/drupal-splitter/jQuery-splitter.mov" />
 <param name="controller" value="true" />
 <param name="autostart" value="false" />
 <object type="video/quicktime" data="/files/drupal-splitter/jQuery-splitter.mov" width="478" height="394" class="mov">
  <param name="controller" value="true" />
  <param name="autostart" value="false" />
  Quicktime embedding doesn't seem to be working. Try <a href="/files/drupal-splitter/jQuery-splitter.mov">downloading the file.</a>
 </object>
</object>
</div></p></div></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Drupal OpenSearch Aggregator]]></title>
    <link href="https://acko.net/blog/drupal-opensearch-aggregator/"/>
    <updated>2006-12-16T00:00:00+01:00</updated>
    <id>https://acko.net/blog/drupal-opensearch-aggregator</id>
    <content type="html"><![CDATA[<div class="g8 i2 first"><div class="pad"><p>I just committed a working version of my new OpenSearch Aggregator module to Drupal Contrib CVS.
</p>

<p>
<a href="http://www.opensearch.org/">OpenSearch</a> is a standard by Amazon which allows you to share search results through RSS. The feeds are valid RSS, they just contain extra meta-data for searching. So, you can use OpenSearch with any RSS reader to set up feeds to track tags or keywords for example.
</p>

<p>
We also have an OpenSearch client module that provides these feeds, and I just updated it to send search relevance information along. So, you could set up 5 Drupal sites with OpenSearch module, and a sixth site with the OpenSearch aggregator. Now, you can search all 5 sites simultaneously, and get a single, ordered list of global results.
</p>

<p>
However, because OpenSearch is an open standard, it can be used for anything. Amazon's A9 search already offers media search for example. The possibilities really are endless.
</p>

<p>
The best part? The OpenSearch Aggregator presents its results through the normal search system. So, if you install the OpenSearch module on top of this, you automatically provide OpenSearch feeds for the aggregated search. In other words, Drupal is now a complete OpenSearch processing suite! There is no other CMS out there that can claim this.
</p>

<p>
More info is on the <a href="http://drupal.org/project/opensearch_aggregator">Drupal.org project page</a>.</p></div></div>
]]></content>
  </entry>
  
</feed>
