Buying a CO alarm

So Illinois is mandating carbon monoxide detector/alarms in residences as of January 1. Today I decided to buy one. I wanted to get a combination smoke/CO detector, that way I wouldn’t need to change two batteries. Sounds easy, doesn’t it?

Let’s see, this one is on clearance because its battery lasts 2 weeks.

This one seems to give a lot of false alarms, and has a rather humorous review attached.

Reviewer: A Kitchen & Housewares enthusiast
This is not and I repeat is not a good alarm. There is one alarm light and you can hardly tell which one is sounding. It looks as if the specs are lying to me and I hate lies. Also the battery died after 6-8 months. The low battery alert is loud and chirps so anoyingly. I also noticed that the alarm sounds a loud shrieking alarm when it sounds. I will return this alarm. Never again will I trust in First Alert!

It also makes me wish I never meet a “kitchen and housewares enthusiast” in person.

This one goes off when you try to use an infrared remote control. The detector goes in the hallway behind my stereo, so that one’s out.

Finally, I give up on Amazon.com and do a Google search. I eventually stumble upon the Firex 12000, which has such useful features as a mute button that actually mutes for longer than you hold it down, an alarm that starts out quiet, a battery that’s easy to replace, and an industrial design that looks vaguely like someone cared. It’s AC/DC so I don’t have to replace batteries every 6 months, and even communicates over the power line with other units of its type. I read prior ones have freaked out after 4–6 years, but I plan to be gone by then.

A bonus review (for a CO-only alarm). The username is a nice touch.

Australian “Engrish”

Yesterday’s Engrish was a sign which actually wasn’t Engrish at all. Unlike all the other posts on the site, however, it’s a sign I’ve seen myself—it’s in Mosman, where I’ve visited relatives many times. Small world as usual.

It was a bit weird of the submitter or site maintainers to obscure the office number (not that such things are hard to find on the Web these days) but not the mobile number on the door below, though.

Anyway, sorry for not much posting recently. I’m still very busy writing a paper, and need to prepare my DLS presentation in the coming week.

Another day, another WordPress upgrade

Running WordPress 2.0.4 now. The upgrade took longer than expected, but I’ve documented what I need to do for next time, and upgraded a couple of my plugins as well. Hopefully nothing broke.

The ICeCoffEE 1.4.3 release went pretty well—I’ve received two crash reports, and one user claimed it didn’t work for him. One of the crashes is not my fault: Safari crashed during a page load triggered by a Command-click. For the other one, I discovered that I had completely stripped the distributed binaries, which isn’t too useful for debugging:

Thread 0 Crashed:
0   com.apple.CoreFoundation       	0x90853b76 CFBundleCopyLocalizedString + 106
1   net.sabi.ICeCoffEE             	0x002e5358 APEBundleMainLateLoad + 23883
2   net.sabi.ICeCoffEE             	0x002e569b APEBundleMainLateLoad + 24718

I haven’t yet figured out how to map those addresses back to the source code, so I’ll repost 1.4.3 with symbols later this weekend. It’s now less than a week until I leave for WWDC, the pace of my research work continues to quicken and I’ve got a lot left to arrange.

Restoring backslashes in WordPress

Sorry if anyone tried the scripts I posted yesterday and found them inoperative—they were missing backslashes. I used to always verify this stuff back when I was using more finicky blogging tools, but given WordPress generally does the right thing™ I didn’t worry.

WordPress strips backslashes inside <pre> tags because quotes get escaped. I spent a while searching for the responsible regular expression substitution before finding out PHP had a function to strip backslashes. The line responsible is the second last of wpautop in wp-includes/functions-formatting.php:

$pee = preg_replace('!(</pre><pre .*?=".*?">)(.*?)</pre>!ise', " stripslashes('$1')
                    .  stripslashes(clean_pre('$2'))  . '' ", $pee);

While this eliminates the extra backslashes before quotation marks, it also removes other backslashes. Here’s a fix:

$pee = preg_replace('!(</pre><pre .*?=".*?">)(.*?)!ise', " stripslashes('$1')
                    .  str_replace('\\\\\"', '\"', clean_pre('$2'))  . '' ", $pee);

This American Life track munger

Since This American Life has switched from streaming in RealAudio to MP3, Jon Udell and Jared Benedict have posted some unofficial podcast feeds. Unlike with my previous RealPlayer-to-Audio Hijack Pro-to-iTunes-as-AAC solution, the MP3 files aren’t bookmarkable on my 3G iPod, but they are certainly a lot more convenient to grab for later listening.

Which reminds me, since other people may find it useful—a few weeks ago, I wrote a script which operates on the selected This American Life MP3 tracks in iTunes, renames them to match my existing scheme, and moves the episode number to the track field (especially useful on older iPods where the episode number takes up half the width of the screen).

TALize.png

Download the script here. Sorry for the image; Script Debugger 3’s HTML export appears to have broken—and since I have primarily switched to appscript, I can’t justify the upgrade to version 4. The string parsing pain above should be enough to send anyone running to Python.

Upgraded to WordPress 2.0.3

Comment spam really is annoying, though it’s getting a run for its money from random Unicode glyph-abusing Brazilians I don’t know asking me to be their friend on Orkut. But four requests in one day!?

It seems WP-Cache was causing the weird blank-page-until-reload issues with WordPress 1.5, which translated into no-page-at-all issues in WordPress 2. Since TextDrive finally seems to have a handle on the server-crashing and performance issues (this server has been up for over 31 days), the caching plugin isn’t as imperative as it used to be, though I do like to be nice about using shared server resources where I can.

Quick WordPress 2 review: AJAXification is good. I don’t like the new admin color scheme; looks too much like a bad ripoff of Slashdot. From time to time gigantic fonts appear, for no apparent reason; being on a 1024×768 display, this sucks. The new WYSIWYG editor isn’t perfect (it turned a paragraph break into a line break the first time I posted this message), but it’s a lot better than most I’ve seen. The dynamic resizability of this editing window is especially slick—alternately, you could say we should have had this kind of stuff on the Web 10 years ago :-)

Still, I think I’ll be going back to MarsEdit as soon as I can; hopefully it’ll get some attention in the form of WebKit content-editable support soon. I’m already very addicted to NetNewsWire 2.1’s syncing, even with the known problems, it works well 99% of the time. When RSS feeds get messed up on iTunes, I end up with tens of old podcasting episodes, which is a lot of data to needlessly download. It’d be cool if I could tell it “don’t accept any posts with dates earlier than the newest (or even oldest) preexisting item in the feed”.

If you notice any site flakiness, please let me know. I realize some of the old posts from the PyCS and (especially) Radio sites still have formatting issues; fixing this is on my to-do list, just rather far down it.

Safari crashes

Safari crashes in exactly one situation in my daily browsing habits: while rendering macworld.com. It’s totally reproducible and happens virtually every day.

Macworld is the most popular US Mac magazine. Safari is the most popular Mac Web browser. Does this seem completely bizarre to anyone else?

Configuring Trac with FastCGI and lighttpd

I initially tried getting tracd to work, but couldn’t get it to generate URLs that made sense. So, I decided to investigate all the fuss about using lighttpd and FastCGI. It works, better than tracd likely, and is certainly more flexible.

Here’s my lighttpd.conf for dev.sabi.net. It essentially implements the “Global authentication” example from the TracMultipleProjects page on the Trac wiki. You need a trunk version of Trac for this to work; 0.8.x don’t have FastCGI support.

server.port         = 9013
server.document-root= "/home/nriley/web/public/"
server.indexfiles   = ( "index.html" )
server.pid-file     = "/home/nriley/var/run/lighttpd.pid"
server.errorlog     = "/home/nriley/logs/lighttpd.error.log"
accesslog.filename  = "/home/nriley/logs/lighttpd.access.log"
url.access-deny     = ( "~", ".inc" )
compress.cache-dir  = "/home/nriley/var/cache/lighttpd/compress/"
compress.filetype   = ( "text/plain", "text/html" )
fastcgi.server      = ( "/trac" =>
                       ( "trac" =>
                        ( "socket" => "/home/nriley/var/run/trac-fastcgi.sock",
                          "bin-path" => "/home/nriley/cgi-bin/trac.fcgi",
                          "bin-environment" =>
                           ( "TRAC_ENV_PARENT_DIR" => "/home/nriley/trac" )
                        )
                       )
                      )
alias.url           = ( "/media/" => "/home/nriley/share/trac/htdocs/" )
auth.backend        = "htdigest"
auth.backend.htdigest.userfile= "/home/nriley/etc/trac.digest.passwd"
$HTTP["url"] =~ "^/trac/[^/]+/login" {
    auth.require    = ( "/" =>
                       ( "method" => "digest",
                         "realm" => "sabi.net Subversion repository",
                         "require" => "user=nicholas"
                       )
                      )
}

In order for the above FastCGI association to work, I must create a file named trac in the server’s document root, so lighttpd has something to pass along to the FastCGI script. (I got this tidbit from this article on using Django with lighttpd).

I needed to use /media instead of /trac or something like /trac-common or /trac/common because I couldn’t get lighttpd to give up the FastCGI assocation with /trac.

It appears there’s nothing equivalent to “Require valid-user” in lighttpd, and the “require” statement isn’t parsed until a request is received, so you’ll need to add a bunch of users to a group and require a group, likely. The parsing error is very poorly identified, too: (http_auth.c.345) = is missing. I had to dig through the lighttpd source to see what it was referring to.

So, everything seemingly works; the only problem I’m having is my log file getting polluted with these messages:

2005-08-01 03:08:38: (mod_fastcgi.c.2110) FastCGI-stderr:  

which I’ve filed as a bug in Trac.

I also had to do some digging to figure out how to enable anonymous access to Subversion via WebDAV. The Subversion repository’s DAV interface was created as private to begin with, a sensible precaution. However, I couldn’t use <LimitExcept> to apply permissions, so instead I have a AuthzSVNAccessFile svn-access.conf that looks like this:

[dev:/]
nicholas = rw
* = r

Then I open up Apache access with Satisfy Any. Some more discussion of this technique is here.