November 09, 2008
I went to NoFluffJustStuff this weekend with coworkers. Spent the weekend in Reston, VA, USA (near Washington, D.C.).
While the nerd level remained high across all the sessions, we spent the nights enjoying live music in small bars in Georgetown and Alexandria.
Downtime consisted of trolling for coffee and reading source material for my WFRP campaign (that is about to get underway again after 4+ weeks off). 
October 25, 2008
With my new PostgreSQL backend, I'm planning some migration of ACD and other services currently “in production.”
Some downtime will be expected, but it should be short. Everything is conceptual at the moment, because there will be some feature loss with moving to the new blog platform series. I'm hoping to improve some resource management on the server at the some time by consolidating the engines running on the backend.
This is a peek behind the curtain how a geek's mind works... 
October 22, 2008
There are a lot of "What's your IP" services on the net. This is not about those.
I had a need today to load a shell script with the IP address of my interface at work. ifconfig told me, but it was noisy. So I crafted the following one-liner on the command line then used it in the shell script (depending on your distro, you might have better ways, but this solved an immediate need):
IP=`ifconfig en0 | grep -w inet | cut -d ' ' -f 2`
October 10, 2008
I just built PostgreSQL.
I'm about to install a wiki for my ongoing
WFRP campaign... and I'm playing with Stripes, a JSP view-controller framework as I continue to study for a professional exam.
September 16, 2008
After almost two years on a pre-order queue comes the promise of a December 2008 release. Panzerblitz: Hill of Death.
Not your father's Panzerblitz? How about not my Panzerblitz... :)

The box art is very evocative of the legacy of Panzerblitz/Panzer Leader. I even like the color. Alas though it is not with critics. And at least one very valid criticism... the photo is a Photoshop'd very well known one from the Battle of the Bulge. British, yes. Period, late, but passable. Operation? Not even close.

But if finding a photo from the Battle of Hill 112 means delaying this game. I say, eh. So what.
August 13, 2008
The library delivered Robert E. Howard's
The Coming of Conan the Cimmerian, the first of a three volume set published in 2002–2003. It is a definitive collection. The first thirteen stories in the order they were released by REH, not a perceived order by those that came after, or a forced chronology.
The Forward and Introduction are alone worth reading. The opinion of pastiches by authors that came after, or of those that attempted to finish the unfinished is raw and frank. An opinion to which I heartily agree.
July 04, 2008
The Fourth of July. A US holiday.
I'm having a donut, some coffee, and exercising some of my JavaScript acumen today sipping on some coffee. The YUI library docs at hand, the Stripes JAR on disk, webapp loaded, and thinking about bagels.
“Bagels? You're having a donut!,” one might query.
My job is such that I have to evaluate tools for improving existing applications. Some quiet time on a holiday let's me do just that. I'm building a bagel club prototype to demo some of the advanced features of the YUI, the Stripes MVC framework, JavaScript, and the DWR for talking to the backend.
Normally, I might devote the day to thinking about Warhammer Fantasy Roleplay, the campaign, &tc. I'll do that tonight. I'll probably, finally, tackle that annoying IE 6/7 display bug in Inns of the Empire. Finally. 
May 29, 2008
I'm sipping from the tub of Maven kool-aid being passed around at work.
mmmmm... my favorite, java flavored.
May 06, 2008
I came across this piece of code poetry today and laughed.
...
Date currDate = new Date();
Date expDate = null;
int array[] = new int[3 ];
if(expirationDate != null && !"".equals(expirationDate)){
int i = 0;
StringTokenizer st = new StringTokenizer(expirationDate,"/");
while (st.hasMoreTokens()) {
array[i++] = Integer.parseInt(st.nextToken());
}
expDate = new Date(array[2 ] - 1900, array[0 ] - 1, array[1 ]);
int x = expDate.compareTo(currDate);
if(x <= 0) {
rd.forward("landingnotfound.html");
}
}
...
It took me a half-hour to figure out what the developer was doing: compare two dates and determine if one was before the other. How he got to the above is lost to his fever dream.
Here's how I refactored this horror...
...
Date currDate = new Date();
Date expDate = new Date();
DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US);
if(!"".equals(expirationDate)){
expDate = df.parse(expirationDate);
if(currDate.after(expDate) {
rd.forward("landingnotfound.html");
}
}
...
At some point in our conversation, I think he said, “It works.” 
May 03, 2008
I picked up three O’Reilly Short Cut PDFs last night on some topics of great interest to me personally or professionally.
What’s New in Apache Server 2.2 is a pretty good introduction to some topics I have been familiar with but never used effectively or investigated. Of particular note is mod_ssls support for TLS upgrade:
SSL
mod_ssl now supports TLS upgrade. This allows an unencrypted connection to be upgraded to a secure connection. Among other benefits, this removes the restriction to one SSL host per IP address that has traditionally applied to SSL.
Unfortunately, this is not yet widely supported by browsers, and so it is of limited value. However, the presence of a server implementation should encourage browser developers to implement this functionality.
This is a very important feature. If you’ve ever had to budget IPs and SSL certs costs then the impact of this feature is big. But alas, I can’t find the list of supporting browsers to share.
Update
TLS Upgrade is better known as RFC 2817. Indeed, it is not widely supported by browsers. Firefox 2 and IE 7 do not. Firefox 3 will. IE 7 never. Not sure about Safari. But it seems that RFC 3546 has more adherents. FF2, IE7 already support RFC 3546 (Safari again absent), which specifies a Server-Name-Indicator (SNI), not unlike the Host header today in HTTP/1.1. SNI support is provided in Apache 2.2 through mod_gnutls. mod_gnutls is still immature, though actively developed.
The caveat to this entire discussion then is: Use at your own risk. And if you work at a bank, don't use at all.
Ximbiot.com Zazzle Store Online
A close friend of mine is a senior committer to CVS and runs Ximbiot LLC, the premiere CVS support company. He just sent me a sample of his new Zazzle line of tees and mugs. Check it out at Zazzle.com/Ximbiot. Some great message tees for the geek.
And you wondered why I discuss arcane topics like source control on this blog. D’uh.
May 01, 2008
As it turns out, sometime ago I built a newer version of CVS than that was provided by Leopard. It broke something important: the ability to use case-sensitive features in my sandbox.
When building CVS from source the configure script will determine, automagically, the type of file system CVS is building on. I noted in To Partition or Not To Partition that my employer's source code sometimes contains different files noted only by the case of the name.
Mac and Windows choke on these names, so I created a case-sensitive partition to make CVS and SVN checkouts work.
To get CVS to work in a case-sensitive file system, you have two choices:
- build CVS on a case-sensitive file system,
- or pass
--enable-case-sensitivity to the configure script
The latter corrected my problems.
March 17, 2008
I love stumbling across a well implemented, open-source, project that does something extremely well. Especially, if it's written in Java.
Today, after reading a rant on a forum about something unrelated, the developer mentioned JForum. The ‘J’ of course a cue to its pedigree.
If you're looking at a forum for your website, JForum looks pretty robust. Check it out.
February 24, 2008
I recently had the need to update an awstats installation on a website. The website had not changed, but the domain name had. CNAME in place, I needed to move the statistical information over so that all of the previous history—three years of it—came with it.
A very simple UNIX command facilitated the move: rename.
awstats stores the records is a proprietary flat file database based on the domain name. Where the data is stored is configurable, so I won't detail this, it might be different for you.
I backed up the files in /tmp and executed the following rename command, in the directory storing the record files:
% rename newDomain oldDomain awstats*
Done.
Need awstats services? Email me, I'm always looking for a little extra cash.
February 20, 2008
So in my first installment, I showed you how to configure Firefox to "grade on a curve," pointing CDNs at "100" when you are not using a CDN, or have no short/long term needs for a CDN.
The configuration method is by far the easiest.
But what if you want to do as Steve Souder points out in the Rule 2 discussion, "ignore or weight CDNs differently"? This will mean you will have to invasively hack YSlow. This option may not be for the faint at heart. Additionally, you have to consider that weighting or ignoring CDNs in YSlow will negatively affect your score. And in the end you might just want to wait for Steve's YSlow update.
How YSlow Works
YSlow uses a weighted averaging scheme. I won't explain what this means, but suffice to say your YSlow score is not averaged against 13 rules, but an effective 64 rules. You can find the default weights in yslowcontext.js.
this.lintweights = { "NumComps" : 8,
"CDN" : 6,
"Expires" : 10,
"Gzip" : 8,
"CssAtTop" : 4,
"JsAtBottom" : 4,
"Expression" : 3,
"ExternalFiles" : 4,
"Domains" : 3,
"Obfuscate" : 4,
"Redirects" : 4,
"JsTwice" : 4,
"ETags" : 2
};
By example, CDNs are weighted "6". This means that a score of 0 is 0, or a score of 100 is 600. So setting a weight of 0 will goose egg your average, and so on. Removing CDNs from the equation changes the number of items, weighted of course, to average against.
Enough math. Now, what to do, what to do?
Method 1, Simple Weighted Average
Finding the yslowcontext.js file will be an exercise for Windows users, but simple enough. The file is located on a Mac is in the following location:
/Users/{user.name}/Library/Application Support/Firefox/Profiles/{profile.name}/extensions/yslow@yahoo-inc.com/chrome/content/yslow/yslowcontext.js
The location is nearly the same on Windows and Linux, just substitute your "Documents and Settings/Application Data" folder and user home as appropriate.
Locate the lintweights object and change the property for CDN to "0". Save, restart Firefox. CDNs are effectively ignored.
But like my first post, the noise is still present about not having a CDN, etc. What about actually changing the behavior of YSlow to truly ignore the CDN rule, removing the noise? It can be done, and is more invasive. Caution, all ye that read further...
Method 2, Alter YSlow Messaging and Averaging
Instead of changing the weighted average, we can add 1) a Firefox configuration and 2) a conditional branch in the lint.js file where YSlow builds the presentation in Firebug. Here we go...
Step 1 is to create a new boolean preference in Firefox. This is not unlike the earlier post:
- Type "about:config" in the location bar
- Right-click in the window and select "New > Boolean"
- Create the preference: name: extensions.firebug.yslow.ignoreCDN, value: true.
- Restart Firefox
Step 2 is to hack the lint.js file to do actually do the "ignoring" part, and present a friendly message when using it.
Find the lint.js file, it is in the same location as yslowcontext.js and back it up.
Around line 80, you will find the function that builds the CDN report. Simple study will show that it loops over the components of the page reported to it from Firebug, appropriately adjusts your score and moves on.
We are now going to wrap this behavior in an if branch based on our new Firefox preference. At line 86, some context provided, insert the following:
...
hLint["rulehref"] = "http://developer.yahoo.com/performance/rules.html#cdn";
if( YSLOW.getPref("yslow.ignoreCDN", false) ) {
// you will be adding some code here later
} else {
var compObj = {};
...
Whew... what is happening here? Basically, we are telling YSlow that if you don't a preference for ignoring CDNs, assume it is false and execute the else statement. Which is where the original code is now blocked at line 88. Let's make sure we don't break this function and close the else block at line 140:
...
FirebugContext.yslowContext["lintscores"]["CDN"] = iScore;
}
return hLint;
Now, it is time to tell YSlow how we want it to behave when ignoring CDNs. We are going to borrow liberally from Rule 8 and it's code. Insert the following, copy and paste if you desire, the following at line 87 (shown above as "blank"):
hLint["nonwarnings"] = "Only consider this if your property is under heavy load, for example from file sharing and streaming media; may not be applicable to small and medium properties.";
hLint["score"] = "n/a";
// This rule should require manual evaluation. Don't score it automatically.
// FirebugContext.yslowContext["lintscores"]["CDN"] = iScore;
Note, line breaks are for readability, see line numbers. Lines reflect the new code inserted.
Save and restart Firefox.
Have fun
Finally, one might wish to clean up the code and indent the new branch, for readability. Or not. It works as is. Comment on your experience or make suggestions.
February 18, 2008
I went code diving tonight as I wanted to test ACD and a few other websites with Steve Souder's YSlow, a Firefox plugin to Firebug, for grading performance of websites against his 14 Rules for High Performance Web Sites.
Seems that Rule 2, "Use a CDN" is so important that YSlow does not take into account a simple matter: most websites a) don't need the overhead, b) most webmasters can't afford a CDN, and c) most websites don't need the overhead. Free or not.
While Steve has stated an update to the tool will better allow the configuration of Rule 2, it currently is not possible to "ignore" Rule 2. If you don't use a CDN, you are given a big fat goose egg ("0") and your website score is appropriately noted in the average.
Some code diving revealed that preference to YSlow is available, undocumented, that will allow you to get full credit for a CDN, even if you don't use one. Follow these steps to "be graded on a curve":
- Type "about:config" in the location bar
- Right-click in the window and select "New > Integer"
- The preference name is: extensions.firebug.yslow.pointsNotCDN, value: 0. Type it precisely as shown here.
- Restart Firefox
You still are told "Use a CDN" but now you get an "A." And you didn't have to study, or really cheat... much.
Hope this little gem is helpful. 