Daniel Rench

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

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

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>

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

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

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

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.

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

I once thought I needed to write to STDERR in some PHP code. This particular phrase (quoted) returned zero documents on well-known search engines, so I felt compelled to do something about it.

PHP provides STDERR (and STDOUT and STDIN) but not when running under a web server. Since that's the environment virtually all PHP code runs, they may as well not be there at all.

Thanks to Andy Bakun, I learned 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. Usually.

Depending on your php.ini settings, error_log() may be going to your syslog, or some log file, which has thrown me a few times. While debugging a Roundcube plugin, I was wondering why none of my error_log() output was making it to the web server's log. Then I noticed this:

    ini_set('error_log', $this->prop['log_dir'].'/errors');

It looks like maybe at one time STDERR, etc. worked as programmers would expect but the last word on that was "Not PHP problem -> bogus." So if you're really, really determined to print to STDERR no matter what the environment or the ini settings, you have to open it yourself:

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

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

Since the Knockoff Project seems dead

Starship album cover

[ref: The Knockoff Project]

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.

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

older things