Daniel Rench

Web application development : Servers : Networks : E-Mail : DNS : Databases : Programming for hire

contact : linkedin : code : links : pictures : facebook : twitter

Shebang: What?


% /usr/local/php5/bin/php --version
PHP 5.2.6 (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.

November 4 2009 : link

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.

January 8 2009 : link

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:

% 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.

July 16 2008 : link

EHANN: 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:


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:


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):

{
 "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:


// 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.

August 11 2007 : link

Hash::Server: a (mostly) memcached-compatible network interface to Perl hashes

You can download Hash::Server here until I get it on the CPAN (after a decade with Perl as my primary programming language I've finally signed up for a PAUSE account, so it could happen). Maybe you'll find this useful.

April 29, 2009 update: this code is now on github.



SYNOPSIS

        use Hash::Server ();
        use DB_File (); # for example
        tie(my %db, 'DB_File', './hash.db') or die $!;
        Hash::Server->new({ hash => \%db, localport => 11211 })->Bind();


DESCRIPTION

While memcached's original purpose was as a networked Memoize, it's also a simple way to distribute key/value hashes. But the official memcached (as the name implies) stores its data in memory, and is temporary. Given there are so many memcached clients for so many languages, it seemed a shame that there were no other ``backing stores'' available.

This module allows you to distribute any Perl hash structure you like with the memcached protocol. Typical use would probably involve a tied hash (as in the DB_File example above); if you want to serve a straight untied hash, you might as well use the real memcached, especially given the limitations of this module...


CAVEATS

This module is not a complete implementation of the memcached protocol.


SEE ALSO

http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt


AUTHOR

Daniel Rench, <citric@cubicone.tmetic.com>


COPYRIGHT AND LICENSE

Copyright (C) 2007 by Daniel Rench

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.7 or, at your option, any later version of Perl 5 you may have available.

June 1 2007 : link

It might help somebody: Flash 9 with Firefox on a Mac

When I install Firefox on a Mac, I always sudo chown -R 0:0 /Applications/Firefox.app after. What, you don't? But when trying to install Flash 9, I got this:

1008:5-5000 Access Denied Error
You do not have enough access privileges for this installation.
So I tried running the Flash install as root. Same error. Then I did this: sudo chown -R drench /Applications/Firefox.app and ran the install again, which worked, and it made me sad.

April 4 2007 : link

Element.getAttribute() doesn't get enough publicity

For years I've been using hacks like overloading the title and class attributes of HTML elements because I didn't know any better. Now I know I can just make up attributes, like 'regex' here, which I defined as a pattern that a form field must match:

<html>
<head><title>attributes</title>
<script>

function make_validator (form) {

	return function () {
		var pat, r;

		for (var i=0, e; e = form[i]; ++i) {

			pat = e.getAttribute('regex');
			if (! pat) continue;

			r = RegExp(pat).exec(e.value);
			if (! r) {
				e.focus();
				alert("Bad value for " + e.name);
				return false;
			}
		}
		return true;
	};
}

window.onload = function () {

	for (var i=0, form; form=document.forms[i]; ++i)
		form.onsubmit = make_validator(form);

};

</script>
</head>

<body>
<form>
	Number: <input type="text" name="number" regex="^\d+$">
	<input type="submit">
</form>

<form>
	Username: <input type="text" name="username" regex="^\w{1,8}$">
	<input type="submit">
</form>

</body>
</html>
April 3 2007 : link

We are all bigots / So filled with hatred / We release our poisons

... like the Bad R&R blog.

More like Rock & Roll Bigot if you ask me (who, "full disclosure" is a contributor to the site).

March 27 2007 : link

Yet another 'radical' idea in Unix file layout

Long before this ImageMagick overflow bug I've been wanting to ditch it completely in favor of GraphicsMagick (still hasn't happened). Aside from the usual bugs, arbitrary API changes and other endearing quirks, ImageMagick's greatest offense is how its utility programs have incredibly generic names like display and identify. GraphicsMagick does away with those by running everything through the gm command, so there's less confusion about what happens when you type gm identify somefile.jpg as you so often do.

This kind of thing is very common; cvs, svn and openssl (to name a few that I use often) all fit this pattern. Decent shells are aware of these programs' "subcommands" and will tab-complete them for you. But the chances that your shell's tab completion is an exact match with whatever version of, say, svn you're running are low. Maybe svn added a new command, but your shell completion doesn't know about it yet. Or maybe your shell completion has all the latest updates but you're stuck running an old version of svn that doesn't have it, allowing your tab completion to taunt you.

Imagine then if your shell was smart enough to detect directories in $PATH entries and gave them special treatment, looking for "subcommands" under them. Then svn could install itself under a directory called /usr/local/bin/svn/, where you'd have /usr/local/bin/svn/checkout, /usr/local/bin/svn/commit, /usr/local/bin/svn/log, etc. Instead of svn checkout you would run svn/checkout. And with a link from checkout to co you would still have your svn co shortcut. The commands themselves wouldn't necessarily need to look different; the shell could automatically translate svn co to svn/co for you and you might not even realize anything changed.

Update: Anonymous commentor made all kinds of good points (particularly about just using something like "gm-whatever") so this is a "nevermind".

December 4 2006 : link

The inexplicable popularity differences of two photos

Changing the diaper on the pretend baby

I realize that by linking to this photo I'm only making things worse, but why is the photo above among my top-viewed flickr pictures? And why is the one below one of the very least popular? It's among my favorites, but not yours? What's your problem?

Lemon #17

October 30 2006 : link

Excitement Has A New Name: Tmetic::Feed::Manager

For a while I've been using the RSS reader built into the Thunderbird mail client. I thought it was kind of cool how it made blog posts look like e-mail messages. But why settle for kind of like e-mail when you can have the real thing?

So I wrote a Perl module: Tmetic::Feed::Manager. Just download it, untar it, then do the usual perl Makefile.PL && make && make test && make install. You may need to install some prerequisite modules like DBD::SQLite, Text::Template, and XML::RSS::Parser; the build process will let you know what you're missing. Except sendmail. If you don't have a working sendmail in your $PATH (whether it's actually qmail or postfix or the real thing) you will run into trouble.

This is an initial release and has some limitations, the biggest being it can only deal with RSS 2.0 feeds; no RSS 0.9x or Atom yet. Enjoy if possible and applicable, and send your thoughts (all of them) to me.

October 25 2006 : link

Because nobody has ever put the phrase "print to STDERR in PHP" on a web page

I needed to know how to do this, and this particular phrase (quoted) returns zero documents on well-known search engines. See, PHP does define STDERR (and STDOUT and STDIN) for use in print() statements, but (this is funny) not when running under a web server. So in order to print debugging information to your server's error log, you have to open it yourself and use fwrite():

	$STDERR = fopen('php://stderr', 'w+');
	fwrite($STDERR, "some debug info\n");

Printing to standard error is the #1 most common debug aid in the universe of all time (almost 6000 years). Yet PHP goes out of its way to take it away from you. It may be there for PHP scripts not run under a web server, but that's almost the same as saying it's not there at all.

It also sounds like maybe at one time STDERR, etc. worked as programmers would expect but the last word on that was "Not PHP problem -> bogus."

Dec 11, 2006 update: Thanks to reader Andy Bakun I now know about PHP's error_log() function. When called with one argument (a message string), it sends the string to the web server's error log (when running under a web server), or to STDERR (when running from the command line). So I think it's safe to say error_log() is PHP's do-what-I-mean equivalent of writing to STDERR in any other language. And now it's documented somewhere.

October 6 2006 : link

Excitement Has a New Name: Excessively Strong Typing in Perl

I haven't used this in "serious" code but that's only because I'm not a freak about strong typing. Don't you worry, it works fine.

package Typed;

sub TIESCALAR {
    my $class = shift;
    my $test_function = shift;
    bless [ undef, $test_function ], $class;
}

sub FETCH {
    my $self = shift;
    $self->[0];
}

sub STORE {
    my $self = shift;
    my $v = shift;
    if ($self->[1]->($v)) {
        $self->[0] = $v;
    } else {
        die "'$v' is an illegal value for " . ref($self) . "\n";
    }
}

package Typed::Integer;

our @ISA = 'Typed';

sub TIESCALAR {
    my $class = shift;
    Typed::TIESCALAR($class, sub { my $n = shift; $n =~ /^[\+-]?\d+$/ });
}

package Typed::Number::Natural;

our @ISA = 'Typed'; # could say 'Typed::Integer' but it makes no difference here

sub TIESCALAR {
    my $class = shift;
    Typed::TIESCALAR(
            $class,
            sub {
                my $n = shift;
                ($n !~ /\D/) && ($n > 0);
            }
        );
}

package Typed::VarChar;

our @ISA = 'Typed';

sub TIESCALAR {
    my $class = shift;
    tie my $n, 'Typed::Number::Natural';
    $n = shift;
    my $r = Typed::TIESCALAR(
            $class,
            sub {
                my $s = shift;
                defined($s) && (length($s) <= $n);
            }
        );
}

package main; # "where the action is"

tie my $x, 'Typed::Integer';
$x = 100; # OK
$x = -12; # OK
$x = 1.1; # dies, uh I mean "throws an exception"
$x = 'stuff'; # dies

tie my $z, 'Typed::VarChar', 5;
$z = 'chars'; # OK
$z = ''; # OK
$z = 'Fairly long string'; # dies
October 2 2006 : link

Since the Knockoff Project seems dead

Starship album cover

[ref: The Knockoff Project]

September 22 2006 : link

arguments.callee: A dren.ch Endorsement

I mostly agree with Mr. JSON's ECMAScript recommendations but not this:

The following features should be depreciated.

[...]

arguments.callee.

It might have a goofy name but arguments.callee is way too useful (inside a Javascript function, this is a reference to the function itself). I don't mean anonymous recursive functions, though that's still kind of cool. Say you wanted a "sequence" function. With arguments.callee:

function sequence () {
	var me = arguments.callee;
	if (! me.n) me.n = 0;
	return me.n++;
}

Without:

var sequence = (function () {
		var n = 0;
		return function () { return n++ };
	})();

You can argue that the "without" version is better but I'm not going to agree with you.

9/12/2006 update: This works and is probably clearer than either of the above:

var sequence = function () { return sequence.n++ };
sequence.n = 0;

It manages to avoid arguments.callee and function-within-a-function closure. It also fixes the (for me) biggest problem with the arguments.callee version: the test for undefined n on every call. But there are a couple minor downsides: the function needs to know its name, and it's not self-contained. Maybe you don't care.

8/15/2007 update: A Canadian named Peter discusses similar problems though he's into using the term "pattern".

September 11 2006 : link

Agitating for green shopping bags

a picture of angry Macy's protesters The shirts are cute and I suppose it's sad to see a "beloved institution" go, but what sort of person gets emotional over corporate name changes I ask rhetorically? I thought it was lame when International Harvester changed its name and clever logo but I got over it. It's not like when Lounge Ax closed or anything. Actually even that event was probably less culturally significant than the Kots and Derogatises made it out to be. By the time Lounge Ax closed in 2000, the Empty Bottle had held the Cool Underground Chicago Rock Saloon torch at least 4 years and still does for all I know.

September 11 2006 : link

Transmutable (?) Objects in Perl and Ruby

I have no idea if "transmutable" is the right word to describe this concept but I'm using it anyway.

In Perl, I sometimes find it useful to "transmute" objects. For example:


sub Grape::new {
	my $class = shift;
	bless {}, $class;
}

sub Grape::dehydrate {
	my $self = shift;
	bless $self, 'Raisin';
}

sub Raisin::new {
	my $class = shift;
	bless {}, $class;
}

my $x = Grape->new();
print ref($x), "\n"; # prints "Grape"
$x->dehydrate();     # it's not a Grape anymore
print ref($x), "\n"; # prints "Raisin"
$x->dehydrate();     # Raisin doesn't have a dehydrate() method, so it dies

To do this in Ruby, I first tried something like this:


class Grape
	def dehydrate
		self = Raisin.new
	end
end

But Ruby complains "Can't change the value of self". I ended up trying something with Ruby's version of AUTOLOAD, method_missing:

class Grape
	def initialize
		@me = Hidden::Grape.new
	end
	def method_missing(method, *args)
		r = @me.method(method).call(*args)
		@me = r if /^Hidden::/.match(r.class.to_s)
		return r
	end
	def class
		@me.class.to_s.sub(/^Hidden::/, '')
	end
	def methods
		@me.methods
	end
end

module Hidden
	class Grape
		def dehydrate
			Raisin.new
		end
	end
	class Raisin
	end
end

x = Grape.new
puts(x.class) # prints "Grape"
x.dehydrate
puts(x.class) # prints "Raisin"
x.dehydrate   # NameError: undefined method `dehydrate' for class `Hidden::Raisin'

Various things seem wrong about it (especially overriding class() and methods()), but it pretty much does what I want.

11/15/2006 update: I no longer think the above seems "wrong". If anything it's probably considered insufficiently weird in Ruby circles.

September 1 2006 : link

The Cookie Hack: using mod_perl to make IE7 think you're not using Basic Auth (even though you are)

You may have heard that the forthcoming MSIE 7 web browser made some "enhancements" for Basic Authentication (warning or optionally disallowing it unless used over SSL). You could buy a certificate or try converting to digest auth or you could implement a cookie hack. It goes something like this (assuming you're running Apache 1.3 with mod_perl):

It's just as "secure" as always (that is, not at all) but it does have some advantages over basic auth:

  1. Delete the cookie, and you're logged out. No need for a browser shutdown as in basic
  2. Add an expiration date to the cookie, and your login "session" can survive a browser shutdown
  3. Set the domain of the cookie to .example.com and suddenly you don't have to maintain separate logins for http://www.example.com/ and http://example.com/ perhaps even https://www.example.com/

If you really want to run with this, you could work around the insecurity by encrypting the the username and password on the client side and expanding the mod_perl handler to decrypt before setting up the fake auth header. You'll have to figure out how to pass the key securely.

August 16 2006 : link

August 2006 Chicago-area Community Calendar

August 7 2006 : link

old things