diff --git a/Gemfile b/Gemfile
index b9c7deb261e5d69bd680b57b0c7be3b049a89319..4a38c552834a6d89792745c26d2c18d0c7c700d9 100644
--- a/Gemfile
+++ b/Gemfile
@@ -5,7 +5,7 @@ group :development, :test do
   gem 'mongoid', '2.6.0'
   gem 'bson_ext', :platforms => :ruby
   gem 'geoip'
-
+  gem 'rubyzip'
   gem 'rails'
 
   platforms :mri do
diff --git a/lib/tasks/maxmind.rake b/lib/tasks/maxmind.rake
index 970a826e992065bbb8afb6c9e57e02984770acd2..c4e7ba39ab67019962ac049078e8bc5092210e41 100644
--- a/lib/tasks/maxmind.rake
+++ b/lib/tasks/maxmind.rake
@@ -1,3 +1,5 @@
+require 'zip'
+require 'fileutils'
 require 'maxmind_database'
 
 namespace :geocoder do
@@ -11,15 +13,21 @@ namespace :geocoder do
       task :download do
         dir = ENV['DIR'] || "tmp/"
         Geocoder::MaxmindDatabase.download(:geolite_city_csv, dir)
-        # TODO: confirm data was fetched properly
       end
 
       desc "Extract (unzip) MaxMind GeoLite City data"
       task :extract do
         dir = ENV['DIR'] || "tmp/"
-        filename = Geocoder::MaxmindDatabase.archive_filename(:geolite_city_csv)
-        `unzip -o #{File.join(dir, filename)} -d #{dir}` # TODO: make platform independent, overwrite w/out confirm
-        # TODO: confirm data was unzipped properly
+        archive_filename = Geocoder::MaxmindDatabase.archive_filename(:geolite_city_csv)
+        Zip::File.open(File.join(dir, archive_filename)).each do |entry|
+          filepath = File.join(dir, entry.name)
+          if File.exist? filepath
+            warn "File already exists (#{entry.name}), skipping"
+          else
+            FileUtils.mkdir_p(File.dirname(filepath))
+            entry.extract(filepath)
+          end
+        end
       end
 
       desc "Load/refresh MaxMind GeoLite City data"