#!/usr/bin/ruby

=begin
Purpose:
  Updates GeoIP Country (paid) database from MaxMind.com. Requires
  valid license key to work.

Why:
  1) I hate the idea of running some weird C code ("geoipupdate")
     from cron, that's why.
  2) I don't want to run "geoipupdate" on all machines using this DB.

Author: Wejn <wejn at box dot cz>
License: GPLv2 (without the "latter" option)
Requires: Ruby >= 1.8, geoip country license (to be of any value)
TS: 20060901171500
Changelog:
  20060626181500 - Initial release.
  20060901081500 - Invalid license key throwed as exception.
                   Update url (base) configurable.
  20060901171500 - Added custom error check (compatibility w/ my geoup server)
=end

# your license key here
$license_key = 'You-wish----'

# destination file
$outfile = '/usr/share/GeoIP/GeoIP.dat'

# temp file -- MUST BE on same filesystem as $outfile
$tmpfile = '/usr/share/GeoIP/GeoIP.dat.tmp'

# base url
$baseurl = 'ht' + 'tp://www.maxmind.com/app/update'

require 'digest/md5'
require 'open-uri'
require 'zlib'
require 'stringio'

# Fetch GeoIP country file from MaxMind
def get_result_for(key, md5) #{{{1
	url = $baseurl + "?license_key=#{key}&md5=#{md5}"

	content = nil
	open(url) do |io|
		compr = StringIO.new(raw = io.read)
		if compr.read(2) == "\x1f\x8b"
			compr.rewind
			gz = Zlib::GzipReader.new(compr)
			content = gz.read
			gz.close
		else
			content = raw
		end
	end

	raise "invalid license key" if content =~ /License key invalid/i
	raise "Remote: #{content.sub(/.*? /, '')}" if content =~ /^WGIU\/Error: /i

	content
end # }}}1

puts "Begin." if $VERBOSE

begin
	omd5sum = Digest::MD5.hexdigest(File.open($outfile, 'r').read) rescue nil
	content = get_result_for($license_key, omd5sum)

	if content =~ /No new updates available/i
		puts "No new updates ..." if $VERBOSE
		exit 0
	end

	md5sum = Digest::MD5.hexdigest(content)
	content2 = get_result_for($license_key, md5sum)
rescue
	puts "Error:  Problem fetching file! >> #{$!} (#{$!.class})"
	exit 1
end

puts "Fetched." if $VERBOSE

if content2 =~ /No new updates available/
	begin
		File.open($tmpfile, 'w') do |f|
			f.write(content)
		end
		File.unlink($outfile) if FileTest.exists?($outfile)
		File.rename($tmpfile, $outfile)
	rescue
		puts "Error: Problem updating file! >> #{$!} (#{$!.class})"
		exit 1
	end
else
	puts "Error: Problem refreshing GeoIP -- new file fails MD5 check!"
	exit 1
end

puts "Updated." if $VERBOSE
exit 0
