Version 1 of Basic GeoIP with Tcl

Updated 2004-09-24 12:26:04 by kroc

Kroc - 24 Sep 2004 - This is basic GeoIP (see http://www.maxmind.com for details) that return country code for a given IP adress.

    ################################################################################
    #
    # Basic GeoIP for tcl.
    #
    # Copyright © 2004 - David Zolli - http://www.kroc.tk
    #
    # This script is under NOL : http://wiki.tcl.tk/nol
    #
    # Version 1.0 - 24 Sep 2004
    #
    ################################################################################

    # Build a list with Maxmind CVS database downloaded here :
    # http://www.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip
    proc buildDB { file {savetofile 0}} {
        set fin [open GeoIPCountryWhois.csv r]
        set ::IPDB {}
        while {![eof $fin]} {
            foreach "1 2 3 4 5 6" [split [gets $fin] ,] {
                set record {}
                # compute numbers from IP adresses :
                foreach "a b c d" [split [lindex $1 0] .] {
                    lappend record [join "[expr 1000 + $a]
                    [expr 1000 + $b]
                    [expr 1000 + $c]
                    [expr 1000 + $d]" {}]
                }
                foreach "a b c d" [split [lindex $2 0] .] {
                    lappend record [join "[expr 1000 + $a]
                    [expr 1000 + $b]
                    [expr 1000 + $c]
                    [expr 1000 + $d]" {}]
                }
                # and register country for this range :
                lappend record [string tolower [lindex $5 0]]
                if {[llength $record] == 3} {
                    lappend ::IPDB $record
                }
            }
        }
        close $fin
        if {$savetofile} {
            set fout [open GeoIP_DB.tcl w]
            puts $fout "set ::IPDB \{$::IPDB\}"
            close $fout
        }
        return "::IPDB built"
    }

    # Return lowercase country code for a given IP :
    proc GeoIP { IP } {
        if {![info exists ::IPDB]} {
            return "You must build IP database first with buildDB."
        }
        foreach "a b c d" [split $IP .] {
            set Value [join "[expr 1000 + $a]
            [expr 1000 + $b]
            [expr 1000 + $c]
            [expr 1000 + $d]" {}]
        }
        foreach record $::IPDB {
            if { $Value >= [lindex $record 0] && $Value <= [lindex $record 1] } {
                return [lindex $record 2]
                break
            }
        }
        return unknown
    }