<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
<channel>
	<title>Brewster's Field Guide to Web 2.666</title>
	<description>Web 2.0, with a little bit of the devil inside.</description>
	<link>http://kentbrewster.com</link>
	<pubDate>Wed, 16 Jul 2008 10:45:19 PDT</pubDate>
	<language>en</language>
	<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/KentBrewster" type="application/rss+xml" /><item>
		<title>Prototype Identica Badge</title>
		<link>http://feeds.feedburner.com/~r/KentBrewster/~3/337282886/identica-badge</link>
		<guid isPermaLink="false">http://kentbrewster.com/identica-badge</guid>
		<comments>http://kentbrewster.com/identica-badge</comments>
		<pubDate>Wed, 16 Jul 2008 10:45:19 PDT</pubDate>
		<dc:creator>Kent Brewster</dc:creator>
		<description><![CDATA[ 
<p>As it says on the About page, <a href="http://identi.ca" target="_blank">Identi.ca</a> is a <a href="http://en.wikipedia.org/wiki/Micro-blogging" target="_blank">micro-blogging</a> service based on the Free Software <a href="http://laconi.ca/" target="_blank">Laconica</a> tool.</p>
<p>For more about the project, see Marshal Kirkpatrick's <a href="http://www.readwriteweb.com/archives/indentica_federated_twitter.php" target="_blank">Identi.ca: May A Million Twitters Bloom</a>, Hugh McGuire's <a href="http://hughmcguire.net/2008/07/08/micro-moblogging-or-why-identica-matters/" target="_blank">Why Identi.ca Matters</a>, and Edd Dumbill's <a href="http://times.usefulinc.com/2008/07/03-identica" target="_blank">Why Identi.ca is Important</a>.  Personally I'm thrilled by the idea and encouraged by its execution so far, and have been poking cautiously at Laconica for the past couple of weeks, hoping to contribute in whatever way I can.  Here's a prototype badge, based on Laconica's RSS feeds and Yahoo! Pipes.</p>
<script type="text/javascript" src="http://kentbrewster.com/js/identica-badge.js">
{
   "user":"kentbrew",
   "server":"identi.ca",
   "headerBackground":"#000"
}
</script>
<p>If you see an author's name in a post, click it to explore his or her friends' posts.  To visit the author's identi.ca page, click the top link, to so-and-so with friends.</p>
<p>To try this yourself, copy and paste the following wherever you want the badge to show up:</p>
<pre class="code">
&lt;script type="text/javascript" src="http://kentbrewster.com/js/identica-badge.js">
{
   "user":"kentbrew",
   "server":"identi.ca",
   "headerBackground":"#000"
}
&lt;/script>
</pre>
<p>Substitute your own ID in the <code>user</code> parameter; many of the other parameters available in <a href="http://kentbrewster.com/twitterati" target="_blank">Twitterati</a> will also work.</p>
<p><s>Although we're waiting for the real API, if you find a working Laconica server that forms its RSS urls the way identi.ca does, the badge should work unmodified if you substitute the server name of your choice for <code>identi.ca</code> in the second parameter.</s></p>
<p>Working through kinks in the real API now ... so far, so good. More to come!</p>
<p>Please keep in mind that this badge will change radically once the API goes live, and will hopefully be hosted by the project.  I don't mind if you try it out, but please host your own copy if you put it in production anywhere.</p>
<p>For background information about how badges like this one work, please see <a href="http://kentbrewster.com/badges/" target="_blank">Case-Hardened Web Badges</a>, which I presented at Web 2.0 earlier this year.</p>
<p>Have fun, and please let me know how it goes!</p>
 ]]></description>
	<feedburner:origLink>http://kentbrewster.com/identica-badge</feedburner:origLink></item>
	<item>
		<title>Case-Hardened Web Badges: the Live Version</title>
		<link>http://feeds.feedburner.com/~r/KentBrewster/~3/313912315/badges</link>
		<guid isPermaLink="false">http://kentbrewster.com/badges</guid>
		<comments>http://kentbrewster.com/badges</comments>
		<pubDate>Thu, 19 Jun 2008 09:30:29 PDT</pubDate>
		<dc:creator>Kent Brewster</dc:creator>
		<description><![CDATA[ 
<p>Here at last is my presentation from Web 2.0, which I've been criminally remiss in posting.  It's live now because of L.M. Orchard's marvelous <a href="http://decafbad.com/blog/2008/06/16/firefox-3-download-day-mega-widget">Firefox Download Day Mega Widget</a>, which uses some of the techniques.</p>
<iframe height="650" width="800" border="none" src="http://kentbrewster.com/badges/preso.html"></iframe>
<p><a href="http://kentbrewster.com/badges/preso.html" target="_preso">Start Presentation in New Window</a></p>
<p>Please keep in mind that this is a presentation, not a book.  Lots of stuff is hinted at; much was said live that isn't here, obviously.  If you'd like me to present this--or something like it--at your conference, please <a href="http://kentbrewster.com/contact/">contact me</a> and I'll see what I can do.</p>
<p>Yes, the examples really do work; copy, paste, save, and run, and you'll see it live, right there in your browser.</p>
<p>As always, have fun, and please let me know how it goes.</p>
 ]]></description>
	<feedburner:origLink>http://kentbrewster.com/badges</feedburner:origLink></item>
	<item>
		<title>Creating Open Profiles</title>
		<link>http://feeds.feedburner.com/~r/KentBrewster/~3/285079813/creating-open-profiles</link>
		<guid isPermaLink="false">http://kentbrewster.com/creating-open-profiles</guid>
		<comments>http://kentbrewster.com/creating-open-profiles</comments>
		<pubDate>Tue, 06 May 2008 20:18:41 PDT</pubDate>
		<dc:creator>Kent Brewster</dc:creator>
		<description><![CDATA[ 
<p>If you're reading this, chances are pretty good you have an online profile.  Unless you're fantastically self-disciplined and all of your profile information is served by a single <a href="http://foaf-project.org">FOAF</a> object which lives on a server in your basement--in which case you're a virtual hermit--there are several branches of "you" out there already, all constantly trying to strangle each other in the endless quest for search rankings and mindshare.</p>
<h3>What I Want</h3>
<ul>
<li>To create, update, and share one (and only one!)  instance of my public profile information--including contacts, status, location, and so forth--and serve it up so anyone who asks can see it with a minimum of fuss.</li>
<li>To delegate the right to update certain branches of my profile to agencies that I trust, such as <a href="http://www.mybloglog.com/buzz/members/kentbrew/">MyBlogLog</a> or <a href="http://twitter.com/kentbrew">Twitter</a>.</li>
<li>To reserve administrative rights--including create, read, update, and delete--over the root of the profile.</li>
</ul>
<p>That last is most important.  For a while now I've been hearing about various "data portability" initiatives, most of which will only allow you to make a copy of some small subset of the current state of your profile.  Everything else--including historic transactions and top-secret personal information--remains online, per the terms of the TOS you ignored when you first joined up.</p>
<p>Remember, if you can't delete it, it's not portable.</p>
<h3>Narrowing the Scope</h3>
<p>Okay, so ... what do I want it to do that I can accomplish myself?  Simple stuff, mostly:</p>
<ul>
<li>I want interested people to be able to hit a single url, <code>http://foo.com/myid</code>, and get back a JSON object containing my complete profile.  If I add a callback to the url, <code>http://foo.com/myid/callback</code>, I want it to come back as JavaScript, properly wrapped for use with the <code>SCRIPT</code> tag hack.  (Oh, and no screwing around with arrays of callback functions and the like; please give me the callback <em>inside</em> the return, like <a href="http://pipes.yahoo.com">Pipes</a> does.)</li>
<li>When I'm signed in, I want to see my public profile in a textarea and make changes that instantly update the whole thing.  None of this hand-holding nonsense; I want the bare metal, please, and if I want to delete it, I want to delete it.</li>
<li>I also want a private object, consisting of nothing but key-value pairs.  Each key will exactly match the branch of my main object I want others to be able to edit; each value will be the password I expect them to submit to make changes.</li>
<li>When one of my outside agents--Fireeagle, for example--makes a <code>POST</code> to my profile, I want it to check for a key-value match in my private object.  If the agent knows the password, I want my profile to allow it to update the validated branch object.</li>
</ul>
<h3>A First Half-Blind Stab</h3>
<p>To pull this off, I needed something big, fast, powerful, and free.  Google's  <a href="http://appengine.google.com">Application Engine</a> was immediately interesting to me because of the single most impressive developer demo I've ever seen, Brett Slatkin's <a href="http://youtube.com/watch?v=bfgO-LXGpTM">Introducing Google App Engine</a>.    Everything Brett showed in the video looked completely doable, and when I tried it out, by golly, it was.  (I'm still looking at it, and cursing the fact that I can't copy and paste directly from the code in the video.  Boy, would that ever be cool.)</p>
<p>Thanks to <a href="http://stevesouders.com">Steve Souders</a>, late of Yahoo but recently moved to the big G, I've acquired early access.  As of this writing App Engine still in closed beta; keep an eye on <a href="http://googleappengine.blogspot.com/">their blog</a> for updates.</p>
<h3>Can we See the Source Code, Please?</h3>
<p>Nawp, sorry, not yet.  It's like this:  Open Profile is my first Python program, ever.  I can see dozens of places where it sucks, and I'm not even remotely qualified to tell if something written in Python sucks or not.  I'm in conversations right now with a Python expert; once I get it vetted I will credit him appropriately and open-source everything.</p>
<p>This thing would definitely work on a non-Google box, with the addition of user authentication plus minor mods to make it talk to MySQL, so if you wanted to put it on that server in the basement and own it completely, you could.</p>
<h3>View My Profile</h3>
<p>Here's my public profile on <code>http://exo.appspot.com/kentbrew/ping</code>:</p>
<iframe name="_obj" src="http://exo.appspot.com/kentbrew/ping" style="width:700px;"></iframe>
<p>The base URL is <code>http://exo.appspot.com/kentbrew</code>; the callback I've wrapped it in is <code>ping</code>.  If you omit the callback, you'll get a pure JSON object, which your browser may or may not be able to handle inline.</p>
<p>As you can see, I have two branch objects in my profile, <code>foo</code>, containing the last value you guys put in, and <code>status</code>, containing an array of objects that you theoretically can't monkey with.  Using my private object, which you don't see here, I've granted permission to edit object <code>foo</code>:</p>
<form method="post" action="http://exo.appspot.com" target="_update"/>
Owner: <input name="owner" value="kentbrew" /> Object: <input name="object" value="foo" /> Password: <input name="password" value="bar" /><br />
New Value: <br /><textarea name="newValue" rows="10" cols="50"></textarea><br />
Confused?  Try <code>"boing"</code>, <code>{"clank":"ding"}</code>, or <code>{"testing":[1, 2, 3]}</code> to start.<br />
<input type="submit" onclick="document.getElementById('_update').style.display = 'block';"/> <a href="http://exo.appspot.com/kentbrew/ping" target="_obj">Reload</a> my public profile to see your changes.
</form>
<iframe id="_update" name="_update" style="width:700px; height:3em; display:none;"></iframe>
<h3>Things to Do and Notice</h3>
<ul>
<li>Enter some valid JSON for the contents of the object you want to update.  Be sure to quote your strings and bracket your objects and arrays.</li>
<li>You'll see an intentionally sparse success-or-failure  message go by when you submit this.  We don't want to give the bad guys any hints about what they might be doing wrong.</li>
<li>If you see the Success message, use the <code>Reload</code> link to see your changes serve up.</li>
<li>This should work for anyone, signed in to Google or not, because I've given you my root object name, my branch object name, and its password.</li>
<li>There's no callback option for the update function, since it's only supposed to be POSTed.</li>
<li>You should not be able to monkey around with my <code>status</code> object, since you don't know the password.</li>
<li>If you head over to <a href="http://exo.appspot.com">exo.appspot.com</a> and create your own object with an open branch, you ought to be able to update it from here.</li>
<li>Right, updates are not even <em>remotely</em> secure.  This could be mitigated somewhat with https ... but please don't use this form for anything mission-critical.</li>
</ul>
<h3>Directions for Future Development</h3>
<ul>
<li>I can see an approach like this lending itself quite nicely to decentralized social networking.  If I have a list of contacts and they each have their own open profiles and they all point back to me in a <code>contacts</code> array, we can deduce the same sorts of relationships we find in FOAF or XFN.</li>
<li>Unlike FOAF or XFN, delegated update rights are built in.  Any service that cares could ask me to put up a branch object and give them a password.</li>
<li>Next up, I'm going to see if I can hook up Twitter and get some real status updates in there.</li>
</ul>
<h3>How It Feels So Far</h3>
<p>Even though it's in an embryonic stage and nobody at all is paying attention, I like it.</p>
<p>I'm creating data.  I'm authorizing access.  I'm giving out passwords to <em>my</em> agents, not begging them from big faceless companies.  Unlike all those other Web profiles, which could change or vanish at the whim of their hosting companies, this one feels powerful, like I own the thing, instead of it owning me.</p>
 ]]></description>
	<feedburner:origLink>http://kentbrewster.com/creating-open-profiles</feedburner:origLink></item>
	<item>
		<title>Mashable FOAF</title>
		<link>http://feeds.feedburner.com/~r/KentBrewster/~3/262966655/foafster</link>
		<guid isPermaLink="false">http://kentbrewster.com/foafster</guid>
		<comments>http://kentbrewster.com/foafster</comments>
		<pubDate>Wed, 02 Apr 2008 16:07:46 PDT</pubDate>
		<dc:creator>Kent Brewster</dc:creator>
		<description><![CDATA[ 

<iframe style="border:2px solid #000;overflow:hidden;margin-top:5px;" height="700" width="700" src="http://kentbrewster.com/foafster/foafster.html?<?php echo $q; ?>"></iframe>
<h3>What's This?</h3>
<p>FOAFster is a prototype visualizer for <a href="http://www.foaf-project.org/">Friend Of A Friend</a> relationship objects.  What you're seeing here are icons for a bunch of FOAF contacts, scattered around the screen, and network services, in a much neater line at the top.</p>
<h3>About FOAF</h3>
<p>I've been interested in FOAF for a long time.  Abstracting out all my social relationships into a separate layer, just as I do with my presentation and behavior layers, really resonates.  Future possibilities like being able to point marketers at my FOAF object so they will quit wasting their time trying to sell me timeshares seems like a very real possibility.</p>
<p>The problem?  As it sits right now, FOAF is a giant pain to update.  Most folks fire it once and forget it; the results range from amusing to disastrous.</p>
<p>What changed today?  <a href="http://mybloglogb.typepad.com/my_weblog/">MyBlogLog rolled out FOAF</a>.  And now, finally, I don't have to worry about keeping a file on my Web site.  All I need to do is add people and services to my network on MyBlogLog, and it's taken care of for me.  Here's my FOAF object, courtesy of MyBlogLog:</p>
<p><code><a href="http://www.mybloglog.com/buzz/members/kentbrew/foaf/" target="_blank">http://www.mybloglog.com/buzz/members/kentbrew/foaf/</a></code></p>
<h3>Why MyBlogLog's FOAF Is Superior</h3>
<p>All this is generated and re-generated for me, whenever I add a service or a contact, and whenever any of those contacts add a service of their own.  So now all I need to do is link it in the HEAD of my document, like so:</p>
<p><code>&lt;link rel="meta" type="application/rdf+xml" title="FOAF" href="http://www.mybloglog.com/buzz/members/kentbrew/foaf/" /&gt;</code></p>
<p>Although other services like LiveJournal and FriendFeed are doing this, MyBlogLog's FOAF is superior.  LiveJournal only points inwards; FriendFeed does not contain your contacts' network connections.  And nobody else in the world is presenting FOAF as a JSON object wrapped in the callback of your choice, if you ask nicely, using <code>format=json&callback=foo</code>.  Although it's possible to run anybody's FOAF object through <a href="http://pipes.yahoo.com">Pipes</a> and get JSON back, MyBlogLog cuts out the middleman by being brave enough to serve it all up live.</p>
<h3>Want to Play?</h3>
<p>It's trivially easy, which is how it ought to be.  Go sign up at <a href="http://mybloglog.com" target="_blank">MyBlogLog</a>, add some services and/or contacts, and your FOAF should be ready to rock, at <code>http://www.mybloglog.com/buzz/members/yourname/foaf/</code>.</p>
<h3>Things to Do and Notice</h3>
<ul>
<li>Click any of the service icons to see what the user in the background is doing over there.  (These use the same Pipes I wrote for <a href="http://kentbrewster.com/blogjuice">Blog Juice</a>, if you're interested.)</li>
<li>Click any of the contact faces to go see what they're up to.  They will always show up in the same spot for each starting profile.</li>
<li>If you need to go back--yes, there are dead ends out there; you'll be alerted if you hit one--click one of the faces in the row of breadcrumbs at the bottom right.</li>
<li>If you'd like to try it out starting from a different ID, enter it at the end of this page's URL, like so:<br /><code><a href="http://kentbrewster.com/foafster?q=johnsampson">http://kentbrewster.com/foafster?q=johnsampson</a></code></li>
</ul>
<h3>Caveats and Gotchas</h3>
<ul>
<li>Some people--Scott Beale, for one--have incomplete information about their Flickr profiles on MyBlogLog. You guys need to go update before you'll see your Flickr photos.</li>
<li>There's a lot going on; the first time you try a FOAF object that hasn't been generated yet it may go slowly, depending on network latency and caching and such.  I'm sneakily changing out the background and the person's name right when you click; you'll see the usual square twirligig while the FOAF query is running.</li>
<li>I've set an arbitrary limit of 400 contact icons, but the whole FOAF object still comes down from MyBlogLog, so it can take a while.  Sometimes--*koff*<a href="http://kentbrewster.com/foafster?q=rafer">Rafer</a>*koff*--a long while.</li>
<li>It's semi-broken on IE, and twitchy on Opera.  This is all my fault, not that of the API; working on it now.</li>
</ul>
<h3>Directions for Future Development</h3>
<ul>
<li>User should be able to click a face from the MyBlogLog reader roll, or automatically start with the signed-in MyBlogLog user.</li>
<li>User should be able to drag and drop those faces, and save their locations as a cookie or to a central server.  Face locations should be consistent no matter who the starting account is.</li>
<li>Individual icons should scurry into and out of the middle when you mouse over a service icon that they have; it ought to look like the Stanford marching band.</li>
</ul>
<p>I'll have the code up once I fix up the IE bugs; for now, adventurous developers should know how to read source, copy, and paste.  Have fun, and please let me know how it goes.</p>
 ]]></description>
	<feedburner:origLink>http://kentbrewster.com/foafster</feedburner:origLink></item>
	<item>
		<title>Pipe Badges</title>
		<link>http://feeds.feedburner.com/~r/KentBrewster/~3/257419482/pipe-badges</link>
		<guid isPermaLink="false">http://kentbrewster.com/pipe-badges</guid>
		<comments>http://kentbrewster.com/pipe-badges</comments>
		<pubDate>Mon, 24 Mar 2008 20:46:51 PDT</pubDate>
		<dc:creator>Kent Brewster</dc:creator>
		<description><![CDATA[ 
<p>About a year ago, I had the enormous good fortune to sit just over the cubicle wall from the <a href="http://pipes.yahoo.com">Yahoo! Pipes</a> team during their launch.  During that time I was lucky enough to overhear talk about a couple of as-yet-undocumented features, the <code>_render=json</code> and <code>_callback=foo</code> parameters.  These two features allowed me to use Pipes to turn any RSS feed into a JSON object wrapped in the callback of my choice, and to launch the <a href="http://kentbrewster.com/badger">Badger</a>, a crude-but-effective wizard-in-a-Web-page that allowed anyone to do the same.</p>
<p>During the intervening months I've had a chance to give Pipes a workout.  Examples range from the simple Badger application to <a href="http;//kentbrewster.com/blogjuice">rolling a complete API layer</a> to cover a multitude of different sites and endpoints.</p>
<p>This morning, the Pipes team launched a new feature, <a href="http://blog.pipes.yahoo.com/2008/03/24/introducing-pipe-badges/">Pipe Badges</a>.  Using several of the ideas collected in <a href="http://kentbrewster.com/case-hardened-javascript">Case-Hardened JavaScript</a>, Pipe Badges allow the site operator to include a single line of JavaScript, hosted by Pipes, and see one of three handy badges--list, image, or map view--pop up instantly.</p>
<p>If I'm not mistaken, this:</p>
<pre>&lt;script src="http://pipes.yahoo.com/js/mapbadge.js">{
   "pipe_id":"WlLkGRj63BGEG7TKiHrL0A",
   "_btype":"map",
   "pipe_params":{
      "q":"pizza",
      "g":"95051"
   }
}&lt;/script></pre>
<p style="margin-top:10px">... is just about the single easiest way to search for something near something, and display the results as a map on your site. Here we're searching for pizza near 95051; parameters <code>q</code> and <code>g</code> can be changed to anything you like.</p>
<script src="http://pipes.yahoo.com/js/mapbadge.js">{"pipe_id":"WlLkGRj63BGEG7TKiHrL0A","_btype":"map","pipe_params":{"q":"pizza","g":"95051"}}</script>
<p>Pipe Badges are the result of many months of coding by the Pipes team, including Jonathan Trevor and Paul Donnelly.  Awesome work, you guys; keep it up!</p>


 ]]></description>
	<feedburner:origLink>http://kentbrewster.com/pipe-badges</feedburner:origLink></item>
	<item>
		<title>Patching Privacy Leaks</title>
		<link>http://feeds.feedburner.com/~r/KentBrewster/~3/248691955/patching-privacy-leaks</link>
		<guid isPermaLink="false">http://kentbrewster.com/patching-privacy-leaks</guid>
		<comments>http://kentbrewster.com/patching-privacy-leaks</comments>
		<pubDate>Sat, 08 Mar 2008 10:33:09 PST</pubDate>
		<dc:creator>Kent Brewster</dc:creator>
		<description><![CDATA[ 
<p>Over the past few months I've published articles documenting an extremely trivial weakness that allows any third-party operator to determine if its users are signed in to several well-known Web services.  This is pretty clearly information that ought not to be shared; even if it's not explicitly stated in the service's terms of service, it's expected by the public.</p>
<p>As a result of several eye-opening conversations I've had while at SxSW this year, I've taken down all of the articles detailing live exploits.  As trivial as they are, I should not have disclosed any specific vulnerabilities without warning the service operators first, and I want to strongly discourage anyone from following my example, which was the wrong thing to do.</p>
<p>I will, however, present an overview of the methods I used, and the lessons I learned during the process.</p>
<h3>Principles:</h3>
<ul>
<li>Any file on your site, whether or not it is actually JavaScript, can be included with a SCRIPT tag by a third party.</li>
<li>If the contents of that file vary sufficiently depending on the user's cookies--which almost always contain his or her login status--a third-party site can infer information which should be private, beginning with the user's login status and potentially including much more.</li>
</ul>
<h3>Detecting Vulnerabilities in Your Service:</h3>
<p>Before you push a new feature to your AJAX-powered site, please run through the following steps:</p>
<ul>
<li>Get Firefox and Firebug, and sign in to your service.</li>
<li>Go to any page that has an AJAX-powered interaction that should only be usable if the user is signed in.  This could be a message post, a profile update, a mailbox read, a social network connection update ... we're looking for anything that affects the content of the page without reloading it that should only be visible if the user is logged in.</li>
<li>Once you've found it, run it.</li>
<li>Open up Firebug, go to the Net tab, and find the interaction.</li>
<li>Open the interaction's URL in a separate browser tab.</li>
<li>Go back to the original tab and sign out of your site.</li>
<li>Open a new tab, and paste in the interaction's URL again.</li>
</ul>
<h3>Analysis</h3>
<p>View the source code of both states, and answer these two questions:</p>
<ul>
<li>Does either state contain executable JavaScript?</li>
<li>If not, when both states are loaded as SCRIPT tags, do they throw different errors?</li>
</ul>
<p>If the answer to either question is Yes, your users' login state can be guessed by a tiny scrap of JavaScript, running only in the client.</p>
<h3>Some Suggestions</h3>
<ul>
<li>Don't serve live JavaScript.  It's trivially easy to exploit.</li>
<li>Make sure your error messages come down in the same format, whether or not the user is logged in.  If an URL returns XML when the user is logged in but redirects to the login page when he's not, you're vulnerable, because they throw different errors when included as SCRIPT tags.</li>
<li>If you're offering an API, be sure that your endpoints throw the same errors whether or not the user is logged in.  Are you offering a JSON object wrapped in a callback to authenticated users and a redirect to your login page to others?  One throws an error and the other does not.</li>
<li>Don't serve up hcards or vcards to signed-in users and HTML errors to outsiders.  While neither is valid JavaScript, they throw different errors when included as SCRIPT tags.</li>
<li>Test all the URLs on your site that are supposed to be POSTed and be absolutely certain they return the same error whether or not the user is logged in, in the event some clever fellow tries a GET.</li>
<li>Keep an eye on your referrer and error logs.  Are your AJAX endpoints starting to throw a lot of those please-go-log-in errors?  Are they being linked from sites that have no business peeking or poking at them?  Somebody may have already found a hole in your site.</li>
<li>Have a clearly marked path for reporting security holes, listen, and be extremely responsive!</li>
</ul>
<h3>Please Note</h3>
<p>This isn't meant to be a definitive list, just cautionary squawking about a very common vulnerability.  Please be careful; your users are depending on you.</p>
 ]]></description>
	<feedburner:origLink>http://kentbrewster.com/patching-privacy-leaks</feedburner:origLink></item>
	<item>
		<title>Blog Juice</title>
		<link>http://feeds.feedburner.com/~r/KentBrewster/~3/234065782/blogjuice</link>
		<guid isPermaLink="false">http://kentbrewster.com/blogjuice</guid>
		<comments>http://kentbrewster.com/blogjuice</comments>
		<pubDate>Tue, 12 Feb 2008 16:52:11 PST</pubDate>
		<dc:creator>Kent Brewster</dc:creator>
		<description><![CDATA[ 
<p>Here's a toolbar bookmarklet that looks for a MyBlogLog identifier on the page you're on, and uses the MyBlogLog API to dig out information about its reader roll:</p>
<h3><a href="javascript:void(d=document);void(b=d.getElementsByTagName('body')[0]);void((s=d.createElement('script')).setAttribute('src','http://kentbrewster.com/bj.js'));void(b.appendChild(s));">Blog Juice</a></h3>
<p>You can try it here, or drag it to your bookmarks toolbar and run it anywhere else on the Web.  (On IE, right-click, add to favorites, say Yes to continue past scary warning, and choose Links.  You may then need to fiddle around with your Tools drop-down in order to get Links to show in your chrome.)</p>
<h3>Things to Do and Notice</h3>
<ul>
<li>Each reader comes up in a toggle-able list item.  You'll see a MyBlogLog avatar, a name, and possibly some tags.  Click the name to visit the MyBlogLog profile; click the tag to see a list of other users with that tag.</li>
<li>Click anywhere else in the reader record to open it up and see details from ten different social networks.  At the moment, they are:  MyBlogLog, Twitter, Upcoming, Digg, LinkedIn, Delicious, Flickr, Last.fm, StumbleUpon, and YouTube.</li>
<li>Inside the detail you'll be able to click the item to go over to the other site and view it.</li>
<li>Up top are a series of icons that match the detail icons for each service.  Mouse over them to only show reader roll items.</li>
<li>The MyBlogLog icon (first on the left at the top) will show the user's authored blogs.  Click the image to open its reader roll up, right there in the badge without leaving the page you're on.  Click the text link to visit the blog.</li>
<li>Each user has a checkbox.  If you check it, the user will be added to your Stalk List, and a small icon resembling a guy cradling a loaf of French bread will show up at the bottom of the badge.  Click the French Bread Guy to see all your buddies.</li>
<li>As of the latest version, the widget comes up in an iframe.  This works seamlessly in all browsers except IE.  We're using an iframe because the CSS is much easier to construct, and when you bookmark a user for your Stalk List, the cookie will be set to my domain, not the domain you're on, so it will be available no matter where you go on the Web.</li>
</ul>
<h3>Rolling Our Own API with Pipes</h3>
<p>Astute readers will immediately recognize that some of the services we're querying don't actually have APIs, and those that do have vastly differing endpoints.  To cut down on the amount of scripting required to send and receive data, I've rolled my own APIs for each of them, using Pipes.</p>
<ul>
<li><a href="http://pipes.yahoo.com/kentbrew/blogjuice_delicious" target="_blank">http://pipes.yahoo.com/kentbrew/blogjuice_delicious</a></li>
<li><a href="http://pipes.yahoo.com/kentbrew/blogjuice_digg" target="_blank">http://pipes.yahoo.com/kentbrew/blogjuice_digg</a></li>
<li><a href="http://pipes.yahoo.com/kentbrew/blogjuice_flickr" target="_blank">http://pipes.yahoo.com/kentbrew/blogjuice_flickr</a></li>
<li><a href="http://pipes.yahoo.com/kentbrew/blogjuice_lastfm" target="_blank">http://pipes.yahoo.com/kentbrew/blogjuice_lastfm</a></li>
<li><a href="http://pipes.yahoo.com/kentbrew/blogjuice_linkedin" target="_blank">http://pipes.yahoo.com/kentbrew/blogjuice_linkedin</a></li>
<li><a href="http://pipes.yahoo.com/kentbrew/blogjuice_stumbleupon" target="_blank">http://pipes.yahoo.com/kentbrew/blogjuice_stumbleupon</a></li>
<li><a href="http://pipes.yahoo.com/kentbrew/blogjuice_twitter" target="_blank">http://pipes.yahoo.com/kentbrew/blogjuice_twitter</a></li>
<li><a href="http://pipes.yahoo.com/kentbrew/blogjuice_upcoming" target="_blank">http://pipes.yahoo.com/kentbrew/blogjuice_upcoming</a></li>
<li><a href="http://pipes.yahoo.com/kentbrew/blogjuice_youtube" target="_blank">http://pipes.yahoo.com/kentbrew/blogjuice_youtube</a></li>
<li><a href="http://pipes.yahoo.com/kentbrew/blogjuice_tumblr" target="_blank">http://pipes.yahoo.com/kentbrew/blogjuice_tumblr</a></li>
</ul>
<p>Each takes an <code>S</code> parameter, the user id, and an optional <code>N</code> parameter, the number of items you want back from each endpoint, which defaults to 3.  Output from all of these pipes looks substantially like this:</p>
<pre>"items":[
   {
      "u":"http:\/\/twitter.com\/jlam\/statuses\/717107112",
      "t":"jlam: Would anyone like to catch http:\/\/tinyurl.com\/3xz6kc tonite?"
   },
   {
      "u":"http:\/\/twitter.com\/jlam\/statuses\/717097392",
      "t":"jlam: @dearlazyweb a 713733562 Ben, John http:\/\/ejohn.org is writing one now. Meanwhile, see http:\/\/jQuery.com and http:\/\/learningJQuery.com"
   },
   {
      "u":"http:\/\/twitter.com\/jlam\/statuses\/705479382",
      "t":"jlam: Indeed @Coley Hong Kong has unbelievably awesome public transportation! The subway costs $0.10\/mile but profitable, and did an IPO in 2000."
   }
]</pre>
<p>If there's a thumbnail in the API, it shows up in the <code>n</code> object.  Using Pipes eases the strain on these outside sites and provides a consistent output stream from many different sources, so a single subroutine can render all the many different results.</p>
<pre>getActivity : function(mbl, api, nick, id) {
   var callback = trueName + '_' + mbl + '_' + api + '_' + nick + '_' + id.replace(/@/, '');
   window[callback] = function(z) {
      var t = callback.split('_');
      var mbl = t[1];
      var api = t[2];
      var nick = t[3];
      var id = t[4];
      if (t.length > 4) {
         var n = t.length - 1;
         for (var i = 5; i &lt; n; i++) {
            nick += '_' + t[i];
         }
         id = t[n];
      }
      if (z && z.value && z.value.items) {
         var r = z.value.items;
         for (var i = 0; i &lt; r.length; i++) {
            var li = document.createElement('LI');
            li.className = api;
            var img = document.createElement('IMG');
            img.src = 'http://l.yimg.com/us.yimg.com/i/us/mbl/services/i' + api + '.png';
            img.align = 'absmiddle';
            li.appendChild(img);
            var tx = r[i].t;
            if (api == 'twitter') {
               var tx = tx.replace(/http:\/\/([^\s,-]*)/gi, '&lt;a href="http://$1" target="_blank">http://$1&lt;/a>').replace(/@([^\s,.!-]*)/gi, '@&lt;a href="http://twitter.com/$1" target="_blank">$1&lt;/a>');
               r[i].u = '';
            }
            if (r[i].u) {
               var a = document.createElement('A');
               a.href = r[i].u;
               a.target = '_blank';
               if (r[i].n) {
                  var img = document.createElement('IMG');
                  img.className = 'v';
                  if (api == 'flickr') {
                     img.className = 'q';
                  }
                  img.align = 'absmiddle';
                  img.src = r[i].n;
                  a.appendChild(img);
                  li.appendChild(a);
                  var a = document.createElement('A');
                  a.target = '_blank';
                  a.href = r[i].u;
               }
            } else {
               var a = document.createElement('SPAN');
            }
            a.innerHTML = tx;
            li.appendChild(a);
            $.s.c.bd[mbl].appendChild(li);
         }
      }
      $.f.addServiceIcon(mbl, api);
      $.f.removeScript(callback);
   };
   if (id) {
      nick = id;
   }
   var url = 'http://pipes.yahoo.com/kentbrew/blogjuice_' + api + '?_render=json&_callback=' + callback + '&s=' + nick;
   $.f.runScript(url, callback);
}</pre>
<p>This function is almost entirely generic; only a couple of exceptions (to remove the @ from Flickr ids, apply a special class name to Flickr thumbnails, and hotlink URLs in Twitter tweets) come into play.  Feel free to clone or use my Pipes for your projects; they're all published and available.</p>
<p>We're using some techniques from <a href="http://kentbrewster.com/case-hardened-javascript">Case-Hardened JavaScript</a> here, most notably the practice of creating a single anonymous variable and a private global to hang all the code from; references to <code>$.f</code> and <code>$.s</code> refer to functions and structure.</p>
<p>When we create our dynamic script tags, we're naming them with <code>window[callback]</code> and passing information about what their user IDs, service nicknames, and API endpoints are inside the callback name.  This allows us to remove each dynamically-generated script tag from the inside, once it's run.</p>

<h3>Filtering URLs in Tweets</h3>
<p>To filter API output <code>tx</code>, we double down on our regular expressions.  The first looks for <code>http://</code>; the second looks for an <code>@</code>:</p>
<pre class="code">
var tweet = tx.replace(/http:\/\/([^\s,-]*)/gi, '&lt;a href="http://$1" target="_blank">http://$1&lt;/a>').replace(/@([^\s,.!-]*)/gi, '@&lt;a href="http://twitter.com/$1" target="_blank">$1&lt;/a>');
</pre>
<h3>Caveats and Gotchas</h3>
<ul>
<li>Firefox, IE7, Opera, and Safari all work ... but the iframe is giving me trouble on IE.  It's ugly.</li>
<li>If it hangs forever, something's busted in one of ten or eleven API endpoints we're banging on.  Suggestions?  Clear your cache; I might be monkeying with the script.  If all else fails, bring up Firebug to track this down.</li>
<li>We're leaning heavily on several different APIs here, so this thing is almost guaranteed to be flaky. Sorry about that; for best results, please be patient, wait for the page to load before trying to juice it, and keep an eye on your status bar.</li>
</ul>
<h3>Directions for Future Development</h3>
<ul>
<li>Right, it would be great to have some indication of when it was done, and when it was stuck on something.  Working on it!</li>
</ul>
<h3>Thank You:</h3>
<p>Adam Platti, Andrew Wooldrige, Aramys Miranda, Ash Patel, Ava Hristova, Bill Scott, Bob Zoller, Bradley Horowitz, Cameron Marlowe, Chad Dickerson, Chanel Wheeler, Chip Morningstar, Chris Goffinet, Christian Heileman, Dan Theurer, Dav Glass, Dave Balmer, David Filo, David Flanagan, Doug Crockford, Dustin Diaz, Ed Ho, Eric Marcoullier, Eric Wu, Ernie Hsiung, Gina Groom, Havi Hoffman, Hedger Wang, Ian Kennedy, Ian Lamb, Isaac Schleuter, JR Conlin, Jason Schupp, Jean-Paul Cozzatti, Jenny Han, Jeremy Gillick, Jeremy Zawodny, Jimmy Byrum, John Greene, Jonathan Trevor, Julian Lecomte, Kevin Brown, Lauri Voss, Leslie Sommer, Luke Wroblewski, Matt McAlister, Matt Sweeney, Micah Laaker, Mike Lee, Nate Koechley, Nathan Arnold, Nicholas Zakas, Norm Francis, PPK, Paul Hammond, Randy Farmer, Scott Schiller, Sean Michael Imler, Steve Souders, Steven Wheeler, Tenni Theurer, Thomas Sha, Tim O'Reilly, Todd Klootz, Todd Sampson, Tom Coates, and (most of all!) Vickie Brewster.</p>
 ]]></description>
	<feedburner:origLink>http://kentbrewster.com/blogjuice</feedburner:origLink></item>
	<item>
		<title>First Steps with the MyBlogLog API</title>
		<link>http://feeds.feedburner.com/~r/KentBrewster/~3/217950550/first-steps-with-the-mybloglog-api</link>
		<guid isPermaLink="false">http://kentbrewster.com/first-steps-with-the-mybloglog-api</guid>
		<comments>http://kentbrewster.com/first-steps-with-the-mybloglog-api</comments>
		<pubDate>Wed, 16 Jan 2008 17:13:41 PST</pubDate>
		<dc:creator>Kent Brewster</dc:creator>
		<description><![CDATA[ <p>Special note to RSS readers: this entry contains live JavaScript.  Please visit the page to see it working!</p>

<style>
#mbl {
   background-color:#ffe;
   border:2px solid #800;
   padding:0;
}

#mbl h3 {
   margin:0;
   padding:5px;
   border-bottom:2px solid #800;
}

#mbl div.r {
   border-bottom:2px dotted #888;
   margin:10px 10px 0 10px;
}

#mbl div.r img {
   border:1px solid #888;
   margin:5px 5px 0 0;
}

#mbl div.attrib{
   text-align:right;
   padding-right:10px;;
}
</style>
<p>After much hard work, the team at <a href="http://mybloglog.com">MyBlogLog</a> and the <a href="http://developer.yahoo.com">Yahoo! Developer Network</a>--including but definitely not limited to Todd Sampson, Ian Kennedy, J.R. Conlin, and the one and only Chris Goffinet--have released the MyBlogLog API into <a href="http://developer.yahoo.com/mybloglog/">limited public beta</a>.</p>
<p>Included in the API are the usual goodies already found in the reader roll, plus other stuff like tags, discussion, and outside communities.</p>
<p>That last bit is important:  suddenly there's a wide-open source of information about who lives where on the Web.  Over the past week I've begun pinging various services as they come up for my users; as of right now, we should see:</p>
<ul>
<li>Sites authored -- if you click an image, the app will re-load and show you the readers from there. This is fun; try it out!</li>
<li>Photos from Flickr</li>
<li>Status updates from Twitter</li>
<li>Current professional status from LinkedIn</li>
<li>Bookmarks from del.icio.us</li>
<li>Pages shared through Digg</li>
<li>Songs scrobbled through Last.fm</li>
<li>Next events on Upcoming</li>
<li>Last five videos favorited on YouTube</li>
</ul>
<div id="mbl">
<h3>My Recent Visitors</h3>
</div>

<h3>Things to Do and Notice</h3>
<ul>
<li>The most recent visitor might not be you if you just got here and have not seen anything else on the site; I can't imagine the API could possibly be that fast.  (I'm willing to be pleasantly surprised, though.)</li>
<li>If you've been tagged on MyBlogLog, they ought to show up here.  If you haven't, go do it now!</li>
<li>If you've registered an outside social service id (like Myspace or Flickr) via MyBlogLog, you ought to see it listed.  If you click it, you'll go straight on over to your profile there.</li>
</ul>
<h3>Caveats and Gotchas</h3>
<ul>
<li>Right, sorry, it's an invite-only beta.  Please trust me on this when I say there are Good and Sufficient Reasons for this, and the closed period will be kept as short as humanly possible.</li>
<li>Missing from the API is an easy way to simply link a user's name to his or her designated home page.  If everybody delegated their openIDs through their home pages--I use <a href="http://idproxy.net/about/delegation/">idproxy.net</a>--this would become a non-problem.</li>
<li>There's a fair bit of bouncing around; we have to make an API call to get user details for each reader from MyBlogLog, and then there's a call to each outside service that person might have listed.  So far nothing's terribly broken, mostly due to the fact that I'm leaning on Pipes quite heavily.</li>
</ul>
<h3>Please Note</h3>
<p>Although I am a developer who works for Yahoo!, I don't work on MyBlogLog or any of the other services that show up here.  Absolutely nothing you see on this page--including random stuff written and broadcast by any of the services that are being returned as a result of connections between the MyBlogLog API and outside services--should be taken as official messaging from Yahoo!</p>
<p>In addition to MyBlogLog, data for this hack comes from a wide variety of sources, including Yahoo's <a href="http://mybloglog.com">MyBlogLog</a>, <a href="http://flickr.com">Flickr</a>, <a href="http://upcoming.yahoo.com">Upcoming</a>, and <a href="http://del.icio.us">del.icio.us</a> services.  I believe I've attributed it properly, by linking to <a href="http://developer.yahoo.com/about/">http://developer.yahoo.com/about</a>, as requried by YDN's <a href="http://developer.yahoo.com/attribution/">attribution page</a>.</p>
<h3>The Code</h3>
<pre class="source">
<?php
   $source = file_get_contents("/home/kentbrew/public_html/inc/js/mybloglog-badge.js");
   $source = str_replace("<", "&lt;", $source);
   $source = str_replace("sqDlksDV34E8tpdApCZMNqKEkAn7NO76MrWcDpIENRca9xhrSWUyGrNsPsAytba9IiHHwQ--", "[my api key here]", $source);
   echo $source;
?>
</pre>
<p>If you're curious about the coding style, please take a look at <a href="http://kentbrewster.com/case-hardened-javascript/">Case-Hardened JavaScript</a>.  More about implementing nothing-but-net API clients using the SCRIPT tag hack may be found under Presentations, in <a href="http://kentbrewster.com/bbc-widget/">BBC Search Widget</a> and <a href="http://kentbrewster.com/wiki-widget/">Wikipedia Search Widget</a>.  I do take these presentations on the road; if you're interested in seeing it in person, please hit me up in <a href="http://kentbrewster.com/contact/">Contact</a>.</p>

<p>Special note to RSS readers: this entry contains live JavaScript.  Please visit the page to see it working!</p>
 ]]></description>
	<feedburner:origLink>http://kentbrewster.com/first-steps-with-the-mybloglog-api</feedburner:origLink></item>
	<item>
		<title>The Well-Tempered iTouch</title>
		<link>http://feeds.feedburner.com/~r/KentBrewster/~3/209499175/hack-your-ipod-touch</link>
		<guid isPermaLink="false">http://kentbrewster.com/hack-your-ipod-touch</guid>
		<comments>http://kentbrewster.com/hack-your-ipod-touch</comments>
		<pubDate>Thu, 10 Jan 2008 09:52:32 PST</pubDate>
		<dc:creator>Kent Brewster</dc:creator>
		<description><![CDATA[ 
<p>Here's a list of notes-to-myself about hacking the iPod Touch.  I'm posting it here in the hope that it may be useful to other owners, who are happy with their new toys but can't help thinking that there might be more fun to be had.</p>
<p>Perhaps you bought the 16-gigabyte model, which now costs exactly what the 8-gig iPhone does, and you're wondering why it didn't come with e-mail, or an RSS reader, or an IRC client, and why you can't just go ahead and add one.  Maybe you'd like to read <a href="http://craphound.com/?p=1990">Cory Doctorow's books</a> on it.  Or maybe you agree with the <a href="http://www.makezine.com/04/ownyourown/" target="_blank">Owner's Manifesto</a> and would like to crack into the thing a little bit and see what's inside.  Remember, if you can't open it, you don't own it.</p>
<p>This list is not guaranteed to be definitive, all encompassing, or kept up-to-date.  Comments are open, however, and I do hope for help from fellow travelers.</p>
<p>Oh, and:  yeah. I know. It's an "iPod Touch," not an iTouch.  Sorry if that makes you crazy; I'm not going to stop saying it.</p>

<h3>Before You Begin: the Scary Warnings</h3>
<p>Please seriously consider not doing this.  It's painful.</p>
<p>If you are not a dedicated hobbyist, hacker, or both, and all you want is the iPhone application bundle--including Mail, Maps, Weather, Stocks, and Notes--update to 1.1.3, visit iTunes, and pay for it.  It's supported by Apple, works on all the mail providers (not just Gmail, which now has IMAP support), and the Maps application has been upgraded to do some really neat stuff with IP location.</p>
<p>If you absolutely must do this, kindly heed the following warnings:</p>
<ul>
<li>Please read the entire (horribly long) page before doing anything, including the comments.  Actually, please read the comments first, since the readers of this page are much, much smarter than I am, and have been responsible for pointing out all critical errors so far.</li>
<li>I won't support you if you demonstrate basic lack of knowledge.  If you can't get a command prompt open and navigate from directory to directory, please go take the BLUE pill; it's avaiable for $20 via iTunes.</li>
<li>Sorry, I don't know where to get those NES ROMs.  Don't ask.  I'm just barely okay with showing how to get the iPhone apps; as soon as the price from Apple drops to $0, that part will be going away.</li>
</ul>
<h3>If your iTouch Freezes, Freaks Out, or Otherwise Becomes Unusable</h3>
<ul>
<li>Check that you have iTunes version 7.5 or below.  If you have 7.6, much of what we're doing won't work.</li>
<li>Start over from Restoring Version 1.1.1, just below.</li>
<li>Give up this madness and update to the current version.</li>
</ul>
<h3>Getting Started</h3>
<p>To install third-party applications, you'll need to jailbreak your iTouch.  When we're done, you'll have a new application, Installer, which will allow you to download and install other programs.</p>
<p>If you just got your iPod out of the box, please go through the steps to download iTunes to your computer and synch it for the first time.</p>
<p>Important: if iTunes offers to install new software on your iPod when you first set it up, say No.</p>
<p>Also take a moment to familiarize yourself with a few important features, namely the Home button, which is a white square inside a round button on the front of your iTouch, and the Sleep button, which is a thin raised line on the top edge of your iTouch, the opposite edge from where the docking cable and earphones plug in.</p>
<p>Make sure you can get to the Internet.  Find the Settings function--the square icon with gears on it--touch WiFi, and then choose a network.  If you can't get to a wireless network, you're not going to be able to get much further than this.  Once it looks like you've joined a network, press your Home button to get out of Settings, and bring up Safari.  If Safari will show you a Web site (any Web site) you are ready to move on.</p>
<p>Check your version.  Press your Home button to get out of Safari, bring up Settings again, go to General, and then About.  If your version starts with 1.1.1--mine says 1.1.1 (3A110a)--skip the next step.  (If you got your iTouch for Christmas, you've probably got 1.1.2.  If you got it after January 18th, you may have 1.1.3; please read the next paragraph carefully!)</p>
<h3>Watch Out for Firmware Version 1.1.3 and iTunes 7.6 or Above!</h3>
<p>If your version number says 1.1.3, you've either got a brand-new post-Macworld iTouch, or you've inadvertently upgraded since the push went out.  If you're not already on firware version 1.1.3 and/or iTunes 7.6 or above, you're going to want to be very careful not to get the iTunes updates.</p>
<p>Before you begin, check your iTunes version.  If it says 7.6, much of what we're going to try to do below won't work.  Make sure all your music is safe in a different directory, uninstall iTunes, and download and install version 7.5, which you can get from <a href="http://filehippo.com/download_itunes/?3402">filehippo.com</a>.</p>
<p>Alert reader Nick says this works to get out of 1.1.3:</p>
<ul>
<li>Download the firmware version you need, which is 1.1.1.  (Link is below, in step 1.)</li>
<li>Connect your iTouch and bring up iTunes 7.5 or below.</li>
<li>Turn off your iTouch, using Home plus Sleep for ten seconds, and then slide the red slider.  (Your iTouch should disappear from iTunes.)</li>
<li>Press and hold Home and Sleep until iTunes sees your iTouch again. (You won't see anything on the screen of the iTouch.  Just watch iTunes.)</li>
<li>Skip to step 4, below, and restore the 1.1.1 firmware.</li>
</ul>

<h3>Restoring Version 1.1.1</h3>
<p>Warning: what we're about to do is absolutely guaranteed to wipe everthing on your iTouch.  Please make sure that any music, video, photos, or other content is backed up before you continue!</p>
<ol>
<li>Open up a Web browser on the computer where iTunes resides and visit the following URL:<br />
<pre><a href="http://appldnld.apple.com.edgesuite.net/content.info.apple.com/iPod/SBML/osx/bundles/061-3932.20070927.p23dD/iPod1,1_1.1.1_3A110a_Restore.ipsw">http://appldnld.apple.com.edgesuite.net/content.info.apple.com/iPod/SBML/osx/bundles/061-3932.20070927.p23dD/iPod1,1_1.1.1_3A110a_Restore.ipsw</a></pre></li>
<li>Save this file to your desktop.  It's quite large (150mb), so it might take a long time.  If you're having trouble downloading it, I recommend the Opera Web browser, which has a very stable pause/resume/recover-after-errors download function.</li>
<li>Once you're done loading, open iTunes, plug in your iTouch, and make sure it's not rigged to automatically do anything--especially upgrade its firmware--when your iTouch is connected.  Leave this setting on forever, or else you may wind up with a factory-reset iPod when Apple pushes out the next update.</li>
<li>When iTunes recognizes your iTouch, shift-click (on a PC) or option-click (on a Mac) the Update button.  Instead of recovering to the most recent version, a special hidden menu will pop up and ask you for the location of the firmware file you'd like to recover.  Choose the 1.1.1 firmware file, which you saved to your desktop, and let it work.</li>
</ol>
<p>When your iTouch reboots, it should come up with version 1.1.1, ready for our next step, Jailbreak.</p>
<h3>Jailbreak!</h3>
<p>Next, we're going to break your iTouch out of jail.  Left at factory settings, you won't be able to access your own file system, add programs, or do anything else our Cupertino overlords don't want you to do.</p>
<ol>
<li>Fortunately, jailbreaking your iTouch from 1.1.1 is easy.  Bring up Safari on your iTouch and go here:
<pre><a href="http://jailbreakme.com" target="_blank">http://jailbreakme.com</a></pre></li>
<li>Scroll to the very bottom, click Install AppSnap, and follow the prompts.</li>
<li>You'll see some loading going on, and then when your iTouch reboots, you'll see a new icon on your home screen, Installer.</li>
</ol>
<p>If you like, you can stop right here.  Many applications run on 1.1.1; feel free to jump right in with Installer and try out a few games.  (Labyrinth is my personal favorite.)</p>
<h3>On to 1.1.2</h3>
<p>You're not really done, because iTunes will bug you constantly about updating your iTouch, and if somebody inadvertently does this for you--say you sych to a different machine, for instance--all your hard work can be wiped in an instant.</p>
<h3>Get Version 1.1.2</h3>
<p>Download and save this file.  It's your 1.1.2 software, which you want to use instead of 1.1.3:</p>
<pre><a href="http://appldnld.apple.com.edgesuite.net/content.info.apple.com/iPod/SBML/osx/bundles/061-4036.20071107.9g3DF/iPod1,1_1.1.2_3B48b_Restore.ipsw">http://appldnld.apple.com.edgesuite.net/content.info.apple.com/iPod/SBML/osx/bundles/061-4036.20071107.9g3DF/iPod1,1_1.1.2_3B48b_Restore.ipsw</a></pre>
<p>Jailbreaking 1.1.2 is not quite as easy as the 1.1.1 jailbreak, but it's close.  Here we go:</p>
<ol>
<li>You'll need Java on the same machine that iTunes resides upon; chances are excellent you already have it if you are running an even remotely up-to-date Web browser.  Check that Java is set up, using Sun's handy <a href="http://www.java.com/en/download/installed.jsp" target="_blank">online tool</a>, and if it's not, go get it.  [Updated: I'm being told that the Sun tool doesn't always work.  To tell for sure if Java is on your machine, open up a command prompt (Windows: Start, then Run, then enter CMD in the box) and enter "java" on the command line.  If a slew of command-line options comes up, Java is installed.  If you get a file-or-command-not-found error, it's not.]</li>
<li>Once you're sure you have Java, download and extract this file:</p>
<pre><a href="http://conceitedsoftware.com/iphone/1.1.2-jailbreak.zip">http://conceitedsoftware.com/iphone/1.1.2-jailbreak.zip</a></pre>
... to a folder on your desktop.</li>
<li>Got the 1.1.2 firmware and jailbreak?  Next, open up Installer on your iTouch, click Install, All Packages, and then install OktoPrep.  OktoPrep will chug for a bit and then tell you your iTouch is ready to update to 1.1.2.</li>
<li>Connect your iTouch and launch iTunes.  When iTunes recognizes your iTouch, shift-click (on a PC) or option-click (on a Mac) the Update button.  Instead of recovering to the most recent version--which you do NOT want to do--a special hidden menu will pop up and ask you for the location of the firmware file you'd like to recover.  Choose the 1.1.2 firmware file, which you saved to your desktop, and let it work.</li>
<li>Once you're all done, your iTouch will come back without the Installer on the desktop; this is fine, since OktoPrep is lurking backstage ready to help break you out of 1.1.2.</li>
<li>Eject your device from iTunes, but keep it connected to your computer.</li>
<li>Close iTunes.</li>
<li>Open up the directory you installed the 1.1.2 jailbreak into.</li>
<li>If you're using a PC, double-click <code>windows.bat</code>; if you're using a Mac, double-click <code>jailbreak.jar</code>.  If you already know what OpenSSH is, go ahead and tell it to install; it's handy later.  (If you don't know what OpenSSH is, don't bother.  You can get it later with Installer.)</li>
</ol>
<p>Sit back, relax, and watch your iTouch being jailbroken.  When your main menu comes back, you should see your old friend Installer, plus your optional new friend OpenSSH, all jailbroken and ready to rumble.</p>
<p>If you're seeing mysterious "cannot connect to your device" errors, you may be missing an <code>/opt</code> directory that needs to be installed in your root.  I found details on <a href="http://forums.macrumors.com/showthread.php?t=386118">macrumors.com</a> that seem like they may help.  I'm not totally clear whether this is a Mac-only problem, or an Intel vs. non-Intel problem; if it happens on PCs as well, I'm not sure where that "root" directory is.</p>
<h3>Your First Installation</h3>
<p>Before you do anything else, use Installer to load up the BSD Subsystem.  Many third-party applications (including the one we're about to install) require it to work.</p>
<p>Do yourself a favor here: any time you're doing package installations on your iTouch, go to Settings, General, and then Auto-Lock, and tell it never to automatically lock.  Some of the stuff you're going to download will take more than five minutes to download and install, and it's chancy, coming back from a lock.</p>
<ol>
<li>Make sure your wireless network is running and bring up Installer.  While it refreshes packages, please consider the karmic benefits of donating to the project ... remember, these folks made a much higher enjoyment of your iTouch possible.</li>
<li>Once Installer is back with packages, tap Install (at the bottom of the screen) and then All Packages.  Slide down a bit and find the BSD Subsystem.</li>
<li>Try out the Contact and More Info functions; they should bring up extra pages about what the BSD Subsystem is and does.</li>
<li>Tap the Install button at the top of the screen (not the one at the bottom; this gets me frequently) and wait for your package to install.</li>
<li>Once you're back to Categories, get Term-VT100, using the same method as above. Term-VT100 is a terminal program that will allow you to open up a command prompt for your iTouch, right there on the screen.  Command-line access looks boring but is actually quite handy; you'll be able to tweak settings without having to load programs designed specifically for that purpose.</p>
<li>When Term-VT100 is done installing, press your Home button.  Your desktop will come back, along with a twirly image that means it's thinking.  It will then reboot to your locked screen; unlock it, and you ought to see a new icon, Term-vt100, with a lovely black command-prompt icon.</li>
</ol>
<p>Got Term-VT100?  Excellent; bring it up and try this:</p>
<pre>pwd</pre>
<p>If all has gone well, you should see this:</p>
<pre>/var/root</pre>
<p>If you're getting a <code>command not found</code> error message, go back to Installer and try installing the BSD Subsystem again.  It didn't take.</p>
<p>When all is well, let's make an important change so you won't run out of storage space when adding more third-party programs.</p>
<h3>Making Sure You Don't Run Out of Storage Space</h3>
<p>Again: this is optional but highly recommended for people who plan on installing more than a few tiny third-party applications.</p>
<p>Since the factory-set iTouch comes with an artificially small size limit on its /Applications directory, you may receive an error message--"Warning: You are running out of disk space. Please delete some photos or videos"--even though you're quite sure you've got lots of space left.</p>
<p>DANGER DANGER WILL ROBINSON: please do this next part slowly and carefully.  Screw it up and you'll have to go back, restore version 1.1.1, and start all over again.</p>
<ol>
<li>Bring up Term-VT100.  If you've never seen one before, you're looking at a Unix prompt.  (You can also do this with OpenSSH, if you installed it and you know what you're doing.)</li>
<li>First task:  move to the iTouch's root directory, copy your Applications directory there, rename your existing Applications directory to Applications.old, and then tell your iTouch to look in the new directory for stuff it previously found in the old directory.  Type the following commands, exactly as shown:
<pre>cd /
cp -pr Applications /var/root
mv Applications Applications.old
ln -s private/var/root/Applications /Applications</pre>
If you're seeing error messages like <code>command not found</code> when you try <code>cd /</code>, you didn't install the BSD Subsystem.  Please go back to Your First Installation and fix this.</li>
<li>Next, let's check that it worked.  Still in Term-VT100, enter these commands:
<pre>cd /
ls -al</pre>
Somewhere in the resulting list--you may need to scroll the screen up to see it; to do this, drag it gently upwards at one of its edges--you'll see something like this:
<pre>rwxr-xr-x 1 root admin  29 Dec 26 23:27 Applications -> private/var/root/Applications</pre>
If it looks like <code>/Applications</code> has been linked to <code>private/var/root/Applications</code>, you're done.  If not, you'll want to keep trying that last <code>ln</code> command again until you get it.</li>
<li>Restart your iTouch, by pressing and holding the Sleep button until the slide-to-power-off prompt appears.  Power off, wait a moment for the twirly thing to stop and for the screen to go completely dark, and power back on again, using the Sleep button.</li>
<li>Here's where things can go wrong, so please be absolutely sure you've created that link.  If you've mis-typed the link, your iTouch may reboot repeatedly, or may come back with no icons on the desktop.  If this happens, you'll need to a) restore version 1.1.1 of the firmware and start over again from scratch, or b) try OpenSSH, if you installed it upstream.</li>
<li>If all is good, bring up VT-100 again, and remove the old <code>/Applications</code> directory, thusly:
<pre>cd /
pwd</pre>
If the output from pwd doesn't look like this: <code>/</code>, try the <code>cd /</code> command again.  You need to be in your root directory for the next command to work.  Once you're there, do this:
<pre>rm -rf Applications.old</pre>
</ol>
<p>Relax, the hairy part is over.  From now on, everything we do will go through Installer.  Let's have some fun monkeying with the interface next.</p>
<h3>Monkeying Around with the User Interface</h3>
<p>Using Installer, load up two new packages, Customize and SummerBoard.  After you have them both, reboot your iTouch, by pressing and holding the Sleep button until the Power Off slider comes up.  (If you get further into this process and Summerboard says it's "inactive" down at the bottom, you didn't reboot.  Told you so.)</p>
<p>Summerboard will allow you to add desktop wallpapers, themes, hide labels, and other cool stuff; Customize will allow you to hide and change the images for your onscreen icons.  I run both, personally; I like the green-grass Leopard background, no icon labels, and a dock containing anything that might have an alert on the icon with number of messages, etc.  I also push as many of my customization options (like Term-VT100) off to the second page as possible, to discourage casual goofballs from messing around with my setup.</p>
<p>What?  Mail?  Yes.  And Maps, too.  And games ... sweet tasty games for everyone!  Hold tight: it's finally time to add some Cool New Toys.</p>
<h3>Cool New Toys</h3>
<p>Lots of fun may be had with the Installer; it's getting fun-er by the day.  My personal favorites include:</p>
<ul>
<li>Labyrinth - tilt the iTouch to roll the ball through the wooden maze. This is the first thing I show people; they instantly "get" the idea that the iTouch is neat, and you ought to be able to hack it.</li>
<li>iFlix - a Netflix queue manager that must be seen to be believed.  (I didn't actually have Netflix until I saw this app running on a colleague's iPhone; it's <em>that</em> compelling.)</li>
<li>MobileRSS - mmm ... feedie goodness!  Consumes output from Yahoo! Pipes really nicely.</li>
<li>iSolitaire - awesome Klondike experience.</li>
<li>Sketches - an Etch-A-Sketch for your iTouch.  Shake to erase, or upload those pictures to Flickr through Mobile Mail, described below.</li>
</ul>
<h3>In General, Install Things Slowly and Carefully</h3>
<p>Especially when dealing with apps that were originalliy intended for the iPhone, install slowly and carefully.  Always go back to the home screen, every time, and pay special attention to those "prep" packages.</p>
<h3>Applications from Apple that were Originally Intended Only for the iPhone</h3>
<p>If you skipped to here instead of reading the rest of the page, please go back to the top and read the warnings, and the strong advise that if all you want are these apps, go pay for them from Apple.</p>
<p>To run Mail, Weather, Stocks, Notes, and Maps on your iTouch, you will need to download and install some Apple property not specifically intended for the iTouch. You will need to lie, cheat, and steal even more than you already have to do this; if you believe in karma, be very, very careful here.</p>
<p>Maps and Mail are hairy; you'll want to follow the instructions about installing the "prep" software first.  Notes, Stocks, and Weather jump right up and run; Notes is really cool, especially when integrated with Mail.</p>
<p>Google Maps on the iTouch may be the single most useful thing I've ever held in one hand.  It's what's got me seriously considering an iPhone ... but that's just not gonna happen until I can run the provider of my choice.</p>
<h3>Getting Mail Working</h3>
<ol>
<li>Add <code>http://applerepo.com/</code> to your list of sources. (Sources, Edit, Add)  If you have the old <code>repo.us.to</code> repository, your iPhone apps won't show on the list of packages any more.</li>
<li>If sources refresh successfully--this may take a long time--it will come up as the Apple Repository.  If it's an anonymous source at the bottom, refresh sources again.</li>
<li>In the package list, find the iPhone 1.1.2 Apps for iTouch category.  (In theory Mail will also work on 1.1.1 ... I recommend going to 1.1.2, however, because the Mail install is a pain and you won't want to go through it again if you decide to move up later.)</li>
<li>Add the Mobile Mail Prep for 1.1.2 application and click your Home button, to get all the way back out to your home screen.</li>
<li>Go back into Installer, Packages, iPhone 1.1.2 Apps, and install Apple MobileMail 1.1.2.  It will warn you that you need to have Mobile Mail Prep 1.1.2 installed; if you don't, you may wind up going all the way back up to the top of this whole dismal list and starting over again with the 1.1.1 recovery.</li>
</ol>
<p>As far as I can tell, Mail won't work with Yahoo! via an iPod Touch.  I can't see myself giving access to my personal IMAP server to a hacked client, and I can't bring myself to start an AOL or .mac account, so ... it's GMail for me.</p>
<h3>Start a New GMail Account</h3>
<ol>
<li>Seriously.  Do this.  Since you're installing the Mail from a non-Apple source, and there's a strong motivation for wily hackers (or maybe even Apple themselves) to code in a back door and grab what personal information they can, start a brand-new GMail account, just for this experiment, using absolutely no personal information--especially that one crucial password you use on all your social networking sites!--that you care about.</li>
<li>Once your new account is up and running, sign in to GMail, go to Settings, Forwarding and POP/IMAP, and enable POP for all mail.  Leave it set to keep GMail's copy in the In box; this will be handy when you have to re-do this entire process in a week.</li>
<li>The one flaky thing you'll notice about Mail on the iTouch is this: when you go into Settings and click the Gmail address, your iTouch may hang, sometimes disastrously so.  When this happens, you need to power off, power back on again, and sometimes plug it into iTunes to get it to come back. (I used to think this was part of running mail on 1.1.1, but it also happens to me on 1.1.2. No idea what's up with this; suggestions will be appreciated.)</li>
</ol>
<h3>Be Afraid. Be Very Afraid.  Of an Update, That Is....</h3>
<p>The next update from Apple is almost guaranteed to hose everything we've done here, and may even make it impossible to downgrade to 1.1.1.</p>
<ul>
<li>Please be sure you've got iTunes rigged to ask you first before updating your iPod; for maximum paranoia, plug it in, click it in the Devices list, and un-check the box marked Open iTunes when this iPod is Connected.</li>
<li>When updates become available, check back here (and elsewhere; resources are listed below; <a href="http://www.tuaw.com/">The Unofficial Apple Weblog</a> is an excellent first stop) before installing anything.  Chances are excellent that whatever comes down next from Apple will break everything you've done to your iTouch and restore it back to factory settings.</li>
</ul>
<h3>So Why Bother?</h3>
<ul>
<li>Because something like this has the potential to truly revolutionize communications.  One Laptop Per Child becomes a moot point if everybody's got one of these things and it's wide-open; if I could plug in a microphone, camera, and keyboard, I could ditch my laptop and cellphone forever.</li>
<li>Because pressure from people like us is causing the folks in charge to reconsider the use of closed-source hardware and software.  There's an SDK coming from Apple in a month or so, for both the iTouch and the iPhone.</li>
<li>Because it's <em>yours</em>, dammit.  It's like buying a car and being told you can only drive it on toll roads.  You paid for it, you're steering it ... so you ought to be able to drive it anywhere you want as long as you're not endangering anybody else's life, liberty, or property.</li>
</ul>
<h3>Development Tools?</h3>
<p>In addition to following several <a href="http://iphonewebdev.com/" target="_blank">really great tutorials</a> for building <a href="http://kentbrewster.com/glint">Safari web apps that run on the iTouch</a>, I've recently downloaded and installed <a href="http://jiggyapp.com">Jiggy</a>, a very impressive little integrated developer's environment and runtime.  Jiggy actually allows you to do iTouch and iPhone development right there on your device.  Inside is a tiny Web server; you bring it up, it tells you its IP address, you log in from a full-sized computer on the same wireless network, and program in JavaScript, inside a Web form.  This is just plain spectacular work on the part of the Jiggy crew; you can (seriously) get an application working in minutes.  More on this, as things develop.</p>
<h3>Other Important Resources</h3>
<ul>
<li><a href="http://jailbreakme.com/" target="_blank">jailbreakme.com</a> -- where it all started for me.</li>
<li><a href="http://iphonewebdev.com/" target="_blank">iPhoneWebDev</a> -- developing content for mobile Safari.</li>
<li><a href="http://www.tuaw.com/" target="_blank">The Unofficial Apple Weblog</a>, especially <a href="http://www.tuaw.com/bloggers/erica-sadun/">Erica Sadun</a>'s stuff</li>
<li><a href="http://http://www.modmyifone.com/" target="_blank">ModMyIFone.com</a> -- don't forget to add <code>modmyifone.com/installer.xml</code> to your installer sources.</li>
<li><a href="http://iphone.nullriver.com/beta/" target="_blank">Nullriver Software</a></li>
<li><a href="http://www.ipodtouchhacks.com/" target="_blank">Ipod Touch Hacks</a></li>
<li><a href="http://iphone-dev.com/" target="_blank">Iphone Dev Team</a></li>
<li><a href="http://www.hackint0sh.org/forum/indexpage.php" target="_blank">Hackint0sh</a></li>
<li><a href="http://iphone.fiveforty.net/wiki/index.php/Main_Page" target="_blank">iPhone Dev Wiki</a></li>
<li><a href="http://forums.macrumors.com/showthread.php?t=386118" target="_blank">MacRumors</a>, for the bit about the Can't Connect error, post 1.1.2 jailbreak.</li>
</ul>
<h3>For Best Results, Please Donate!</h3>
<p>Heinlein was right, as usual:  supreme artistic appreciation may only be expressed by the phrase "Pay to the Order Of."</p>
<p>Third-party projects for the iTouch and iPhone are shoestring-budget affairs, done for the love of it.  You can help increase the love many times, by donating to the project of your choice.  (Hint:  jailbreakme.com, Nullriver, and the iPhone Dev Team are really, really good choices.)  $20 is a tiny amount compared to the $300 or $400 you paid for the thing, and doesn't even begin to compare to that one crucial opportunity you'll gain because you had an RSS reader, or maps, or e-mail.  Your iTouch is a tool, not a toy, and these unsung heroes have set you free to swing that hammer as hard as you want.  Donate!</p>
 ]]></description>
	<feedburner:origLink>http://kentbrewster.com/hack-your-ipod-touch</feedburner:origLink></item>
	<item>
		<title>Glint: an iPhone Toy</title>
		<link>http://feeds.feedburner.com/~r/KentBrewster/~3/183925766/glint-an-iphone-toy</link>
		<guid isPermaLink="false">http://kentbrewster.com/glint-an-iphone-toy</guid>
		<comments>http://kentbrewster.com/glint-an-iphone-toy</comments>
		<pubDate>Sat, 05 Jan 2008 19:48:56 PST</pubDate>
		<dc:creator>Kent Brewster</dc:creator>
		<description><![CDATA[ <p>Special note to RSS readers: this entry contains live JavaScript.  Please visit the page to see it working!</p>

<div id="glint" style="float:right;margin:10px;"><div id="board" class="black"></div><div id="status"></div><div id="help"><p><strong>Glint, by <a href="http://kentbrewster.com">Kent Brewster</a></strong></p><p>Fill the board without repeating in rows, columns, or sub-boards.</p><p>The background color is the color of the next piece. If you duplicate a color in a row, column, or sub-board, it will clear.</p><p>Puzzles change every day - come back tomorrow!</p><p><a onclick="KENTBREW.glint.hideHelp()">play</a> - <a href="http://kentbrewster.com/glint-an-iphone-toy">discuss</a> - <a href="http://digg.com/playable_web_games/Glint_an_iPhone_Toy">digg</a> - <a href="http://reddit.com/submit?url=http%3A%2F%2Fkentbrewster.com%2Fglint&title=Glint%3A+an+iPhone+Toy">reddit</a></p></div></div>
<p>Welcome to Glint.  In its current incarnation, it's a six-color Sudoku board; to finish, you need to fit one piece of each color into each row, column, and two-by-three sub-board.</p>
<ul>
<li>You get one piece at a time; the current background color is the color of the piece you're placing.</li>
<li>If you make an illegal move, enough of the board (the row, column, and sub-board, in that order) will be cleared to make your move legal.</li>
<li>When you fit all the pieces in, you're done; the fewer moves you make, the better.</li>
<li>To try Glint on your iPhone or iPod Touch, visit <a href="http://kentbrewster.com/glint">http://kentbrewster.com/glint</a></li>
<li>If you had fun today, check back tomorrow; there's a fresh puzzle every day.</li>
<li>For quite a bit more fun, check out the <a href="http://www.apple.com/webapps/games/">Games</a> section of the Apple developer gallery.</li>
</ul>
<h3>
<h3 class="toggle closed">How It Works</h3>
<ul>
<li>It's a pretty standard Web page, containing structure, presentation, and markup.  Since I'll be pushing a fresh game every day, I'm inserting it directly into the source via PHP.  This will show up in the <code>config.status</code> object, if you peek at the source.</p>
<li>The interesting bit is that <code>&lt;meta></code> tag in the document head:<br />
<code>&lt;meta name="viewport" id="iphone-viewport" content="width=228, height=260, user-scalable=no" /></code></li>
<li>This plus some explicit sizing in the body makes the board exactly fit the width of the browser, and not roll around on the screen too much when the user accidentally drags it around.</li>
<li>I've had good luck finding information about iPhone web development on <a href="http://www.iphonewebdev.com/">iphonewebdev.com</a>, the <a href="http://groups.google.com/group/iphonewebdev">iPhoneWebDev Google Group</a>, <a href="http://iphonedojo.net">iphonedojo.net</a>, and (of course) <a href="http://developer.apple.com/iphone/devcenter/">the official Apple site</a>.  Have fun with Glint, and please let me know how it goes.</li>
</ul>

<p>Special note to RSS readers: this entry contains live JavaScript.  Please visit the page to see it working!</p>
 ]]></description>
	<feedburner:origLink>http://kentbrewster.com/glint-an-iphone-toy</feedburner:origLink></item>
	<item>
		<title>In Which Tom Boyd Punches my Wife in the Face</title>
		<link>http://feeds.feedburner.com/~r/KentBrewster/~3/190322318/tom-boyd-punched-my-wife-in-the-face</link>
		<guid isPermaLink="false">http://kentbrewster.com/tom-boyd-punched-my-wife-in-the-face</guid>
		<comments>http://kentbrewster.com/tom-boyd-punched-my-wife-in-the-face</comments>
		<pubDate>Sun, 25 Nov 2007 10:09:00 PST</pubDate>
		<dc:creator>Kent Brewster</dc:creator>
		<description><![CDATA[ 
<p>[1/8: we've been stumbled upon.  While I understand some folks would like more detail, it won't be posted here. Unless you're the sort of person who thinks "she pissed me off" is a good reason for a man to sucker-punch a woman, details are not important.]</p>
<p>Beyond the occasional trip report, I don't post much personal information here.  I'm putting this up on the chance that someone may be seeking information about Mr. Thomas Edward Boyd Jr., usually abbreviated as Tom Boyd, of 1563 Tobias Dr., San Jose, CA, doing business under California insurance agent's license <a href="http://interactive.web.insurance.ca.gov/webuser/LIC_STS_UTL.GET_LIC_DETAILS?P_IL_LIC_NBR=0D88155" target="_blank">#0D88155</a>.</p>
<p>On 22 November 2007, after Thanksgiving dinner at his sister's home, Mr. Boyd punched my wife, <a href="http://sff.net/people/k.brewster/vickie.htm" target="_blank">Dr. Victoria Brewster</a>, full in the face.</p>
<p>Mr. Boyd is a big, beefy guy, and weighs at least what I do, 230 or more.  Mr. Boyd stepped in and hit Vickie with a hard right.  Vickie's head snapped sharply around, her eyes rolled, and she fell into her niece's arms.  Mr. Boyd then assumed a fighting stance and backed away into a narrow hallway.</p>
<p>Several sets of circumstances--very tight quarters, and the presence of innocent bystanders, including Vickie, her niece and daughter, Tom and Vickie's elderly parents, and the possibility that his seven-year-old daughter was standing directly behind him--combined to save Mr. Boyd from eating through a tube for the rest of his life.  Instead of risking further harm to the family, I put my chin down, my hands up, and walked straight into him.  Mr. Boyd struck me about the head and neck, and then we were tangled up on the floor, immobile.  After a brief struggle on the ground, our host and his son peeled Mr. Boyd loose, escorted him out the door, and that was that.</p>
<p>We still can't believe he did it.</p>
<p>Three days later, Vickie's still not herself.  She's tired and sore, and sad, and angry.  Her neck hurts, and her jaw hurts, and her teeth were rearranged a bit; she's got a sharp corner that wasn't there before, which her dentist is going to have to look at.</p>
<p>The rest of the family seems to be doing as well as can be expected.  Vickie's daughter witnessed the attack at close range and was utterly distraught; we had to put her on a train back to her university the next morning, but we're staying in close contact.  Small blessings: Vickie's son was out of the room playing video games, and Mr. Boyd's daughter didn't actually see any of it, having been removed from the scene by her parents--convenient timing, there--immediately before the unfortunate incident took place.</p>
<p>I'm scuffed up in a couple of places that haven't seen use since I quit practicing martial arts.  Mr. Boyd caught me in the forehead and gave me a bit of a mouse that's noticeable whenever my eyebrows move.  My knee is skinned, my neck and ear are bruised, and my elbow doesn't want to be leaned on or straighten all the way out.</p>
<p>While none of the above has any relation to Mr. Boyd's competence to sell insurance or dispense financial advice, I mention it because I believe the public makes an implicit assumption that a man in his position is a gentleman who can be trusted to do the right thing in times of stress.  In my personal opinion, this is clearly not the case with Mr. Boyd.</p>
<p>Mr. Boyd?  If you're concerned about any effect this post may have on your reputation, I'll be happy to take it down without further comment after Vickie and the rest of your family have accepted your apology. Personally, I believe that any man who strikes a woman is a miserable coward, and a bully, and an unfit parent.  If you disagree with this and feel like setting me straight, simply name the time and place.</p>
<p>One request: this time, let's leave the women and children out of it.</p>
<p><em>[Updated, Monday morning:  I've disabled comments on this post--and will delete comments posted elsewhere about this matter--due to the potential for misunderstanding. Family and friends know how to reach us; thanks for your support!]</em></p>
 ]]></description>
	<feedburner:origLink>http://kentbrewster.com/tom-boyd-punched-my-wife-in-the-face</feedburner:origLink></item>
	<item>
		<title>Overheard at Defrag</title>
		<link>http://feeds.feedburner.com/~r/KentBrewster/~3/182034120/overheard-at-defrag</link>
		<guid isPermaLink="false">http://kentbrewster.com/overheard-at-defrag</guid>
		<comments>http://kentbrewster.com/overheard-at-defrag</comments>
		<pubDate>Thu, 08 Nov 2007 20:20:43 PST</pubDate>
		<dc:creator>Kent Brewster</dc:creator>
		<description><![CDATA[ 
<p>Back late last night from <a href="http://defragcon.com">Defrag</a>, which I hope to attend again next year. It's been <a href="http://www.readwriteweb.com/archives/defrag_five_themes.php">noted elsewhere</a> that most speakers at the conference repeated several main themes; this seems true to me. What follows is a long list of highlights, sorted in alphabetical order, which seems as good as any.</p>
<ul>
<li>Art helps us share experiences we don't have in common.</li>
<li>As long as the gaming is transparent, the community will figure it out and deal with it.</li>
<li>Communication has gone from e-mail, open by default, filtered through a black list--to instant messaging, closed by default, filtered through a white list.</li>
<li>Computers are explicit; it's digital, so it either is or is not.</li>
<li>Dark Webs will cease to exist. If it can't be found via search, it's not out there.</li>
<li>Data becomes information when you need to know it.</li>
<li>Don't sugar-coat what it is we do for a living. Don't dumb it down. Managers are voracious consumers of theory; they want to be able to make decent predictions.</li>
<li>Every new parent company understands that it can't have a traditional command-and-control relationship with a distributed sales force.</li>
<li>Gaming comes from structural issues around a site. Transaction costs are minimal with Digg, so it's hard to analyze past behavior. There's no construction of a person doing a thing. Richer systems will emerge, where you can see what a person has done in the past.</li>
<li>Half of all information is disinformation. Is the preceding statement part of that 50%?</li>
<li>How can I experience insight and intepretation? How about surprise?</li>
<li>How can we do a better job of making people feel okay that they're wrong all the time?</li>
<li>How do I make sure I don't miss anything?</li>
<li>I grew up in Detroit and I live in Oakland now. Where I'm from, "user" is a bad word.</li>
<li>If everybody knows what I do, what is my value?</li>
<li>If you try to prevent collusion, you prevent collaboration.</li>
<li>In the 1950s. 60s, and 70s, computers were about reducing us to facts. "Informationalization" is about classifying everything. Nowadays we do it ourselves, every time we fill out a Preferences form.</li>
<li>In the future, "I'm not showing you my data" will be far less important than "I'm not showing you my connections."</li>
<li>Information is just stuff I need to know. Knowledge is information with semantic content.</li>
<li>Interestingness is data mining around people's activities, and the social relationships between them and the photos. It's not a voting scheme, and not susceptible to gaming; interestingness is an organic measure that can be applied retroactively, before the feature came online. The magic word is "implicit." Even thought the average Flickr user doesn't think of himself as an editor, his progress through the system makes it better for everyone.</li>
<li>It's amazing that Wikipedia still works. Under every page is a flame war. It doesn't feel like a scalable system.</li>
<li>Kids today are confident enough that they'll be able to create a new idea that they don't need to lock away the rights to old ones.</li>
<li>Language consists of words, paragraphs, punctuations, and now links. Being able to make content permanent--first words, then writing--was a founding event. Links make the relationships permanent, for the first time.</li>
<li>Last year we were talking about breaking identity out of the walled garden. We were terribly concerned with the explicit: this is who I am. This year we're talking about breaking networks out of the walled garden, and are just starting to think about the importance of the implicit: this is who I'm connected to.</li>
<li>Links reveal the world in a way that matters.</li>
<li>Links are the opposite of information. They are impossible to understand without society.</li>
<li>Networking sites take off for tiny reasons about the site, not the intended architecture of the network.</li>
<li>Often the most loyal employees know that their company is wrong. They will treat customers well even though they may lose their jobs for doing so. We need to legitimize the position of these people. They are putting themselves at risk for no personal gain; if caught, they will be fired, but if not caught, the company will profit.</li>
<li>Our children need to understand the difference between potential and possibility.</li>
<li>Overload is a choice: you choose to be overwhelmed, or you focus. You use tools.</li>
<li>Poets have to decide how much to make explicit. So do we, when we make a site, or write a program. </li>
<li>Social software accrues value to the users, the readers, and the owner of the system. In that order.</li>
<li>Some decisions should not be coded.</li>
<li>Sometimes it's a mistake to declare your preferences up front. Life is complex!</li>
<li>Team blogs seem to fit better at work than individual blogs or wikis. Blogging is writing in a way that contributing to a wiki isn't. You find an authorial voice.</li>
<li>The for: tag is a gift. What my friends and contacts are bookmarking is incredibly powerful.</li>
<li>The Semantic Web is self-describing, linked data.</li>
<li>The Web works outstandingly well ... it enables us to do the basic thing that peace wants us to do: live with other people in difference, yet share the fundamental things that make us human.</li>
<li>The social graph connects people. The semantic graph connects everything.</li>
<li>The take from electronic crime is now higher than the drug industry. Within a remarkably short period of time, they'll be messing in our space.</li>
<li>Think augmentation, not automation.</li>
<li>To be implicit is human.</li>
<li>Using social software will not homogenize the ties within a network. The impact will be differentiation: things will be less alike than they were before. The world is spiky, not flat.</li>
<li>We focus on the explicit. It misleads us.</li>
<li>We're at the end of 5000 years of yang ... convincing users to embrace the ying is going to be very, very hard.</li>
<li>What people don't want from search is a bunch of pages. They want a visualization based on their query.</li>
<li>What we care about turns possibility into potential, and makes information inadequate. What's between us is what we don't say.
<li>Where's the history of the Web? When Google updates, it ceases to exist.</li>
<li>Words don't carry meaning. They point towards shared understanding.</li>
</ul>
<p>Next Defrag: 11/4/2008, in Denver again.  Get those absentee ballots in early!</p>
 ]]></description>
	<feedburner:origLink>http://kentbrewster.com/overheard-at-defrag</feedburner:origLink></item>
	<item>
		<title>Hide Recent Document History in WinXP</title>
		<link>http://feeds.feedburner.com/~r/KentBrewster/~3/174028856/document-history-privacy</link>
		<guid isPermaLink="false">http://kentbrewster.com/document-history-privacy</guid>
		<comments>http://kentbrewster.com/document-history-privacy</comments>
		<pubDate>Tue, 23 Oct 2007 16:01:22 PDT</pubDate>
		<dc:creator>Kent Brewster</dc:creator>
		<description><![CDATA[ 
<p>If you're like me and you prefer the "classic" Windows start menu and task bar--flat gray, minimal distraction, not so Teletubbies-looking--you may have already noticed that there's no easy way to tell the Classic version not to track and show your recently opened documents.</p>
<p>Here's how I did it today, with my new best friend, the Group Policy editor:</p>
<p>In your Windows taskbar--usually on the lower left corner of your screen--click Start, then Run, then enter <code>gpedit.msc</code> in the resulting Run: window, and then click OK.  If all goes well, the Group Policy editor will pop up.  If this does not happen, you may be running the Home Edition of WinXP.</p>
<p>In the left pane, navigate your way to User Configuration : Administrative Templates : Start Menu and Taskbar.  Lurking in a long list of ways to screw up your user experience--seriously, be careful with this--are three important options concerning document history privacy:</p>
<h3>Remove Documents Menu from Start Menu</h3>
<p>This seems like it may be what you're looking for, but read the fine print, by double-clicking it and then checking the Explain tab.  Contrary to what's been said elsewhere, Remove Documents From Start Menu <em>does not</em> prevent Windows from displaying shortcuts to recently-opened documents, so if this option is re-enabled, your recently opened files will be back.</p>
<p>Also seen elsewhere: removing Documents from the Start menu has been known to hose programs like Adobe Premiere, which depends on it.</p>
<h3>Do Not Keep History of Recently Opened Documents</h3>
<p>Maximum paranoia, but if you gotta, you gotta.  This is almost certainly going to mess up your work flow if you commonly edit the same documents.  While you're in there under Administrative Templates, don't forget:</p>
<ul>
<li>Start Menu and Taskbar : Turn Off User Tracking</li>
<li>Windows Components : Windows Explorer : Common Open File Dialog : Hide the Dropdown List of Recent Files</li>
</ul>
<p>That last should hide recently opened files from the drop-down list of all Win2K-and-above programs, including Windows Media Player.</p>
<h3>Clear History of Recently Opened Documents on Exit</h3>
<p>This is the one I went with.  As long as I'm in, I see my recent document history; as soon as I log out, it's gone.  This also includes the name of the last few programs I ran using the Run... window.</p>
<p>Sadly, there is no matching Clear History of Recently-Opened Documents over in the Common Open File Dialog section mentioned above; that would be really, really nice.</p>
<h3>Bonus Tidbit: Applying Changes Without Rebooting</h3>
<p>Contrary to what the program says, you won't need to reboot to see these changes.  Go back to Start : Run : and enter <code>GPupdate /force</code>.  Say "No" when it asks you if you want to reboot, wait a moment, and your changes should be up.</p>
 ]]></description>
	<feedburner:origLink>http://kentbrewster.com/document-history-privacy</feedburner:origLink></item>
	<item>
		<title>Recover Lost Flash Drive Data</title>
		<link>http://feeds.feedburner.com/~r/KentBrewster/~3/172678658/easy-flash-drive-data-recovery-with-photorec</link>
		<guid isPermaLink="false">http://kentbrewster.com/easy-flash-drive-data-recovery-with-photorec</guid>
		<comments>http://kentbrewster.com/easy-flash-drive-data-recovery-with-photorec</comments>
		<pubDate>Sat, 20 Oct 2007 16:03:22 PDT</pubDate>
		<dc:creator>Kent Brewster</dc:creator>
		<description><![CDATA[ 
<p>Had a bit of trouble today: one of Vickie's two-gig thumb drives went catatonic.  All Windows could come up with was the scary message that the disk in drive E wasn't formatted, and did she want to format it now?  (Answer: nooooooo!)  After a bit of investigation--the usual stuff: reboot, pray, try it on several machines, sacrifice a chicken--we came to the conclusion that the thing's file system had broken.</p>
<p>So, armed with foggy memories of how Norton Utilities used to work, off I went into the wilds of the Net, searching for recovery advice.  Mostly I found questionable stuff; there are many operators out there who will charge you hundreds of dollars to take a crack at your data with no guarantees, and there are plenty of freeware/shareware downloads that claim to recover lost files but were last updated in 1997, and have since been turned into those $49.95 bloatware packages you see at Office Depot.  Most of these are about hard drives or floppy disks, not memory sticks; I tried a half-dozen, but got nothing back from Vickie's poor dead baby.</p>
<p>Finally I found Christophe Grenier's TestDisk/PhotoRec suite, at <a href="http://www.cgsecurity.org/">http://cgsecurity.org</a>.  PhotoRec ignores the file system in favor of finding lost files, so it works on FAT, NTFS, EXT2/EXT3, HFS, and (with certain caveats) ReiserFS.  And since it's looking for known file headers and using <a href="http://www.cgsecurity.org/wiki/PhotoRec_Data_Carving">data carving</a> techniques, more than eighty file types--among them DOC, PDF, and PPT--are instantly recoverable.  Here's how it went:</p>
<ul>
<li>I downloaded the ZIP file, extracted it to my desktop--no installation required, awesome!--and fired up PhotoRec.  After smiling at the text-only interface, I hit the down-arrow to highlight the drive--in my case it was <code>/dev/sdb</code>--and hit Enter to continue.</li>
<li>Next I needed to choose the partition table type.  Not knowing what else to do, I chose <code>Intel</code>, since the last time the thing had run successfully was on a Windows machine.  (I'm guessing this would want to be set to Macintosh if one was attempting recovery from a Mac-formatted iPod.)</li>
<li>The next screen showed an empty partition and a FAT16 partition, both of which took up pretty much the entire disk.  I crossed my fingers and hit Enter again, choosing the empty partition.</li>
<li>Next, it asked me to choose my filesystem; I was pretty sure we weren't looking at an EXT2/EXT3 system, so I hit Enter to accept <code>Other</code>, the highlighted default.</li>
<li>Finally it asked for a location to store recovered data; I went again with the default, which creates a new directory wherever you have the program installed.  And we were off and running; the first file to pop up was a PDF, and since my new directory showed thumbnails by default, I could see that everything was going to be okay.  Four minutes later, we were all done; all Vickie had to do was re-create her directory structure, re-name her files, and figure out which belonged where.</li
</ul>
<p>Many thanks, Christophe; you ought to be receiving one of your US Amazon wish-list items from us shortly.</p>
 ]]></description>
	<feedburner:origLink>http://kentbrewster.com/easy-flash-drive-data-recovery-with-photorec</feedburner:origLink></item>
	<item>
		<title>Adobe MAX / UIUC Hack Day</title>
		<link>http://feeds.feedburner.com/~r/KentBrewster/~3/169638284/adobe-max-uiuc-hack-day</link>
		<guid isPermaLink="false">http://kentbrewster.com/adobe-max-uiuc-hack-day</guid>
		<comments>http://kentbrewster.com/adobe-max-uiuc-hack-day</comments>
		<pubDate>Mon, 08 Oct 2007 09:35:29 PDT</pubDate>
		<dc:creator>Kent Brewster</dc:creator>
		<description><![CDATA[ 
<p>Back from a week-long jaunt to the heartland:  to Chicago, for <a href="http://www.adobe.com/events/max/">Adobe MAX</a>, and thence to Champaign-Urbana, for a lecture to Mike Woodley's class and the kick-off event for the UIUC chapter of Yahoo!'s <a href="http://developer.yahoo.com/hacku">University Hack Day</a>.</p>
<a href="http://flickr.com/photos/kentbrew/1471836761/"><img style="float:right;margin:10px;" src="http://farm2.static.flickr.com/1009/1471836761_11edeb5212_m.jpg" title="The Bean" height="180" width="240" /></a></img>
<p>The first thing I did in Chicago was to visit Millennium Park, home to the most engaging piece of public art I've seen since Sagrada Familia.  It's a 50-foot mirrored object roughly the shape of a jelly bean, mounted on a stone pavillion in the middle of downtown Chicago.  People were there in droves; I don't think I've ever seen that many smiles on random strangers' faces in a long while.  If you ever have the chance, do check out the Bean.  (One thing: I cannot recommend the walk from McCormick Center to Millennium Park; although you do eventually pass by the fountain in the credits from "Married, With Children," the walk is long, and takes you through some genuinely nasty areas on the way out from the convention center.  I cabbed it back.)</p>
<p>MAX was an eye-opener; I don't think I've ever seen better large-scale presentations.  The keynotes and general sessions were nothing short of spectacular; imagine an OSX desktop, but in triplicate, with super-high resolution, maybe 200 feet wide.  Add whomping sound, interesting content, and 4000 fans of the product, and you've got a really nice event.</p>
<p><a href="http://flickr.com/photos/kentbrew/1471835721/"><img src="http://farm2.static.flickr.com/1439/1471835721_ef9bae2d26_m.jpg" style="float:left; margin:10px;" title="Thomas Sha lights up the room" height="240" width="180" /></a>At MAX I did a ten-minute talk about <a href="http://kentbrewster.com/air-search/">AIR Search</a>, and worked the booth in the Community Pavillion.  We showed up with 288 of the same t-shirt we had for the Rich Web Experience in September; these are a very nice variation on an internal Hack Day shirt, featuring the Kung Fu Dude on the front and the (okay, rather presumptuous) inscription "My Kung Fu Is The Best" on the back.  Nobody else had a decent t-shirt in the Community Pavillion; when one of our developers accidentally opened a box in a crowd we found out very quickly that a) the shirts were popular and b) we were out of extra-large, just like that.</p>
<p>So: short on shirts, we huddled briefly and came up with a plan.  From then on, anybody who wanted a shirt would need to show us their kung fu.  We set up a couple of laptops and invited anyone brave enough to step up and show us their site.  This worked on two levels: first, we connected on a personal level with dozens of nice folks who had no idea YDN was out there.  And second, we didn't have to struggle to establish a background of relatedness: everybody who stepped up had something interesting to show.  We ran <a href="http://developer.yahoo.com/yslow">YSlow</a> to break the ice, found a couple of interesting things about each site--several of which were already running stuff like YUI--and sent everybody away with the Coveted Kung Fu Shirt.</p>
<p>And, yeah, somebody actually did show up and demonstrate some real live kung fu; video should be available shortly. :)</p>
<p>On Wednesday I hopped the train to Champaign, did my thing for Mike Woodley's class, and met up with a close friend for excellent native cuisine.  Thursday I found the local Yahoo! office.  Apparently we've bitten off a tiny piece of Motorola; it's a very smart crew of (what I assume to be) mobile-app developers, in sweet new quarters with sparkly new laptops and the same 24" monitors it took me three years to requisition back home.  Nice folks, all.</p>
<p>Friday was the Hack Day kick-off; we had a full house, thanks to local hacktivists Greg and Rahul, and the ACM chapter at UIUC.  Friday was also the night before the Big Game with Wisconsin, so when we went out for drinks after the kick-off event, we found ourselves swimming upstream through a sea of dark blue and bright orange--dark blue polo shirts, worn by dead-serious Alumni Dads, and blazing orange t-shirts, worn by just about everybody else.  They do take their football seriously out there.</p>
<p>UIUC's Hack Day seems like it went okay; at last count there were about five times the number of entries as last year, which bodes well.</p>
<p>Next up: <a href="http://www.defragcon.com/">Defrag</a>, in Denver.</p>
 ]]></description>
	<feedburner:origLink>http://kentbrewster.com/adobe-max-uiuc-hack-day</feedburner:origLink></item>
	<item>
		<title>Yahoo! Search + Adobe AIR = Air Search</title>
		<link>http://feeds.feedburner.com/~r/KentBrewster/~3/160814883/air-search</link>
		<guid isPermaLink="false">http://kentbrewster.com/air-search</guid>
		<comments>http://kentbrewster.com/air-search</comments>
		<pubDate>Sun, 30 Sep 2007 13:34:20 PDT</pubDate>
		<dc:creator>Kent Brewster</dc:creator>
		<description><![CDATA[ <p>Special note to RSS readers: this entry contains live JavaScript.  Please visit the page to see it working!</p>

<p>In which our friends Structure, Presentation, and Behavior go on a New Adventure, outside the browser window....</p>
<h3>What's This?</h3>
<div id="yahooSearch" style="float:right; margin:10px;"></div>
<p>Adobe's Integrated Runtime (AIR) environment claims to builds cross-platform desktop widgets from Flex files or plain old HTML, CSS, and JavaScript.  As somebody who's been suspicious of Flash since it first started hanging Netscape 4, I was very interested to see whether Adobe's claims of interoperability and transparent development were true.</p>
<p>The short answer:  yes.  They are.  The <em>very first time</em> I tried compiling an AIR app, it worked.  Hopefully what follows will convey some of the delight I felt when my little widget popped up and ran.</p>
<p>We're going to build a Yahoo! Search widget, made with nothing but standards-compliant HTML, CSS, JavaScript, and a little help from the <a href="http://developer.yahoo.com/search">Yahoo! Developer Network</a>.</p>
<h3>Not a Coder?  Just Want the Widget?</h3>
<p>Go ahead and grab the <a href="/air-search/YahooSearch.air">compiled version</a>, which looks and acts exactly like the little purple box immediately to my right.  Thanks for stopping by!</p>
<h3>Want to Poke at the Source First?</h3>
<p>Of course you do!  Here it is:</p>
<h3 class="toggle closed">Structure:</h3>
<pre><?php
   $source = file_get_contents("structure.html");
   $source = str_replace("<", "&lt;", $source);
   echo $source;
?></pre>
<h3 class="toggle closed">Presentation:</h3>
<pre><?php
   $source = file_get_contents("presentation.css");
   $source = str_replace("<", "&lt;", $source);
   echo $source;
?></pre>
<h3 class="toggle closed">Behavior:</h3>
<pre class="source"><?php
   $source = file_get_contents("behavior.js");
   $source = str_replace("<", "&lt;", $source);
   echo $source;
?></pre>
<h3 class="toggle closed">XML Wrapper:</h3>
<pre><?php
   $source = file_get_contents("YahooSearch.xml");
   $source = str_replace("<", "&lt;", $source);
   echo $source;
?></pre>
<h3>Couldn't All This Stuff Go In One File?</h3>
<p>Not quite.  The XML wrapper still needs to be separate.  But yes, we could put the CSS and JavaScript into the HTML and not have to worry about separate files.  I'm not doing this, because it's not good Web development practice; unless you're running PHP or some other build process behind your site, linking your CSS and JavaScript is definitely the way to go.</p>
<h3>Let's Build It!</h3>
<p>If you have not already done so, you'll need to install <a href="http://labs.adobe.com/technologies/air/">Adobe's Integrated Runtime</a> environment.  When it's all installed and working, come on back and download the source:</p>
<ul>
<li><a href="air-search/structure.html">structure.html</a> - the structure</li>
<li><a href="air-search/presentation.css">presentation.css</a> - the CSS</li>
<li><a href="air-search/behavior.js">behavior.js</a> - the javascript</li>
<li><a href="air-search/YahooSearch.xml">YahooSearch.xml</a> - package file</li>
</ul>
<p>Download all of these to your Adobe development directory, go there (mine is <code>C:\Program Files\Adobe\AIR\dev\</code>) and run this:</p>
<p><code>adl YahooSearch.xml</code></p>
<p>Did your widget come up and run?  When you're ready to build it, do this:</p>
<p><code>adt -package ys.air YahooSearch.xml structure.html presentation.css behavior.js</code></p>
<p>If all goes well, your search widget will be ready to install in just a few seconds.  As always, have fun with this, and please let me know how it goes.</p>
<h3>Interested in Learning How the Search Part Works?</h3>
<p>I've done a bunch of these things; see <a href="http://kentbrewster.com/spiffysearch">SpiffY!Search</a>, <a href="http://kentbrewster.com/bbc-widget">Build a BBC Search Widget</a>, and <a href="http://kentbrewster.com/wiki-widget">Build a Wikipedia Widget</a>, for three.  The heavy lifting is all done by Yahoo!'s Search APIs, which are documented on the <a href="http://developer.yahoo.com/search">Yahoo! Developer Network</a>.  All we're doing here is creating some script tags on the fly to generate and receive the output, and a bit of structure to display it when it shows up.</p>

<p>Special note to RSS readers: this entry contains live JavaScript.  Please visit the page to see it working!</p>
 ]]></description>
	<feedburner:origLink>http://kentbrewster.com/air-search</feedburner:origLink></item>
	<item>
		<title>Case-Hardening the Del.icio.us Tag-O-Meter</title>
		<link>http://feeds.feedburner.com/~r/KentBrewster/~3/161812542/delicious-badge</link>
		<guid isPermaLink="false">http://kentbrewster.com/delicious-badge</guid>
		<comments>http://kentbrewster.com/delicious-badge</comments>
		<pubDate>Wed, 26 Sep 2007 20:50:39 PDT</pubDate>
		<dc:creator>Kent Brewster</dc:creator>
		<description><![CDATA[ 
<p>During my first redesign--this would be two years ago or so--I decided I wanted to include a link to <a href="http://del.icio.us">del.icio.us</a> on each page, so my visitors could easily bookmark it if they wanted.  A bit more research showed that there was an existing piece of hosted javascript that did this, and also showed the number of saves that had already occurred, and (optionally) popular tags and links to those who'd saved it recently.</p>
<p>Unfortunately, implementing the <a href="http://del.icio.us/help/tagometer">del.icio.us tagometer badge</a> on the new site clashed with my main goal for the redesign: it had to be as fast as possible. I'm using <a href="http://developer.yahoo.com/yslow">YSlow</a> to benchmark my site, and it's just not going to work for me if it's not getting an A.</p>
<p>When I tore it down to see how it worked, I discovered that--in addition to the first call to get the script--the tag-o-meter made three other calls, one to the script that actually returned the data, another to include some CSS, and a third to return an image.</p>
<p>What I'm currently running does only one thing: it queries the database, gets the save count, and displays it if it's there.  (Popular tags come back from the script, but I haven't decided how--or if--I want to show them.)  It's a tiny 6k script, and since I'm rendering it inline with PHP instead of calling it with a separate <code>LINK</code>, it does nothing to my YSlow score, which is currently a 96% on pages that don't have a bunch of external includes.</p>
<h3>Building the Logo Without an Image Call</h3>
<p>Images slow things down, jack up your HTTP call count, and kill your YSlow grade if they don't come down from a content distribution network.  As it turns out, just a dash of non-semantic HTML plus a little CSS trickery will simulate the del.icio.us logo at the client end, in your choice of size and color.  Here's the structure:</p>
<pre>&lt;span class="delicious">
&lt;div class="db">&lt;b>&lt;/b>&lt;i>&lt;/i>&lt;u>&lt;/u>&lt;/div>
&lt;a href="http://del.icio.us/post?url=http%3A%2F%2Fkentbrewster.com%2Fdelicious-badge%2F&title=Case-Hardening+the+del.icio.us+Badge">save to del.icio.us&lt;/a>
&lt;span id="dc">&lt;/span>
&lt;/span></pre>
<p>Span <code>dc</code> is reserved for the save count; more on this later.  Span <code>db</code> has three empty deprecated tags (bold, italic, and underline) that we're going to style as blocks and position absolutely within the containing <code>DIV</code>.  Here's the CSS:</p>
<pre>.db { display:block; float:left; margin:3px 5px; height:10px; width:10px; position:relative; background-color:#fff; overflow:hidden;}
.db * {display:block; position:absolute; height:50%; width:50%;}
.db b {top:0; left:50%; background-color:#00f;}
.db i {top:50%; left:0; background-color:#000;}
.db u {top:50%; left:50%; background-color:#ddd;}</pre>
<p>To change the size of your del.icio.us logo, alter the <code>height</code> and <code>width</code> in the first line.  To change colors, look at the <code>background-color</code> parameter in the last three.</p>
<h3>Getting the Save Count</h3>
<p>The script uses several of the methods documented in <a href="http://kentbrewster.com/case-hardened-javascript">Case-Hardened JavaScript</a>, including the randomly-generated global global, dynamic script node and function creation, and delayed loading.  It also leans heavily on Paul Johnson's <a href="http://pajhome.org.uk/crypt/md5">JavaScript MD5 function</a>, which I swiped straight from the original badge.  Here it is:</p>
<pre><?php
   $source = file_get_contents("/home/kentbrew/public_html/inc/js/delicious-badge.js");
   $source = str_replace("<", "&lt;", $source);
   echo $source;
?></pre>
<p>When the data returns, it winds up in the <code>div</code> identified by id <code>dc</code>, which can be changed at need, along with the messaging around the counts.</p>
<p>To truly case-harden this script I'd need to call it inline and build the entire structure and presentation package from scratch, instead of depending on my external CSS and <code>&lt;span id="dc"></code> to be there when I needed it.  (Remember: CSS IDs are global variables, and <a href="http://yuiblog.com/blog/2006/06/01/global-domination/">global variables are evil!</a>)  Stay tuned ... this may actually happen at a later date, once the <a href="http://www.techcrunch.com/2007/09/06/exclusive-screen-shots-and-feature-overview-of-delicious-20-preview/">new-and-improved</a> <a href="http://www.readwriteweb.com/archives/delicious_preview_next_gen_search.php">del.icio.us</a>--which is spectacular, by the way--hits the aether.</p>
<p>Next time on This Old Site: we take a jackhammer to the MyBlogLog tracker! :)</p>
 ]]></description>
	<feedburner:origLink>http://kentbrewster.com/delicious-badge</feedburner:origLink></item>
	<item>
		<title>Inside Amazon Widgets</title>
		<link>http://feeds.feedburner.com/~r/KentBrewster/~3/160814875/inside-amazon-widgets</link>
		<guid isPermaLink="false">http://kentbrewster.com/inside-amazon-widgets</guid>
		<comments>http://kentbrewster.com/inside-amazon-widgets</comments>
		<pubDate>Sun, 23 Sep 2007 23:19:21 PDT</pubDate>
		<dc:creator>Kent Brewster</dc:creator>
		<description><![CDATA[ 
<p>A week or so back, Amazon released their <a href="http://widgets.amazon.com">Widgets</a> page, which seems to be a corral for many existing widgets and services, plus some neat-looking new ones.</p>
<p>What's most interesting to me is that the cool new toys all seem to be in HTML, and not Flash.  Amazon seems to be going after a smaller, more-capable crowd (bloggers, hackers, small business operators) and not the denizens of the MySpace/Facebook walled gardens.</p>
<p>Most of the new badges are basic script tags that make iframes full of static ads.  The iframe approach seems to be the only sensible way to make the ten out of sixteen that want you to be signed in before showing personalized recommendations work in a secure fashion.</p>
<p>At least one of these new widgets, however, is interactive and not just a static ad.  See here:</p>
<p><code><a href="http://widgets.amazon.com/Amazon-Search-Widget/">http://widgets.amazon.com/Amazon-Search-Widget/</a></code></pre>
<p>They're using the script tag hack, JSON, and callbacks.  They are not, however, deleting their dynamic scripts after they run, or returning a final semicolon in their returns ... tssk tssk tssk!</p>
<p>The badge framework itself is large, heavily obfuscated, and makes four more calls to bring in support libraries, including Alessandro Fulciniti's <a href="http://www.html.it/articoli/niftycube/index.html">Nifty Corners Cube</a>, for a total of 108k in scripts alone.  There's also a CSS call, which--depending on what badge and what chrome you choose--pulls in up to 20 more images to build the thing.  It seems like it could be done in a cleaner fashion, especially with regards to all those HTTP calls ... <a href="http://developer.yahoo.com/yslow/">YSlow</a> gives a maximum grade of 76% to any page with my tiny search badge on it, and it can't get possibly better as you make the badge bigger.</p>
<p>To play with my search badge, save the next few lines as <code>amazonSearch.html</code> and drag it into your browser:</p>
<pre class="source">&lt;html>
&lt;body>
&lt;script src="http://ws.amazon.com/widgets/q?ServiceVersion=20070822&MarketPlace=US&ID=V20070822/US/widgetsamazon-20/8002/12eddf18-620f-4108-bbe5-7f530ee45f23">&lt;/script>
&lt;/body>
&lt;/html></pre>
<p>What's interesting--to me, anyway, because they're hackable--are the APIs that Amazon has released with this widget.  Bring it up under Firefox, open up Firebug, and switch to your Net tab.  As the badge builds you'll see output labeled <code>q</code> go by twice.  The first is my badge styling information, which you can ignore.</p>
<p>The second is a call to <code>Operation=getTopSellers</code>, which runs automatically to populate the badge:</p>
<pre>http://ws.amazon.com/widgets/q?Operation=GetTopSellers&InstanceId=0&ResponseCount=20&TemplateId=8002&ServiceVersion=20070822&MarketPlace=US</pre>
<p>Here's the reply:</p>
<pre>topseller_display_callback( {
   results:[ {
      ASIN : "B000QDLSR0",
      Title : "Heroes - Season One",
      Price : "$39.99",
      ImageUrl : "http:\/\/g-ec2.images-amazon.com\/images\/I\/21e%2B0TZImQL.jpg",
      ImageHeight : "160",
      ImageWidth : "118" ,
      ThumbImageUrl : "http:\/\/g-ec2.images-amazon.com\/images\/I\/11uZ1UXZbiL.jpg" ,
      ThumbImageHeight : "75" ,
      ThumbImageWidth : "55" ,
      category : "DVD" ,
      DetailPageURL : "http:\/\/www.amazon.com\/dp\/B000QDLSR0" ,
      Rating : "4.5" ,
      TotalReviews : "129" ,
      Subtitle : "Hayden Panettiere, Masi Oka, Ali Larter, Adrian Pasdar (DVD)"
   },
   { ... more results here ... }
   ],
   MarketPlace: "US",
   InstanceId: "0" }
)</pre>
<p><code>InstanceId</code> looks like it would be useful to determine which of your script tags was the one you were waiting for.  While I haven't figured out how to specify a callback, I can pass arbitrary text to <code>InstanceId</code>, which I'd probably fill with the ID of the script tag that called it, so I could delete it and clean things up.</p>
<p>Side note:  I'm hoping Amazon is keeping an eye on whatever goes through <code>InstanceId</code> ... it seems like there ought to be an XSS vulnerability in there somewhere, if I can pass <code>InstanceId=alert('ding')</code> and see it back in my results.  Which, by the way ... I can.</p>
<p>After the Search badge comes up for the first time, it waits for input and then runs a different API, <code>Operation=getResults</code>:</p>
<pre>http://ws.amazon.com/widgets/q?Operation=GetResults&Keywords=cool&SearchIndex=All&multipageStart=0&InstanceId=0&multipageCount=10&TemplateId=8002&ServiceVersion=20070822&MarketPlace=US</pre>
<p>Here's the reply you'll see if you enter <code>cool</code> and click the Go button:</p>
<pre>search_callback( {
   results : [ {
      ASIN : "B000RHRGOO",
      Title : "Forever Cool",
      Price : "$12.99",
      ImageUrl : "http:\/\/ec1.images-amazon.com\/images\/I\/21xS4SwS-DL.jpg",
      ImageHeight : "160",
      ImageWidth : "160",
      ThumbImageUrl : "http:\/\/ec1.images-amazon.com\/images\/I\/11y96t9bKyL.jpg",
      ThumbImageHeight : "75",
      ThumbImageWidth : "75",
      category : "Music",
      DetailPageURL : "http:\/\/www.amazon.com\/dp\/B000RHRGOO",
      Rating : "4.0",
      TotalReviews : "13",
      Subtitle : "Dean Martin (Audio CD - Aug 14, 2007)"
  },
  { ... more results here ... }
  ],
  NumRecords : "75511",
  CorrectedQuery : "",
  MarketPlace : "US",
  InstanceId: "0"
} )</pre>
<p>Yes, before you ask:  plugging in one of Amazon's ASINs into <code>Keywords</code> will yield the single definitive record for that product.  I'm guessing there has to be a way to run <code>GetResults</code> without making the poor thing run a full search ... all we need to do is figure out the right parameter name.</p>
<p>So:  here's the ASIN for that Heroes Season One DVD entered into <code>GetResults</code>:</p>
<pre>http://ws.amazon.com/widgets/q?Operation=GetResults&Keywords=B000QDLSR0&SearchIndex=All&TemplateId=8002&ServiceVersion=20070822&InstanceId=0</pre>
<p>... and here's the output:</p>
<pre>search_callback( {
   results : [ {
      ASIN : "B000QDLSR0",
      Title : "Heroes - Season One",
      Price : "$39.99",
      ImageUrl : "http:\/\/ec1.images-amazon.com\/images\/I\/21e%2B0TZImQL.jpg",
      ImageHeight : "160",
      ImageWidth : "118",
      ThumbImageUrl : "http:\/\/ec1.images-amazon.com\/images\/I\/11uZ1UXZbiL.jpg",
      ThumbImageHeight : "75",
      ThumbImageWidth : "55",
      category : "DVD",
      DetailPageURL : "http:\/\/www.amazon.com\/dp\/B000QDLSR0",
      Rating : "4.5",
      TotalReviews : "136",
      Subtitle : "Hayden Panettiere, Masi Oka, Ali Larter, Adrian Pasdar (DVD)"
   } ],
   NumRecords : "1",
   CorrectedQuery : "",
   MarketPlace : "US",
   InstanceId: "0"
} )</pre>
<h3>So What?</h3>
<p>Amazon has already created a universal identifier for just about any product that might be ordered online or discussed in an online community by a consumer.  From here on out, anybody who discovers and records an ASIN and wants to pull down an image, an average rating, or a price need only poke <code>GetResults</code>.</p>
<p>I can already see how to create rate-this-product pages and communities that show recommended or related sets of products and allow the Web site operator to instantly cash in on Amazon's Associate program.</p>
<p>Bravo, Amazon ... now please consider officially opening the API!</p>
 ]]></description>
	<feedburner:origLink>http://kentbrewster.com/inside-amazon-widgets</feedburner:origLink></item>
	<item>
		<title>Things to Do with the Yahoo! Answers API</title>
		<link>http://feeds.feedburner.com/~r/KentBrewster/~3/160814876/yahoo-answers-api</link>
		<guid isPermaLink="false">http://kentbrewster.com/yahoo-answers-api</guid>
		<comments>http://kentbrewster.com/yahoo-answers-api</comments>
		<pubDate>Sun, 23 Sep 2007 07:28:42 PDT</pubDate>
		<dc:creator>Kent Brewster</dc:creator>
		<description><![CDATA[ <p>Special note to RSS readers: this entry contains live JavaScript.  Please visit the page to see it working!</p>

<h3>A Quick Intro to Answers:</h3>
<blockquote>Yahoo! Answers is an online community where you can ask questions on a range of topics, from the serious to the purely fun, and get answers from real people. Or you might help others by answering their burning questions. Either way, you have the chance to share ideas and information with millions of Yahoo! users about politics, sports, health, or whatever else interests you. By asking and answering questions you can accumulate points and build a reputation as a valuable and knowledgeable community participant.</blockquote>
<h3>So ... what possible good is an Answers API?</h3>
<p>Beyond the obvious social-networking stuff (who's talking about what I'm interested in, etc.) I can see at least one compelling business use for <a href="http://answers.yahoo.com">Yahoo! Answers</a>.  Answers users--especially high-scoring ones--are what Seth Godin refers to in <a href="http://ideavirus.com">Unleashing the Ideavirus</a> as "promiscuous sneezers."  According to Godin, ideas are like viruses, and the more powerful they are, the more likely they are to be retransmitted by important people:</p>
<blockquote>Powerful sneezers can't be bought. But don't forget that they are selfishly motivated. Will this make me look smart? Will it make someone else happy? Will it make the world a better place? There are plenty of levers that motivate powerful sneezers to spread the word, and they are often complicated and subtle.</blockquote>
<p>Because of the way Answers is set up, high-level users--and by "high-level," I mean "anybody level 3 and above"--are not powerful because of what they know, but because of the frequency and tone with which they <em>communicate</em> what they know.  They're on the service a lot.  They answer questions quickly and accurately.  And they have high status because they write graceful, easy-to-digest answers that don't make the person who was brave enough to ask the question feel stupid for having done so in public.</p>
<h3>The Business Use</h3>
<p>Okay, let's say you're a provider of goods or services on the Web, and you'd like to find out who your happy users are.  In the <a href="http://developer.yahoo.com/answers/V1/questionSearch.html">questionSearch</a> API, send a link to your main site in <code>query</code> and set the optional <code>search_in</code> parameter to <code>best_answer</code>.  Any answers that come up were pretty clearly posted by users who 1) know what they're talking about and 2) like your stuff.  These folks are your volunteer evangelists.  Snuggle up to them.  Be nice.  Send them a T-shirt, or a job offer.</p>
<p>Here's an example I've used at work.  We'll search for best answers in the Programming & Design category that have a link to <code>developer.yahoo.com</code>:</p>
<pre>http://answers.yahooapis.com/AnswersService/V1/questionSearch?appid=kentbrew&category_name=Programming&amp;Design&search_in=best_answer&query=developer.yahoo.com</pre>
<p><a target="_blank" href="http://answers.yahooapis.com/AnswersService/V1/questionSearch?appid=kentbrew&category_name=Programming&amp;Design&search_in=best_answer&query=developer.yahoo.com">Run It!</a></p>
<h3>Try Out the Rest of the API:</h3>
<p>Here's a pocket-sized API explorer for Answers.  For best results, start with something simple like "cars" in questionSearch. Once you see some results, poke around inside and find a user, question, or category ID, copy it, paste it into the Find box, select the appropriate API, and you're off and running.  If you'd like to see your results in <a href="http://developer.yahoo.com/common/json.html">JSON</a>, check the box.</p>
<p>
<select id="apex_s">
<option value="http://answers.yahooapis.com/AnswersService/V1/questionSearch?appid=YahooDemo&query=">questionSearch (find text, like "cars")</option>
<option value="http://answers.yahooapis.com/AnswersService/V1/getQuestion?appid=YahooDemo&question_id=">getQuestion (enter question ID)</option>
<option value="http://answers.yahooapis.com/AnswersService/V1/getByCategory?appid=YahooDemo&category_id=">getByCategory (enter category ID)</option>
<option value="http://answers.yahooapis.com/AnswersService/V1/getByUser?appid=YahooDemo&user_id=">getByUser (enter user ID)</option>
</select>
Find: <input id="apex_q" value="">
<button onclick="javascript:apex_go();"> Go!</button><br />
<input id="j" type="checkbox"> Show results in Javascript Object Notation (JSON)</p>
<pre style="display:none;" id="apex_u">http://answers.yahooapis.com/AnswersService/V1/questionSearch?appid=YahooDemo&amp;query=car&amp;output=json</pre>
<p><iframe src="" id="apex_v" style="display:none;" height="300" width="795"></iframe></p>


<p>Special note to RSS readers: this entry contains live JavaScript.  Please visit the page to see it working!</p>
 ]]></description>
	<feedburner:origLink>http://kentbrewster.com/yahoo-answers-api</feedburner:origLink></item>
	<item>
		<title>In Which the Site is Redesigned</title>
		<link>http://feeds.feedburner.com/~r/KentBrewster/~3/160814877/about</link>
		<guid isPermaLink="false">http://kentbrewster.com/about</guid>
		<comments>http://kentbrewster.com/about</comments>
		<pubDate>Fri, 21 Sep 2007 17:08:23 PDT</pubDate>
		<dc:creator>Kent Brewster</dc:creator>
		<description><![CDATA[ 
<p>Brewster's Law of Developer Psychoanalytics:  if you want to find out exactly how screwed up in the head a front-end engineer is, have him write a content management system and analyze the resulting user experience.  You'll see.  (Oh, yes ... you will see....)</p>
<p>Some home-grown CMSs are punishingly anal.  Others  are incomprehensibly random.  All, however, are weird little rat's-nests of code, built with insufficient product requirements, patched only under circumstances of extreme duress, and prone to break at the Exact Wrong Time.</p>
<p>After suffering through the vicissitudes of my very own hand-whittled CMS for way too long, I'm pleased to unveil the new and improved Brewster's Field Guide to Web 2.666, code-named "Lelijk maar Snel," which is Dutch for "Ugly but Fast."  I'm doing my best to bring all the old posts, content, and comments over, and have added something new.  Here and there you'll spot a closed norgie next to a purplish headline, indicating that there's something behind the curtain that you might or might not want to see.  In this case, it's the nerdish details of how the new site works.  (Or, in the words of the folk singer:  "I've suffered for my art; now it's your turn.")</p>
<h3 class="toggle closed">The Nerdish Details</h3>
<ul class="hidden">
<li>Basic principles:  each page on the site should consist of structure, presentation, and behavior layers, with a single CSS link in the <code>HEAD</code> and a single script tag at the bottom of the <code>BODY</code>.  In my case I'm getting a little bit obsessive-compulsive about things, and have rigged it so all my JS and CSS shows up inline, rather than coming in on separate HTTP calls.  (Take <em>that</em>, YSlow!)  Other scripts and styles might pop up occasionally, especially when I'm showing an example.</li>
<li>I'm using a heavily modified version of the Yahoo User Interface library's Grids, Fonts, and Reset stylesheets.  Most of the mods were to Grids, which had no way of doing a 15% column.  I've renamed some of the class names so they made more sense to me (<code>content-unit</code> and <code>content-wrapper</code>, instead of <code>yui-u</code> and <code>yui-gg</code>).  I've also added a decorative wrapper around the main <code>bd</code> division and fiddled with some margins, to show a right-height vertical line between content and navigation.</li>
<li>As already noted, I'm hiding some content using the methods described in <a href="toggle">Toggling Element Visibility</a>.  I'm a wordy little so-and-so; hopefully this will allow only marginally-interested readers to get all the main points of what I'm trying to say before giving up in disgust.</li>
</ul>
<p>So: it's looking less like a blog and more like a collection of quasi-random pages and projects, which is what it always was.  I've also added a chunk of my fiction, celebrating the ten-year anniversary of my last professional sale.  Someday When I Have Time&trade;, I will get back at it.  Also on the site is a set of <a href="faq">Frequently Asked Questions</a> and a <a href="contact">contact form</a>, but please keep in mind that the best way to reach me is to leave a comment in public, somewhere on the site.</p>
 ]]></description>
	<feedburner:origLink>http://kentbrewster.com/about</feedburner:origLink></item>
</channel>
</rss>
