Daniel Rench

programming, etc.

Git on GoDaddy

“Could you help me with my web site?”

“Where’s it hosted?”

“GoDaddy! Here’s the FTP login.”

Don’t get depressed. It’s possible to make even GoDaddy’s entry-level Linux shared hosting tolerable by enabling ssh and installing git, even though they seem to go out of their way to make it difficult.

Phemca, a JavaScript-to-PHP5 Compiler (Written in Ruby)

Why am I writing a JavaScript-to-PHP5 compliler (in Ruby)?

PHP is everywhere and is inescapable these days.

A typical hosting plan includes PHP. Maybe not PHP 5.3 yet, but definitely some version. And “regular people” like PHP, or more accurately, they like stuff written in PHP: WordPress, Drupal, Magento, SugarCRM, and just about every other common CMS, shopping cart, and bulletin board system.

Irregular people (programmers) typically aren’t as keen on PHP. Programmers may not agree on many things, but they do tend to think JavaScript is not too bad, and that’s high praise. It’s everybody’s 2nd favorite language.

Backing Up MySQL: The Last Resort Method

One of the first things I do when taking on maintenance for a web site is to do my own backups. This usually means database snapshots, and that database is usually MySQL. Unfortunately I am rarely allowed a shell login to the server, and sometimes not allowed to connect to MySQL from outside the host’s network either. But one thing I can always expect is access to PhpMyAdmin, the virtually-standard web frontend for MySQL administration.

That’s fine, but I need my backups automated. I found a Python program that screen-scraped PhpMyAdmin, but I ran into a big problem: the PhpMyAdmin installation for one site had a robots.txt file at its root that excluded everything. Python’s urllib2 honored the robots.txt rules and I was not finding anything in its documentation on how to override it. It was time to fall back to something that would bend to my will: Perl 5 with WWW::Mechanize.

coordinate.js Adds Interesting Properties to Boring HTML Tables

Did you ever wish you could address HTML table cells by X and Y coordinates?

1
2
3
4
5
var table = document.getElementsByTagName('table')[0];
coordinate(table);

// The origin (0,0) is the top, leftmost cell
table.coordinates[3][2].innerHTML = '(3,2)';

Did you ever wish you could, given a table cell, easily address its neighbors?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var table = document.getElementsByTagName('table')[0];
coordinate(table);

var cell = table.coordinates[3][2];

// 'edge' cells have 1 undefined direction
// corner cells have 2 undefined directions
// a cell in a 1x1 table would have all 4 directions undefined
// (but why would you do that?)

if (cell.north) cell.north.innerHTML = 'up';
if (cell.south) cell.south.innerHTML = 'down';
if (cell.west)  cell.west.innerHTML  = 'left';
if (cell.east)  cell.east.innerHTML  = 'right';

Did you wish you could, given a table cell, know its X and Y coordinates?

1
2
3
4
5
6
7
8
9
var table = document.getElementsByTagName('table')[0];
coordinate(table);

var cells = table.getElementsByTagName('td');

for (var i=0,td; td=cells[i]; ++i)
    td.onclick = function () {
        console.log('You just clicked on the cell at ' + this.x + ',' + this.y);
    };

Try the demo!

Of course it’s on github

Shebang: What?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
% /usr/local/php5/bin/php --version
PHP <b>5.2.6</b> (cli) (built: May 11 2008 13:09:39) 
Copyright (c) 1997-2008 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies
    with Zend Extension Manager v1.2.2, Copyright (c) 2003-2007, by Zend Technologies
    with Zend Optimizer v3.3.3, Copyright (c) 1998-2007, by Zend Technologies

% echo '<?= phpversion() ?>' | /usr/local/php5/bin/php
5.2.6

% printf '#!/usr/local/php5/bin/php\n<?= phpversion() ?>' > version
% chmod +x version
% ./version
5.2.6

% mv version x.php
% ./x.php
4.4.9

In case you’re wondering, this machine is running Linux, not Windows.

November 6, 2009 update: I asked and got a quick answer on serverfault: somebody changed /proc/sys/fs/binfmt_misc/php.

Modiff: The Perl Module Differ

Here’s something else I wrote (like acuff) for working on Apache/Perl installations, particularly unfamiliar ones: modiff, the Perl module differ.

Say you need to update a certain Perl module. You check out the latest version, make your edits, "make install", and everything’s great. Usually. Only this time you’ve just overwritten a hack that guy who got laid off never committed 6 months ago, and now everything’s broken. Even rolling back to the previous svn revision can’t save you now.

You should have run modiff first:

% cd ~/project/Really-Important-Module && svn update && modiff
U    lib/Really/Important/Module.pm
Updated to revision 32767.
*** /usr/local/lib/perl5/site_perl/5.8.7/Really/Important/Module.pm   Tue Apr  1 16:59:59 2008
--- lib/Really/Important/Module.pm    Wed Jan  7 20:35:37 2009
***************
*** 2,9 ****

  sub init {
        my $self = shift;
!       # $self->{conf} = parse_config('/etc/x.conf');
!       # This always bombs. Comment out until I figure out why
        return 1;
  }

--- 2,8 ----

  sub init {
        my $self = shift;
!       $self->{conf} = parse_config('/etc/x.conf');
        return 1;
  }

I first wrote modiff in Ruby but I eventually needed to use it on a server that did not have Ruby, and you probably will too. The version here is the sensible Perl rewrite.

Note that modiff works only if your module’s source is in CPAN-style where *.pm files are under lib/. For nonstandard directory layouts or detecting changes to other files like *.pod or anything XS-related, you’re on your own.

October 5, 2009 update: modiff is now part of my "futilities" collection on github.

Acuff: Apache Configuration File Finder

If you’ve ever worked on an unfamiliar Apache installation you know how it is trying to follow all the includes (which may in turn include more files) to track down the source of a mysterious rewrite rule or LocationMatch. So I wrote acuff. It searches for an Apache executable in your $PATH and typical locations like /usr/local/apache2/bin and spits out its config filenames (with full paths) to standard output. My typical usage goes something like this:

1
2
% acuff | xargs grep -il '<location /logout'
/usr/local/etc/apache22/conf/app.conf

It’s in Perl, and anything running Apache is bound to have Perl on it. It uses no extra CPAN modules but it does need Perl 5 (this being 2008 it’s completely reasonable to ignore Perl 4 and earlier, I hope). Enjoy.

October 5, 2009 update: acuff is now part of my “futilities” collection on github.

Javascript (and Perl and Ruby) Bloom Filters

I’ve never seen a Javascript Bloom filter implementation so I had to write one, and then had to port it to Perl and Ruby. You’ll understand why soon if you don’t already.

Quick aside: more than half of “my” bloomfilter.js is somebody else’s BSD-licensed Javascript MD5 library but you could pretty easily replace it with some other hash library if you felt the compulsion.

I don’t think this one would be practical for really large input sets (like a spell check dictionary built from /usr/dict/words), but I’m sure you’ll think of something if you work at it. Get moving on that.

To get your brain in gear, here’s a small demonstration.

First, I put the text of a really excellent Wire song (I won’t say which), one word per line (minus punctuation) in a file. Then using the Ruby version I ran the file through this:

1
2
3
4
5
6
7
require 'bloomfilter'

bf = BloomFilter.new({ 'bits' => 0xff, 'salts' => %w(z A) })

STDIN.each_line { |l| l.chomp!; bf.add(l.downcase) }

print(b.to_json)

Or maybe I used the Perl one and ran it through this:

1
2
3
4
5
6
require 'bloomfilter.pl'; # what is this, 1994?

my $bf = BloomFilter->new({ bits => 0xff, salts => [qw(z A)] });

while(<>) { chomp; $bf->add(lc $_); }
print $bf->as_JSON();

Doesn’t matter. Both give the same output (though I changed the formatting to make it a little easier to read):

1
2
3
4
5
6
{
 "buckets":[1509645767,990260715,1062483727,150062916,551224088,354022058,1818090233,1463314593,110],
 "bucketsize":31,
 "bits":255,
 "salts":["z","A"]
};

Type some Wire lyrics into the box below and smell the magic:

 

The filter check code runs ‘onchange’ for that text box. Just type (or paste in) some text, then click outside the box and you should get some feedback.

I encourage you to view the source of this page to see what’s really going on but here’s a quick example of the Javascript interface for the impatient:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// choose an appropriate number of bits and salts
// (don't ask me; you can figure it out)

var bf = new BloomFilter({ bits: 0xffff, salts: ['x','y','z','!'] });

bf.add('one');
bf.add('two');
bf.add('three');

bf.test('one'); // will definitely return true
bf.test('two'); // will definitely return true
bf.test('three'); // will definitely return true

bf.test('eins'); // will probably return false
bf.test('zwei'); // will probably return false
bf.test('drei'); // will probably return false

If you find bugs in this, please let me know. Also I’d really like to hear from anyone who finds other cool uses for this (aside from Wire lyric guessing games). And just to get this out of the way, I have no idea if this code can interoperate with the Bloom::Filter module on the CPAN but I should probably find out.