Benjamin Heiskellhttp://xdxa.org/ben.heiskell@xdxa.orgXDXAtag:xdxa.org,2011-06-11:/atom/http://xdxa.org/favicon.icohttp://xdxa.org/feed-logo.png2023-02-19T20:57:00ZacrylamidFoundryVTT Module Test Automationtag:xdxa.org,2023-02-19:/2023/foundryvtt-module-test-automation2023-02-19T20:57:00ZBenjamin Heiskellhttp://xdxa.org/ben.heiskell@xdxa.org<p>I really loath manual testing. In a professional setting, nearly all of my
projects are developed using TDD (test driven development). However, a bit to my
embarassment, most of my personal projects haven't received this level of care.
In this article, I'm going to overview how I bucked that trend by introducing
testing to a friend's project.</p>
<p>Back in 2017, I started GM'ing the FFG Star Wars Tabletop RPG for my friends.
Over the years, folks moved and eventually the game migrated online.
In early 2021, a friend suggested I explore <a href="https://foundryvtt.com">FoundryVTT</a>.
It quickly became our favorite tabletop RPG platform due to its extensibility.</p>
<p>We used the <a href="https://foundryvtt.com/packages/starwarsffg">Star Wars FFG System</a>,
and shortly thereafter, my friend began development of an add-on module
(<a href="https://foundryvtt.com/packages/ffg-star-wars-enhancements">FFG Star Wars Enhancements</a>)
with features not really suited for the core system.</p>
<p>Since then, FoundryVTT has undergone three major releases. While I've
contributed a number of features to the module, the majority of the maintenance
and testing during those releases has fallen on my friend's shoulders.
After discussing options, I decided to use my background in CI/CD workflow
development to setup automated testing.</p>
<h3>Challenges</h3>
<p>In many projects, a good mocking framework will give you sufficient coverage for
testing against integration points with other libraries. In our case, FoundryVTT
effectively acts as a framework for the module. This tightly couples the
project's code with the implementation of the FoundryVTT API. The level of
mocking that would be required to adequetly test a feature would prove extremely
unreliable during a major version change. Many frameworks eventually create a
testing scaffold that blends production code and <a href="https://martinfowler.com/articles/mocksArentStubs.html">fake</a>s.
This may be in FoundryVTT's future, but at time of writing it does not exist
yet.</p>
<p>That leaves the next best option being integration and end-to-end tests. The
difference between them is subtle. For the purposes of this article,
integration tests attempt to minimize their reliance on UI interactions and
end-to-end tests attempt to primarily test the UI.</p>
<p>Additionally, FoundryVTT (reasonably) restricts distribution of their software.
That makes automating tests challenging, particularly in CI.</p>
<h3>Quench</h3>
<p><a href="https://github.com/Ethaks/FVTT-Quench">Quench</a> is a FoundryVTT module that can
be used to run tests from your module within FoundryVTT. This allows you to
write <a href="https://mochajs.org/">Mocha tests</a> and run them within FoundryVTT.
We use Quench for our integration tests, where we try to avoid UI interactions.</p>
<p>Excerpt from a quench test:</p>
<div class="highlight"><pre><span></span><span class="nx">it</span><span class="p">(</span><span class="sb">`creates a new </span><span class="si">${</span><span class="nx">option</span><span class="si">}</span><span class="sb"> journal`</span><span class="p">,</span> <span class="nx">async</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="c1">// Hook to capture when our dialog has actually rendered</span>
<span class="kr">const</span> <span class="nx">rendered</span> <span class="o">=</span> <span class="nx">$</span><span class="p">.</span><span class="nx">Deferred</span><span class="p">();</span>
<span class="nx">Hooks</span><span class="p">.</span><span class="nx">once</span><span class="p">(</span><span class="s2">"renderApplication"</span><span class="p">,</span> <span class="p">(...</span><span class="nx">args</span><span class="p">)</span> <span class="o">=></span> <span class="nx">rendered</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">args</span><span class="p">));</span>
<span class="kr">const</span> <span class="nx">dialog</span> <span class="o">=</span> <span class="nx">await</span> <span class="nx">create_datapad_journal</span><span class="p">();</span>
<span class="kr">const</span> <span class="p">[</span><span class="nx">application</span><span class="p">,</span> <span class="nx">$html</span><span class="p">]</span> <span class="o">=</span> <span class="nx">await</span> <span class="nx">rendered</span><span class="p">.</span><span class="nx">promise</span><span class="p">();</span>
<span class="c1">// Sanity check the renderApplication hook returned our dialog</span>
<span class="nx">expect</span><span class="p">(</span><span class="nx">dialog</span><span class="p">).</span><span class="nx">to</span><span class="p">.</span><span class="nx">equal</span><span class="p">(</span><span class="nx">application</span><span class="p">);</span>
<span class="p">...</span> <span class="mi">8</span><span class="o"><</span> <span class="nx">snip</span> <span class="p">...</span>
<span class="kr">const</span> <span class="nx">datapad</span> <span class="o">=</span> <span class="nx">game</span><span class="p">.</span><span class="nx">journal</span><span class="p">.</span><span class="nx">getName</span><span class="p">(</span><span class="nx">option</span><span class="p">);</span>
<span class="nx">expect</span><span class="p">(</span><span class="nx">datapad</span><span class="p">).</span><span class="nx">to</span><span class="p">.</span><span class="nx">not</span><span class="p">.</span><span class="nx">be</span><span class="p">.</span><span class="kc">undefined</span><span class="p">;</span>
<span class="kr">const</span> <span class="nx">page</span> <span class="o">=</span> <span class="nx">datapad</span><span class="p">.</span><span class="nx">pages</span><span class="o">?</span><span class="p">.</span><span class="nx">values</span><span class="p">()</span><span class="o">?</span><span class="p">.</span><span class="nx">next</span><span class="p">().</span><span class="nx">value</span><span class="p">;</span>
<span class="nx">expect</span><span class="p">(</span><span class="nx">page</span><span class="p">).</span><span class="nx">to</span><span class="p">.</span><span class="nx">not</span><span class="p">.</span><span class="nx">be</span><span class="p">.</span><span class="kc">undefined</span><span class="p">;</span>
<span class="nx">expect</span><span class="p">(</span><span class="nx">page</span><span class="p">.</span><span class="nx">text</span><span class="o">?</span><span class="p">.</span><span class="nx">content</span><span class="p">).</span><span class="nx">to</span><span class="p">.</span><span class="nx">have</span><span class="p">.</span><span class="nx">string</span><span class="p">(</span><span class="nx">needle</span><span class="p">);</span>
</pre></div>
<p>To see how we use Quench in action, check out <a href="https://github.com/wrycu/StarWarsFFG-Enhancements/tree/main/tests">our Quench tests</a>.</p>
<h3>Cypress</h3>
<p>For full end-to-end tests, we've opted for <a href="https://www.cypress.io/">Cypress</a>.
Cypress is a good fit for our project, because our tests really are purely
frontend tests. Cypress's opinionated approach to testing encourages us to
write tests in a way that avoids a lot of the patterns that make UI tests
brittle.</p>
<p>We developed a number of <a href="https://github.com/wrycu/StarWarsFFG-Enhancements/blob/main/cypress/support/commands.js">Cypress Commands</a>
that handle installing systems, modules, and creating a test world.</p>
<p>Excerpt from a cypress test:</p>
<div class="highlight"><pre><span></span><span class="c1">// Open the crawl dialog</span>
<span class="nx">cy</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">'[data-control="ffg-star-wars-enhancements"]'</span><span class="p">).</span><span class="nx">click</span><span class="p">();</span>
<span class="nx">cy</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s1">'[data-tool="opening-crawl"]'</span><span class="p">).</span><span class="nx">click</span><span class="p">();</span>
<span class="c1">// Create a folder for the Opening Crawl journals</span>
<span class="nx">cy</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s2">".window-content .yes"</span><span class="p">).</span><span class="nx">click</span><span class="p">();</span>
<span class="c1">// Create a crawl</span>
<span class="nx">cy</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s2">"#ffg-star-wars-enhancements-opening-crawl-select .create"</span><span class="p">).</span><span class="nx">click</span><span class="p">();</span>
</pre></div>
<blockquote>
<p>Aside: If you end-up exploring Cypress, I strongly recommend reading their
documentation. Specifically, <a href="https://docs.cypress.io/guides/core-concepts/conditional-testing">Conditional Testing</a>.
Wrapping your head around the "Element existence" section will go a long way to
avoiding common pitfalls.</p>
</blockquote>
<h4>Tests inside your tests?</h4>
<p>An astute reader might have noticed that Quench requires a running instance of
FoundryVTT to execute tests. To support running Quench tests in CI, we actually execute the
<a href="https://github.com/wrycu/StarWarsFFG-Enhancements/blob/main/cypress/e2e/01_quench.cy.js">Quench tests via Cypress</a>.</p>
<p>Honestly, this feels a bit hack. But, writing integration tests in Quench feels
more fluid, and this gives us a bit of the best of both worlds.</p>
<h3>Docker Compose</h3>
<p>Having the ability to quickly spin up and tear down different versions of
FoundryVTT is extremely useful when testing. Locally, I'm using Docker Compose
with <a href="https://github.com/felddy/foundryvtt-docker">felddy/foundryvtt-docker</a>'s
docker container.</p>
<p>The container is really well designed and pretty flexible. To learn more about
our Docker Compose configuration and usage, check out our
<a href="https://github.com/wrycu/StarWarsFFG-Enhancements/blob/main/cypress/README.md">Cypress README.md</a>.</p>
<h3>GitHub Actions</h3>
<p>Tests that don't run as part of CI inevitably end up broken.</p>
<blockquote>
<p>Aside: I actually worked backwards from this requirement to design all of the
above, but explaining it in that order would have been very difficult.</p>
</blockquote>
<p>Cypress makes testing in GitHub very each.
They expose a <a href="https://github.com/cypress-io/github-action">github-action</a> for
running Cypress tests that handle launch and readiness checks for your server.
Additionally, it automatically archives video recordings of your test runs.</p>
<p>To run FoundryVTT in a GitHub action, we reuse the learnings from Docker Compose.
The GitHub Ubuntu runners come preloaded with Docker. It's easy enough to craft
a <code>docker run</code> command that will launch FoundryVTT with our module's code
installed.</p>
<p>From there, a few challenges remained:</p>
<ol>
<li>Caching the installation to avoid abusive downloads of FoundryVTT</li>
<li>Securing FoundryVTT credentials while still supporting tests on user forks</li>
<li>Requiring approval only on PRs from forks</li>
<li>Race conditions!</li>
</ol>
<p>Excerpt from our GitHub action configuration. See
<a href="https://github.com/wrycu/StarWarsFFG-Enhancements/tree/95fe244ad7eb48521c1aff70588c1dfc4a1f3162/.github/workflows">StarWarsFFG-Enhancements repository</a>
for all workflows.</p>
<div class="highlight"><pre><span></span><span class="p p-Indicator">-</span> <span class="l l-Scalar l-Scalar-Plain">if</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">${{ steps.container_cache.outputs.cache-hit != 'true' }}</span>
<span class="l l-Scalar l-Scalar-Plain">name</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">Launch FoundryVTT and run Cypress Tests</span>
<span class="l l-Scalar l-Scalar-Plain">uses</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">cypress-io/github-action@v5</span>
<span class="l l-Scalar l-Scalar-Plain">with</span><span class="p p-Indicator">:</span>
<span class="l l-Scalar l-Scalar-Plain">start</span><span class="p p-Indicator">:</span> <span class="p p-Indicator">>-</span>
<span class="no">sudo docker run</span>
<span class="no">--name foundryvtt</span>
<span class="no">--env FOUNDRY_ADMIN_KEY=test-admin-key</span>
<span class="no">--env FOUNDRY_USERNAME=${{ secrets.FOUNDRY_USERNAME }}</span>
<span class="no">--env FOUNDRY_PASSWORD=${{ secrets.FOUNDRY_PASSWORD }}</span>
<span class="no">--env FOUNDRY_LICENSE_KEY=${{ secrets.FOUNDRY_LICENSE_KEY }}</span>
<span class="no">--publish 30001:30000/tcp</span>
<span class="no">--volume ${{ github.workspace }}/data:/data</span>
<span class="no">felddy/foundryvtt:release</span>
<span class="l l-Scalar l-Scalar-Plain">wait-on</span><span class="p p-Indicator">:</span> <span class="s">"http://localhost:30001"</span>
<span class="l l-Scalar l-Scalar-Plain">wait-on-timeout</span><span class="p p-Indicator">:</span> <span class="l l-Scalar l-Scalar-Plain">120</span>
</pre></div>
<p>More detail about the repository configuration can be found in the <a href="https://github.com/wrycu/StarWarsFFG-Enhancements/tree/main/cypress">Cypress README.md</a>.</p>
<h4>1. Caching</h4>
<p>To ensure we don't repetitively download the FoundryVTT application, we need to
setup caching within the GitHub workflow. Fortunately, the <code>felddy/foundryvtt</code>
docker image supports this natively. All we need to do is cache the
<code>data/container_cache</code> directory. Unfortunately, the container entrypoint will
still authenticate to the FoundryVTT API if a username/password is provided.
Normally, this feature gives you a way to make sure you're running the latest
release. In our case, we don't want that. To avoid it, we have two "steps": one
if the cache hits and one if the cache misses. We omit the <code>FOUNDRY_USERNAME</code> and
<code>FOUNDRY_PASSWORD</code> when we have a cache hit, skipping the check entirely.</p>
<p>To actually cache, we use the <code>actions/cache@v3</code> action provided by GitHub. The
only special thing we do here is an additional step that saves on failure to
ensure we capture the installation regardless of whether the tests pass. The
cache should hang around for at least seven days.</p>
<h4>2. Security credentials</h4>
<p>Getting the level of flexibility we wanted out of GitHub proved a little
difficult. We wanted to know that tests would pass before merging a pull request.
To support contributors forking our repository, that means checking out their
code and running tests against it. However, these tests launch a docker
container that requires secrets (<code>FOUNDRY_USERNAME</code>, <code>FOUNDRY_PASSWORD</code>, and
<code>FOUNDRY_LICENSE_KEY</code>). To make those secrets accessible in workflows run
with code from forks, we use the <code>pull_request_target</code> event.</p>
<p>This is <a href="https://securitylab.github.com/research/github-actions-preventing-pwn-requests/">potentially <em>very</em> risky</a>.
To limit our exposure, we use a GitHub "environment" on PRs originating from forks
called <code>requires-approval</code>. The environment has a few contributors assigned to
it that must manually approve every run.</p>
<h4>3. Approval only on forks</h4>
<p>Requiring approval only for PRs coming from forks was tricky to configure.
The yaml SDL provided by GitHub actions is pretty flexible, but code reuse can
get difficult. There isn't a good way to specify the workflow environment based on
the origin. To work around that limitation, we create two jobs: one for upstream
and one for forks. That splits the workflow across <code>cypress.yaml</code> where the
jobs are defined and <code>cypress-impl.yaml</code> where the actual steps are defined.</p>
<p>This was a bit quirky to setup, but the sharp edges are pretty well documented
in the configs.</p>
<h4>4. Race conditions!</h4>
<p>The free GitHub Actions runners are awesome! But they definitely run in a low
performance environment. The heavy load will unfortunately/fortunately highlight
every sloppy race condition in your tests. Adding fixed length timeouts
generally is not reliable.</p>
<p>This makes tests trickier to write. You have to be very careful to be sure
you've waited for the right thing before proceeding.</p>
<p>Additionally, some of our code, the system code, and FoundryVTT itself is not
written in a way that makes it easy to know when you can proceed.</p>
<p>A few examples:</p>
<ul>
<li>The close button on "Applications" have a 500ms timer before it attaches the
<code>onClick</code> handler to prevent accidentally closing. Meaning, clicking it does
nothing from fast automation.</li>
<li>FoundryVTT has <code>Hook</code>s for a lot of asynchronous events, but reasonably not
everything. If you launch a dialog, you need to be thoughtful about how to
know the dialog resolved. This could be done with a custom Hook, or by looking
for a side-effect (like the creation of a Journal).</li>
</ul>
<h3>Summary</h3>
<p>I hope that this proves useful to someone who hopes to setup test automation for
a FoundryVTT module.</p>String Concatenation - Root of all Eviltag:xdxa.org,2014-02-04:/2014/string-concatenation-root-of-all-evil2014-02-04T20:04:00ZBenjamin Heiskellhttp://xdxa.org/ben.heiskell@xdxa.org<p>After college, I spent three years in software security acting as a <a href="https://en.wikipedia.org/wiki/Penetration_test">pen-tester</a>.
It was my job to identify security vulnerabilities in the company's software via exploitation.
During that time, string concatenation was the root cause of the vast majority of my findings.
For that reason, it is my general philosophy that:</p>
<blockquote>
<p>If you're concatenating strings, you're doing it wrong.</p>
</blockquote>
<h3>What?</h3>
<p>To make my point easier to grok, let's start with a simple example:</p>
<div class="highlight"><pre><span></span><span class="o">>>></span> <span class="n">person</span><span class="o">.</span><span class="n">first_name</span> <span class="o">+</span> <span class="s2">" "</span> <span class="o">+</span> <span class="n">person</span><span class="o">.</span><span class="n">last_name</span>
<span class="s1">'Bob Smith'</span>
</pre></div>
<p>We've joined a person's first and last name with a space.
The concatenated value can be thought of as a space delimited string.
In of itself, this is not an issue.
But, what happens when we need to reverse this transformation?
Easy enough. Using the previous output as our input, we split on the space character.</p>
<div class="highlight"><pre><span></span><span class="o">>>></span> <span class="n">name</span> <span class="o">=</span> <span class="s2">"Bob Smith"</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">" "</span><span class="p">)</span>
<span class="o">>>></span> <span class="k">print</span> <span class="n">name</span>
<span class="p">[</span><span class="s1">'Bob'</span><span class="p">,</span> <span class="s1">'Smith'</span><span class="p">]</span>
</pre></div>
<p>What happens if the first name contains a space?
If an attacker controls that value, an injected space could break the application's intended behavior.
It's conceivable to imagine that after <em>deserialization</em>, the value might be used in some security related decision.</p>
<div class="highlight"><pre><span></span><span class="o">>>></span> <span class="n">name</span> <span class="o">=</span> <span class="s2">"Bob Smith RealLastName"</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">" "</span><span class="p">)</span>
<span class="o">>>></span> <span class="k">print</span> <span class="n">name</span>
<span class="p">[</span><span class="s1">'Bob'</span><span class="p">,</span> <span class="s1">'Smith'</span><span class="p">,</span> <span class="s1">'RealLastName'</span><span class="p">]</span>
<span class="o">>>></span> <span class="k">if</span> <span class="s2">"Smith"</span> <span class="o">==</span> <span class="n">name</span><span class="p">[</span><span class="mi">1</span><span class="p">]:</span>
<span class="o">...</span> <span class="k">print</span> <span class="s2">"Welcome Smith!"</span>
<span class="o">...</span>
<span class="n">Welcome</span> <span class="n">Smith</span><span class="err">!</span>
</pre></div>
<p>To address the vulnerability, we have a few options:</p>
<ul>
<li>Validate the first name, rejecting requests with spaces</li>
<li>Sanitize the first name, removing spaces</li>
<li>Introduce an escape sequence and <em>escape</em> the names</li>
</ul>
<p>Validation and sanitization are appealing choices, but if the business logic forbids it, our only option is escaping.
A simple solution would be to replace spaces with <code>'\ '</code> and backlashes with <code>'\\'</code>.</p>
<div class="highlight"><pre><span></span><span class="o">>>></span> <span class="n">person</span><span class="o">.</span><span class="n">first_name</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">' '</span><span class="p">,</span> <span class="s1">'\ '</span><span class="p">)</span> <span class="o">+</span> <span class="s2">" "</span> <span class="o">+</span>
<span class="n">person</span><span class="o">.</span><span class="n">last_name</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">' '</span><span class="p">,</span> <span class="s1">'\ '</span><span class="p">)</span>
<span class="s1">'Bob</span><span class="se">\\</span><span class="s1"> Smith RealLastName'</span>
</pre></div>
<p>You might be inclined to argue that this is a sufficient fix (nevermind that it's not to spec).
However, I'm here to suggest that's not true.
Manually escaping and concatenating strings is implicitly brittle.
Forgetting to apply escaping algorithm in one place is enough to introduce a severe vulnerability.</p>
<p>The mistake here was <em>casually</em> performing serialization rather than utilizing some library, whose sole responsibility is serialization.
This example is somewhat contrived, but the fundamental principal can be expanded to CSVs, XML, JSON, URIs, SQL, or any <em>formatted</em> data.</p>
<h3>Examples</h3>
<p>Let's break down a few exploits to demonstrate my point.</p>
<h4>SQL</h4>
<p>Here we have a simple <a href="https://en.wikipedia.org/wiki/SQL_injection">SQL injection</a> in PHP:</p>
<div class="highlight"><pre><span></span><span class="cp"><?</span> <span class="s2">"SELECT * FROM table WHERE col='"</span> <span class="o">.</span> <span class="nv">$input</span> <span class="o">.</span> <span class="s2">"'"</span><span class="p">;</span>
</pre></div>
<p>If the input contains a single quote, <code>"'"</code>, the SQL query's structure is disrupted.
An attacker can use this to alter the query.
(This example is benign.
There are significantly more malicious uses for SQL injection, but that's not what I'm here to discuss.)</p>
<div class="highlight"><pre><span></span><span class="cp"><?</span>
<span class="nv">$input</span> <span class="o">=</span> <span class="s2">"' OR ''='"</span><span class="p">;</span>
<span class="nv">$query</span> <span class="o">=</span> <span class="s2">"SELECT * FROM table WHERE col='"</span> <span class="o">.</span> <span class="nv">$input</span> <span class="o">.</span> <span class="s2">"'"</span><span class="p">;</span>
<span class="k">echo</span> <span class="nv">$query</span><span class="p">;</span>
<span class="nx">SELECT</span> <span class="o">*</span> <span class="nx">FROM</span> <span class="nx">table</span> <span class="nx">WHERE</span> <span class="nx">col</span><span class="o">=</span><span class="s1">''</span> <span class="k">OR</span> <span class="s1">''</span><span class="o">=</span><span class="s1">''</span>
</pre></div>
<p>How do we fix it? There are three general approaches:</p>
<div class="highlight"><pre><span></span><span class="cp"><?</span>
<span class="mf">1.</span> <span class="s2">"...WHERE col='"</span> <span class="o">.</span> <span class="nb">str_replace</span><span class="p">(</span><span class="s2">"'"</span><span class="p">,</span> <span class="s2">""</span><span class="p">,</span> <span class="nv">$x</span><span class="p">)</span> <span class="o">.</span> <span class="s2">"'"</span>
<span class="mf">2.</span> <span class="s2">"...WHERE col='"</span> <span class="o">.</span> <span class="nb">mysql_real_escape_string</span><span class="p">(</span><span class="nv">$x</span><span class="p">)</span> <span class="o">.</span> <span class="s2">"'"</span>
<span class="mf">3.</span> <span class="nv">$mysqli</span><span class="o">-></span><span class="na">prepare</span><span class="p">(</span><span class="s2">"...WHERE col=?"</span><span class="p">,</span> <span class="nv">$x</span><span class="p">)</span>
</pre></div>
<p>The first approach manually sanitizes the input by blacklisting the single quote character.
This approach is problematic, because it doesn't account for all possible special characters.
If the surrounding quotes were instead double quotes, this method would fail.
When I've seen this type of sanitization, it is typically done at the beginning of the request, far away from the code which actually utilizes the variable.
That increases the probability of such a mistake.</p>
<p>The second approach utilizes a library call to escape the input.
The last approach parameterizes the query, sending the query and its arguments separately to the database.
Both the second and third approach utilize a library call, and both work for this query.
If that's the case, what's wrong with using the version that utilizes string concatenation?
What if the column was instead a number?</p>
<div class="highlight"><pre><span></span><span class="cp"><?</span> <span class="s2">"...WHERE number="</span> <span class="o">.</span> <span class="nb">mysql_real_escape_string</span><span class="p">(</span><span class="nv">$x</span><span class="p">);</span>
</pre></div>
<p>There are no characters to escape in this case! An injection like <code>"0 OR 1=1"</code> will still work.
If the variable <code>$x</code> had been validated as an integer prior to use, there wouldn't have been an issue.
However that's a brittle solution, because a simple mistake (or refactor) could still compromise the application's security.</p>
<p>What's really wrong here?
The query <em>is</em> the formatted data.
The library call is used to escape a value which is being <em>serialized</em> into the query.
That's the responsibility of the library.
By using string concatenation, we've effectively written part of a SQL serializer.</p>
<p>(Learn more about <a href="http://www.codinghorror.com/blog/2005/04/give-me-parameterized-sql-or-give-me-death.html">motivations to use parameterized queries</a>.)</p>
<h4>URI</h4>
<p>The URI is a fascinating point to perform injection attacks upon.
They are extremely easy to construct without a library, which means it's done frequently, and the results work <em>most</em> of the time.
As more applications move towards <a href="https://en.wikipedia.org/wiki/Service-oriented_architecture">service oriented architectures</a>,
URIs are increasingly used as a component of the communication.
If unescaped input is placed into the URI, it might be possible to alter the application's intended behavior.</p>
<p>In the following example, we have a web application which transfers funds by dispatching to an HTTP service.
The user controls the variable <em>amount</em>, but not <em>user</em> or <em>target</em>.
The service domain <em>s.xdxa.org</em> is not internet accessible.
We can assume the backend service will validate <em>amount</em> as a positive integer prior to use.</p>
<div class="highlight"><pre><span></span><span class="o">>>></span> <span class="k">print</span> <span class="s1">'http://s.xdxa.org/pay?amount='</span> <span class="o">+</span> <span class="n">amount</span> <span class="o">+</span>
<span class="s1">'&from='</span> <span class="o">+</span> <span class="n">user</span> <span class="o">+</span>
<span class="s1">'&to='</span> <span class="o">+</span> <span class="n">target</span>
<span class="s1">'http://s.xdxa.org/pay?amount=100&from=eve&to=bob'</span>
</pre></div>
<p>To force Bob to pay Eve, we only need to alter the URI structure.</p>
<div class="highlight"><pre><span></span><span class="o">>>></span> <span class="n">amount</span> <span class="o">=</span> <span class="s1">'100&from=bob&to=eve#'</span>
<span class="o">>>></span> <span class="k">print</span> <span class="o">...</span>
<span class="s1">'.../pay?amount=100&from=bob&to=eve#&from=eve&to=bob'</span>
</pre></div>
<p>The fragment (everything after the <code>'#'</code>) is dropped before making the backend request.
As a result, the service's log will look completely normal.
To fix this, use a library to generate URIs.
This is typically accomplished by using either a builder or providing a map of "parameter to argument"s.</p>
<p>Unfortunately, libraries for RESTful URIs, where arguments may be part of the path, are more scarce.
In that circumstance, concatenation + escaping may be your only option.
However, if you do that, segment that code into its own domain, i.e., create a library.
The Java library <a href="https://github.com/damnhandy/Handy-URI-Templates">Handy URI Templates</a> is a good model for generating said URIs.</p>
<p>Additionally, be careful in other sections of the URI.
Other components of the URI have different rules, i.e., scheme and authority.
If you want to know more, <a href="http://lcamtuf.coredump.cx/tangled/">The Tangled Web</a> has an entire chapter dedicated to the URL.</p>
<h4>HTML</h4>
<p><a href="https://en.wikipedia.org/wiki/Cross-site_scripting">XSS</a>
(Cross-Site Scripting) is a vulnerability where an attacker is able to inject JavaScript into a page, which is then executed in a victim's browser.
It's a subset of the attacks against poorly serialized HTML.
The attack is made possible by the fact that HTML mingles mark-up and code.
In fact, HTML is composed of a number of different data formats within a single document:</p>
<ul>
<li>HTML Tags</li>
<li>JavaScript</li>
<li>CSS</li>
<li>URIs</li>
</ul>
<p>When represented in a object structure, we refer to the page as a DOM (document object model).
However to get that page to the browser, it's serialized as a string and transmitted over HTTP.
It is in that process that XSS is made possible.
To make this concrete, let's take a look at an example.
What happens if an attacker includes a script tag in the URL <code>arg</code> parameter?
(Again, this is a simplistic example. There are significantly more malicious XSS attacks.)</p>
<div class="highlight"><pre><span></span><span class="x"><span></span><span class="cp"><?php</span> <span class="k">echo</span> <span class="nv">$_GET</span><span class="p">[</span><span class="s1">'arg'</span><span class="p">];</span> <span class="cp">?></span><span class="x"></span></span>
<span class="x">becomes</span>
<span class="x"><span>Hello! <script>alert(1);</script></span></span>
</pre></div>
<p>The user content altered the structure of the document.
To fix this, we could escape the variable prior to output.
However, that is simply string concatenation.
The output is exactly the same.</p>
<div class="highlight"><pre><span></span><span class="x"><span></span><span class="cp"><?php</span> <span class="k">echo</span> <span class="nb">htmlentities</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'arg'</span><span class="p">]);</span> <span class="cp">?></span><span class="x"></span></span>
<span class="x">is the same as</span>
<span class="cp"><?</span> <span class="k">echo</span> <span class="s1">'<span>'</span> <span class="o">.</span> <span class="nb">htmlentities</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'arg'</span><span class="p">])</span> <span class="o">.</span> <span class="s1">'</span>'</span><span class="p">;</span>
</pre></div>
<p>This means, it falls prey to all the same risks as above.
One missed escape, or escaping for the wrong context, and we have a vulnerability.</p>
<div class="highlight"><pre><span></span><span class="x"><span href="</span><span class="cp"><?php</span> <span class="k">echo</span> <span class="nb">htmlentities</span><span class="p">(</span><span class="nv">$_GET</span><span class="p">[</span><span class="s1">'arg'</span><span class="p">]);</span> <span class="cp">?></span><span class="x">">...</span></span>
<span class="x">becomes</span>
<span class="x"><span href="javascript:alert(1);">...</span></span>
</pre></div>
<p>But wait! XSS is <em>really</em> because a programmer failed to check for JavaScript within the user inlined content.
That's true, in the implementation of HTML we know and love.
If the issue wasn't truly with the failure to preserve the document structure, we could simply introduce a tag which would disable all scripts within the child element.
That hasn't happened, because the issue is really about the injection.
(As an aside, avoid using HTML for user supplied markup. It's a losing battle.)</p>
<p>So what do I recommend? Templating engines.
(Keep in mind, templating engines may <em>not</em> automatically escape variables within your output.
Escaping must be configured on a per-engine basis.)</p>
<div class="highlight"><pre><span></span><span class="p"><</span><span class="nt">span</span><span class="p">></span>{{ input.arg }}<span class="p"></</span><span class="nt">span</span><span class="p">></span>
</pre></div>
<p>That having been said, automatic escaping is typically <em>not</em> a panacea.
Why? The escaping is normally context unaware, which means it's performed for HTML tags.
If your templating engine allows bad markup, it's doubtful that it understands the context for which it's escaping.
Where can this bite you?</p>
<ol>
<li>Tag Attributes</li>
<li>URIs</li>
<li>CSS</li>
<li>JavaScript <br /> (It is rarely safe to output content into a script tag. Avoid this whenever possible.)</li>
</ol>
<p>Another even safer approach is to construct your page as a DOM.
This will ensure tags, attributes, and possible URIs are properly escaped, but probably not CSS or Javascript.
Almost no frameworks actually do this, because it's cumbersome and (probably) more cpu/memory costly.</p>
<p>Tangential from string concatenation, is a perfect templating engine enough?
Unfortunately, browsers suck (from a security perspective).
You could trace this back to the browser wars, where browsers which refused to render bad markup were labeled at fault.
Regardless of the history, browsers have extremely "flexible" parsers.
As a result, even if a document looks rightish, it might still contain an XSS.
While I generally do not recommend sanitizing user input (it feels too much like a blacklist), input destined for HTML is an exception for the reasons outlined above.
See <a href="https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet#RULE_.236_-_Sanitize_HTML_Markup_with_a_Library_Designed_for_the_Job">OWASP's Sanitization Recommendations</a> for candidate libraries.</p>
<p>You could easily write a book on injection attacks against HTML. For that reason, I'm going to stop here. Want to know more?</p>
<ul>
<li><a href="http://html5sec.org/">HTML5 Security Cheatsheet</a></li>
<li><a href="https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet">XSS Filter Evasion Cheat Sheet</a></li>
<li><a href="http://lcamtuf.coredump.cx/postxss/">Postcards from the post-XSS world</a></li>
<li><a href="http://www.slideshare.net/x00mario/the-innerhtml-apocalypse">The innerHTML Apocalypse</a></li>
<li><a href="http://lcamtuf.blogspot.co.uk/2010/10/http-cookies-or-how-not-to-design.html">HTTP cookies, or how not to design protocols</a></li>
<li><a href="http://lists.webappsec.org/pipermail/websecurity_lists.webappsec.org/2006-March/000843.html">Path Insecurity</a></li>
<li><a href="http://www.xdxa.org/presentations/xss-csrf/">My XSS/CSRF Slide Deck</a></li>
</ul>
<h4>JSON</h4>
<p>To avoid making this article much longer, I'm not going to break out a JSON
example. However, I do want to mention it, because I have frequently seen
engineers construct JSON from a string. Don't do this.</p>
<h3>Embedded Variables</h3>
<p>Note, there is no distinction between embedding a variable and string concatenation.
Neither of the following two examples address the serialization problem:</p>
<div class="highlight"><pre><span></span><span class="cp"><?</span> <span class="s2">"</span><span class="si">$first</span><span class="s2"> </span><span class="si">$last</span><span class="s2">"</span> <span class="o">===</span> <span class="nv">$first</span> <span class="o">.</span> <span class="s1">' '</span> <span class="o">.</span> <span class="nv">$last</span><span class="p">;</span>
</pre></div>
<p>Or with sprintf like substitution:</p>
<div class="highlight"><pre><span></span><span class="s2">"</span><span class="si">%s</span><span class="s2"> </span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">person</span><span class="o">.</span><span class="n">first_name</span><span class="p">,</span> <span class="n">person</span><span class="o">.</span><span class="n">last_name</span><span class="p">)</span>
</pre></div>
<h3>Logging</h3>
<p>Before we conclude, I want to make a special note with regards to logging.
In my code, casual string concatenation most frequently occurs in logging statements.
Logs are typically loosely formatted, newline delimited files.
Loosely structured output is <em>mostly</em> fine when intended for human consumption.
However, this casual serialization format is a nightmare for log parsers.</p>
<p>For this reason, one must be careful when logging output which will eventually be consumed by some downstream process.
While not strictly the responsibly of the logger, HTML log viewers have been susceptible to XSS attacks <a href="http://www.cvedetails.com/cve/CVE-2012-2094">in the past</a>.</p>
<p>See <a href="http://cwe.mitre.org/data/definitions/117.html">CWE-117</a> and
<a href="http://capec.mitre.org/data/definitions/106.html">CAPEC-106</a> for more
information.</p>
<h3>Clarification</h3>
<p>This concept is not new or innovative.
The weakness I'm describing is actually
<a href="http://cwe.mitre.org/data/definitions/707.html">CWE-707: Improper Enforcement of Message or Data Structure</a>,
and it is not exclusive to string concatenation or even strings.
I wag my finger at string concatenation, because it makes these mistakes easy.
And consequentially, common.</p>
<h3>Hyperboles</h3>
<p>The title is mostly meant as tongue and cheek, but I'm quite serious in the severity of this topic.
In my opinion there are only two places string concatenation should occur:</p>
<ol>
<li>Serialization/Deserialization Libraries</li>
<li>Unformatted Data</li>
</ol>
<p>Many security issues simply do not have an easy solution, e.g. <a href="https://en.wikipedia.org/wiki/Side_channel_attack">side channel attacks</a>.
However, if engineers consistently use libraries for serialization, the majority of injection based attacks will simply go away.</p>
<p>Is it possible to write secure code with concatenation? Yes.
However, this code will almost always be brittle.
You might understand the security considerations, but the next engineer probably will not.
Writing secure code isn't just preventing a certain type of attack.
It's following best practice throughout the entire code base to set the standard which avoids careless mistakes.</p>Vertical Rhythmtag:xdxa.org,2013-11-17:/2013/vertical-rhythm2013-11-17T17:54:00ZBenjamin Heiskellhttp://xdxa.org/ben.heiskell@xdxa.org<p>I've always found interface usability fascinating. Subtle differences in
coloring, spacing, and layout can drastically impact the functionality of your
application. I think it's important for programmers to understand some of the
basic principals of usability.</p>
<p>A few years back, I read about a design concept referred to as Vertical Rhythm.
The way I like to think about it is to imagine a web page as a sheet of lined
paper. All text is written upon the lines, which is referred to as the
baseline. A heading could pass through multiple lines, but it shouldn't impact
the following text's ability to align with the baseline.</p>
<p>Why go through the effort of creating a repetitive baseline? People are
extremely good at pattern recognition. If we utilize this skill set, our
interfaces will feel natural to use. When skimming text, a consistent baseline
makes it easier to read, because the text lands in the location expected by our
brains.</p>
<p>I set out today with the intent to write a script to assist verification of a
page's baseline, but it seems someone has already accomplished this.
<a href="http://keyes.ie/things/baseliner/">Baseliner</a> provides a bookmarklet. When
executed on a page, it will overlay a series of horizontal lines. These lines
can be adjusted to match your page's line-height and layout. At the time of
writing, this page has a grid size of 21 with an offset of 15.</p>
<p>Like all things CSS, numerous styling issues can arise. When styling your web
application, keep the following in mind:</p>
<ul>
<li>Top margins will collapse into previous tag's bottom margin.</li>
<li>Images may not be a multiple of the line-height.</li>
<li>Headings whose line-height is not a multiple of the baseline line-height will cause issues if wrapped.</li>
</ul>
<p>When I initially discovered vertical rhythm, there wasn't much written on the
web covering the subject. That has changed. If this interests you, I suggest
check out the following:</p>
<ul>
<li><a href="http://coding.smashingmagazine.com/2012/12/17/css-baseline-the-good-the-bad-and-the-ugly/">CSS Baseline: The Good, The Bad and The Ugly</a></li>
<li><a href="http://www.creativebloq.com/maintain-vertical-rhythm-css-and-jquery-2124274">Maintaining Vertical Rhythm</a></li>
</ul>
<p>How important is this really? One of my favorite browser extensions,
<a href="http://readability.com/">Readability</a>, which reformats poorly laid out blogs,
doesn't maintain vertical rhythm. Nor does Wikipedia. Ironically, neither does
the Baseliner page or the two links above. In fact, I couldn't find a single
site that followed this advice.</p>
<p>Does that mean it's wrong? The lack of a consistent baseline on the web could
be due to the difficulties in establishing rhythm with CSS. Or, it could be
that there are more optimal spacing practices. In the end, I don't really know
whether it's right or wrong. Regardless, this principle isn't dogma. It's a
tool, just like the color wheel. For someone who is not a designer, I find it
useful in establishing an application's foundation. Next time you're working on
a layout, give it a try and see what you think.</p>Vagranttag:xdxa.org,2013-04-28:/2013/vagrant2013-04-28T11:21:00ZBenjamin Heiskellhttp://xdxa.org/ben.heiskell@xdxa.org<p>I love the notion of a clean, repeatable install. In my side projects, I've
historically accomplished this through strict documentation practices and
directory organization. However, this process inevitably breaks down for me
when a machine becomes multi-purpose.</p>
<p>Either locally or in the cloud, I'll end up installing packages, hacking
together configuration, or otherwise making the environment murky. In fact,
the server that currently hosts this blog is a perfect example. This instance
hosts this site, riiga.net, and has been a sandbox for toy projects I've worked
on over the past two years.</p>
<p>While I'm reasonably confident I can redeploy this machine within a couple of
hours, it would be far more flexible if I could do this in minutes. Or even
better, selectively re-deploy projects to alternate hosts.</p>
<p>For this reason, <a href="http://www.vagrantup.com/">Vagrant</a> has become my new
favorite toy. Vagrant provides simple VM construction and provisioning. This
enables easy provisioning of development environments, testing large system
upgrades, and migrating projects to alternative cloud providers.</p>
<p>To begin exploring the world of automated provisioning, I decided to create a
VM that would serve the <a href="http://docs.services.mozilla.com/howtos/run-sync.html">Mozilla Sync server</a>.
I've hosted the <a href="https://github.com/bheiskell/vagrant-mozilla-sync">Vagrant Mozilla Sync Configuration</a>
on my GitHub. (Disclaimer: this was a warm-up project. All dependencies are
automatically pulled from other source controls. Meaning, this will likely
break in the future.)</p>
<p>Isn't this overkill? It certainly seemed so... that is, until the first VM
corrupted. When that happened, I simply re-provisioned a new instance. About an
hour later, I was back up and running with minimal engineering effort.</p>
<p>What next? I've been itching to try Linux Mint. And what better way than to
automatically provision my standard desktop deployment!</p>Acrylamidtag:xdxa.org,2013-04-13:/2013/acrylamid2013-04-13T19:09:00ZBenjamin Heiskellhttp://xdxa.org/ben.heiskell@xdxa.org<p>For a long while I've wanted to host this blog rather than utilize a service
like Google's blogger. My biggest hesitation was blogging software tends to
be a common means of getting pwned. I could write straight HTML, but then
the content is mingled with the markup - it feels dirty. FrontPage you say?
Well, that's just not cool enough.</p>
<p>Enter <a href="https://github.com/posativ/acrylamid">Acrylamid</a>, a simple, but powerful
means of generating a static website. Out of the box, it supports:</p>
<ul>
<li><a href="http://daringfireball.net/projects/markdown/">Markdown</a></li>
<li><a href="http://jinja.pocoo.org/docs/">Jinja2</a> templating</li>
<li>Code highlighting with <a href="http://pygments.org/">Pygments</a></li>
</ul>
<p>To convert the contents of the old blog, I downloaded it using <a href="https://en.wikipedia.org/wiki/Google_Takeout">Google Takeout</a>.
Through a combination of xpath, <a href="https://github.com/aaronsw/html2text">html2text</a>,
and some python hackery, I converted the previous entries to markdown.</p>
<p>For styling, I'm utilized the <a href="http://www.initializr.com/">responsive template from Initializr</a>.
While I've used both Bootstrap and their HTML5 reset in the past, this is the
first time I've gone responsive. It's surprisingly straight forward and seems
to work well on my android devices.</p>
<p>But wait! Where are the comments? Sorry folks - no comments. I debated about
using a service like <a href="http://disqus.com/">Disqus</a>, but I just dislike the idea
of including a third-party service (and consequentially tracking) on my site.
If you have feedback, see the about page. There are numerous means of
communicating with me there.</p>CakePHP's error handlingtag:xdxa.org,2011-02-17:/2011/cakephp-s-error-handling2011-02-17T09:04:00ZBenjamin Heiskellhttp://xdxa.org/ben.heiskell@xdxa.org<p>Whenever possible, I like to trigger the appropriate HTTP status code for an
error. CakePHP has a mechanism to throw 404 errors by simply calling:</p>
<div class="highlight"><pre><span></span><span class="cp"><?php</span>
<span class="nv">$this</span><span class="o">-></span><span class="na">cakeError</span><span class="p">(</span><span class="s1">'error404'</span><span class="p">);</span>
</pre></div>
<p>This is handy when a request to a view action passes an id that doesn't
actuallyexist. However, what about 403 or 500 errors? If you're like me, you
probably stumbled upon <a href="http://book.cakephp.org/view/154/Error-Handling">AppError in the CakePHP book</a>.</p>
<p>I defined a simple error403 method, and used it where appropriate throughout
my application. But when I rolled out to production, every 403 became a 404!
Upon a bit of digging around in the code, I found the root of the problem in
the ErrorHandler constructor. In version 1.2.9, you can find this in
cake/libs/error.php:</p>
<div class="highlight"><pre><span></span><span class="cp"><?php</span>
<span class="k">if</span> <span class="p">(</span><span class="nv">$method</span> <span class="o">!==</span> <span class="s1">'error'</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">Configure</span><span class="o">::</span><span class="na">read</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$method</span> <span class="o">=</span> <span class="s1">'error404'</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">isset</span><span class="p">(</span><span class="nv">$code</span><span class="p">)</span> <span class="o">&&</span> <span class="nv">$code</span> <span class="o">==</span> <span class="mi">500</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$method</span> <span class="o">=</span> <span class="s1">'error500'</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>(Side note: Although in production error500 technically can be called, $code
doesn't appear to be declared in the constructors scope. Also, the method
error500 isn't actually defined, which adds to my confusion.)</p>
<p>In production, all methods translate to either 404 or 500 errors! Now let me
note, this does not appear to be mentioned anywhere in the book... So, how do
we resolve this? Well, I found <a href="http://nuts-and-bolts-of-cakephp.com/2008/08/29/dealing-with-errors-in-cakephp/">someone having a similar problem</a>.</p>
<p>Teknoid sets debug to 1 when the error handler constructor is called. This
causes the error handler to believe it's in debug mode and run whatever error
method is passed its way.</p>
<p>But, there's a very important distinction. Teknoid overrides his
_outputMessage method to send an email to himself, not to display errors to
users. If you were to simply set debug to 1 in the constructor, all CakePHP
errors would be displayed to the user. This is why only error404 is allowed in
vanilla CakePHP.</p>
<p>To resolve this, I created a white-list of allowed error handlers. When these
error handlers are requested, I enable debug mode.</p>
<div class="highlight"><pre><span></span><span class="cp"><?php</span>
<span class="k">class</span> <span class="nc">AppError</span> <span class="k">extends</span> <span class="nx">ErrorHandler</span> <span class="p">{</span>
<span class="k">var</span> <span class="nv">$allowedMethods</span> <span class="o">=</span> <span class="k">array</span><span class="p">(</span>
<span class="s1">'error403'</span><span class="p">,</span>
<span class="s1">'error500'</span><span class="p">,</span>
<span class="p">);</span>
<span class="k">function</span> <span class="nf">__construct</span><span class="p">(</span><span class="nv">$method</span><span class="p">,</span> <span class="nv">$messages</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">in_array</span><span class="p">(</span><span class="nv">$method</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-></span><span class="na">allowedMethods</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">Configure</span><span class="o">::</span><span class="na">write</span><span class="p">(</span><span class="s1">'debug'</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">parent</span><span class="o">::</span><span class="na">__construct</span><span class="p">(</span><span class="nv">$method</span><span class="p">,</span> <span class="nv">$messages</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">function</span> <span class="nf">error403</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">// I do some logging here to audit</span>
<span class="c1">// who made the forbidden request</span>
<span class="nb">header</span><span class="p">(</span><span class="s2">"HTTP/1.1 403 Forbidden"</span><span class="p">);</span>
<span class="nv">$this</span><span class="o">-></span><span class="na">controller</span><span class="o">-></span><span class="na">set</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
<span class="s1">'name'</span> <span class="o">=></span> <span class="nx">__</span><span class="p">(</span><span class="s1">'403 Forbidden'</span><span class="p">,</span> <span class="k">true</span><span class="p">),</span>
<span class="s1">'title'</span> <span class="o">=></span> <span class="nx">__</span><span class="p">(</span><span class="s1">'403 Forbidden'</span><span class="p">,</span> <span class="k">true</span><span class="p">),</span>
<span class="p">));</span>
<span class="nv">$this</span><span class="o">-></span><span class="na">_outputMessage</span><span class="p">(</span><span class="s1">'error403'</span><span class="p">);</span>
<span class="p">}</span>
<span class="o">...</span> <span class="nx">error500</span> <span class="k">and</span> <span class="nx">so</span> <span class="nx">on</span> <span class="o">...</span>
<span class="p">}</span>
</pre></div>
<p>This is less than ideal, because turning on debug may have other implications
throughout your application. We could reimplement (or copy and paste) the
constructor with allowedMethods in mind, but that feels even more hack to me.</p>Asus P4C800 Rev 2tag:xdxa.org,2009-11-18:/2009/asus-p4c800-rev-22009-11-18T09:49:00ZBenjamin Heiskellhttp://xdxa.org/ben.heiskell@xdxa.org<p>This board has been my latest personal hell. Back in the year 2005, my Asus
P4C800 Deluxe fried. After taking their time, Asus sent me a replacement
board. I simply assumed that it was a Deluxe and reinstalled it.
Unfortunately, it was actually a P4C800 Rev 2. There are three models of the
P4C800: P4C800, P4C800 deluxe, and P4C800-e deluxe. From what I can tell
online, the Rev 2 is actually the e deluxe, but it looks like a hacked
together mix between the P4C800 and the e deluxe.</p>
<p>This is where I made a mistake. One night when trying to get suspend to work
in Linux, I decided to flash this board. I flashed it without checking what
bios version was already on there. Stupid. Worse, since I knew it wasn't the
deluxe (because the updater rejected the bios), I assumed it was the e deluxe.
As would be expected, after the flash, the system wont boot. Flash forward a
few days, and I've managed to force a flash downgrading the system to a
P4C800.</p>
<p>Now looking back, I honestly can't remember what the board was originally and
which bios I first forced onto the board. Never flash bios when tired and in a
rush. I still can't believe I did that. Anyways, the system suffered from
random shutoffs. I assumed this was due to the flash. (Honestly I can't be
sure one way or the other now.) Over time these flickers grew increasingly
annoying. So, I tried another flash. That time I managed to brick the board.</p>
<p>Yesterday I received two replacement bios chips. (One is a backup for hot
swapping.) The latest version of the P4C800-e deluxe bios works, but it wont
reboot. The latest version of the P4C800 bios works and will reboot. Both
suffer from the intermittent shutoffs, and both have bios errors referring to
the IRQ routing table. At this stage, I'm pretty sure the problem either isn't
a bios issue or at least isn't a bios issue that I can resolve.</p>
<p>I installed this board into a new case with new hardware and the shutoff
problems ensued. This has brought me to the conclusion that the problem has to
be with the board. Removing all hardware except the bare bones still results
in the shutoff. Another irritation is the problem wont normally occur when the
system is idle. Also odd is the problems happen most in XP, less in Ubuntu,
and the least in Windows 7. I don't know what that means exactly, but it
suggests that whatever is triggering the problem may be a deprecated technique
that modern OS's don't use. Though it may be that the board is just getting
old and needs to be tossed.</p>
<p>However, the two things that keep bring me back to suspecting the bios are:
the coinciding timing of the first shut offs / bios flash and the fact that
the board looks like a P4C800 with a Rev 2 sticker slapped on it instead of a
P4C800-e deluxe board. There might be some bios out there that will stabilize
this system that I have yet to find. I should probably contact Asus.</p>
<p>Although I'm sure this isn't the conclusion to this story, it should be noted
that suspend still doesn't work. :(</p>
<p>Edit - 28/10/2010:
This is the conclusion, because the pieces are now sitting in a box. My
brother upgraded and let me keep his old hardware, which is newer than the
P4C800. I'm now looking for a good way to get rid of this old hardware.</p>GBA Development on a Mactag:xdxa.org,2009-10-30:/2009/gba-development-on-a-mac2009-10-30T08:19:00ZBenjamin Heiskellhttp://xdxa.org/ben.heiskell@xdxa.org<p>In my media devices architecture class, we are developing on the GBA.
Unfortunately, most of the students are developing on windows machines, which
leaves me and a few others the odd men out. On macs, we're using devkitarm as
our compiler with a provided makefile. Unfortunately, the Makefile had a few
flags misconfigured.</p>
<p>The stock makefile worked perfectly until we started dealing with sound. The
problem was two fold:</p>
<ol>
<li>Setting the interrupt handler would cause the GBA to reset</li>
<li>Sound files larger than thirty seconds would overflow the ewram</li>
</ol>
<p>There were two macros in the make file that were used for compiling and
linking respectively:</p>
<div class="highlight"><pre><span></span><span class="nv">MODEL</span> <span class="o">=</span> -mthumb -mthumb-interwork
<span class="nv">SPECS</span> <span class="o">=</span> -specs<span class="o">=</span>gba_mb.specs
</pre></div>
<p>The model affects how the assembly is compiled, and the specs defines the way
the linker will link the c objects together. I figured out that mthumb wasn't
needed by looking at the windows makefile. Removing it resolved the rebooting
issue.</p>
<p>I knew that the overflow had to do with the linker, because that's where it
failed. I was at the point where I was actually trying to modify the linker
script to manually force the audio memory to go to the right region when I
realized there was a second gba .specs file. Switching to that file resolved
the issue.</p>
<p>The resulting makefile macros are as followed:</p>
<div class="highlight"><pre><span></span><span class="nv">MODEL</span> <span class="o">=</span> -mthumb-interwork
<span class="nv">SPECS</span> <span class="o">=</span> -specs<span class="o">=</span>gba.specs
</pre></div>
<p>I am not a compiler expert. So, I can't tell you the full implications of
changing these flags, but it did work for me. I'm still working on what I
believe to be a compiler bug and plan to submit a bug report soon. If it turns
out to be interesting, I'll make another post here.</p>Microsoft Natural Ergonomictag:xdxa.org,2009-10-26:/2009/microsoft-natural-ergonomic2009-10-26T17:09:00ZBenjamin Heiskellhttp://xdxa.org/ben.heiskell@xdxa.org<p>I decided I wanted to enable the zoom key on my "Microsoft Natural Ergonomic
Keyboard 4000" under Linux. Ideally, this would be used for scrolling up and
down a page instead of triggering Compiz's zoom feature.</p>
<p>Unfortunately, the kernel fix is triaged on <a href="https://bugs.launchpad.net/ubuntu/+source/linux/+bug/264287">ubuntu's bugtracker</a>.
This of course meant recompiling the kernel manually (or semi-manually since
Ubuntu makes this task relatively easy). You'll notice, if you care to check,
that there is a patch in the bugtracker to remap the zoom and spellcheck keys
to something that xev (and therefore X11) can read.</p>
<p>If you don't know how to recompile your kernel, this fix probably isn't for
you. However, should you choose to proceed anyways (or if you're just not
familiar with recompiling your kernel under Ubuntu), you can find
<a href="https://help.ubuntu.com/community/Kernel/Compile#AltBuildMethod">instructions for recompiling Ubuntu's kernel here</a>.</p>
<p>Once you've downloaded and uncompressed the source, edit "/usr/src/linux-
source-*/include/linux/input.h". Search for ZOOMIN, ZOOMOUT, and SPELLCHECK
and change these constants to match the following:</p>
<div class="highlight"><pre><span></span><span class="cp">#define KEY_ZOOMIN 246 </span><span class="cm">/* AC Zoom In */</span><span class="cp"></span>
<span class="cp">#define KEY_ZOOMOUT 247 </span><span class="cm">/* AC Zoom Out */</span><span class="cp"></span>
<span class="p">...</span>
<span class="cp">#define KEY_SPELLCHECK 235 </span><span class="cm">/* AL Spell Check */</span><span class="cp"></span>
</pre></div>
<p>Keep in mind that if some other input device already uses these key codes,
then you'll have a conflict. Otherwise, once you've recompiled your kernel,
you should be able to access these buttons in Gnome now.</p>
<p><strong>Additional Information</strong></p>
<p>What does this do and why do we do it? From my understanding, the reason this
is a problem is X11 can't read key codes above a 255. Although this is a bug
with X11, we can modify the kernel to remap these keys to a value lower. This
enables X11 to read them and thus Gnome to use them.</p>
<p>I dislike patch files for problems that are not going to be fixed, because
they often break on the next kernel release. This is why I chose to manually
edit the file instead of offer a patch file</p>
<p>If you recompile your kernel, you'll likely have to recompile any other third
party drivers you have installed. For instance, I had to recompile my Nvidia
driver after rebooting. I also had to purge the nvidia-common package.</p>
<p><strong>Mapping to Page Up / Down</strong></p>
<p>Next, I wanted to map 246 and 247 to page up and page down respectively. To do
this, I edited my ~/.Xmodmap file to include:</p>
<div class="highlight"><pre><span></span>keycode 254 = Prior
keycode 255 = Next
</pre></div>
<p>You can activate this by running "xmodmap ~/.Xmodmap" or adding the command to
startup applications. However, the next time you log in, I think you'll get
an option to enable this automatically without having to add it to startup
apps. (I haven't setup xmodmap in a while, because I already use it to swap
caplocks and escape... yes, I'm a vim user.)</p>
<p>Edit:
I should note that I have since reverted to a stock kernel. For some reason
the recompiled kernel would kill my mouse periodically.</p>Mac OS X Snow Leopard Port Winetag:xdxa.org,2009-10-21:/2009/mac-os-x-snow-leopard-port-wine2009-10-21T04:56:00ZBenjamin Heiskellhttp://xdxa.org/ben.heiskell@xdxa.org<p>Currently, wine is not happy with my 64bit upgrade to Snow Leopard. Just for
the record, I find no fault in either port or wine for this, because I was an
early adopter. I upgraded port with a simple reinstall. (I know there are more
elegant solutions than this, but I was being lazy.) After upgrading port,
installing wine resulted in the following error:</p>
<div class="highlight"><pre><span></span>Error: wine 1.0.1 is not compatible with Mac OS X 10.6 or later. Until wine 1.2 is released, please install wine-devel instead.
</pre></div>
<p>This is pretty straightforward. Obviously, the next step was "port install
wine-devel". However, I was promptly stopped with another error in the
following format:</p>
<div class="highlight"><pre><span></span>Error: You cannot install wine-devel <span class="k">for</span> the architecture<span class="o">(</span>s<span class="o">)</span> i386
Error: because /opt/local/lib/libjpeg.dylib only contains the architecture<span class="o">(</span>s<span class="o">)</span> x86_64.
Error: Try reinstalling the port that provides /opt/local/lib/libjpeg.dylib with the +universal variant.
Error: Target org.macports.extract returned: incompatible architectures in dependencies
</pre></div>
<p>I'm not too familiar with port or the complexities of 64bit architectures
working with 32bit binaries, but I do understand the principle behind OS X's
universal (fat) binaries. After googling around a bit I discovered that the
way to compile in the universal format is with the following command:</p>
<div class="highlight"><pre><span></span>sudo port upgrade --enforce-variants jpeg +universal
</pre></div>
<p>The part that hung me up was figuring out which package was associated with
that file. After digging around in the man page I found the following
solution:</p>
<div class="highlight"><pre><span></span>port provides /opt/local/lib/libjpeg.dylib
</pre></div>
<p>That's it! Just keep installing the dependencies and retrying "sudo port
install wine-devel". After about eight dependencies are recompiled, you'll be
finished. Good luck.</p>