#!/usr/bin/perl
#
#	Copyright (C) 2008, Paul Grinber <gri6507@yahoo.com>
#
#	This program is free software; you can redistribute it and/or modify
#	it under the terms of the GNU General Public License as published by
#	the Free Software Foundation; either version 2 of the License, or
#	(at your option) any later version.
#	
#	This program is distributed in the hope that it will be useful,
#	but WITHOUT ANY WARRANTY; without even the implied warranty of
#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#	GNU General Public License for more details.
#	
#	You should have received a copy of the GNU General Public License
#	along with this program; if not, write to the Free Software
#	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#	02111-1307, USA

use strict;
use warnings;
use Geo::IP;
use Getopt::Long;
use Pod::Usage;
use File::Basename;
use File::Temp;
use File::Copy;

my $VERSION = "2.0";
my $target = undef;
my $geoipdatdir = "/usr/share/GeoIP/";
my $db = "$geoipdatdir/GeoLiteCity.dat";
my $gi = undef;
my $update = 0;
my $help = 0;

GetOptions ("help|?"                 => \$help,
            "version"                => \&VersionMessage,
            "<>"                     => \&process,
            "db|database:s"          => \$db,
            "update|updatedatabase"  => \$update) or pod2usage(2);;
pod2usage(1) if $help;
updatedb() if $update;

sub VersionMessage {
    $gi = Geo::IP->open($db, GEOIP_STANDARD) unless defined $gi;
    print basename($0) . " version: $VERSION\n database version: ";
    my $db_version = $gi->database_info if (defined $gi);
    if (defined($db_version)){
        print $db_version;
    } else {
        print "unknown"
    }
    print "\n";
    die "\nGeoIP database error\n" unless defined $gi;
}

sub process {
    my $target = shift;

    VersionMessage();

    my $record = $gi->record_by_addr($target);
    if (!defined($record)) {
        $record = $gi->record_by_name($target);
        if (!defined($record)) {
            die "Information for $target could not be obtained.\n";
        }
    }

    print "\nInformation for $target";

    print "
        Country Code:   " . $record->country_code . "
        Country Code 3: " . $record->country_code3 . "
        Country Name:   " . $record->country_name . "
        Region:         " . $record->region . "
        City:           " . $record->city . "
        Postal Code:    " . $record->postal_code . "
        Latitude:       " . $record->latitude . "
        Longitude       " . $record->longitude . "
        DMA Code:       " . $record->dma_code . "
        Area Code:      " . $record->area_code . "
    \n";
}

sub updatedb {
   use Compress::Zlib;

    # first, let's test to see if we have the priviledges for the update
    my $tmpfile = dirname($db) . '/' . basename(scalar tmpnam());
    open (TMP, ">$tmpfile") ||
      die "The directory containing the GeoIP database (" . dirname($db) . ") is not writable.\n";
    close(TMP);
    unlink($tmpfile);

    # now, let's get the file and uncompress it
    `wget -O $tmpfile http://www.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz`;
    if (! open FH, "> $tmpfile.new") {
        die "Unable to write to temporary GeoIP Database file\n";
    } else {
        binmode FH;
        my $gz = undef;
        my $buffer;
        if ($gz = gzopen($tmpfile, "rb")) {
            print FH $buffer while ($gz->gzread($buffer) > 0);
            die "ZLib Error: $gzerrno: $!\n" if ($gzerrno != Z_STREAM_END);
            $gz->gzclose;
        }
        else {
            die "ZLib Error: opening $tmpfile - $gzerrno: $!\n";
        }
        close FH;
    }
    move("$tmpfile.new", $db);
    unlink($tmpfile);

    print "\n GeoIP database $db was updated successfully.\n";
}

__END__

=head1 NAME

=head1 SYNOPSIS

geoipfind [options] <ipaddress|hostname>

 Options:
   -help            This message
   -version         Version information
   -db=s            Same as -database
   -database=s      Specify the full path to your own copy of the GeoIP standard database
   -update          Same as -updatedatabase
   -updatedatabase  Update the copy of the GeoIP database distributed with this program.
                    This requires a network connection. This option can only be used by
                    the root user.

=head1 OPTIONS

=over 8

=item B<-help>

geoipfind is a program to find the Geographical location of a computer based on its IP address or its hostname using the GeoIP database.

=back

=cut