Archived Posts

Displaying posts 131 - 140 of 649

Internet Explorer 8 doesn't matter

Thursday December 06, 2007 @ 11:55 AM (PST)

Microsoft's complete silence on the status of Internet Explorer 8 has resulted in much wailing and gnashing of teeth from web developers, but ultimately it's not an issue worth getting worked up about (note: the Ryan G. quoted in that article isn't me).

The status of IE8 is unimportant. Whether or not IE8 will be less of a piece of shit than IE6 and IE7 is unimportant. What is important is that in spite of the release of IE7 over a year ago, IE6 is still the world's dominant web browser, and it's holding the web back.

Even if Microsoft were to release a fully standards-compliant IE8 tomorrow, it wouldn't solve this problem, because IE users have no interest in upgrading until they're forced. The people who are still using IE6 are grandparents and casual computer users — people who don't necessarily know or care what a web browser is — and corporate users who have no control over what browser their IT department lets them use.

Microsoft needs to figure out how to get these users to upgrade, and they need to do it now. They botched the IE7 release utterly by giving it a horrid, unfamiliar UI that alienated casual users and by failing to address many of the concerns of web developers, thus providing virtually no incentive for anyone to upgrade to it or develop for it. They also tied IE7 too tightly to Vista, which has itself been an utter failure, so Windows XP and IE6 are still shipping on many (possibly even most) new PCs.

Unless Microsoft relearns how to develop usable, marketable software, it won't matter how good IE8 is or how soon it arrives, because web developers will still have to develop for the lowest common denominator.

War Rocket Ajax takes a hit

Friday November 30, 2007 @ 09:06 PM (PST)

Driving home on highway 101 during rush hour every evening is a lot like playing with fire, only not nearly as much fun, and when you get burned it costs a lot of money. It sure does light up the night sky real pretty though.

Tonight, just as I was settling into my evening commute, the car in front of me hit the brakes, I hit my brakes, and the guy behind me hit his brakes. None of this is really newsworthy, since it happens about 18 times a second on the 101. What made it interesting was the guy behind the guy behind me, who didn’t hit his brakes. Car #2 and I came to a complete stop, but car #3 hit car #2 hard enough to slam him into me, creating a nice car #2 sandwich. Car #2 hit me so hard the impact actually knocked the hat off my head (the driver of car #2 later told me that his hat ended up in the back seat).

As car #2 and I limped to the shoulder, car #3 caught fire.

There happened to be an ambulance a few hundred yards behind us. It joined us on the shoulder and the paramedics called the fire department. By this time, the other two drivers and I were exchanging information and watching car #3 burn as traffic swerved to avoid it. The paramedics seemed strangely disappointed that none of us was injured and had us each sign a statement saying we had refused care and wouldn’t sue them. Lovely society we live in. Meanwhile, car #3 burned bigger and brighter and there wasn’t much we could do about it.

After another ten or fifteen minutes, two fire engines arrived nearly simultaneously (one from each direction) and the firefighters had the fire out in a jiffy. They were followed shortly by a CHP officer, who began trying to figure out how to get the mangled, smoldering wreck out of the middle of the highway. What they ended up doing was brilliant:

The firefighters attacked the wreck with their axes, pounding down the crumpled hood and peeling back protruding bits of metal to make enough room for one of them to squeeze into the driver’s seat. Then, after stopping all five lanes of traffic on the 101, the cop got in his cruiser, nudged up against the wreck from behind, and floored it. There ensued a cacaphony of squealing tires and a cloud of smoke, and somehow the firefighter managed to steer the wreck (with wheels pointing in opposite directions) onto the side of the road. It was great fun to watch.

This was followed by lots of boring statement-giving and report-taking. Luckily the damage to my car was minor and seems to have been limited to the rear bumper, so I was able to drive home. The guy in car #2 was also able to drive away, but just barely, and accompanied by a lot of unhappy grinding noises. Car #3 wasn’t going anywhere, so I assume he waited around for a tow truck.

Now I get to deal with insurance and hope my headache (which existed before the accident, but which the accident didn’t help) doesn’t get worse.

Gaia Online is doing awesome things with LazyLoad

Wednesday November 28, 2007 @ 11:42 AM (PST)

Jakob Heuser wrote to let me know about this big meaty blog post describing how he and the other folks at Gaia Online have implemented an impressive just-in-time CSS and JavaScript loader based in part on LazyLoad.

They've made some very nice improvements (such as replacing LazyLoad's queue-based loading with method chaining, which ends up being much faster) and fixed some bugs, all while keeping the library down to a slim 5.6K (minified) without any external dependencies. Very nice.

Why Assassin's Creed fails

Sunday November 25, 2007 @ 10:32 AM (PST)

Chris Kohler's review of Assassin's Creed for Wired pretty much sums up my feelings on the game. I'm as disappointed as he is that it didn't live up to any of the hype. Luckily Rock Band and Call of Duty 4 have washed the bad taste out of my mouth.

Rock Band is almost perfect

Saturday November 24, 2007 @ 10:52 AM (PST)

Yesterday afternoon, after waiting for what I hoped was a long enough time for the Black Friday morning crowds to abate, I headed out in search of Rock Band. The huge new Best Buy down the road was sold out, but the huge new Target next door had two left, crammed into a tiny space on the bottom shelf near the Xbox 360 accessories. The box this thing comes in is pretty huge, so I can see why stores are having trouble keeping it in stock. There's just not enough room.

Anyway, I got it home, set everything up, and Loren and Felicity and I rocked out until the wee hours of the morning. For the most part, the game is absolutely awesome, and even after hours of continuous rockage we didn't experience any of the hardware problems some people have been reporting. However, there are three things about Rock Band that really, really suck:

  1. When you start a band, one player must be designated the leader. This player is now the band leader for all eternity, and the band can't play without him or her. Period. The game won't let you change who the leader is, it won't let you swap the leader to a different instrument, and it won't let your band play without the leader. This sucks epic amounts of ass.
  2. I was totally digging the drums until about halfway through the medium progression, when I just couldn't deal with the damn foot pedal anymore. It's uncomfortable to use, impossible to position well (for me anyway), and I seem to have a complete inability to control both my feet and my hands at the same time. While Felicity and Loren were rocking out without any problems on the medium vocals and bass, I was being thwarted by that damn foot pedal. If I ignored the foot pedal, then I had no trouble being awesome on the drums, but our score suffered horribly due to all the missed kick drum notes. I'm sure there are plenty of people who have no problem with it, but it was a dealbreaker for me. I want a "no foot pedal" option.
  3. For some reason, the first three or four songs end up getting repeated over and over and over and over again, both in new venues and in random setlists. By the end of the night, we were so sick of Weezer (and even Nirvana) that it sucked all the fun out of the game every time we had to slog through those songs yet again in order to progress. There are plenty of great songs, but for some reason it's the mildly annoying ones that get repeated endlessly until you want to stab yourself in the eardrums with your drumsticks. Lame.

Aside from these gripes, the game is huge amounts of fun. I just wish Harmonix had gone a few steps further and made it perfect. Nothing ruins a nearly-perfect game like a few dumb flaws.

Ports freezes suck

Monday November 19, 2007 @ 10:16 AM (PST)

While FreeBSD is, on the whole, a lovely server operating system and the ports collection was, at one time, a lovely software distribution mechanism created in an era when such things weren't at all common, the ports collection has been showing its age for quite a while now.

One of the most infuriating things about the ports collection is the ports freeze. These occur for periods of several weeks (sometimes even a month or more) during the runup to every FreeBSD release. Since ports is entirely dependent on CVS, and since, for reasons I don't understand but nevertheless find utterly baffling, the ports management team aren't willing to create a stable branch of the ports tree from which to do the release and would rather freeze the trunk, this means that there is a long, dead period when software managed via the ports collection cannot be updated through ports.

Invariably, ports freezes seem to be the time when all manner of security vulnerabilities are patched, particularly in PHP. Of course, since the ports tree is frozen, these patches can't be committed, so FreeBSD server administrators are left with the choice of waiting out the freeze and hoping nobody bothers exploiting the vulnerabilities or patching the affected software manually, which can (in the case of something as huge and with as many dependencies as PHP) be an enormous pain in the ass.

I'm not sure what malevolent entity is responsible for ensuring that ports freeze announcements are always followed by a plethora of vulnerability announcements, but I sure wish they'd stop it. It's annoying.

Our first earthquake!

Tuesday October 30, 2007 @ 08:20 PM (PDT)

We just felt our very first earthquake since moving to California! It was a nice little 5.6er centered just a few miles away that shook the house pretty thoroughly for ten seconds or so. Whee!

Moving forward

Sunday October 28, 2007 @ 08:30 PM (PDT)

Yesterday morning I nipped down to my local Apple Store and bought a MacBook Pro. This is the second Apple product I've ever bought; the first was my iPhone. I'd be lying if I said the iPhone didn't have something to do with this.

I've been a Windows user all my life, mostly by choice. On the whole, I like Windows. I know it inside and out, upside-down and backwards, and I'm wildly productive with it. I'm also very aware of its many shortcomings, and one of the things Windows has never had that I've always wished it did is a solid Unix foundation under the hood.

Over the last few years I've watched as Mac OS X has risen in popularity and grown more mature. Part of me was always jealous — of the sexy UI, the powerful Unix underpinnings, the thriving open source community that sprang up around it — but another part of me was hesitant because there were things I liked very much about Windows that I would have to give up if I moved to Mac OS. So I watched from afar, often thinking about switching, but never making the leap because I could always think of at least a few things I wouldn't be able to live with (or without) if I switched.

Now, though, the time is right. Leopard resolves many of the minor complaints I've had about past OS X releases and brings a bevy of glorious new capabilities that Windows just can't compete with. And for those times when I still have to fall back on Windows — of which there will be, and already have been, many — I can rely on almost seamless virtualization thanks to VMWare Fusion and Parallels. And when that's not enough, I can still retreat to native Windows land via Boot Camp, whereupon my MacBook Pro shines in comparison with even the best PC laptops.

There have been, and will continue to be, frustrations and inconveniences (I still can't believe how slow and crappy Mac Firefox is), but I've made my choice. I'm betting on the OS that embraces tried and true technology rather than pretending it doesn't exist and that doesn't assault its users with DRM or unauthorized software updates.

Don't worry, Windows. We can still be friends. I just need some space.

Ruby script to sync email from any IMAP server to Gmail

Wednesday October 24, 2007 @ 02:45 PM (PDT)

Update (2009-03-16): This script has been superseded by Larch, a full-fledged Ruby application that does the same thing, only faster and more reliably.

Last night after Gmail began rolling out IMAP support, I started investigating ways to copy my huge email archive (thousands and thousands of messages dating back to 2003) from my IMAP server to Gmail’s IMAP server.

Copying the messages from one account to the other in Thunderbird works, but it’s glacially slow, needs babysitting, and is prone to creating duplicate messages unless the entire copy operation works right the first time. Great for copying a few messages, not so great for copying thousands.

I also investigated imapsync, a Perl script that’s somewhat faster and more reliable than Thunderbird and doesn’t create duplicate messages, but for some reason using imapsync results in the messages on Gmail being timestamped with the time they were imported rather than the time they were sent or received, which is unacceptable. I tried using the --syncinternaldates option to rectify this, but it didn’t work.

So, since the best way to get something done right is to do it yourself, I set about writing my own tool to transfer my email. Thanks to Ruby and Net::IMAP, this turned out to be pretty easy.

Here’s what I came up with. It’s not pretty, it’s not user friendly, and it doesn’t do much error checking, but it’s extremely fast, it works, and if it fails at any point you can just run it again and it’ll pick up where it left off. Share and enjoy.

#!/usr/bin/env ruby
require 'net/imap'

# Source server connection info.
SOURCE_NAME = 'username@example.com'
SOURCE_HOST = 'mail.example.com'
SOURCE_PORT = 143
SOURCE_SSL  = false
SOURCE_USER = 'username'
SOURCE_PASS = 'password'

# Destination server connection info.
DEST_NAME = 'username@gmail.com'
DEST_HOST = 'imap.gmail.com'
DEST_PORT = 993
DEST_SSL  = true
DEST_USER = 'username@gmail.com'
DEST_PASS = 'password'

# Mapping of source folders to destination folders. The key is the name of the
# folder on the source server, the value is the name on the destination server.
# Any folder not specified here will be ignored. If a destination folder does
# not exist, it will be created.
FOLDERS = {
  'INBOX' => 'INBOX',
  'sourcefolder' => 'gmailfolder'
}

# Maximum number of messages to select at once.
UID_BLOCK_SIZE = 1024

# Utility methods.
def dd(message)
   puts "[#{DEST_NAME}] #{message}"
end

def ds(message)
   puts "[#{SOURCE_NAME}] #{message}"
end

def uid_fetch_block(server, uids, *args)
  pos = 0

  while pos < uids.size
    server.uid_fetch(uids[pos, UID_BLOCK_SIZE], *args).each {|data| yield data }
    pos += UID_BLOCK_SIZE
  end
end

@failures = 0
@existing = 0
@synced   = 0

# Connect and log into both servers.
ds 'Connecting...'
source = Net::IMAP.new(SOURCE_HOST, SOURCE_PORT, SOURCE_SSL)

ds 'Logging in...'
source.login(SOURCE_USER, SOURCE_PASS)

dd 'Connecting...'
dest = Net::IMAP.new(DEST_HOST, DEST_PORT, DEST_SSL)

dd 'Logging in...'
dest.login(DEST_USER, DEST_PASS)

# Loop through folders and copy messages.
FOLDERS.each do |source_folder, dest_folder|
  # Open source folder in read-only mode.
  begin
    ds "Selecting folder '#{source_folder}'..."
    source.examine(source_folder)
  rescue => e
    ds "Error: select failed: #{e}"
    next
  end

  # Open (or create) destination folder in read-write mode.
  begin
    dd "Selecting folder '#{dest_folder}'..."
    dest.select(dest_folder)
  rescue => e
    begin
      dd "Folder not found; creating..."
      dest.create(dest_folder)
      dest.select(dest_folder)
    rescue => ee
      dd "Error: could not create folder: #{e}"
      next
    end
  end

  # Build a lookup hash of all message ids present in the destination folder.
  dest_info = {}

  dd 'Analyzing existing messages...'
  uids = dest.uid_search(['ALL'])

  if uids.length > 0
    uid_fetch_block(dest, uids, ['ENVELOPE']) do |data|
      dest_info[data.attr['ENVELOPE'].message_id] = true
    end
  end

  dd "Found #{uids.length} messages"

  # Loop through all messages in the source folder.
  uids = source.uid_search(['ALL'])

  ds "Found #{uids.length} messages"

  if uids.length > 0
    uid_fetch_block(source, uids, ['ENVELOPE']) do |data|
      mid = data.attr['ENVELOPE'].message_id

      # If this message is already in the destination folder, skip it.
      if dest_info[mid]
        @existing += 1
        next
      end

      # Download the full message body from the source folder.
      ds "Downloading message #{mid}..."
      msg = source.uid_fetch(data.attr['UID'], ['RFC822', 'FLAGS',
          'INTERNALDATE']).first

      # Append the message to the destination folder, preserving flags and
      # internal timestamp.
      dd "Storing message #{mid}..."

      tries = 0

      begin
        tries += 1
        dest.append(dest_folder, msg.attr['RFC822'], msg.attr['FLAGS'],
            msg.attr['INTERNALDATE'])

        @synced += 1
      rescue Net::IMAP::NoResponseError => ex
        if tries < 10
          dd "Error: #{ex.message}. Retrying..."
          sleep 1 * tries
          retry
        else
          @failures += 1
          dd "Error: #{ex.message}. Tried and failed #{tries} times; giving up on this message."
        end
      end
    end
  end

  source.close
  dest.close
end

puts "Finished. Message counts: #{@existing} untouched, #{@synced} transferred, #{@failures} failures."

Update: Now includes Steve K’s patch to fix BadResponseError exceptions. Thanks Steve!

Update (2009-03-02): Brought the script up to date with several bug fixes and enhancements (including those contributed in comments below). Thanks everyone!

Update (2009-03-16): This script has been superseded by Larch, a full-fledged Ruby application that does the same thing, only faster and more reliably.

Gmail + IMAP == <3

Tuesday October 23, 2007 @ 08:04 PM (PDT)

Gmail has just added full-on IMAP support, and it's awesome. And by awesome I mean totally sweet.

This has pushed me over the edge. I'm finally ready to use Gmail as my primary email provider. Now that I can access all my email (including my old archived mail) however I want to from whatever client I choose to use, whether that's Gmail itself, Thunderbird, my iPhone, or good old Pine, Gmail is perfect.

Google, you rock.

Copyright © 2002-2012 Ryan Grove. All rights reserved.
Powered by Thoth.