Time for a New Computer

 The oldest computer in the household, "That Fucking Laptop", running Windows XP, is finally giving up the ghost.

We're thrilled!  Finally, we get to replace it with something that can actually run a client for Minecraft.  Finally, we get to replace it with a system that'll run the latest Firefox correctly.  (Firefox 4.0 doesn't show the Bookmarks Button in Windows XP.)  Nevermind that Microsoft itself won't allow that computer to upgrade to a modern Internet Explorer.

So, here are the uses for the computer:
  • Web Browsing
  • Casual Gaming, especially Minecraft (for now)
  • Web Development (Often remote via ssh, usually PHP, Python and Javascript.)
Here are the things I'm really curious about:
  • Google Go  (Suggests Linux/Apple, but I don't have products in mind.)
  • Xcode (Suggests Apple, but I don't have products in mind.)
We've been saving up forever.  Options include buying a generic laptop and installing a Linux distro on it.  (But which one?)  Or, I could hop on down to the Apple store.  Here are some contenders:
  • MacBook Pro 15" - Most expensive, but the bigger screen is really good for development.
  • MacBook Pro 13" - Less expensive, but more powerful than the air.
  • MacBook Air 13" - Wonderfully portable, probably as powerful as I need, but it costs a little extra.
  • Some cheap, powerful laptop that I could install a Linux distro on - Lots of work to maintain, but a fun experiment.
What are we going to do?  Suggestions?

Compromised Blogs

 Now that it's been a few months (since the second attack), I'll admit that when my WordPress blog was originally compromised over a year ago, I didn't know that I didn't completely fix it.  I missed a back door, and a virtual storefront later appeared deep in my blog's hierarchy.

I wrote a script to find out which other websites were affected by the same attacker, and wrote an anonymous post about it, List Of Compromised Blogs.

I contacted most of the other victims, and got a lot of great responses.  Most people were grateful to be informed of the issue and had it fixed.

Minecraft, Local File Storage, Home Networking and the Internet

I've got a couple of kids who are beginning to use the computer more and more for their own purposes. A couple of days ago, My son couldn't enable monsters on his Minecraft server, because he didn't know which of the files was the properties file, "Server" or "Server".

Yeah, "Server" or "Server". I forgot to check "Show file extensions" for his user profile when I set up the computer, even though that's one of the things I always do for new installations for myself.

I set up his preferences. There: One was "Server.log" and the other was "Server.properties." Now he could find it. That got me to thinking that these kids should have a primer on computers. Things like:
  • What do computers do?
  • What are files?
  • Where is the stuff I'm working on?
I started drawing clouds, computers, disks, and even WiFi antennae. And then it hit me: Minecraft! Minecraft is a great usecase for these kids. They're familiar with it!

Textures are stored on everyone's individual computer. That's local file storage. That's why everyone can have a different look for the same world. That's why when the same kid goes to different computers, the different computers might render the same Minecraft world differently. The texture is local to the computer.

Worlds are stored at the Minecraft server. And the server tells every player about the world. That's how all players can share the same world. The one server tells everybody the same story.  In our case, access to the server is contained to our home network.

Skins are stored on the Internet. Notch has a huge database with everybody's skin on it. That's why you can go to different computers, log on to different servers, but your skin always follows you around. Everytime you log in, your computer retrieves the skin from Notch's one huge skin database in the Internet.

The actual explanation goes a little differently, and is age appropriate. But it's useful that this one game that they love, customize, and know well actually illustrates the difference between local file storage, home networks, and the Internet.

Scene from the Minecraft server logs

Our household server logs reveal that stratestar110, a 10 year-old girl was playing with bumppup, an 8 year-old boy, playing as the admin. The first transaction was innocent enough:

[INFO] <stratestar110> CAN I HAVE BRICK BLOCKS
[INFO] CONSOLE: Giving stratestar110 some 45

The girl asked the admin to give her some blocks, and "CONSOLE" shows that he issued the command to give her what she wanted. Then the following happened:

[INFO] <bumppup> Lok at me.
[INFO] <stratestar110> WHERE ARE YOU
[INFO] <bumppup> Look at me!
[INFO] <stratestar110> WHERE ARE YOU
[INFO] <stratestar110> HOW DO YOU DO THAT
[INFO] <bumppup> Look at me!
[INFO] <stratestar110> CAN YOU GIVE NE 64 BRICK BLOCKS
[INFO] <bumppup> I am down here.
[INFO] <bumppup> Look at me then I wiil give you 64 bricks.
[INFO] CONSOLE: Giving stratestar110 some 45

They were in classic form. The boy just wanted somebody to look at something cool he was doing, and the girl just wanted some more stuff. Same as it ever was. Those are my kids.

Fire in the Belly

My pet projects seem to choose themselves, as if I had nothing to do with it. Yesterday, one sunk its teeth into me and won't let go. Tenacious little bugger.

Maybe I should say my muse gave me a present for New Year's. But it doesn't feel like that. When a project like this, no matter how small, takes hold, there's little else you can do. You can't enjoy sitting with a cup of coffee and a book. You can't enjoy working out, or watching a video. You're compelled to explore the idea.

This time, the project came from a comment that Sjon Svenson left in my last entry, Happy Birthday, Me. I got you data portability.

I was happy that I'd completed the migration of my contacts to Google Contacts, but Sjon mentioned that a hardcopy of his contacts survived an electronic device failure, and the hardcopy is the version that the whole family maintains now.

The beauty of that is that my brother can update that just as well, and his wife can -and does-.

That is really handy. So it's something that I'm going to implement across my family's Google Contacts accounts. We'll use the tags to designate with whom we want to share the contacts, and only those will be synced across accounts. Everybody will benefit from the improvements anybody else makes. It'll also keep a history of changes, in case changes or merges were incorrect.

It's very similar to a private wiki, or a shared Docs page, but it's important that this is done directly to the contacts that get synced to all of our mobile devices, too.

It seems like a pretty obvious project. If there's already an open source project for this, or if this is already your 20% project, leave me a comment.

[Update 2011-01-03]: Drat. The proper way to do this, with OAuth and the contacts stream in the official feed won't work. It doesn't enumerate all the fields available when you export contacts. I can still do what I want as a one-off, because I can have my script get the exported CSV values from the accounts I need access to, but I dearly hate code that scrapes or otherwise does actions meant for humans. I wish Google provided (or made apparent how to get) all the data, every single field, for each contact in the API's feed.

Happy Birthday, Me. I got you data portability!

My list of addresses has made its way from a physical address book, to a Palm Pilot, to Microsoft Outlook, to Google Contacts to the iPhone Contacts app. Along the way, each of the transitions has played fast and loose with the mappings of the individual fields.

Nowadays, the normal way for a Windows user to export contacts from an iPhone is to sync between the iPhone and Microsoft Outlook, then export from Outlook to a CSV file. I hate having to go through that middleman.

I prefer to take stronger ownership of my own data, and have settled on Google Contacts as the primary place for my data. There are a few reasons. I really like the open "group" (tagging) feature of contacts. I like that they have a public API for accessing and manipulating contacts. But most important is the ability to easily export and import contacts. As Joel Spolsky noticed ten years ago, a good way to get me to try a service, is to make it easy for me to change my mind and leave the service.

By default only the contacts group named "My Contacts" will sync with the iPhone when you set up an Exchange sync between the two end points. That suits my purposes just fine.

I've taken some time to groom my contacts list for Google Contacts. Here are some notes from that experience:

When you export contacts, use the Google CSV format. Your contacts will be exported to a UTF-16 file, and all the special characters you use will be retained. If you choose Outlook CSV format, then the file generated will be 8-bit regardless of the characters used in your contact list, and characters that don't map to 8-bit characters will be changed to question marks. So for 安室奈美恵's sake, choose Google CSV format.

Most people edit their CSV files in a spreadsheet editor. That's fine, but I don't trust my own eyes and hands to get everything right, so I prefer to do batch editing programmatically.

If you want to do some batch processing of the CSV file in Python, here are some snippets. These snippets have been pared down to the essentials, and don't represent good coding practices.

To read in the Google CSV:

# unicode_csv_reader and UnicodeWriter are provided
# in the documentation from the cvs module.

f = unicode_csv_reader(codecs.open( 'google.csv', 'r', 'utf-16' ))

headings = f.next()
col = {}
for i in range(len(headings)):
    col[headings[i]] = i

rows = []
for row in f:

If you want to print out a list of contacts sorted by last name:

rows.sort(key=operator.itemgetter(col['Family Name']))

Beverly Howard suggests that contacts with no "Name" field but only a "Company" field won't sync with Outlook.
You could check for that:

if row[col['Organization 1 - Name']] and not row[col['Name']]:
    # Ensure these get synced across all devices, some don't!

Finally, after you've made your batch changes, you can write them back to a UTF-16 file like so:

out_file = open( 'google_out.csv', 'wb' )
google_out = UnicodeWriter( out_file, encoding='utf-16' )
google_out.writerow( headings )
google_out.writerows( rows )

It's been a long time coming, but I'm glad I've got more of my data in a place where it's easy for me to get it out and manipulate it any way I like.

Tron and the Realm of Fantastic Opportunity

Around 1982, I was a teenager working off-the-books at the local arcade. I took out the trash, cleaned the front windows, the bathroom, and the machines for a handful of bills that'd usually get converted to tokens and fed right back into the machines.

When I went to church, I had a trick to stay awake. I imagined playing the upper levels of Tempest.

Planning judicious use of the Superzapper is enough to get you through even the most boring sermons.

That was the year that Tron came out. And Tron spoke to me personally. I had an Apple ][+ and loved programming on it. Computers were full of so much potential, and Flynn knew how to take advantage of that. I wanted to be him.

That helped set my life on its course. I went to college, studied Computer Science, and got a job as a Programmer, just like Flynn.

I'm still a programmer, and I watch over a village of cron jobs and daemons who report to me how they're doing, and have permission to email me when they get into trouble with the other programs on the net.

Now it's 2010, and Tron Legacy has come out. Nobody's mistaking it for high art.

Tron Legacy did get some things right. In both the original and the sequel, life in the Grid was surreal, and I mean surreal etymologically. Life in the grid was above or beyond reality. In 1982's Tron, artists hand-painted the digital glow to programs in the Grid, and in 2010's Tron, only the scenes in the Grid were 3D.

There was reality, which was normal; and then there was the grid, where its reality was capable of more. I still feel that way about computers and the Internet. Nearly anything is possible.

Computers remain the realm of fantastic opportunities.

Really Awesome Dream: Vampire Babe vs. Me vs. Great White Shark

Once you grow up, hold down a steady job, marry your girlfriend and raise a family with her, what do you dream about? Getting your next promotion? The stock market? Political success?

Not in my case.

A few days ago, I had this dream where everyone but me was sorta Simpson's look influenced. They were life-like and cartoony both at once. Towards the end of the dream, it got more realistic. The scene was a bay with some steep rocky walls falling into the ocean water. My nemesis was a great white shark, Jaws style. He hadn't killed me yet, but he would the first chance he got.

I was doing battle with a hot vampire babe on the cliff by the bay. I had her in a wrestling lock, but she had a counter on me, we were sorta stalemated. If I moved, she might be able to get a bite in. Or, she'd be able to throw me into the bay, where the shark was waiting.

It was just before dawn, and if the sun hit the vampire babe, she'd perish. I could tell from the way she was fighting me, that she knew it was going to be the end for one of us soon, and she was considering allowing me to keep her in this stalemate until the sun got her. Did she love me? Would she allow me to live at the cost of her own life? Would I go on to defeat the shark?

I woke up.

But it was the beginning of the best day ever.

Amazon Really Doesn't Care For Your Business. Error 410: Gone

It really frustrates me to have to follow up Amazon Still Hates Your Life(stream) with more poor decisions by the eCommerce leader and giant.

In late October 2010, Amazon removed the ListLookup operation from the AWSECommerceService Service. When I noticed it, I tweeted about it. I was sorta late to the game, though. Amazon announced they would deprecate the service in June 2010. The thing is, they didn't deprecate the service. They removed it. Trying to call it now results in an HTTP Error 410, and the text, "Gone."

What's that mean? Well...

That's the function to access your wishlists at Amazon. Some people wrote blogging engine tools or phone apps that access Amazon wishlists. The more people that make easier access to wishlists, the more items that get purchased. You'd think Amazon would like that, right?

You'd be wrong. Amazon unplugged the mechanism they wrote to programmatically access their wishlists. I really can't see a justifiable reason behind it. It may have been "little used" by their standards, but it couldn't have been that hard to maintain.

You can blame Amazon for making their own wishlists even less accessible and useful now.