<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><!-- generator="FeedCreator 1.7.2" --><rss xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
    <channel>
        <title>Steve Kehlet's Pages</title>
        <description>Steve's pages.</description>
        <link>http://www.kehlet.cx/</link>
        <lastBuildDate>Thu, 25 Feb 2010 17:57:32 -0800</lastBuildDate>
        <generator>FeedCreator 1.7.2</generator>
        <image>
            <url>http://www.dailyphp.net/images/logo.gif</url>
            <title>dailyphp.net logo</title>
            <link>http://www.dailyphp.net</link>
            <description>Feed provided by dailyphp.net. Click to visit.</description>
        </image>
        <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/SteveKehletsPages" /><feedburner:info uri="stevekehletspages" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>SteveKehletsPages</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
            <title>One-Way Notifications to Your iPhone</title>
            <link>http://feedproxy.google.com/~r/SteveKehletsPages/~3/OFcWz0HHGSM/196.html</link>
            <description>The &lt;a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=320876271"&gt;Prowl app&lt;/a&gt; costs $2.99 and provides a web services API for one-way, push notifications to your iPhone.  There are services like &lt;a href="http://googlevoice.ub3rk1tten.com/voicegrowl/"&gt;Google Voice Growl&lt;/a&gt; and &lt;a href="http://preyfetcher.com/settings"&gt;Prey Fetcher&lt;/a&gt; that can notify you--for free, using Apple's push notification service--when interesting things happen to your Google Voice or Twitter accounts, respectively.  

&lt;br /&gt;&lt;br /&gt;

My interest has been in replacing changing my Nagios notifications from SMS messages to something free--all it takes is a major problem to start racking up a number of SMS charges.  And unlike SMSes, you can tell Prowl to stop bugging you, if it gets that bad.

&lt;br /&gt;&lt;br /&gt;

If you have Prowl, the following &lt;code&gt;curl&lt;/code&gt; command will send a free notification to your iPhone:

&lt;br /&gt;&lt;br /&gt;

&lt;code&gt;curl -d apikey=YOUR_PROWL_API_KEY -d application=curl-test -d event='testing from curl' -d description='this is a test from curl' https://prowl.weks.net/publicapi/add&lt;/code&gt;

&lt;br /&gt;&lt;br /&gt;

It's that easy.  Worked on the first try.  Still left to consider is it I trust this as much as I trust AT&amp;T's email-to-SMS gateway service, which has never been an issue for me.  

&lt;br /&gt;&lt;br /&gt;

It can also tie into &lt;a href="http://growl.info/"&gt;Growl&lt;/a&gt;, and given the name I imagine this was its first intended use, so things happening on your Mac, like bittorrent downloads completing and adium messages, could also notify your phone.&lt;img src="http://feeds.feedburner.com/~r/SteveKehletsPages/~4/OFcWz0HHGSM" height="1" width="1"/&gt;</description>
            <author>steven@kehlet.cx</author>
            <pubDate>Thu, 29 Oct 2009 19:54:56 -0800</pubDate>
        <feedburner:origLink>http://www.kehlet.cx/articles/196.html</feedburner:origLink></item>
        <item>
            <title>I </title>
            <link>http://feedproxy.google.com/~r/SteveKehletsPages/~3/xRm4xNlepAw/195.html</link>
            <description>For a while I've been reading &lt;i&gt;&lt;a href="http://ilovetypography.com"&gt;I Love Typography&lt;/a&gt;&lt;/i&gt;, which describes itself as a means of bringing the subject of Typography to the masses.  I am definitely part of the masses, I know I don't have the critical eye and patience needed for good page design, as made evident by my site with its uninspired look, horrible colors, blocky layout, and general failure to render properly in any browser but Safari.  But as &lt;i&gt;I Love Typography&lt;/i&gt; says, it is truly inspiring at times to see these beautiful fonts and what people have done with them.  Each article showcases numerous typefaces and sometimes works of art created with them.  It's a fascinating read on a beautiful topic I now realize I know so little about.

&lt;br /&gt;
&lt;br /&gt;

One humorous thing that's stuck with me is the professional typography community's distaste for Arial.  Why hate Arial?  As an outsider reading about it, it seems like one of those things that really only those in the know, know.  One detailed explanation can be found &lt;a href="http://www.ms-studio.com/articles.html"&gt;here&lt;/a&gt;.  About the closest thing I can compare it to is why do computer hackers generally hate Windows and love Linux--you really can't explain that to a normal person who uses Windows for normal stuff, and it generally works just fine.  On the surface, the whole Arial thing has to do with it being a notably poor knockoff of Helvetica, the beloved font of designers everywhere.  While it was created to be a drop-in replacement, certain things about it are subtly different and look ugly to the trained eye.  Compare Arial on the left to Helvetica on the right, and judge if you think one is better than the other (you might read &lt;a href="http://www.ms-studio.com/articlesarialsid.html"&gt;How to Spot Arial&lt;/a&gt; first):

&lt;br /&gt;

&lt;img src="http://www.kehlet.cx/images/2009/07/arial.png" width="213" height="314" alt="serif" style="float: left" /&gt;
&lt;img src="http://www.kehlet.cx/images/2009/07/helvetica.png" width="215" height="329" alt="serif" /&gt;

&lt;br /&gt;
&lt;br /&gt;

I'd have to agree that Arial's &lt;i&gt;R&lt;/i&gt; is indeed, well, rather pointy and unattractive, like a pirate's peg-leg or something.  Since learning about this, it's become fun to try to spot Arial when used in various everyday places.  For example, one of my favorite magazines, &lt;a href="http://discovermagazine.com/"&gt;Discover&lt;/a&gt;, uses what appears to be Arial on their web site and on the top of every magazine (the 'R' is the dead giveaway, as well as the 'C'):

&lt;br /&gt;

&lt;img src="http://www.kehlet.cx/images/2009/07/discover-com.png" width="513" height="110" alt="Discover brand" /&gt;

&lt;br /&gt;
&lt;br /&gt;

Compare this to what I created in TextEdit with Arial Narrow, it looks like all they did was squish it together a bit:

&lt;br /&gt;

&lt;img src="http://www.kehlet.cx/images/2009/07/discover-arial.png" width="425" height="94" alt="Discover written with Arial Narrow" /&gt;

&lt;br /&gt;
&lt;br /&gt;

It's easy to get carried away.  &lt;a href="http://lmnop.blogs.com/lauren/2006/10/americas_most_f.html"&gt;America's Most Fonted: The 7 Worst Fonts&lt;/a&gt; describes several fonts you should never use, including Comic Sans and Papyrus, which (ack!) I think I had on my wedding invitations. 

&lt;br /&gt;

&lt;img src="http://www.kehlet.cx/images/2009/07/papyrus.png" width="361" height="98" alt="Papyrus" /&gt;

&lt;br /&gt;
&lt;br /&gt;

If nothing else, this shows how easy it is as to make what more trained eyes would see as a n00b mistake when it comes to design.  Hire someone who knows, when it matters.

&lt;br /&gt;
&lt;br /&gt;

In the news recently, &lt;a href="http://hacks.mozilla.org/2009/06/beautiful-fonts-with-font-face/"&gt;Firefox 3.5&lt;/a&gt; joins other browsers in &lt;a href="http://webfonts.info/wiki/index.php?title=%40font-face_browser_support"&gt;supporting the CSS tag &lt;code&gt;@font-face&lt;/code&gt;&lt;/a&gt;.  Designers can now instruct a visitor's browser to download and use specific fonts on your page, which seems great, given the otherwise unpredictable and varied selection that otherwise exists by default.  Again, it's highly browser dependent, but with Firefox now supporting it, there's a good chance a fair percentage of your audience will benefit.  I switched the heading at the top of every article to use a cool looking font, &lt;a href="http://nicewebtype.com/fonts/graublau-sans-web/"&gt;Graublau Sans Web&lt;/a&gt; (freely licensed), with the following css:

&lt;pre&gt;
@font-face {
  font-family: "Graublau Sans Web";
  src: url("http://www.kehlet.cx/fonts/GraublauWeb.otf") format("opentype");
}
@font-face {
  font-family: "Graublau Sans Web";
  font-weight: bold;
  src: url("http://www.kehlet.cx/fonts/GraublauWebBold.otf") format("opentype");
}

#articleHeading {
  font-family: "Graublau Sans Web", "Lucida Grande", "Lucida Sans Unicode", sans-serif;
.....
}
&lt;/pre&gt;

As you can see, it will try to use the new font first, but fall back to how I had it before: Lucida Grande (on Macs) or Lucida Sans Unicode (on Windows).  And it looks like the following, compare it to what you see:

&lt;br /&gt;

&lt;img src="http://www.kehlet.cx/images/2009/07/fontface-example.png" width="430" height="185" alt="font-face tag" /&gt;

&lt;br /&gt;
&lt;br /&gt;

To much to say on this topic.  Some interesting links:
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://arstechnica.com/web/news/2009/07/font-face-typekit-and-font-licensing-the-state-of-web-type.ars?utm_source=Ars+Technica+Newsletter&amp;utm_campaign=b1a1e44c82-July_10_2009_Newsletter&amp;utm_medium=email"&gt;The hazy future of Web typography&lt;/a&gt;&lt;/i&gt;
&lt;li&gt;&lt;a href="http://vimeo.com/1994310?pg=embed&amp;sec="&gt;Comic Sans&lt;/a&gt;, a fascinating documentary about the oft-reviled Comic Sans font.  The opening quote from the creator of Comic Sans, Vincent Connare, is great: "If you love it, you don't know much about typography.  And if you hate it, you really don't know much about typography either and you should get another hobby."
&lt;li&gt;&lt;a href="http://justcreativedesign.com/2009/03/04/the-top-100-best-fonts-of-all-time/"&gt;The Top 100 Best Fonts Of All Time&lt;/a&gt; (note: Helvetica is #1)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://justcreativedesign.com/featured-articles/type-classification-ebook/"&gt;Page Type Classification eBook&lt;/a&gt;.  Free (registration required) PDF discussing the 10 broad classifications of type.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://justcreativedesign.com/2008/03/02/30-best-font-downloads-for-designers/"&gt;30 Fonts That All Designers Must Know &amp; Should Own&lt;/a&gt;.    Caslon is mesmerizing.  Mac OS X appears to come with &lt;a href="http://en.wikipedia.org/wiki/Caslon#Big_Caslon"&gt;Big Caslon&lt;/a&gt;.
&lt;/ul&gt;&lt;img src="http://feeds.feedburner.com/~r/SteveKehletsPages/~4/xRm4xNlepAw" height="1" width="1"/&gt;</description>
            <author>steven@kehlet.cx</author>
            <pubDate>Fri, 10 Jul 2009 23:27:30 -0800</pubDate>
        <feedburner:origLink>http://www.kehlet.cx/articles/195.html</feedburner:origLink></item>
        <item>
            <title>Kean Coffee Open in Tustin</title>
            <link>http://feedproxy.google.com/~r/SteveKehletsPages/~3/mP8zgacU-yo/193.html</link>
            <description>&lt;div style="float: right"&gt;
&lt;div class="right-pullout"&gt;
&lt;a href="http://www.kehlet.cx/images/2009/03/full/IMG_0184.jpg"&gt;&lt;img src="http://www.kehlet.cx/images/2009/03/IMG_0184.jpg" alt="Kean Coffee in Tustin Now Open" class="right-pullout-image"&gt;&lt;/a&gt;
&lt;div class="right-pullout-caption"&gt;
Kean Coffee in Tustin Now Open
&lt;/div&gt;
&lt;/div&gt;

&lt;br /&gt;

&lt;div class="right-pullout"&gt;
&lt;a href="http://www.kehlet.cx/images/2009/03/full/IMG_0185.jpg"&gt;&lt;img src="http://www.kehlet.cx/images/2009/03/IMG_0185.jpg" alt="The Diedrich Roaster" class="right-pullout-image"&gt;&lt;/a&gt;
&lt;div class="right-pullout-caption"&gt;
The Diedrich Roaster
&lt;/div&gt;
&lt;/div&gt;

&lt;br /&gt;

&lt;div class="right-pullout"&gt;
&lt;a href="http://www.kehlet.cx/images/2009/03/full/IMG_0186.jpg"&gt;&lt;img src="http://www.kehlet.cx/images/2009/03/IMG_0186.jpg" alt="The Order Counter" class="right-pullout-image"&gt;&lt;/a&gt;
&lt;div class="right-pullout-caption"&gt;
The Order Counter
&lt;/div&gt;
&lt;/div&gt;

&lt;br /&gt;

&lt;div class="right-pullout"&gt;
&lt;a href="http://www.kehlet.cx/images/2009/03/full/IMG_0187.jpg"&gt;&lt;img src="http://www.kehlet.cx/images/2009/03/IMG_0187.jpg" alt="Lots of People" class="right-pullout-image"&gt;&lt;/a&gt;
&lt;div class="right-pullout-caption"&gt;
Lots of People
&lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


I am thrilled to see Diedrich coffee returning to Tustin under a new brand, Kean Coffee.  The Tustin location has quite a history for me, and from several other people I recognized and/or talked to on Saturday, quite a history for many others as well.

&lt;br /&gt;
&lt;br /&gt;

At age 15 I was introduced to good coffee at the Tustin Diedrich's, and it soon grew to be my regular stomping grounds with friends in high school.  I imagine the older clientele didn't appreciate our loud teenage behavior (I will never forget an incident of slipping on wet floor near the bathroom, falling on my back side, and swearing loudly like only a teenager could in front of at least a dozen other customers), but the coffee was excellent, and the atmosphere upscale but relaxed, so we all managed to get along.  I have so many memories of sitting and talking to friends there over coffee through college.

&lt;br /&gt;
&lt;br /&gt;

That was all quite a while ago.  Fast forward to 2006, and one day I walked into my regular Trabuco Hills Diedrich's and read a little sign on the counter that said &lt;a href="http://www.kehlet.cx/articles/145.html"&gt;Diedrich's was closing its stores and selling them all to Starbucks&lt;/a&gt;.  The horror!  A little piece of myself was getting bulldozed by the evil juggernaut.  Indeed, some time later I recall driving by my old Diedrich's and seeing a cookie cutter Starbucks in its place.  I didn't stop.

&lt;br /&gt;
&lt;br /&gt;

A little while after that, I learned that Martin Diedrich had actually left his namesake business some time ago, and had started up &lt;a href="http://www.kehlet.cx/articles/146.html"&gt;Kean Coffee in Newport Beach&lt;/a&gt;.  That's K&amp;eacute;an, "Kee'-uhn", named after his son.  I visited and actually met the man behind my coffee addiction.  Great coffee.

&lt;br /&gt;
&lt;br /&gt;

Two years later, Starbucks, facing a serious glut of stores in a declining economy, closed the Tustin location.  And an opportunity was born.

&lt;br /&gt;
&lt;br /&gt;

In March 2009 Kean Coffee opened up its second store at that very same location in Tustin.  And on Saturday and Sunday this weekend Angela and I visited it and had coffee.  The choice in locations was obviously no coincidence.  Angela recognized one of the baristas behind the counter, the same guy that used to make her drinks way back when.  I asked one of the other baristas how long the shop had been open--he wasn't quite sure (a few days maybe?), it was his second day, but for him too it was a bit of a homecoming.  He and I exchanged a few stories of how we'd been fans of the old Diedrich's, and the trademark roaster on the premises.  He was clearly a coffee lover and a much bigger connoisseur than I am.  He described his experience so far of working there with the people who select and roast the coffee there every day, and he described a difference between Starbucks and Kean's was that at Kean's, coffee making is a culinary art.  I could sense the awe in his voice.  He said several of the people there had all worked at Diedrich's in the past (some at that very store).  I could only imagine what they had done or given up to come back to where they used to work.  On the way out, the roaster was spinning away under careful oversight.

&lt;br /&gt;
&lt;br /&gt;

I am glad my Diedrich's is back, even better than I remember it.&lt;img src="http://feeds.feedburner.com/~r/SteveKehletsPages/~4/mP8zgacU-yo" height="1" width="1"/&gt;</description>
            <author>steven@kehlet.cx</author>
            <pubDate>Mon, 30 Mar 2009 22:16:28 -0800</pubDate>
        <feedburner:origLink>http://www.kehlet.cx/articles/193.html</feedburner:origLink></item>
        <item>
            <title>Here's Your 99 Cents Change, Sir</title>
            <link>http://feedproxy.google.com/~r/SteveKehletsPages/~3/mAtSyG1H-aw/192.html</link>
            <description>&lt;div class="right-pullout"&gt;
&lt;a href="http://www.kehlet.cx/images/2009/01/full/innout.jpg"&gt;&lt;img src="http://www.kehlet.cx/images/2009/01/innout.jpg" alt="99 cents change" class="right-pullout-image"&gt;&lt;/a&gt;
&lt;div class="right-pullout-caption"&gt;
99 Cents Change
&lt;/div&gt;
&lt;/div&gt;

I saw the amount for my Double-Double combo come up, $6.01, and thought, "Damn, I have no change on me".   I looked through my wallet and handed the guy seven dollars.  He took it, put the money down on the cash register, and started making noises in the coin compartments.  I shot him a look that could only have been interpreted like, "You're not really going to hand me 99 cents in change, are you?"  (Whisk!  Whisk!  Whisk!  The coins kept coming).  

&lt;br /&gt;&lt;br /&gt;

"Here's your 99 cents change, sir".  Three quarters, two dimes, and four pennies.  Not quite the most amount of change one could have in his pocket and still not be able to change it in for a dollar (that would be three quarters, four dimes, and four pennies, see &lt;a href="http://answers.yahoo.com/question/index?qid=20071215111344AAcYjxM"&gt;this post&lt;/a&gt; for that little bit of trivia), but enough to essentially rip me off of one extra dollar, weigh down my pocket, and put a little cha-ching sound into every step.  Sure, I didn't really loose that dollar, I put my change in a bowl at home at night, and every 6-12 months or so we take it to the bank for deposit, but that pocket full of change was aggravating all the same.

&lt;br /&gt;&lt;br /&gt;

Upon sitting down, I noticed my buddy David had ordered the same thing, but his cashier had rung him up as having paid that extra penny, so his change could be handed back in whole dollars.&lt;img src="http://feeds.feedburner.com/~r/SteveKehletsPages/~4/mAtSyG1H-aw" height="1" width="1"/&gt;</description>
            <author>steven@kehlet.cx</author>
            <pubDate>Thu, 22 Jan 2009 18:54:13 -0800</pubDate>
        <feedburner:origLink>http://www.kehlet.cx/articles/192.html</feedburner:origLink></item>
        <item>
            <title>Ruby GD2 and Gradients</title>
            <link>http://feedproxy.google.com/~r/SteveKehletsPages/~3/ZdFwNgHjn6c/190.html</link>
            <description>&lt;img src="/images/2008/09/gradients.png" alt="gradients" width="536" height="56" /&gt;
&lt;br /&gt;
Looks like GD2 doesn't support gradients out of the box.  There are &lt;a href="http://www.google.com/search?client=safari&amp;rls=en-us&amp;q=php+gd+gradient&amp;ie=UTF-8&amp;oe=UTF-8"&gt;tons of PHP gradient implementations&lt;/a&gt; out there, so I borrowed ideas from them to create the following using &lt;a href="http://gd2.rubyforge.org/"&gt;Ruby's GD2 gem&lt;/a&gt;:

&lt;pre class="prettyprint"&gt;
require 'rubygems'
require 'gd2'

# monkey patch in a gradient method
module GD2
  class Canvas
    def gradient(x1, y1, x2, y2, r1, g1, b1, r2, g2, b2)
      height = y2 - y1
      r_delta = (r1 - r2) / height
      g_delta = (g1 - g2) / height
      b_delta = (b1 - b2) / height

      my_y = y1
      my_r = r1
      my_g = g1
      my_b = b1

      0.upto(height) do |i|
        self.color = @image.palette.resolve Color[my_r, my_g, my_b]
        self.rectangle(x1, my_y, x2, my_y + 1, true)

        my_y += 1
        my_r -= r_delta
        my_g -= g_delta
        my_b -= b_delta
      end
    end
  end
end


if __FILE__ == $0
  colors = [[0.77, 0.12, 0.23], [1.00, 0.49, 0.04], [0.67, 0.83, 0.45],
            [0.41, 0.80, 0.94], [0.96, 0.55, 0.73], [1.00, 1.00, 1.00],
            [1.00, 0.96, 0.41], [0.14, 0.35, 1.00], [0.58, 0.51, 0.79],
            [0.78, 0.61, 0.43]]

  i = 1
  colors.each do |c|
    image = GD2::Image.new(50, 50)
    image.draw do |pen|
      pen.gradient(0, 0, 100, 100, c[0], c[1], c[2], 0, 0, 0)
    end
    image.export("gradient-#{i}.png")
    i += 1
  end
end
&lt;/pre&gt;

Monkey patching for the win :-).  The code as-is only creates vertical gradients, but hey, it works and maybe it'll be useful to someone.  Bonus points if anyone can spot the significance of those 10 colors.

&lt;link href="/prettify.css" type="text/css" rel="stylesheet" /&gt;
&lt;script type="text/javascript" src="/prettify.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;prettyPrint();&lt;/script&gt;&lt;img src="http://feeds.feedburner.com/~r/SteveKehletsPages/~4/ZdFwNgHjn6c" height="1" width="1"/&gt;</description>
            <author>steven@kehlet.cx</author>
            <pubDate>Fri, 19 Sep 2008 00:22:59 -0800</pubDate>
        <feedburner:origLink>http://www.kehlet.cx/articles/190.html</feedburner:origLink></item>
        <item>
            <title>Crashes Happen At the Worst Possible Moments</title>
            <link>http://feedproxy.google.com/~r/SteveKehletsPages/~3/J-xUdLkD3WM/189.html</link>
            <description>&lt;a href="/images/2008/09/IMG_0078.jpg"&gt;&lt;img src="/images/2008/09/IMG_0078_small.jpg" width="200" height="150" alt="crash1" /&gt;&lt;/a&gt;
&lt;a href="/images/2008/09/IMG_0079.jpg"&gt;&lt;img src="/images/2008/09/IMG_0079_small.jpg" width="200" height="150" alt="crash2" /&gt;&lt;/a&gt;

&lt;br /&gt;

Crashes happen at the worst possible moments.  I was just logging into the timesheet system, ready to get out of here on Friday...  and my system blew up.  Granted, I was pushing it pretty hard--look at my dock in the second image--I had about a million Safari windows open, a dozen terminals, Eclipse, &lt;i&gt;both&lt;/i&gt; VMWare and VirtualBox going, streaming music with iTunes, some IO-intensive file copies going (copying some 2GB disk images around to create a few more VM Linux instances), and so on.  

&lt;br /&gt;
&lt;br /&gt;

On Friday, I was determined to title this post "Mother F---er", but a while back I decided to keep things PG around here.  So use your imagination.&lt;img src="http://feeds.feedburner.com/~r/SteveKehletsPages/~4/J-xUdLkD3WM" height="1" width="1"/&gt;</description>
            <author>steven@kehlet.cx</author>
            <pubDate>Thu, 18 Sep 2008 00:17:26 -0800</pubDate>
        <feedburner:origLink>http://www.kehlet.cx/articles/189.html</feedburner:origLink></item>
        <item>
            <title>QotD: I think the pressure that we feel mostly is not necessarily from outside, but from ...</title>
            <link>http://feedproxy.google.com/~r/SteveKehletsPages/~3/E4jZzZTkUMI/188.html</link>
            <description>From Eurogamer's &lt;a href="http://www.eurogamer.net/article.php?article_id=221566&amp;page=1"&gt;World of Warcraft: Wrath of the Lich King interview by Oli Welsh&lt;/a&gt;:

&lt;blockquote&gt;
Eurogamer: You're at the stage where the game's getting a bit older and you've got stiffer competition out there, certainly than when Burning Crusade released. Do you feel under more pressure this time?
&lt;br /&gt;
&lt;br /&gt;
Tom Chilton: Well, we are definitely trying to one-up ourselves. I feel that in a lot of ways, we're doing that - I feel very confident about the quality of the zones and quests, the fact that we're introducing a new class that seems to be going over pretty well. But there's definitely pressure, no doubt about it, and I'm sure that's going to continue to mount, year on year. But at this point, we're feeling pretty good about it.
&lt;br /&gt;
&lt;br /&gt;
J. Allen Brack: But I think the pressure that we feel mostly is not necessarily from outside, but from ourselves and our fans.
&lt;/blockquote&gt;

You bet the pressure is coming from the fans.  Watch &lt;a href="http://www.gametrailers.com/player/38372.html"&gt;the latest Warhammer Online&lt;/a&gt; trailer and tell me that you wouldn't want to play &lt;i&gt;that&lt;/i&gt;.

&lt;br /&gt;
&lt;br /&gt;

&lt;a href="http://www.gametrailers.com/player/38372.html"&gt;&lt;img src="/images/2008/08/warhammer.jpg" width="200" height="120" alt="Warhammer" /&gt;&lt;/a&gt;&lt;img src="http://feeds.feedburner.com/~r/SteveKehletsPages/~4/E4jZzZTkUMI" height="1" width="1"/&gt;</description>
            <author>steven@kehlet.cx</author>
            <pubDate>Thu, 28 Aug 2008 19:47:27 -0800</pubDate>
        <feedburner:origLink>http://www.kehlet.cx/articles/188.html</feedburner:origLink></item>
        <item>
            <title>Hello, JRuby Rack and Glassfish</title>
            <link>http://feedproxy.google.com/~r/SteveKehletsPages/~3/JImPnCfplLg/187.html</link>
            <description>&lt;a href="http://rack.rubyforge.org/"&gt;Rack&lt;/a&gt; "provides an minimal interface between webservers supporting Ruby and Ruby frameworks" and &lt;a href="http://wiki.jruby.org/wiki/JRuby_Rack"&gt;JRuby Rack&lt;/a&gt; is its logical extension to Java servlet containers.  The latter states "JRuby-Rack supports Rails, Merb, &lt;i&gt;as well as any Rack-compatible Ruby web framework.&lt;/i&gt;"  While &lt;a href="http://wiki.jruby.org/wiki/Warbler"&gt;Warbler&lt;/a&gt; makes deploying Rails apps to Glassfish and other Java servlet containers easier than ever, there are scant few (or at least, none I could find) examples of deploying any old Rack-based Ruby web application to Glassfish.  So here's what I figured out.

&lt;br /&gt;
&lt;br /&gt;

Basically, create a war file with a web.xml, jruby-complete-1.1.3.jar, and jruby-rack-0.9.1.jar.  Here's the directory structure I used to build the war:

&lt;pre class="prettyprint"&gt;
$ find .
.
./WEB-INF
./WEB-INF/lib
./WEB-INF/lib/jruby-complete-1.1.3.jar
./WEB-INF/lib/jruby-rack-0.9.1.jar
./WEB-INF/web.xml
&lt;/pre&gt;

Grab a &lt;a href="http://repository.codehaus.org/org/jruby/jruby-complete/1.1.3/jruby-complete-1.1.3.jar"&gt;precompiled version of jruby-complete-1.1.3.jar&lt;/a&gt; or &lt;a href="http://www.ruby-forum.com/topic/160345"&gt;follow these instructions&lt;/a&gt; to build it from the &lt;a href="http://dist.codehaus.org/jruby/"&gt;source&lt;/a&gt;.  Likewise, grab &lt;a href="http://repository.codehaus.org/org/jruby/rack/jruby-rack/0.9.1/"&gt;jruby-rack-0.9.1.jar&lt;/a&gt;.  (I had local copies of both from using Warbler to build a war for one of my Rails apps, look around).

&lt;br /&gt;
&lt;br /&gt;

Here's the "tricky" part, the web.xml, with the interesting parts in red:

&lt;br /&gt;
&lt;br /&gt;

&lt;code&gt;
&amp;lt;!DOCTYPE&amp;nbsp;web-app&amp;nbsp;PUBLIC&lt;br /&gt;
&amp;nbsp;&amp;nbsp;"-//Sun&amp;nbsp;Microsystems,&amp;nbsp;Inc.//DTD&amp;nbsp;Web&amp;nbsp;Application&amp;nbsp;2.3//EN"&lt;br /&gt;
&amp;nbsp;&amp;nbsp;"http://java.sun.com/dtd/web-app_2_3.dtd"&amp;gt;&lt;br /&gt;
&amp;lt;web-app&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;context-param&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;param-name&amp;gt;public.root&amp;lt;/param-name&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;param-value&amp;gt;/&amp;lt;/param-value&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;/context-param&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;context-param&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;param-name&amp;gt;&lt;span style="color: red"&gt;rackup&lt;/span&gt;&amp;lt;/param-name&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;param-value&amp;gt;&lt;br /&gt;
&lt;span style="color: red"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;app&amp;nbsp;=&amp;nbsp;lambda&amp;nbsp;{&amp;nbsp;|env|&amp;nbsp;[200,&amp;nbsp;{},&amp;nbsp;'Hello&amp;nbsp;World!']&amp;nbsp;}&amp;nbsp;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;run&amp;nbsp;app&lt;br /&gt;
&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/param-value&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;/context-param&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;filter&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;filter-name&amp;gt;RackFilter&amp;lt;/filter-name&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;filter-class&amp;gt;org.jruby.rack.RackFilter&amp;lt;/filter-class&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;/filter&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;filter-mapping&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;filter-name&amp;gt;RackFilter&amp;lt;/filter-name&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;url-pattern&amp;gt;/*&amp;lt;/url-pattern&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;/filter-mapping&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;listener&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;listener-class&amp;gt;&lt;span style="color: red"&gt;org.jruby.rack.RackServletContextListener&lt;/span&gt;&amp;lt;/listener-class&amp;gt;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;/listener&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/web-app&amp;gt;&lt;br /&gt;
&lt;/code&gt;

&lt;br /&gt;
&lt;br /&gt;

The &lt;code&gt;rackup&lt;/code&gt; parameter is the key, it glues the servlet to your backend application (I see in the TODO is to allow this script to be defined in a file instead of in the web.xml).  The value of the parameter is a simple Rack-compliant application, borrowed from &lt;a href="http://yeahnah.org/files/rack-presentation-oct-07.pdf"&gt;this Rack presentation&lt;/a&gt;.

&lt;br /&gt;
&lt;br /&gt;

You can build a war from this:

&lt;pre&gt;
$ jar cvf ../test.war
*added manifest
adding: WEB-INF/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/lib/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/lib/jruby-complete-1.1.3.jar(in = 7341701) (out= 6541093)(deflated 10%)
adding: WEB-INF/lib/jruby-rack-0.9.1.jar(in = 192848) (out= 53055)(deflated 72%)
adding: WEB-INF/web.xml(in = 794) (out= 351)(deflated 55%)
&lt;/pre&gt;

and deploy it to your favorite Java servlet container.  Hit it with your browser and you should see "Hello World!"  It's amazing, it just works.

&lt;br /&gt;
&lt;br /&gt;

Baby steps!  Next to figure out is how to get a full Rack-compliant app, like something built using &lt;a href="http://ramaze.net/"&gt;Ramaze&lt;/a&gt;, running in Glassfish.

&lt;br /&gt;
&lt;br /&gt;

Thanks go to &lt;a href="http://www.gittr.com/index.php/archive/jruby-rack-doesnt-work-with-sinatra/"&gt;this post&lt;/a&gt;, which was very helpful in figuring out what to do.&lt;img src="http://feeds.feedburner.com/~r/SteveKehletsPages/~4/JImPnCfplLg" height="1" width="1"/&gt;</description>
            <author>steven@kehlet.cx</author>
            <pubDate>Thu, 14 Aug 2008 20:29:51 -0800</pubDate>
        <feedburner:origLink>http://www.kehlet.cx/articles/187.html</feedburner:origLink></item>
        <item>
            <title>Handy tcpdump Expression to Gather CDP Information</title>
            <link>http://feedproxy.google.com/~r/SteveKehletsPages/~3/Vmz8Nh9-h4Y/186.html</link>
            <description>This &lt;code&gt;tcpdump&lt;/code&gt; command will sniff for Cisco switches' &lt;a href="http://en.wikipedia.org/wiki/Cisco_Discovery_Protocol"&gt;Cisco Discovery Protocol (CDP)&lt;/a&gt; packets.  It's useful to add to your regular arsenal of pings and traceroutes if you're working on a system on a foreign network of which you were given little to no information.  Oh, this assumes you have root access of course.  Change &lt;code&gt;eth0&lt;/code&gt; of course to match the network interface(s) you want to examine.  

&lt;br /&gt;
&lt;br /&gt;

&lt;code&gt;tcpdump -nn -v -i eth0 -s 1500 -c 1 'ether[20:2] == 0x2000'&lt;/code&gt;

&lt;br /&gt;
&lt;br /&gt;

CDP packets offer some additional insight to the network you're on:

&lt;blockquote&gt;
The information contained in CDP announcements varies by the type of device and the version of the operating system running on it. Information contained includes the operating system version, hostname, every address for every protocol configured on the port where CDP frame is sent eg. IP address, the port identifier from which the announcement was sent, device type and model, duplex setting, VTP domain, native VLAN, power draw (for Power over Ethernet devices), and other device specific information. 
&lt;/blockquote&gt;

You &lt;code&gt;tcpdump&lt;/code&gt; output might look something like (IP address XX'd out):

&lt;pre&gt;
14:42:57.087609 CDPv2, ttl: 180s, checksum: 692 (unverified), length 358
      Device-ID (0x01), length: 11 bytes: 'Public_DMZ'
      Address (0x02), length: 13 bytes: IPv4 (1) XXX.XXX.XX.X
      Port-ID (0x03), length: 16 bytes: 'FastEthernet0/21'
      Capability (0x04), length: 4 bytes: (0x00000028): L2 Switch,
IGMP snooping
      Version String (0x05), length: 220 bytes:
        Cisco Internetwork Operating System Software
        IOS (tm) C2950 Software (C2950-I6Q4L2-M), Version 12.1(12c)EA1,
RELEASE SOFTWARE (fc1)
        Copyright (c) 1986-2002 by cisco Systems, Inc.
        Compiled Sun 24-Nov-02 23:31 by antonino
      Platform (0x06), length: 21 bytes: 'cisco WS-C2950G-24-EI'
      Protocol-Hello option (0x08), length: 32 bytes:
      VTP Management Domain (0x09), length: 0 byte: ''
1 packets captured
2 packets received by filter
0 packets dropped by kernel
&lt;/pre&gt;&lt;img src="http://feeds.feedburner.com/~r/SteveKehletsPages/~4/Vmz8Nh9-h4Y" height="1" width="1"/&gt;</description>
            <author>steven@kehlet.cx</author>
            <pubDate>Fri, 08 Aug 2008 18:48:43 -0800</pubDate>
        <feedburner:origLink>http://www.kehlet.cx/articles/186.html</feedburner:origLink></item>
        <item>
            <title>Equal Suffering in JavaScript</title>
            <link>http://feedproxy.google.com/~r/SteveKehletsPages/~3/A5EABIfBdAw/185.html</link>
            <description>/sigh
&lt;br /&gt;

&lt;pre class="prettyprint"&gt;
&amp;lt;script type="text/javascript"&amp;gt;
document.write("0 == \"\": " + (0 == "") + "&amp;lt;br /&amp;gt;\n");
&amp;lt;/script&amp;gt;
&lt;/pre&gt;

yields:

&lt;pre class="prettyprint"&gt;
0 == "": true
&lt;/pre&gt;

Yes, zero is equal to a blank string in JavaScript.

&lt;br /&gt;
&lt;br /&gt;

This bit me today in a form validation function in a publicly-released app and marred what was otherwise a triumphant rewrite of someone else's steaming heap of cow dung (trust me on this one).  I suppose there's a lesson there, for as well-intentioned as I was, but I'm not going to get into it.  

&lt;br /&gt;
&lt;br /&gt;

As I discovered, &lt;code&gt;==&lt;/code&gt; performs type coercion and, to JavaScript, &lt;code&gt;0&lt;/code&gt; is the same thing as an empty string (nothing?).  It helps a little to see that &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;""&lt;/code&gt;, and &lt;code&gt;false&lt;/code&gt; are all equal.  But then, a little frightening that a string full of whitespace is also equal to &lt;code&gt;false&lt;/code&gt; but &lt;i&gt;not&lt;/i&gt; equal to an empty string (transitive property, anyone?).

&lt;br /&gt;
&lt;br /&gt;

The &lt;code&gt;===&lt;/code&gt; (triple equals) operator is available if you want exact type and value matching:

&lt;pre class="prettyprint"&gt;
&amp;lt;script type="text/javascript"&amp;gt;
document.write("0 === \"\": " + (0 === "") + "&amp;lt;br /&amp;gt;\n");
&amp;lt;/script&amp;gt;
&lt;/pre&gt;

yields:

&lt;pre class="prettyprint"&gt;
0 === "": false
&lt;/pre&gt;

But watch out!  You probably want coercion most of the time (e.g. strings in input fields to ints).  Just be aware.

&lt;br /&gt;
&lt;br /&gt;

For the curious there's plenty more info on the topic &lt;a href="http://www.google.com/search?hl=en&amp;client=safari&amp;rls=en-us&amp;q=javascript+%3D%3D%3D+triple+equals&amp;btnG=Search"&gt;out there&lt;/a&gt;.  A good reference is &lt;a href="http://dreaminginjavascript.wordpress.com/2008/07/27/falsies/"&gt;this matrix of == and === equalities&lt;/a&gt;.

&lt;link href="/prettify.css" type="text/css" rel="stylesheet" /&gt;
&lt;script type="text/javascript" src="/prettify.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;prettyPrint();&lt;/script&gt;&lt;img src="http://feeds.feedburner.com/~r/SteveKehletsPages/~4/A5EABIfBdAw" height="1" width="1"/&gt;</description>
            <author>steven@kehlet.cx</author>
            <pubDate>Fri, 08 Aug 2008 01:39:10 -0800</pubDate>
        <feedburner:origLink>http://www.kehlet.cx/articles/185.html</feedburner:origLink></item>
        <item>
            <title>Latest DNS Cache Poisoning Vulnerability Explained</title>
            <link>http://feedproxy.google.com/~r/SteveKehletsPages/~3/yA-fF-fcFX8/184.html</link>
            <description>The recent, urgent news about the majority of the Internet's DNS system being vulnerable to poisoning attacks have been all over the &lt;a href="http://news.google.com/news?hl=en&amp;ned=us&amp;q=dns+exploit&amp;btnG=Search+News"&gt;news&lt;/a&gt;.  At the high level, the vulnerability is that tons of existing, publicly accessible DNS servers can be tricked fairly easily, using readily available exploit scripts, into storing and serving up bogus DNS information, and that people could thus be unknowingly tricked into accessing malicious sites and, say, possibly compromise their sensitive information (e.g. entering credentials at a fake wellsfargo.com). Note for any HTTPS-enabled site it would still be fairly obvious that you are not accessing the real site because your browser would detect and alert you of the invalid certificates--however, ultimately it is still left to the user's discretion to recognize the danger when the browser warns him or her, instead of just clicking "proceed anyway".

&lt;br /&gt;
&lt;br /&gt;

Poisoning DNS servers is nothing new.  However this particular exploit is far more feasible and dangerous than its predecessors.  Credit is generally given to &lt;a href="http://www.doxpara.com"&gt;Dan Kaminsky&lt;/a&gt; for raising awareness of the criticality of this issue and coordinating a massive effort with vendors to issue patches.  He gave the vendors time to make patches, then the public time to apply them before publicly releasing all the details.  In admirably white hat fashion, he did everything altruistically and "right".  Kudos.

&lt;br /&gt;
&lt;br /&gt;

The exploit builds off the old trick of spoofing replies back to the requesting name server.  
The challenges for the attacker are:

&lt;ol&gt;
&lt;li&gt;Knowing when a DNS server is issuing a particular DNS lookup,&lt;/li&gt;
&lt;li&gt;Guessing the DNS query's transaction ID (the spoofed reply must have a transaction ID matching what was used in the original query),&lt;/li&gt;
&lt;li&gt;Creating a proper spoofed packet with poisoned information in it, and&lt;/li&gt;
&lt;li&gt;Getting the spoofed response to the requester before the real response comes back.&lt;/li&gt;
&lt;/ol&gt;

How can an attacker overcome these challenges?

&lt;ol&gt;
&lt;li&gt;#1 is a real challenge since a DNS server will only perform a name lookup every once in a while (every Time To Live [TTL], usually hours or days).  If the server doesn't already have a name cached, you know you can try to spoof the response right then, but you only get one shot.&lt;/li&gt;
&lt;li&gt;#2 is not as hard, theoretically it should be possible to blast back 65,536 spoofed responses (one for each transaction ID).  The fact this ID is only 16 bit is generally accepted as being too weak.&lt;/li&gt;
&lt;li&gt;For #3, the vulnerable DNS servers in question reuse the same source port for every outgoing request, which makes crafting the spoofed return UDP packets trivial (&lt;i&gt;DNS servers that already randomized the source port are generally seen as being practically immune to this exploit, since attackers would have to guess nearly 2^32 combinations instead of only 65,536&lt;/i&gt;). 
&lt;li&gt;For #4, optional "good netizen" ISP egress filtering may stop spoofed packets.  And latency may work against an attacker.  But an attacker attacking his own ISP might not face either of these problems.
&lt;/ol&gt;

Overall, an attacker would need an insane amount of patience and luck to pull this off.

&lt;br /&gt;
&lt;br /&gt;

The two twists with the new exploit are that it overcomes challenge #1, and indirectly poisons the DNS server through the use of additional Resource Records (RRs).  (&lt;i&gt;Side note: as another security precaution, RRs are only trusted in a response if they're in the same "bailiwick", or domain, as the name requested (i.e. you can't poison a server with bad RRs for someone else's domain, say yahoo.com,  if the lookup was for google.com).  However this is not an issue at all for this particular exploit.&lt;/i&gt;).  The attacker repeatedly asks the victim DNS server for tons of different lookups for subdomains of the desired name to spoof (1.google.com, 2.google.com, 3.google.com, etc), blasts tons of spoofed responses back hoping one transaction ID will match, and in each response adds an additional, poisoned RR, containing the name to spoof and whatever IP address the attacker desires.

&lt;br /&gt;
&lt;br /&gt;

Example:

&lt;ol&gt;
&lt;li&gt;Attacker asks Victim DNS Server: who is 1.google.com?&lt;/li&gt;
&lt;li&gt;Victim DNS server asks the authority for google.com, who is 1.google.com?&lt;/li&gt;
&lt;li&gt;Attacker blasts Victim with spoofed responses, each containing a different transaction ID.  The packet contains a response with an IP for 1.google.com, as well as an additional RR stating www.google.com is an IP address of the Attacker's choosing.&lt;/li&gt;
&lt;li&gt;(Here is the exploit) If a valid, spoofed response is received before the real response comes back, the Victim updates its cache with both the requested info &lt;i&gt;as well as the poisonous IP information contained in the RR&lt;/i&gt;.  The subsequent response from the authority for google.com is discarded.&lt;/li&gt;
&lt;/ol&gt;

This is repeated as necessary, with new subdomain requests, until one of the spoofed responses takes.  When it takes, the attacker has circumvented the TTL problem and outsmarted the bailiwick defense.  Reports are this can happen in less than 10 minutes.

&lt;br /&gt;
&lt;br /&gt;

10 minutes to replace cnn.com, or youtube.com, or any other popular site with a site of your own choosing.  Defame a site, get people to read your manifesto or see something embarrassing or obscene, or try to phish for their personal information.  Yes, this really is a big deal--yes, only for the people using the victimized DNS server, but if an attacker were able to target DNS servers at several large ISPs, it could have a huge impact.

&lt;br /&gt;
&lt;br /&gt;

If the above wasn't clear enough, I would recommend reading &lt;a href="http://beezari.livejournal.com/141796.html"&gt;this copy of someone leaking the information&lt;/a&gt; before it should have been publicly disclosed (it has been &lt;a href="http://www.google.com/search?hl=en&amp;q=Poisoning+CXOPQ.VICTIM.COM+is+not+super+valuable+to+Mallory"&gt;mirrored everywhere&lt;/a&gt;).  While it's not perfect (enough with the deli analogy), it does explain the problem fairly well.

&lt;br /&gt;
&lt;br /&gt;

Also &lt;a href="http://www.securiteam.com/exploits/5EP0M15OUQ.html"&gt;this sample exploit code&lt;/a&gt; provides a good technical summary of what the problem is and how it works.  It's worth reading through the code to get a feel for how it all works.  I particularly like the technique in cmd_check() of discovering what port your DNS server uses to make requests (issuing a TXT lookup to spoofprobe-check-x-xxxxxx.red.metasploit.com, which returns a value of hostname:port).

&lt;blockquote&gt;
This exploit attacks a fairly ubiquitous flaw in DNS implementations which
Dan Kaminsky found and disclosed ~Jul 2008. This exploit caches a single
malicious host entry into the target nameserver by sending random sub-domain
queries to the target DNS server coupled with spoofed replies to those
queries from the authoritative nameservers for the domain which contain a
malicious host entry for the hostname to be poisoned in the authority and
additional records sections. Eventually, a guessed ID will match and the
spoofed packet will get accepted, and due to the additional hostname entry
being within bailiwick constraints of the original request the malicious host
entry will get cached.
&lt;/blockquote&gt;

&lt;br /&gt;

So what's the fix?  There really is no fix, short of &lt;a href="http://www.isc.org/index.pl?/sw/bind/index.php"&gt;using DNSSEC&lt;/a&gt;, or moving to some other cryptographic method of trust.  &lt;a href="http://blogs.zdnet.com/security/?p=1552"&gt;Using TCP instead of UDP&lt;/a&gt; has come up (this would add the additional, now nearly impossible challenge of guessing sequence numbers), but was shot down as being too resource intensive.  So the accepted workaround is what was already mentioned above: DNS servers should &lt;a href="http://www.circleid.com/posts/87143_dns_not_a_guessing_game/"&gt;randomize their source ports&lt;/a&gt;.  Then attackers would have a much, much harder time spoofing the return packets.  There appears to be &lt;a href="http://www.mail-archive.com/cryptography@metzdowd.com/msg09466.html"&gt;some reaction&lt;/a&gt; that this is old news, and many DNS server implementations had already done this, long ago.  Just not the big ones :-) (e.g. BIND).

&lt;br /&gt;
&lt;br /&gt;

Finale: Patches for all affected DNS servers should be up by now.  Be sure to patch your systems.

&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;Update 6:12pm:&lt;/i&gt; &lt;a href="http://www.caughq.org/exploits/CAU-EX-2008-0003.txt"&gt;a newer version of the example exploit code&lt;/a&gt; demonstrates how to replace NS records for an entire domain (vs. a single A record).&lt;img src="http://feeds.feedburner.com/~r/SteveKehletsPages/~4/yA-fF-fcFX8" height="1" width="1"/&gt;</description>
            <author>steven@kehlet.cx</author>
            <pubDate>Fri, 25 Jul 2008 23:46:12 -0800</pubDate>
        <feedburner:origLink>http://www.kehlet.cx/articles/184.html</feedburner:origLink></item>
        <item>
            <title>Handy Mac OS Instant Dictionary Lookup</title>
            <link>http://feedproxy.google.com/~r/SteveKehletsPages/~3/Z33lEeffrGM/183.html</link>
            <description>Reading the NY Times, and finding its writers love using just a bit too much obscure language?  Reading a reference to a person that you don't quite remember?  No problem, just mouse over the word, hit Control-Command-D, and get an instant popup dictionary lookup of the word.

&lt;br /&gt;
&lt;br /&gt;

Sorry Firefox users, this only works for Cocoa apps.  Another reason to use Safari.

&lt;img src="http://www.kehlet.cx/images/2008/07/ctrl-cmd-d.jpg" width="400" height="141" alt="Instant Dictionary Lookup" /&gt;&lt;img src="http://feeds.feedburner.com/~r/SteveKehletsPages/~4/Z33lEeffrGM" height="1" width="1"/&gt;</description>
            <author>steven@kehlet.cx</author>
            <pubDate>Fri, 25 Jul 2008 17:32:16 -0800</pubDate>
        <feedburner:origLink>http://www.kehlet.cx/articles/183.html</feedburner:origLink></item>
        <item>
            <title>My Bloody Valentine are Back</title>
            <link>http://feedproxy.google.com/~r/SteveKehletsPages/~3/4947592bWpI/182.html</link>
            <description>&lt;img src="/images/2008/07/mbv.jpg" width="474" height="277" alt="MBV" /&gt;

&lt;br /&gt;

Just now, on a whim (actually, after reading something else that jogged my memory), I googled around to see if anything had happened in the last decade from a favorite band of mine from my college days, &lt;i&gt;My Bloody Valentine&lt;/i&gt;.  For years, Kevin Shields, the lead of the group, kept promising more albums to follow the group's most successful album from '92, &lt;a href="http://en.wikipedia.org/wiki/Loveless_(album)"&gt;&lt;i&gt;Loveless&lt;/i&gt;&lt;/a&gt;, but it just never happened.  Rumor was they had nearly bankrupted Creation records in creating &lt;i&gt;Loveless&lt;/i&gt;, and it seemed he was set to do it again with his new label, Island, spending lots of money but never quite coming up with anything good enough (in his opinion) to release.

&lt;br /&gt;
&lt;br /&gt;

I was even on a mailing list for fans of the group.  Slowly, after years of false promises, rumors, and nothing but "Hey, Kevin played with such-and-such group the other day...", we finally gave up on any new MBV content and slowly trickled off.

&lt;br /&gt;
&lt;br /&gt;

I still listen to &lt;i&gt;Loveless&lt;/i&gt; in the car occasionally.  

&lt;br /&gt;
&lt;br /&gt;

Today my googling revealed the band are back together, and playing concerts.  They will be in the US this fall.  A new album may be on the way.  And with the marvels of our modern Internet, right now I'm watching &lt;a href="http://www.youtube.com/watch?v=jNlwE4Bxd0U&amp;feature=related"&gt;a YouTube video of &lt;i&gt;My Bloody Valentine&lt;/i&gt;&lt;/a&gt; blasting the eardrums out of every single person in what looks like a packed room full of people.  Amazing!  Horrible sound and video quality aside, you are still assaulted by the heavily-distorted guitar wails and "glides" that are the band's signature, more powerful and raw than I've ever heard before.

&lt;br /&gt;
&lt;br /&gt;

A search away and I also found &lt;a href="http://www.youtube.com/watch?v=NiuRoJr-eOQ"&gt;a recent performance of &lt;i&gt;To Here Knows When&lt;/i&gt;&lt;/a&gt;, a nonsensical title of one of my favorites.  Wow, all kinds of videos up there.

&lt;br /&gt;
&lt;br /&gt;

There is also an &lt;a href="http://webinfront.net/?p=478/"&gt;mp3 recording&lt;/a&gt; available of the whole concert.  Apparently, they're just playing existing material, nothing new, which is a small disappointment, but after slowly becoming disillusioned long ago, and frankly never expecting to hear anything from them again, it's a welcome treat.&lt;img src="http://feeds.feedburner.com/~r/SteveKehletsPages/~4/4947592bWpI" height="1" width="1"/&gt;</description>
            <author>steven@kehlet.cx</author>
            <pubDate>Sat, 19 Jul 2008 00:38:17 -0800</pubDate>
        <feedburner:origLink>http://www.kehlet.cx/articles/182.html</feedburner:origLink></item>
        <item>
            <title>Safari + GreaseKit + Auto BBC Self for Gmail.  Oh, and Fluid Too</title>
            <link>http://feedproxy.google.com/~r/SteveKehletsPages/~3/BJQYx7WmFl4/178.html</link>
            <description>I keep trying Firefox, but ultimately I keep coming back to Safari.  Safari is faster, less system resource intensive, and looks and feels better on the Mac.  Firefox 3 has come a very, very long way since version 2 (kudos to you guys for continually trying), but still, it's just not as nice of a browser as Safari.

&lt;br /&gt;&lt;br /&gt;

Unfortunately, running Safari means living in the minority and running into those occasional issues.  People don't test their sites with Safari.  Safari is less forgiving, so crappy html/javascript/css that works in IE or Firefox sometimes doesn't work in Safari.  

&lt;br /&gt;&lt;br /&gt;

And finally, we miss out on the single biggest thing Firefox has going for it: the wealth of community-driven addons and extensions.  While there are a few I miss, the basics are there, and they're really all you need.  Here are a few:

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://safariadblock.sourceforge.net/"&gt;Safari AdBlock&lt;/a&gt; is a must have.  Stop those banner ads, and &lt;a href="http://www.kehlet.cx/articles/159.html"&gt;annoying Vibrant mouseover popups&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://8-p.info/greasekit/"&gt;GreaseKit&lt;/a&gt;: GreaseMonkey for Safari.  What's &lt;a href="http://en.wikipedia.org/wiki/Greasemonkey"&gt;GreaseMonkey&lt;/a&gt;?  It's a scripting engine that allows you to tweak web pages your browser, using Javascript.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://userscripts.org/scripts/show/8810"&gt;Folders4Gmail&lt;/a&gt;: hierarchical tags for Gmail (requires GreaseMonkey/Kit).&lt;/li&gt;
&lt;/ul&gt;

Unfortunately, &lt;a href="http://userscripts.org/scripts/show/2255"&gt;Gmail Auto BCC&lt;/a&gt; (a handy GreaseMonkey script to always bcc yourself on GMail, since Gmail currently doesn't offer this feature) does not work in GreaseKit.  It uses a persistence API that GreaseKit had to remove for security reasons a while ago (hopefully it will come back soon).  

&lt;br /&gt;&lt;br /&gt;

So in its place, I present a slimmer, cleaner "Gmail Auto Self BCC" GreaseMonkey/Kit script (that works in Safari, of course) that simply populates your From address into the bcc field whenever you hit Send in GMail.  The source is below, or you can &lt;a href="/docs/2008/06/gmailautoselfbcc.user.js"&gt;download it here&lt;/a&gt;.  Compare this source code to &lt;a href="http://userscripts.org/scripts/review/2255"&gt;the original&lt;/a&gt;, from which I borrowed some ideas.

&lt;br /&gt;&lt;br /&gt;

&lt;img src="http://www.kehlet.cx/images/2008/06/Dock.png" alt="Dock" /&gt;
&lt;br /&gt;

On a related note, I recently gave Firefox another try for a couple weeks.  What finally got me to switch back to Safari/Webkit was &lt;a href="http://fluidapp.com/"&gt;Fluid&lt;/a&gt;.  Fluid allows you to create standalone apps out of any web page.  Now I can have standalone, dockable apps for Gmail (work and home), Calendar, Reader, and not have any of my testing and development work in Safari or Firefox hang or crash or otherwise mess them up.  It's awesome.

&lt;pre class="prettyprint"&gt;
// ==UserScript==
// @name          Gmail Auto Self BCC
// @namespace     http://www.kehlet.cx/
// @description   Automatically copy your From address into the bcc field (done upon hitting Send) so all mail you originate shows up in your Inbox.  For GMail v2.
// @include       http*://mail.google.com/*
// ==/UserScript==

window.addEventListener("load", loader, false);

function loader() {
   var api = typeof unsafeWindow != "undefined" &amp;amp;&amp;amp; unsafeWindow.gmonkey ||
             (frames.js ? frames.js.gmonkey : null);
   if (api) api.load("1.0", init);
}

function init(gmail) {

   function findElement(root, name) {
      var elts = root.getElementsByName(name);
      return elts ? elts[0] : null;
   }

   function handleClicks(event) {
      var elt = event.target;
      if (elt.innerText == 'Send') {
         var fromElt = findElement(elt.ownerDocument, 'from');
         if (fromElt) {
            var bccElt = findElement(elt.ownerDocument, 'bcc');
            if (bccElt) {
               var re = new RegExp(fromElt.value);
               if (!bccElt.value.match(re)) {
                  bccElt.value = bccElt.value ? bccElt.value + ', ' + fromElt.value : fromElt.value;
               }
            }
         }
      }
   }
   
   function viewChanged() {
      var view = gmail.getActiveViewType();
      if (view == 'co' || view == 'cv') {
         var root = gmail.getNavPaneElement().ownerDocument;
         root.addEventListener('click', handleClicks, true);
      }
   }

   gmail.registerViewChangeCallback(viewChanged);
}
&lt;/pre&gt;

&lt;link href="/prettify.css" type="text/css" rel="stylesheet" /&gt;
&lt;script type="text/javascript" src="/prettify.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;prettyPrint();&lt;/script&gt;&lt;img src="http://feeds.feedburner.com/~r/SteveKehletsPages/~4/BJQYx7WmFl4" height="1" width="1"/&gt;</description>
            <author>steven@kehlet.cx</author>
            <pubDate>Tue, 17 Jun 2008 21:35:33 -0800</pubDate>
        <feedburner:origLink>http://www.kehlet.cx/articles/178.html</feedburner:origLink></item>
        <item>
            <title>Ruby Sequel</title>
            <link>http://feedproxy.google.com/~r/SteveKehletsPages/~3/8b1U7liIN_M/174.html</link>
            <description>Recently I needed to write a one-shot script to migrate data from one database to another, as my employer rolled out a new version of one of the company's internal software apps.  Instead of just cranking out something in PHP, I decided to give &lt;a href="http://sequel.rubyforge.org/"&gt;Sequel&lt;/a&gt; a shot.  

&lt;br /&gt;&lt;br /&gt;

Sequel presents the database to you as if it were a nested set of arrays.  My script was a bigger and only slightly more elaborate version of the following simple script:

&lt;pre class="prettyprint"&gt;
sourcedb = Sequel.open 'postgres://user:pass@x.x.x.x/dbname'
destdb = Sequel.open 'postgres://user:pass@y.y.y.y/dbname'

destdb.transaction do

  destdb[:devicemodel].delete

  sourcedb[:devicemodel].each do |row|

    # perform fixup/conversion here

    destdb[:devicemodel] &lt;&lt; row
  end

  # other tables here

end
&lt;/pre&gt;

The neat thing too is if you just want to run some SQL because you know exactly what you need to do, it's easy, and the results are returned to you in the same way that you can iterate over:

&lt;pre class="prettyprint"&gt;
  emails = db["select distinct emailcontact from contact where accountkey in (select distinct accountkey from contract)"].all

  emails.each do |row|
    next if row[:emailcontact].nil?
    puts row[:emailcontact]
  end
&lt;/pre&gt;

For a more thorough introduction I'd read this &lt;a href="http://on-ruby.blogspot.com/2008/01/sequel-interview-with-sharon-rosner.html"&gt;interview with Sharon Rosner&lt;/a&gt;, the creator of Sequel, discussing why Sequel was born and where it's a good fit versus other existing ORM tools.  For my migration script, it was great, allowing me to write simple Ruby loops  manipulating the data as an array, yet allowing me to do raw SQL wherever it was easier.

&lt;link href="/prettify.css" type="text/css" rel="stylesheet" /&gt;
&lt;script type="text/javascript" src="/prettify.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;prettyPrint();&lt;/script&gt;&lt;img src="http://feeds.feedburner.com/~r/SteveKehletsPages/~4/8b1U7liIN_M" height="1" width="1"/&gt;</description>
            <author>steven@kehlet.cx</author>
            <pubDate>Mon, 16 Jun 2008 23:02:04 -0800</pubDate>
        <feedburner:origLink>http://www.kehlet.cx/articles/174.html</feedburner:origLink></item>
    </channel>
</rss>
