strip_tags is just awful

strip_tags is possibly the worst of all the builtin PHP functions. It doesn’t even remotely do what it says. It is absolutely useless on user input because it strips everything from the first “<” it sees to the next “>” so if your input is

"<p>I <3 Monkeys</p>

its output is

I 

!!! And what else are you stripping tags from apart from user input? Avoid.

badmatch CRASH REPORT couch_file:init/1

I got this Couch DB crash running a view:

Error: EXIT

{{badmatch,[]},
 [{couch_query_servers,new_process,3,
                       [{file,"couch_query_servers.erl"},{line,472}]},
  {couch_query_servers,lang_proc,3,
                       [{file,"couch_query_servers.erl"},{line,462}]},
  {couch_query_servers,handle_call,3,
                       [{file,"couch_query_servers.erl"},{line,334}]},
  {gen_server,handle_msg,5,[{file,"gen_server.erl"},{line,578}]},
  {proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,227}]}]}

This is caused by “language”: “JavaScript” in the view. It must be “javascript” (case sensitive) or omitted for javascript queries. Not sure where I copied that from.

Loading Dependencies in PhantomJS without using a Webserver

We run our javascript QUnit unit tests “headless” using the amazing PhantomJS. Originally our dependency loading code was overridden as a no-op within the tests. But that began to cause problems and require tests to run in a certain order and other Bad Things.

Within the WebPage environment in PhantomJS it is possible to form <script> tags and load code from a webserver, but not so easy to keep things running entirely from the commandline. Especially when you also want to run the same tests in the browser in QA (not everything that passes in WebKit passes in IE8, as if you didn’t know that).

To make this work I overrode the dependency loading code so that it just stores strings of dependencies in a variable xq.required. Then:


...

// Load the tests.
for (var i = 0; i < sources.length; i++) {
    _.page.injectJs(sources[i]);
}

// Now that we've loaded some tests we will have registered some
// dependencies (with require calls in the page).  Load the
// dependencies, recursively if they themselves have dependencies.
_.loadDependencies(_.page);

...

// Loop over the known dependencies and load them.  Also load any of their
// dependencies and so on, turtles all the way down.
_.loadDependencies = function(page) {
    var loaded = [];
    while (true) {
        // Ask the page what dependencies it has
        toLoad = page.evaluate(function () {
            return window.xq.required; // executes inside page, not phantom
        });

        // Diff toLoad with loaded to get stuff that hasn't been loaded yet
        toLoad = toLoad.filter(function(i) { return (loaded.indexOf(i) < 0); });
        if (toLoad.length === 0) {
            break;
        }

        // Load the stuff that hasn't been loaded yet
        for (var i = 0; i < toLoad.length; i++) {
            _.loadByNamespace(page, toLoad[i]);
        }
        // Add what we just loaded to the list of stuff we've already loaded
        loaded = loaded.concat(toLoad);
    }
}

Where loadByNamespace converts its second argument to a file path and loads it into the first argument with page.injectJs.

Now all the dependencies are loaded we can run the tests and report the results.

Google Street View Image API

One of the many cool APIs available through Google Maps is the Street View Image API. This gives you full access to the images taken by the Google vans that photograph streets.

The API is dead simple in the basic form, just a URL:

http://maps.googleapis.com/maps/api/streetview?size=WIDTHxHEIGHT&location=LOCATION&sensor=false

(The required “sensor” param tells Google if you are getting the location from a GPS device or similar – probably a privacy thing.)

The images are not necessarily spectacular brochure shots:

http://maps.googleapis.com/maps/api/streetview?size=400x400&location=Parliament+Square,+London&sensor=false

Unspectacular Street View of Parliament Square, London

but it is a useful API for any app that is displaying places that a user might not have been to before. It can both give them an idea of it’s the kind of place they are looking for and help them find it. Here’s an example, a local keycutters:

http://maps.googleapis.com/maps/api/streetview?size=400x400&location=Timpson,+Victoria+Station,+London&sensor=false

Street View of Timpson key cutters at Victoria Station, London

CoffeeScript Web App Framework

I’ve been working on a CoffeeScript web app in RailwayJS which is a rails-alike framework for nodejs built on top of Express.

One cool thing about RailwayJS is that you can write most of your code (not views?) in CoffeeScript instead of JavaScript. The generators, etc. will do the right thing if you give them the --coffee switch.

RailwayJS also has ORM with MongoDB and localization baked in.

#!/usr/bin/env coffee

app = module.exports = require('railway').createServer()

if not module.parent
  port = process.env.PORT or 3000
  app.listen port
  console.log "Railway server listening on port %d within %s environment", port, app.settings.env

App Screen Shot

History (Again)

[bakert@fenchurch ~]$ history | awk '{a[$2]++}END{for(i in a){print a[i] " " i}}' | sort -rn | head
24899 git
9575 vi
7366 cd
3929 ls
2517 php
2162 mate
2125 rsync
2022 cat
1950 ssh
1938 make

Compare to four years ago. New: git, php, mate, rsync, cat, make. Climbers: ls. Same: cd, ssh. Fallers: vi. Old: u, ruby, svn, td, mysql, gd.

Newlines at the end of files

For

Against

  • git considers a trailing newline a whitespace error.
  • Trailing whitespace is easily lost when, for example, exchanging patches via email.
  • A newline after a closing “?>” in PHP can cause problems with header() (although closing tags are no longer required in PHP).
  • It uses one more byte.

You Know You Are Trying to Do Too Much in a Bash One-Liner When …

find ~/bazel/src/main/webapp/lib -type f | grep -v "lib/deps/" | grep -v "lib/ext/" | grep -v "XG_MessageCatalog_" | xargs -I{} -L1 sh -c "echo {}; phpcs -d memory_limit=1024M -p -n -s --standard=/Users/bakert/Desktop/BazelCodingStandard {}"

Edit: Better:

#!/bin/env ruby

BAZEL_HOME = '/Users/bakert/bazel'
STANDARD_PATH = '/Users/bakert/Desktop/BazelCodingStandard'
VERBOSE = false

def main
  exclude_patterns = [ /XG_MessageCatalog_/, /\/lib\/deps\//, /\/lib\/ext\// ]
  files = Dir.glob("#{BAZEL_HOME}/src/main/webapp/**/*").reject do |f|
    exclude_patterns.any? { |p| f.match(p) } \
      || ! File.file?(f) \
      || File.extname(f) != '.php'
  end
  files.each do |f|
    puts f if VERBOSE
    print %x[phpcs -d memory_limit=1024M -n -s --standard=#{STANDARD_PATH} #{f}]
  end
end

main