diff options
Diffstat (limited to '')
-rw-r--r-- | scripts/localize.pl | 1642 |
1 files changed, 1642 insertions, 0 deletions
diff --git a/scripts/localize.pl b/scripts/localize.pl new file mode 100644 index 0000000..b836c92 --- /dev/null +++ b/scripts/localize.pl @@ -0,0 +1,1642 @@ +#!/usr/bin/perl +# +# +# By Stefan 'tommie' Tomanek, stefan@kann-nix.org +# +# +# This script works fine on DFN (german universities) and T-Oline sites +# +# 01.03.2002 +# *Changed to GPL +# +# 15.03.2002 +# *Now works on QUERIES as well +# +# 24.04.2002 +# *the nick does not have to be on the channel +# *switched to /WHO +# +# 27.04.2002 +# *localization of hosts (/localize @hostname) +# +# 29.04.2002 +# *tweaked Design +# *added channel statistics +# +# 04.05.2002 +# *added alternate database (IP Atlas) +# +# 05.05.2002 +# *the script is now able to use both databases simultaniously +# */set localize_use_<database> to enable or disable them +# +# 10.05.2002 +# *non-blocking IO via fork() +# +# 13.05.2002 +# *finally improved forking and background localizing +# *now using XML +# +# 26.05.2002 +# *Implemented auto-localize +# +# 28.05.2002 +# *major updates +# *fixed race conditions +# +# 30.05.2002 +# *finally rendered traceroute support usefull +# +# 31.05.2002 +# *moved database to this file +# +# 03.07.2002 +# *switched to Data::Dumper +# +# 25.11.2014 +# Added utrace.de as a localizer +# http://www.utrace.de/ + +use strict; +use vars qw($VERSION %IRSSI); + +$VERSION = "2017040101"; +%IRSSI = ( + authors => "Stefan 'tommie' Tomanek", + contact => "stefan\@pico.ruhr.de", + name => "localize", + description => "Localizes users using traceroute, the localizer database or IP-Atlas", + license => "GPLv2", + url => "", + changed => "$VERSION", + modules => "Data::Dumper LWP::UserAgent HTML::Entities", + commands => "localize" +); + +use Irssi 20020324; +use LWP::UserAgent; +use HTML::Entities; +use Data::Dumper; +use POSIX; +use Socket; + +use vars qw(%queries %cache %ipdb $procs @tracer $debug); +$debug = 0; +$procs = 0; + + +# host regexps for trace_host +# + +@tracer = ( + { provider => 'tonline', + regexp => [ '.*?-.*?\.(.*?)(\.DE|)\.net\.dtag\.de', ] + }, + { provider => 'uunet', + regexp => [ '.*?-\d+-\d+\..*?\.(.*?)\d?\.uunet\.de', ] + }, + { provider => 'kpnqwest', + regexp => [ '.*?-.*?\.(\w?)\.de\.kpnqwest\.net', ] + }, + { provider => 'ewetel', + regexp => [ '.*?-.*?-.*?\.rt8\.(.*?)\.ewetel\.net', + '(.*?)[0-9]*-.*?\.ewetel\.net', + 'so\d+-\d+-\d+-bbrt\d+\.(.*?)\.ewe-ip-backbone\.de'] + }, + { provider => 'arcor', + regexp => [ '((?!dsl)\w+)-\d+-\d+-\d+-\d+\.arcor-ip\.net', + '.*?-(.*?)-.*?\d*\.arcor-online\.net'] + }, + { provider => 'mediaways', + regexp => ['.*-(.*)-de.*-.*-.*-.*\..*\.mediaways.net', ] + }, + { provider => 'mobilcom', + regexp => ['.*\.(.*?)[0-9]+-.\.mcbone\.net',] + }, + { provider => 'vianetworks', + regexp => ['\w+\.(.*?)\.revmap\.vianetworks\.de', + 'rt\d{3}(.*?)\.de\.vianw\.net',] + }, + { provider => 'mfnx', + regexp => ['.+-\d+-\d+-\d+\..+\.(.*?)[0-9]+\.de\.mfnx\.net',] + }, + { provider => 'colt', + regexp => ['.+-.*\..+\.(.*?)\.DE.COLT-ISC.NET', + '.+\.((?!dsl)(?!host)\w+)\.de\.colt\.net', + '..\d\.(\w+)\.de\.colt\.net',] + }, + { provider => 'telia', + regexp => ['(.*?)-.+-.+-.+\.telia.net',] + }, + { provider => 'hansanet', + regexp => ['.*\.(.*?)-[0-9]+\.hansenet\.net',] + }, + { provider => 'isis', + regexp => ['isis-gw-(.*?)[0-9]\.de\.cw\.net', ] + }, + { provider => 'cable & wireless', + regexp => ['.*-\d+-\d+-\d+-.*?-(.*?)\d+\.de\.cw\.net', + '.*?-.*?-(.*?)\d+\.de\.cw\.net'] + }, + { provider => 'NEFkom', + regexp => ['nefkom-gw-(.*?)\.de\.cw\.net',] + }, + { provider => 'eastlink', + regexp => ['.*?-.*?-.*?-.*?-(.*?)\.eastlink.de',] + }, + { provider => 'alternet', + regexp => ['.*\.(.*?)\d?\.de\.alter\.net',] + }, + { provider => 'CompleTel', + regexp => ['.+-.+-.+-.+\.(.*)\.ipcenta\.de',] + }, + { provider => 'mediascape', + regexp => ['.+\..+\.(.*?)\.mediascape\.net',] + }, + { provider => 'schlund', + regexp => ['gw-prtr-[0-9]+-.+\.(.+)[0-9]+\.schlund.net',] + }, + { provider => 'bisping', + regexp => ['(.*?)-gw-pmx[0-9]*\.bisping\.net',] + }, + { provider => 'gatel', + regexp => ['ser[0-3]+-[0-3]+\.(.*?)[0-3]+\.de\.gatel\.net',] + }, + { provider => 'qsc', + regexp => ['rqsc-(.*?)-de[0-9]+-.+[0-9]+-[0-9]+-[0-9]+\.nw\.mediaways\.net', + 'bsn\d+\.(.*?)\.qdsl-home\.de', + 'bsn\d+\.(.*?)\.qsc\.de', + 'core1\.(.*?)\.qsc\.de'] + }, + { provider => 'dfn', + regexp => ['.r-(.*?)[0-9]+\.g-win.dfn.de', + '.*\.uni-(.*?)\.de', + '.*\.fh-(.*?)\.de', + '.*\.tu-(.*?)\.de', + '.*\.fu-(.*?)\.de',] + }, + { provider => 'mops.net', + regexp => ['.*?\.core\d\.(.*?)\.mops\.net',] + }, + { provider => 'schule.de', + regexp => ['.*\.(.*?)\..*?\.Schule\.DE',] + }, + { provider => 'belwue', + regexp => ['(?:.*?-)?(.*?)\d+\.BelWue\.DE',] + }, + { provider => 'lambdanet', + regexp => ['.*?\.(.*?)\.de\.lambdanet\.net',] + } +); + +%ipdb = ( + # For utrace.de API documentation, see http://en.utrace.de/api.php + d1utrace=>{ name=>'utrace', + active=>1, + url=>'http://xml.utrace.de/?query=', + city=>'<region>(.*?)<\/region>', + province=>'<org>(.*?)<\/org>', + country=>'<countrycode>(.*?)<\/countrycode>', + provider=>'<isp>(.*?)<\/isp>', + failure=>'request-limit-exceeded|Host not found'}, + d2ipatlas=> { name=>'IP-Atlas', + active=>0, + url=>'http://www.xpenguin.com/plot.php?address=', + city=>'is located in (.*?),', + province=>'is located in.*, (.*?) \(state\),', + country=>'is located in.*, (.*?)\. ', + failure=>'cannot be located|does not resolve' }, + d3netgeo => { name=>'NetGeo', + active=>0, + url=>'http://netgeo.caida.org/perl/netgeo.cgi?target=', + city=>'CITY:\ *(\w+)<br>', + province=>'STATE:.*?, (.*?) \(state\)<br>', + country=>'COUNTRY:\ *(\w+)<br>', + failure=> "SHOULD NOT"}, +); + +sub draw_box ($$$) { + my ($title, $text, $footer) = @_; + my $box = ''; + $box .= '%R,--[%n%9%U'.$title.'%U%9%R]%n'."\n"; + foreach (split(/\n/, $text)) { + $box .= '%R|%n '.$_."\n"; + } + $box .= '%R`--<%n'.$footer.'%R>->%n'; + return $box; +} + +sub show_help() { + my $help="Localize $VERSION +/localize <nickname> + Try to localize the user 'nickname' +/localize @<hostname> + Try to localize the host +/localize <#channel> + Create a tree of the people inside the channel +/localize -s + Save the localize cache and settings +/localize -r + Reload the localize cache from file +/localize -c + Clear the cache +/localize -sc + Shows the current content of the cache +/localize -h + Display this help +"; + my $text = ""; + foreach (split(/\n/, $help)) { + $_ =~ s/^\/(.*)$/%9\/$1%9/; + $text .= $_."\n"; + } + print CLIENTCRAP draw_box("Localize", $text, "Help"); +} + +sub get ($) { + my ($url) = @_; + my $ua = LWP::UserAgent->new(env_proxy => 1,keep_alive => 1,timeout => 30); + $ua->agent('Irssi'); + my $request = HTTP::Request->new('GET', $url); + my $response = $ua->request($request); + if ($response->is_success()) { + return $response->content(); + } else { + return undef; + } +} + +sub parse_page ($$) { + my ($page, $item) = @_; + my %empty; + my (%location); + $_ = $page; + my $regexp = $item->{failure}; + return(%location) if /$regexp/; + foreach my $key ('city', 'province', 'country') { + $location{$key} = ''; + my $regexp = $item->{$key}; + if (/$regexp/) { + $location{$key} = $1; + } else { + return(%empty); + } + } + if (defined $item->{provider}) { + if (/$item->{provider}/) { + $location{provider} = $1; + } + } + $location{map} = $item->{name} if (%location); + return (%location); +} + +sub trace_host ($) { + my ($host) = @_; + my $cmd = Irssi::settings_get_str('localize_trace_cmd'); + local *F; + my $pid = open(F, '-|', $cmd.' '.$host.' 2>/dev/null'); + my $loc_host; + my $provider; + my $hops = 0; + my $maxhops = Irssi::settings_get_int('localize_trace_distance'); + $_ = $host; + while (defined $_) { + print $_ if $debug; + $hops++; + if (/\*/) { + kill 15, $pid; + close(F); + return([$loc_host, $provider]) if ($hops < $maxhops && $hops >= 0); + return([undef, undef]); + } else { + foreach my $traced (@tracer) { + foreach my $regexp (@{$traced->{regexp}}) { + if (/[0-9]+ $regexp /i) { + $loc_host = $1; + $provider = $traced->{provider}; + print $regexp if $debug; + print "$loc_host <-> $provider" if $debug; + $hops = 0; + last; + } + } + } + } + $_ = <F>; + } + close(F); + if ( ($hops < $maxhops) && ($hops >= 0)) { + if ($debug) { + print $loc_host."-".$provider foreach (1..10); + } + return([$loc_host, $provider]); + } else { + print $hops." -> ".$maxhops if $debug; + } + return([undef, undef]); +} + +sub localize($$) { + my ($nicks, $query) = @_; + if (Irssi::settings_get_bool('localize_background')) { + bg_fetch($nicks, $query); + } else { + fg_fetch($nicks, $query); + } +} + +sub fg_fetch ($$) { + my ($nicks, $query) = @_; + my $data = create_output(@{$nicks}); + my $auto = $queries{$query}->[0]{auto}; + remove_request($query); + process_input($query, $auto, $data); +} + +sub bg_fetch ($$) { + my ($nicks, $query) = @_; + my ($rh, $wh); + pipe($rh, $wh); + my $pid = fork(); + $procs++; + if ($pid > 0) { + close $wh; + my $size = scalar(@{$nicks}); + my $auto = $queries{$query}->[0]{auto}; + remove_request($query); + unless ($auto ne '') { + print CLIENTCRAP '%R>>%n Localizing '.$size.' host(s) in background [pid '.$pid.']...' if Irssi::settings_get_bool('localize_show_message'); + } + Irssi::pidwait_add($pid); + my $pipetag; + my @args = ($rh, $query, $auto, \$pipetag); + $pipetag = Irssi::input_add(fileno($rh), INPUT_READ, \&pipe_input, \@args); + } else { + my $data = create_output(@{$nicks}); + eval { + print($wh $data); + close($wh) + }; + POSIX::_exit(1); + } +} + + +sub create_output(@) { + my (@nicks) = @_; + my @new_db; + my @stuff; + my @data; + my $i = 0; + foreach (@nicks) { + my $nick = $$_[0]; + my $host = $$_[1]; + my (%location); + if (defined $cache{$host}) { + %location = %{$cache{$host}}; + $location{$_} = $location{$_} foreach (keys %location); + $location{'map'} .= " (cached)"; + } else { + if (Irssi::settings_get_bool('localize_use_traceroute')) { + unless (%location) { + my ($sign, $provider) = @{ trace_host($host) }; + print "\n\n>>>>".$sign if $debug; + %location = kfz2location($sign) if $sign; + $location{map} = 'traceroute' if (%location); + $location{provider} = $provider if (%location); + } + } + if (Irssi::settings_get_bool('localize_use_databases')) { + unless (%location) { + foreach (sort keys(%ipdb)) { + my $item = $ipdb{$_}; + next unless $item->{active}; + #my $ip = gethostbyname($host); + #next unless $ip; + my $url = $item->{url}.$host; #inet_ntoa($ip); + my $text = get($url); + %location = parse_page($text, $item); + } + } + } + if (Irssi::settings_get_bool('localize_get_coordinates')) { + if (%location) { + my $city = $location{city}; + my $ua = LWP::UserAgent->new(env_proxy=>1, keep_alive=>1, timeout=>30); + my $data = $ua->get('http://www.astro.com/atlas/horoscope/?expr='.$city)->content(); + foreach (split /\n/, $data) { + decode_entities($_); + if (/^<li><a href="\/cgi\/ade\.cgi\?&(?:.*?)">(.*?)<\/a>, (?:.*?): <b>(\d+)n(\d+)<\/b>, <b>(\d+)e(\d+)<\/b>/i) { + $location{latitude} = "$2.$3"; + $location{longitude} = "$4.$5"; + last; + } + } + } + } + } + $location{'nick'} = $nick if (%location); + $location{'host'} = $host if (%location); + #$location{$_} = $location{$_} foreach (keys %location); + push @stuff, \%location; + $i++; + } + my %foo = ("nicks" => \@stuff); + my $dumper = Data::Dumper->new([\%foo]); + $dumper->Purity(1)->Deepcopy(1); + my $data = $dumper->Dump; + return($data); +} + +sub pipe_input ($$$$) { + my ($rh, $query, $auto, $pipetag) = @{$_[0]}; + my @lines = <$rh>; + close($rh); + Irssi::input_remove($$pipetag); + my $text = join("", @lines); + process_input($query, $auto, $text); +} + +sub process_input($$$) { + my ($query, $auto, $text) = @_; + my $channel_prefix = '^(\#|\+|\!)'; + my %stuff; + $procs--; + no strict; + %stuff = %{ eval "$text" }; + return(0) unless (%stuff); + my @items = @{$stuff{nicks}}; + my %channel; + foreach (@items) { + my %location = %{$_}; + if (not %location) { + unless ($query =~ /$channel_prefix/) { + print CLIENTCRAP '%R>>%n Unable to localize '.$query if ($auto eq ''); + } + } else { + my $nocache = Irssi::settings_get_str('localize_ipatlas_nocache'); + add_to_cache(%location) unless ($location{'map'} eq 'IP-Atlas' && $location{'host'} =~ /$nocache/); + + $location{$_} = $location{$_} foreach (keys %location); + my $nick = $location{'nick'}; + if ($query =~ /$channel_prefix/) { + push @{ $channel{$location{"country"}}{$location{"province"}}{$location{"city"}} }, [$nick, $location{"map"}]; + } else { + if ($auto eq '') { + show_location(%location); + } else { + auto_localize($auto, %location); + } + } + #remove_request($query); + } + } + if ($query =~ /$channel_prefix/) { + show_cities($query, %channel); + } +} + +sub add_to_cache (%) { + my (%location) = @_; + my $host = $location{'host'}; + return if defined $cache{$host}; + foreach (keys %location) { + next if ($_ eq 'nick' || $_ eq 'host'); + $cache{$host}{$_} = $location{$_}; + } +} + +sub save_cache { + my $filename = Irssi::settings_get_str('localize_cache_filename'); + my $data = Dumper(\%cache); + local *F; + open(F, '>',$filename); + print(F $data); + close(F); + print CLIENTCRAP "%R>>%n localize cache (".scalar(keys(%cache))." entries/".length($data)." bytes) saved to ".$filename; +} + +sub load_cache { + no strict; + my $filename = Irssi::settings_get_str('localize_cache_filename'); + my (%new_cache, $text); + local *F; + open F, "<",$filename || return; + $text .= $_ foreach (<F>); + close(F); + eval { %new_cache = %{ eval "$text" }; }; + foreach (keys %new_cache) { + $cache{$_} = $new_cache{$_} unless defined $cache{$_}; + } + print CLIENTCRAP "%R>>%n localize cache (".scalar(keys %new_cache)." hosts) loaded"; +} + +sub clear_cache { + foreach (keys(%cache)) { + delete $cache{$_}; + } + print CLIENTCRAP "%R>>%n localize cache cleared"; +} + +sub show_location (%) { + my (%location) = @_; + my $query = Irssi::query_find($location{"nick"}); + my $output = \&Irssi::print; + $output = sub { $query->print(@_); } if ($query); + my $text = ""; + my $headline = '%R,--[%n%9%ULocation of '.$location{"nick"}." (".$location{"host"}.")%U%9%R]%n"; + foreach ('Country', 'Province', 'City', 'Provider') { + my $fill = ' 'x(9-length($_)); + $text .= '%B'.$fill.$_.':%n '.$location{lc $_}."\n" if defined $location{lc $_}; + } + #$text .= $location{latitude}."/".$location{longitude}; + &$output(draw_box('Location of '.$location{nick}.' ('.$location{host}.')', $text, $location{map}), MSGLEVEL_CLIENTCRAP); + show_map($location{latitude}, $location{longitude}, $location{nick}) if Irssi::settings_get_bool('localize_xplanet_show_map'); +} + +sub show_map ($$$) { + my ($lat, $long, $nick) = @_; + return unless defined $lat && defined $long; + my $cmd = Irssi::settings_get_str('localize_xplanet_cmd'); + my $file = Irssi::settings_get_str('localize_xplanet_temp_file'); + local *F; + open F, '>',$file; + print F $lat.' '.$long.' "'.$nick.'"'; + close F; + system("$cmd -markerf $file &"); +} + +sub show_cities ($%) { + my ($channel, %cities) = @_; + print CLIENTCRAP "%R,---[%n%9%U".$channel."%U%9%R]%n"; + foreach (sort keys %cities) { + print CLIENTCRAP "%R+-+[%n".$_."%R]%n"; + print CLIENTCRAP "%R| | %n"; + my $n_provs = scalar( keys %{$cities{$_}}); + foreach my $province (sort keys %{$cities{$_}}) { + my $cp = '|'; + $cp = ' ' if ($n_provs == 1); + print CLIENTCRAP "%R| +-+%n"."%R[%n".$province."%R]%n"; + my $n_cities = scalar(keys %{$cities{$_}{$province}}); + foreach my $city (sort keys %{$cities{$_}{$province}}) { + my $cc = '|'; + $cc = ' ' if ($n_cities == 1); + print CLIENTCRAP "%R| $cp +-+%n"."%R[%n".$city."%R]%n"; + my $n_nicks = scalar(@{$cities{$_}{$province}{$city}}); + foreach my $nick (sort @{$cities{$_}{$province}{$city}}) { + my $cn = '|`'; + $cn = '`-' if ($n_nicks == 1); + print CLIENTCRAP "%R| $cp $cc $cn-----%n%B[%n".$nick->[0]."%B]%n"; + $n_nicks--; + } + $n_cities--; + } + print CLIENTCRAP "%R| $cp "; + $n_provs--; + } + #print CLIENTCRAP "%R| "; + } + print CLIENTCRAP "%R`----->%n"; +} + + +sub cmd_localize ($$$) { + my ($args, $server, $witem) = @_; + my @names = split(/ /, $args); + foreach (@names) { + if ( substr($_, 0, 1) eq '@' ) { + my $ip = substr(lc($_), 1); + new_request($server, $ip, 2, ''); + localize([[$ip, $ip]], $ip); + } elsif ($_ eq '-h') { + show_help(); + } elsif ($_ eq '-c') { + clear_cache(); + } elsif ($_ eq '-s') { + save_cache(); + } elsif ($_ eq '-r') { + load_cache(); + } elsif ($_ eq '-sc') { + show_cache(@names); + return(); + } else { + new_request($server, lc($_), 0, ''); + } + } +} + +sub show_cache (@) { + my (@params) = @_; + unless (defined $params[1] && $params[1] eq '-i_am_insane') { + my $entries = scalar(keys(%cache)); + print CLIENTCRAP '%R>>%n There are '.$entries.' saved locations in the cache. If you really want to display them all, type /localize -sc -i_am_insane'; + } else { + my $text = ""; + foreach my $key (sort keys %cache) { + my %item = %{$cache{$key}}; + $item{$_} = $item{$_} foreach (keys %item); + my $string .= $key; + foreach ('country', 'province', 'city', 'map') { + $string .= ' | '.$item{$_}; + } + $text .= $string."\n"; + } + print CLIENTCRAP draw_box("Localize Cache", $text, "cache listing"); + } +} + +sub process_reply ($$$$) { + my ($server, $args, $sender, $address) = @_; + if ($args =~ /^(.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?)/) { + if (defined $queries{lc $6} && scalar(@{$queries{lc $6}}) > 0) { + foreach (@{$queries{lc $6}}) { + my %query = %{$_}; + next unless ($query{status} <2); + Irssi::signal_stop(); + push @{${$_}{buffer}},[$6, $4]; + ${$_}{status} = 1; + } + } elsif (defined $queries{lc $2} && scalar(@{$queries{lc $2}}) > 0) { + foreach (@{$queries{lc $2}}) { + my %query = %{$_}; + next unless ($query{status} <2); + Irssi::signal_stop(); + push @{${$_}{buffer}},[$6, $4]; + ${$_}{status} = 1; + } + } + } elsif ($args =~ /^(.*?) (.*?) :End of (|\/)WHO list\./) { + my ($self, $target) = ($1, $2); + return unless (defined $queries{lc $target} && scalar(@{$queries{lc $target}}) > 0); + my $needed = 0; + foreach (@{$queries{lc $target}}) { + my %query = %{$_}; + $needed = 1 if $query{status} < 2; + next unless ($query{status} == 1); + if ($query{status} == 1) { + Irssi::signal_stop; + $query{status} = 2; + localize \@{$query{buffer}}, $target; + delete $query{buffer}; + return(); + } + } + if ($needed) { + Irssi::signal_stop; + unless ($queries{lc $target}[0]{auto} ne '') { + print CLIENTCRAP '%R>>%n No such nick '.$target; + } + remove_request($target); + } + } +} + +sub event_message_join ($$$$) { + my ($server, $channel, $nick, $address) = @_; + return() unless Irssi::settings_get_bool('localize_auto_localize_on_join'); + my $maxreq = Irssi::settings_get_int('localize_auto_localize_maxrequests'); + my $channels = Irssi::settings_get_str('localize_auto_localize_channel_list'); + if ($channel =~ /$channels/i) { + $address =~ /(.*)@(.*)/; + my $host = $2; + if ($procs < $maxreq) { + new_request($server, $nick, 2, lc($channel)); + localize([[lc($nick), $host]], lc($nick)); + } else { + #Irssi::print "%R>>%n Too many processes running"; + } + } +} + +sub event_query_created($$) { + my ($query, $auto) = @_; + my $nick = $query->{name}; + my $server = $query->{server}; + my $maxreq = Irssi::settings_get_int('localize_auto_localize_maxrequests'); + return(0) unless (scalar(keys %queries) < $maxreq && Irssi::settings_get_bool('localize_auto_localize_on_query')); + $nick = substr($nick, 1) if (substr($nick, 0, 1) eq '='); + new_request($server, $nick, 0, lc($query->{name})); +} + +sub auto_localize ($%) { + my ($auto, %location) = @_; + my $nick = lc($location{'nick'}); + my $channel = Irssi::window_item_find($auto); + $channel->printformat(MSGLEVEL_CLIENTCRAP, 'auto_localize', $nick, $location{host}, $location{'city'}, $location{'province'}, $location{'country'}, $location{'map'}) if defined $channel; +} + +sub new_request ($$$$) { + my ($server, $nick, $status, $auto) = @_; + return unless ref $server; + # 0 nothing done + # 1 started to fetch hosts + # 2 all hosts fetched + push(@{$queries{lc $nick}}, {status => $status, auto=>$auto}); + $server->command('who '.lc($nick)) if $status == 0; +} + +sub remove_request ($) { + my ($nick) = @_; + shift @{$queries{$nick}}; + delete $queries{$nick} if scalar(@{$queries{$nick}}) == 0; +} + +# Yes, I know tat this i huge +sub kfz2location($) { + my %trans = ( + "rklh"=> "RE", + "wstk"=> "Wk", + "essn"=> "E", + "stgt"=> "S", + "ffm" => "F", + "mnz" => "MZ", + "fra" => "F", + "esn" => "E", + "dtm" => "DO", + "kln" => "K", + "dus" => "D", + "mue" => "M", + "mnch"=> "M", + "brln"=> "B", + "hmb" => "HH", + "brmn"=> "HB", + "hmbg"=> "HH", + "han" => "H", + "kiel"=> "KI", + "lpz" => "L", + "bln" => "B", + "ber" => "B", + "mch" => "M", + "erf" => "EF", + "mdb" => "MD", + "nbg" => "N", + "hnv" => "H", + "dui" => "DU", + "mnhm" => "MA", + "mhm" => "MA", + "flf" => "FL", + "lwhf" => "LU", + "wue" => "WÜ", + "frnk" => "F", + "dsdf" => "D", + "sgt" => "S", + "aug" => "A", + "mch" => "M", + "ddn" => "DD", + "drs" => "DD", + "jen" => "J", + "che" => "C", + "nuremberg" => "N", + "weingarten" => "RV", + "munich" => "M", + "muc" => "M", + "goe" => "GÖ", + "obhs" => "OB", + "dus" => "D", + ); + + my %province = ( + 1=>'Baden-Württemberg', + 2=>'Bayern', + 3=>'Berlin', + 4=>'Brandenburg', + 5=>'Bremen', + 6=>'Hamburg', + 7=>'Hessen', + 8=>'Mecklenburg-Vorpommern', + 9=>'Niedersachsen', + 10=>'Nordrhein-Westfalen', + 11=>'Rheinland-Pfalz', + 12=>'Saarland', + 13=>'Sachsen', + 14=>'Sachsen-Anhalt', + 15=>'Thüringen', + 16=>'Schleswig-Holstein' + ); + + my %added = ( + "PLA"=>{city=>"Plattling", province=>2}, + ); + my %de_kfz = ( + "A"=>{city=>"Augsburg", province=>2}, + "AA"=>{city=>"Ostalbkreis", province=>1}, + "AB"=>{city=>"Aschaffenburg", province=>2}, + "ABG"=>{city=>"Altenburger Land", province=>15}, + "AC"=>{city=>"Aachen", province=>10}, + "AE"=>{city=>"Auerbach", province=>13}, + "AH"=>{city=>"Ahaus ", province=>10}, + "AIB"=>{city=>"Bad Aibling", province=>2}, + "AIC"=>{city=>"Aichach-Friedberg", province=>2}, + "AK"=>{city=>"Altenkirchen", province=>11}, + "AL"=>{city=>"Altena", province=>10}, + "ALF"=>{city=>"Alfeld (Leine)", province=>9}, + "ALS"=>{city=>"Alsfeld", province=>7}, + "ALZ"=>{city=>"Alzenau", province=>2}, + "AM"=>{city=>"Amberg", province=>2}, + "AN"=>{city=>"Ansbach", province=>2}, + "ANA"=>{city=>"Annaberg", province=>13}, + "ANG"=>{city=>"Angermünde", province=>4}, + "ANK"=>{city=>"Ostvorpommern, Anklam", province=>8}, + "AP"=>{city=>"Weimarer-Land", province=>15}, + "APD"=>{city=>"Weimarer Land, Apolda", province=>15}, + "AR"=>{city=>"Arnsberg", province=>10}, + "ARN"=>{city=>"Ilm-Kreis", province=>15}, + "ART"=>{city=>"Artern", province=>15}, + "AS"=>{city=>"Amberg-Sulzbach", province=>2}, + "ASD"=>{city=>"Aschendorf-Hümmling", province=>9}, + "ASL"=>{city=>"Aschersleben", province=>14}, + "ASZ"=>{city=>"Aue-Schwarzenberg", province=>13}, + "AT"=>{city=>"Altentreptow", province=>8}, + "AU"=>{city=>"Aue", province=>13}, + "AUR"=>{city=>"Aurich", province=>9}, + "AW"=>{city=>"Ahrweiler", province=>11}, + "AZ"=>{city=>"Alzey", province=>11}, + "AZE"=>{city=>"Anhalt-Zerbst", province=>14}, + "AÖ"=>{city=>"Altötting", province=>2}, + "B"=>{city=>"Berlin", province=>"3"}, + "BA"=>{city=>"Bamberg", province=>2}, + "BAD"=>{city=>"Baden-Baden", province=>1}, + "BAR"=>{city=>"Barnim", province=>4}, + "BB"=>{city=>"Böblingen", province=>1}, + "BBG"=>{city=>"Bernburg", province=>14}, + "BC"=>{city=>"Biberach", province=>1}, + "BCH"=>{city=>"Buchen", province=>1}, + "BE"=>{city=>"Beckum", province=>10}, + "BED"=>{city=>"Brand-Erbisdorf", province=>13}, + "BEI"=>{city=>"Beilngries", province=>2}, + "BEL"=>{city=>"Belzig", province=>4}, + "BER"=>{city=>"Bernau", province=>4}, + "BF"=>{city=>"Burgsteinfurt", province=>10}, + "BGD"=>{city=>"Berchtesgaden", province=>2}, + "BGL"=>{city=>"Berchtesgadener Land", province=>2}, + "BH"=>{city=>"Bühl", province=>1}, + "BI"=>{city=>"Bielefeld", province=>10}, + "BID"=>{city=>"Biedenkopf", province=>7}, + "BIN"=>{city=>"Bingen", province=>11}, + "BIR"=>{city=>"Birkenfeld", province=>11}, + "BIT"=>{city=>"Bitburg", province=>11}, + "BIW"=>{city=>"Bischofswerda", province=>13}, + "BK"=>{city=>"Backnang", province=>1}, + "BKS"=>{city=>"Bernkastel", province=>11}, + "BL"=>{city=>"Zollernalbkreis", province=>1}, + "BLB"=>{city=>"Bad Berleburg", province=>10}, + "BLK"=>{city=>"Burgenlandkreis", province=>14}, + "BM"=>{city=>"Erftkreis", province=>10}, + "BN"=>{city=>"Bonn", province=>10}, + "BNA"=>{city=>"Borna", province=>13}, + "BO"=>{city=>"Bochum", province=>10}, + "BOG"=>{city=>"Bogen", province=>2}, + "BOH"=>{city=>"Bocholt", province=>10}, + "BOR"=>{city=>"Borken", province=>10}, + "BOT"=>{city=>"Bottrop", province=>10}, + "BR"=>{city=>"Bruchsal", province=>1}, + "BRA"=>{city=>"Wesermarsch", province=>9}, + "BRB"=>{city=>"Brandenburg", province=>4}, + "BRG"=>{city=>"Burg", province=>14}, + "BRI"=>{city=>"Brilon", province=>10}, + "BRK"=>{city=>"Bad Brückenau", province=>2}, + "BRL"=>{city=>"Braunlage", province=>9}, + "BRV"=>{city=>"Bremervörde", province=>9}, + "BS"=>{city=>"Braunschweig", province=>9}, + "BSB"=>{city=>"Bersenbrück", province=>9}, + "BSK"=>{city=>"Beeskow", province=>4}, + "BT"=>{city=>"Bayreuth", province=>2}, + "BTF"=>{city=>"Bitterfeld", province=>14}, + "BU"=>{city=>"Burgdorf", province=>9}, + "BUL"=>{city=>"Burglengenfeld", province=>2}, + "BZ"=>{city=>"Bautzen", province=>13}, + "BZA"=>{city=>"Bergzabern", province=>11}, + "BÖ"=>{city=>"Bördekreis", province=>14}, + "BÜD"=>{city=>"Büdingen", province=>7}, + "BÜR"=>{city=>"Büren", province=>10}, + "BÜS"=>{city=>"Büsingen", province=>1}, + "BÜZ"=>{city=>"Bützow", province=>8}, + "C"=>{city=>"Chemnitz", province=>13}, + "CA"=>{city=>"Calau", province=>4}, + "CAS"=>{city=>"Castrop-Rauxel", province=>10}, + "CB"=>{city=>"Cottbus", province=>4}, + "CE"=>{city=>"Celle", province=>9}, + "CHA"=>{city=>"Cham", province=>2}, + "CLP"=>{city=>"Cloppenburg", province=>9}, + "CLZ"=>{city=>"Clausthal-Zellerfeld", province=>9}, + "CO"=>{city=>"Coburg", province=>2}, + "COC"=>{city=>"Cochem-Zell", province=>11}, + "COE"=>{city=>"Coesfeld", province=>10}, + "CR"=>{city=>"Crailsheim", province=>1}, + "CUX"=>{city=>"Cuxhaven", province=>9}, + "CW"=>{city=>"Calw", province=>1}, + "D"=>{city=>"Düsseldorf", province=>10}, + "DA"=>{city=>"Darmstadt", province=>7}, + "DAH"=>{city=>"Dachau ", province=>2}, + "DAN"=>{city=>"Lüchow-Dannenberg", province=>9}, + "DAU"=>{city=>"Daun", province=>11}, + "DBR"=>{city=>"Bad Doberan", province=>8}, + "DD"=>{city=>"Dresden", province=>13}, + "DE"=>{city=>"Dessau", province=>14}, + "DEG"=>{city=>"Deggendorf", province=>2}, + "DEL"=>{city=>"Delmenhorst", province=>9}, + "DGF"=>{city=>"Dingolfing-Landau", province=>2}, + "DH"=>{city=>"Diepholz", province=>9}, + "DI"=>{city=>"Dieburg", province=>7}, + "DIL"=>{city=>"Dillenburg", province=>7}, + "DIN"=>{city=>"Dinslaken", province=>10}, + "DIZ"=>{city=>"Diez", province=>11}, + "DKB"=>{city=>"Dinkelsbühl", province=>2}, + "DL"=>{city=>"Döbeln", province=>13}, + "DLG"=>{city=>"Dillingen a. d. Donau", province=>2}, + "DM"=>{city=>"Demmin", province=>8}, + "DN"=>{city=>"Düren", province=>10}, + "DO"=>{city=>"Dortmund", province=>10}, + "DON"=>{city=>"Donau-Ries", province=>2}, + "DS"=>{city=>"Donaueschingen", province=>1}, + "DT"=>{city=>"Detmold", province=>10}, + "DU"=>{city=>"Duisburg", province=>10}, + "DUD"=>{city=>"Duderstadt", province=>9}, + "DW"=>{city=>"Weißeritzkreis", province=>13}, + "DZ"=>{city=>"Delitzsch", province=>13}, + "DÜW"=>{city=>"Bad Dürkheim", province=>11}, + "E"=>{city=>"Essen", province=>10}, + "EA"=>{city=>"Eisenach, Stadt", province=>15}, + "EB"=>{city=>"Eilenburg", province=>13}, + "EBE"=>{city=>"Ebersberg", province=>2}, + "EBN"=>{city=>"Ebern", province=>2}, + "EBS"=>{city=>"Ebermannstadt", province=>2}, + "ECK"=>{city=>"Eckernförde", province=>16}, + "ED"=>{city=>"Erding", province=>2}, + "EE"=>{city=>"Elbe-Elster", province=>4}, + "EF"=>{city=>"Erfurt", province=>15}, + "EG"=>{city=>"Eggenfelden", province=>2}, + "EH"=>{city=>"Eisenhüttenstadt", province=>4}, + "EHI"=>{city=>"Ehingen", province=>1}, + "EI"=>{city=>"Eichstätt", province=>2}, + "EIC"=>{city=>"Eichsfeld", province=>15}, + "EIH"=>{city=>"Eichstätt-Kreis", province=>2}, + "EIL"=>{city=>"Eisleben", province=>14}, + "EIN"=>{city=>"Einbeck", province=>9}, + "EIS"=>{city=>"Saale-Holzlandkreis, Eisenberg", province=>15}, + "EL"=>{city=>"Emsland", province=>9}, + "EM"=>{city=>"Emmendingen", province=>1}, + "EMD"=>{city=>"Emden", province=>9}, + "EMS"=>{city=>"Rhein-Lahn-Kreis", province=>11}, + "EN"=>{city=>"Ennepe-Ruhr-Kreis", province=>10}, + "ER"=>{city=>"Erlangen", province=>2}, + "ERB"=>{city=>"Odenwaldkreis", province=>7}, + "ERH"=>{city=>"Erlangen-Höchstadt", province=>2}, + "ERK"=>{city=>"Erkelenz", province=>10}, + "ES"=>{city=>"Esslingen", province=>1}, + "ESA"=>{city=>"Eisenach", province=>15}, + "ESB"=>{city=>"Eschenbach i.d.Oberpfalz", province=>2}, + "ESW"=>{city=>"Werra-Meißner-Kreis", province=>7}, + "EU"=>{city=>"Euskirchen", province=>10}, + "EUT"=>{city=>"Eutin", province=>16}, + "EW"=>{city=>"Eberswalde", province=>4}, + "F"=>{city=>"Frankfurt am Main", province=>7}, + "FAL"=>{city=>"Fallingbostel", province=>9}, + "FB"=>{city=>"Wetteraukreis", province=>7}, + "FD"=>{city=>"Fulda", province=>7}, + "FDB"=>{city=>"Friedberg", province=>2}, + "FDS"=>{city=>"Freudenstadt", province=>1}, + "FEU"=>{city=>"Feuchtwangen", province=>2}, + "FF"=>{city=>"Frankfurt / Oder", province=>4}, + "FFB"=>{city=>"Fürstenfeldbruck", province=>2}, + "FG"=>{city=>"Freiberg", province=>13}, + "FH"=>{city=>"Frankfurt / Main-Höchst", province=>7}, + "FI"=>{city=>"Finsterwalde", province=>4}, + "FKB"=>{city=>"Frankenberg", province=>7}, + "FL"=>{city=>"Flensburg", province=>16}, + "FLÖ"=>{city=>"Flöha", province=>13}, + "FN"=>{city=>"Bodenseekreis", province=>1}, + "FO"=>{city=>"Forchheim", province=>2}, + "FOR"=>{city=>"Forst", province=>4}, + "FR"=>{city=>"Freiburg", province=>1}, + "FRG"=>{city=>"Freyung-Grafenau", province=>2}, + "FRI"=>{city=>"Friesland", province=>9}, + "FRW"=>{city=>"Bad Freienwalde", province=>4}, + "FS"=>{city=>"Freising", province=>2}, + "FT"=>{city=>"Frankenthal", province=>11}, + "FTL"=>{city=>"Freital", province=>13}, + "FW"=>{city=>"Fürstenwalde", province=>4}, + "FZ"=>{city=>"Fritzlar", province=>7}, + "FÜ"=>{city=>"Fürth", province=>2}, + "FÜS"=>{city=>"Füssen", province=>2}, + "G"=>{city=>"Gera", province=>15}, + "GA"=>{city=>"Gardelegen", province=>14}, + "GAN"=>{city=>"Bad Gandersheim", province=>9}, + "GAP"=>{city=>"Garmisch-Partenkirchen", province=>2}, + "GC"=>{city=>"Chemnitzer Land", province=>13}, + "GD"=>{city=>"Schwäbisch Gmünd", province=>1}, + "GDB"=>{city=>"Gadebusch", province=>8}, + "GE"=>{city=>"Gelsenkirchen", province=>10}, + "GEL"=>{city=>"Geldern", province=>10}, + "GEM"=>{city=>"Gemünden a.Main", province=>2}, + "GEO"=>{city=>"Gerolzhofen", province=>2}, + "GER"=>{city=>"Germersheim", province=>11}, + "GF"=>{city=>"Gifhorn", province=>9}, + "GG"=>{city=>"Groß-Gerau", province=>7}, + "GHA"=>{city=>"Geithain", province=>13}, + "GHC"=>{city=>"Gräfenhainichen", province=>14}, + "GI"=>{city=>"Gießen", province=>7}, + "GK"=>{city=>"Geilenkirchen-Heinsberg", province=>10}, + "GL"=>{city=>"Rheinisch-Bergischer Kreis", province=>10}, + "GLA"=>{city=>"Gladbeck", province=>10}, + "GM"=>{city=>"Oberbergischer Kreis", province=>10}, + "GMN"=>{city=>"Grimmen", province=>8}, + "GN"=>{city=>"Gelnhausen", province=>7}, + "GNT"=>{city=>"Genthin", province=>14}, + "GOA"=>{city=>"St. Goar", province=>11}, + "GOH"=>{city=>"St. Goarshausen", province=>11}, + "GP"=>{city=>"Göppingen", province=>1}, + "GR"=>{city=>"Görlitz", province=>13}, + "GRA"=>{city=>"Grafenau", province=>2}, + "GRH"=>{city=>"Großenhain", province=>13}, + "GRI"=>{city=>"Griesbach i. Rottal", province=>2}, + "GRM"=>{city=>"Grimma", province=>13}, + "GRS"=>{city=>"Gransee", province=>4}, + "GRZ"=>{city=>"Greiz", province=>15}, + "GS"=>{city=>"Goslar", province=>9}, + "GT"=>{city=>"Gütersloh", province=>10}, + "GTH"=>{city=>"Gotha", province=>15}, + "GUB"=>{city=>"Guben", province=>4}, + "GUN"=>{city=>"Gunzenhausen", province=>2}, + "GV"=>{city=>"Grevenbroich", province=>10}, + "GVM"=>{city=>"Grevesmühlen", province=>8}, + "GW"=>{city=>"Greifswald Land", province=>8}, + "GZ"=>{city=>"Günzburg", province=>2}, + "GÖ"=>{city=>"Göttingen", province=>9}, + "GÜ"=>{city=>"Güstrow", province=>8}, + "H"=>{city=>"Hannover", province=>9}, + "HA"=>{city=>"Hagen", province=>10}, + "HAB"=>{city=>"Hammelburg", province=>2}, + "HAL"=>{city=>"Halle", province=>14}, + "HAM"=>{city=>"Hamm", province=>10}, + "HAS"=>{city=>"Haßberge", province=>2}, + "HB"=>{city=>"Bremen", province=>5}, + "HBN"=>{city=>"Hildburghausen", province=>15}, + "HBS"=>{city=>"Halberstadt", province=>14}, + "HC"=>{city=>"Hainichen", province=>13}, + "HCH"=>{city=>"Hechingen", province=>1}, + "HD"=>{city=>"Rhein-Neckar-Kreis", province=>1}, + "HDH"=>{city=>"Heidenheim (Brenz)", province=>1}, + "HDL"=>{city=>"Haldensleben", province=>14}, + "HE"=>{city=>"Helmstedt", province=>9}, + "HEB"=>{city=>"Hersbruck", province=>2}, + "HEF"=>{city=>"Hersfeld-Rotenburg", province=>7}, + "HEI"=>{city=>"Dithmarschen", province=>16}, + "HER"=>{city=>"Herne", province=>10}, + "HET"=>{city=>"Hettstedt", province=>14}, + "HF"=>{city=>"Herford", province=>10}, + "HG"=>{city=>"Hochtaunus-Kreis", province=>7}, + "HGN"=>{city=>"Hagenow", province=>8}, + "HGW"=>{city=>"Greifswald", province=>8}, + "HH"=>{city=>"Hamburg", province=>6}, + "HHM"=>{city=>"Hohenmölsen", province=>14}, + "HI"=>{city=>"Hildesheim", province=>9}, + "HIG"=>{city=>"Eichsfeld, Heiligenstadt", province=>15}, + "HIP"=>{city=>"Hilpoltstein", province=>2}, + "HL"=>{city=>"Lübeck", province=>16}, + "HM"=>{city=>"Hameln-Pyrmont", province=>9}, + "HMÜ"=>{city=>"Hann. Münden", province=>9}, + "HN"=>{city=>"Heilbronn", province=>1}, + "HO"=>{city=>"Hof", province=>2}, + "HOG"=>{city=>"Hofgeismar", province=>7}, + "HOH"=>{city=>"Hofheim i. Ufr.", province=>2}, + "HOL"=>{city=>"Holzminden", province=>9}, + "HOM"=>{city=>"Saarpfalz-Kreis", province=>12}, + "HOR"=>{city=>"Horb", province=>1}, + "HOT"=>{city=>"Hohenstein-Ernstthal", province=>13}, + "HP"=>{city=>"Bergstraße", province=>7}, + "HR"=>{city=>"Schwalm-Eder-Kreis", province=>7}, + "HRO"=>{city=>"Rostock", province=>8}, + "HS"=>{city=>"Heinsberg", province=>10}, + "HSK"=>{city=>"Hochsauerland-Kreis", province=>10}, + "HST"=>{city=>"Stralsund", province=>8}, + "HU"=>{city=>"Main-Kinzig-Kreis", province=>7}, + "HUS"=>{city=>"Husum", province=>16}, + "HV"=>{city=>"Havelberg", province=>14}, + "HVL"=>{city=>"Havelland", province=>4}, + "HW"=>{city=>"Halle/Westfalen", province=>10}, + "HWI"=>{city=>"Wismar", province=>8}, + "HX"=>{city=>"Höxter", province=>10}, + "HY"=>{city=>"Hoyerswerda", province=>13}, + "HZ"=>{city=>"Herzberg", province=>4}, + "HÖS"=>{city=>"Höchstadt a. d. Aisch", province=>2}, + "HÜN"=>{city=>"Hünfeld", province=>7}, + "IGB"=>{city=>"St. Ingbert", province=>12}, + "IK"=>{city=>"Ilm-Kreis", province=>15}, + "IL"=>{city=>"Ilmenau", province=>15}, + "ILL"=>{city=>"Illertissen", province=>2}, + "IN"=>{city=>"Ingolstadt", province=>2}, + "IS"=>{city=>"Iserlohn", province=>10}, + "IZ"=>{city=>"Steinburg", province=>16}, + "J"=>{city=>"Jena", province=>15}, + "JB"=>{city=>"Jüterbog", province=>4}, + "JE"=>{city=>"Jessen", province=>14}, + "JEV"=>{city=>"Jever", province=>9}, + "JL"=>{city=>"Jerichower Land", province=>14}, + "JÜL"=>{city=>"Jülich", province=>10}, + "K"=>{city=>"Köln", province=>10}, + "KA"=>{city=>"Karlsruhe", province=>1}, + "KAR"=>{city=>"Karlstadt", province=>2}, + "KB"=>{city=>"Waldeck-Frankenberg", province=>7}, + "KC"=>{city=>"Kronach", province=>2}, + "KE"=>{city=>"Kempten", province=>2}, + "KEH"=>{city=>"Kelheim", province=>2}, + "KEL"=>{city=>"Kehl", province=>1}, + "KEM"=>{city=>"Kemnath", province=>2}, + "KF"=>{city=>"Kaufbeuren", province=>2}, + "KG"=>{city=>"Bad Kissingen", province=>2}, + "KH"=>{city=>"Bad Kreuznach", province=>11}, + "KI"=>{city=>"Kiel", province=>16}, + "KIB"=>{city=>"Donnersberg-Kreis", province=>11}, + "KK"=>{city=>"Kempen-Krefeld", province=>10}, + "KL"=>{city=>"Kaiserslautern", province=>11}, + "KLE"=>{city=>"Kleve", province=>10}, + "KLZ"=>{city=>"Klötze", province=>14}, + "KM"=>{city=>"Kamenz", province=>13}, + "KN"=>{city=>"Konstanz", province=>1}, + "KO"=>{city=>"Koblenz", province=>11}, + "KR"=>{city=>"Krefeld", province=>10}, + "KRU"=>{city=>"Krumbach", province=>2}, + "KS"=>{city=>"Kassel", province=>7}, + "KT"=>{city=>"Kitzingen", province=>2}, + "KU"=>{city=>"Kulmbach", province=>2}, + "KUS"=>{city=>"Kusel", province=>11}, + "KW"=>{city=>"Königs-Wusterhausen", province=>4}, + "KY"=>{city=>"Kyritz", province=>4}, + "KYF"=>{city=>"Kyffhäuserkreis", province=>15}, + "KÖN"=>{city=>"Bad Königshofen i. Grabfeld", province=>2}, + "KÖT"=>{city=>"Köthen", province=>14}, + "KÖZ"=>{city=>"Kötzting", province=>2}, + "KÜN"=>{city=>"Hohenlohekreis", province=>1}, + "L"=>{city=>"Leipzig / Leipziger Land", province=>13}, + "LA"=>{city=>"Landshut", province=>2}, + "LAN"=>{city=>"Landau a.d.Isar", province=>2}, + "LAT"=>{city=>"Lauterbach", province=>7}, + "LAU"=>{city=>"Nürnberger Land", province=>2}, + "LB"=>{city=>"Ludwigsburg", province=>1}, + "LBS"=>{city=>"Lobenstein", province=>15}, + "LBZ"=>{city=>"Lübz", province=>8}, + "LC"=>{city=>"Luckau", province=>4}, + "LD"=>{city=>"Landau i. d. Pfalz", province=>11}, + "LDK"=>{city=>"Lahn-Dill-Kreis", province=>7}, + "LDS"=>{city=>"Dahme-Spreewald", province=>4}, + "LE"=>{city=>"Lemgo", province=>10}, + "LEO"=>{city=>"Leonberg", province=>1}, + "LER"=>{city=>"Leer", province=>9}, + "LEV"=>{city=>"Leverkusen", province=>10}, + "LF"=>{city=>"Laufen", province=>2}, + "LG"=>{city=>"Lüneburg", province=>9}, + "LH"=>{city=>"Lüdinghausen", province=>10}, + "LI"=>{city=>"Lindau", province=>2}, + "LIB"=>{city=>"Bad Liebenwerda", province=>4}, + "LIF"=>{city=>"Lichtenfels", province=>2}, + "LIN"=>{city=>"Lingen", province=>9}, + "LIP"=>{city=>"Lippe", province=>10}, + "LK"=>{city=>"Lübbecke", province=>10}, + "LL"=>{city=>"Landsberg am Lech", province=>2}, + "LM"=>{city=>"Limburg-Weilburg", province=>7}, + "LN"=>{city=>"Lübben", province=>4}, + "LOH"=>{city=>"Lohr a.Main", province=>2}, + "LOS"=>{city=>"Oder-Spree", province=>4}, + "LP"=>{city=>"Lippstadt", province=>10}, + "LR"=>{city=>"Lahr", province=>1}, + "LSZ"=>{city=>"Bad Langensalza", province=>15}, + "LU"=>{city=>"Ludwigshafen", province=>11}, + "LUK"=>{city=>"Luckenwalde", province=>4}, + "LWL"=>{city=>"Ludwigslust", province=>8}, + "LÖ"=>{city=>"Lörrach", province=>1}, + "LÖB"=>{city=>"Löbau", province=>13}, + "LÜD"=>{city=>"Lüdenscheid, Stadt", province=>10}, + "LÜN"=>{city=>"Lünen", province=>10}, + "M"=>{city=>"München", province=>2}, + "MA"=>{city=>"Mannheim", province=>1}, + "MAB"=>{city=>"Marienberg", province=>13}, + "MAI"=>{city=>"Mainburg", province=>2}, + "MAK"=>{city=>"Marktredwitz", province=>2}, + "MAL"=>{city=>"Mallersdorf", province=>2}, + "MAR"=>{city=>"Marktheidenfeld", province=>2}, + "MB"=>{city=>"Miesbach", province=>2}, + "MC"=>{city=>"Malchin", province=>8}, + "MD"=>{city=>"Magdeburg", province=>14}, + "ME"=>{city=>"Mettmann", province=>10}, + "MED"=>{city=>"Meldorf /Suderdithmarschen", province=>16}, + "MEG"=>{city=>"Melsungen", province=>7}, + "MEI"=>{city=>"Meißen", province=>13}, + "MEK"=>{city=>"Mittlerer Erzgebirgskreis", province=>13}, + "MEL"=>{city=>"Melle", province=>9}, + "MEP"=>{city=>"Meppen", province=>9}, + "MER"=>{city=>"Merseburg", province=>14}, + "MES"=>{city=>"Meschede", province=>10}, + "MET"=>{city=>"Mellrichstadt", province=>2}, + "MG"=>{city=>"Mönchengladbach", province=>10}, + "MGH"=>{city=>"Bad Mergentheim", province=>1}, + "MGN"=>{city=>"Meiningen", province=>15}, + "MH"=>{city=>"Mülheim an der Ruhr", province=>"Nordrhein-Westfalen."}, + "MHL"=>{city=>"Unstrut-Hainich-Kreis, Mühlhausen", province=>15}, + "MI"=>{city=>"Minden", province=>10}, + "MIL"=>{city=>"Miltenberg", province=>2}, + "MK"=>{city=>"Märkischer Kreis", province=>10}, + "ML"=>{city=>"Mansfelder Land", province=>14}, + "MM"=>{city=>"Memmingen", province=>2}, + "MN"=>{city=>"Unterallgäu", province=>2}, + "MO"=>{city=>"Moers", province=>10}, + "MOD"=>{city=>"Marktoberdorf", province=>2}, + "MOL"=>{city=>"Märkisch-Oderland", province=>4}, + "MON"=>{city=>"Monschau", province=>10}, + "MOS"=>{city=>"Neckar-Odenwald-Kreis", province=>1}, + "MQ"=>{city=>"Merseburg-Querfurt", province=>14}, + "MR"=>{city=>"Marburg-Biedenkopf", province=>7}, + "MS"=>{city=>"Münster", province=>10}, + "MSP"=>{city=>"Main-Spessart", province=>2}, + "MST"=>{city=>"Mecklenburg-Strelitz", province=>8}, + "MT"=>{city=>"Montabaur", province=>11}, + "MTK"=>{city=>"Main-Taunus-Kreis", province=>7}, + "MTL"=>{city=>"Muldentalkreis", province=>13}, + "MW"=>{city=>"Mittweida", province=>13}, + "MY"=>{city=>"Mayen", province=>11}, + "MYK"=>{city=>"Mayen-Koblenz", province=>11}, + "MZ"=>{city=>"Mainz (-Bingen)", province=>11}, + "MZG"=>{city=>"Merzig-Saar", province=>12}, + "MÜ"=>{city=>"Mühldorf am Inn", province=>2}, + "MÜB"=>{city=>"Münchberg", province=>2}, + "MÜL"=>{city=>"Müllheim", province=>1}, + "MÜN"=>{city=>"Münsingen", province=>1}, + "MÜR"=>{city=>"Müritz", province=>8}, + "N"=>{city=>"Nürnberg", province=>2}, + "NAB"=>{city=>"Nabburg", province=>2}, + "NAI"=>{city=>"Naila", province=>2}, + "NAU"=>{city=>"Nauen", province=>4}, + "NB"=>{city=>"Neubrandenburg", province=>8}, + "ND"=>{city=>"Neuburg-Schrobenhausen", province=>2}, + "NDH"=>{city=>"Nordhausen", province=>15}, + "NE"=>{city=>"Neuss", province=>10}, + "NEA"=>{city=>"Neustadt a. d. Aisch", province=>2}, + "NEB"=>{city=>"Nebra", province=>14}, + "NEC"=>{city=>"Neustadt b.Coburg", province=>2}, + "NEN"=>{city=>"Neunburg vorm Wald", province=>2}, + "NES"=>{city=>"Rhön-Grabfeld", province=>2}, + "NEU"=>{city=>"Titisee-Neustadt im Schwarzwald", province=>1}, + "NEW"=>{city=>"Neustadt an der Waldnaab", province=>2}, + "NF"=>{city=>"Nordfriesland", province=>16}, + "NH"=>{city=>"Neuhaus am Rennweg", province=>15}, + "NI"=>{city=>"Nienburg", province=>9}, + "NIB"=>{city=>"Niebüll", province=>16}, + "NK"=>{city=>"Neunkirchen", province=>12}, + "NM"=>{city=>"Neumarkt", province=>2}, + "NMB"=>{city=>"Naumburg", province=>14}, + "NMS"=>{city=>"Neumünster", province=>16}, + "NOH"=>{city=>"Bentheim", province=>9}, + "NOL"=>{city=>"Niederschlesische Oberlausitz", province=>13}, + "NOM"=>{city=>"Northeim", province=>9}, + "NOR"=>{city=>"Norden", province=>9}, + "NP"=>{city=>"Neuruppin", province=>4}, + "NR"=>{city=>"Neuwied", province=>11}, + "NRÜ"=>{city=>"Neustadt a.Rübenberge", province=>9}, + "NT"=>{city=>"Nürtingen", province=>1}, + "NU"=>{city=>"Neu-Ulm", province=>2}, + "NVP"=>{city=>"Nordvorpommern", province=>8}, + "NW"=>{city=>"Neustadt a. d. Weinstraße", province=>11}, + "NWM"=>{city=>"Nordwestmecklenburg", province=>8}, + "NY"=>{city=>"Niesky", province=>13}, + "NZ"=>{city=>"Neustrelitz", province=>8}, + "NÖ"=>{city=>"Nördlingen", province=>2}, + "OA"=>{city=>"Oberallgäu", province=>2}, + "OAL"=>{city=>"Ostallgäu", province=>2}, + "OB"=>{city=>"Oberhausen", province=>10}, + "OBB"=>{city=>"Obernburg a. Main", province=>2}, + "OBG"=>{city=>"Osterburg", province=>14}, + "OC"=>{city=>"Oschersleben", province=>14}, + "OCH"=>{city=>"Ochsenfurt", province=>2}, + "OD"=>{city=>"Stormarn", province=>16}, + "OE"=>{city=>"Olpe", province=>10}, + "OF"=>{city=>"Offenbach", province=>7}, + "OG"=>{city=>"Ortenaukreis", province=>1}, + "OH"=>{city=>"Ostholstein", province=>16}, + "OHA"=>{city=>"Osterode am Harz", province=>9}, + "OHV"=>{city=>"Oberhavel", province=>4}, + "OHZ"=>{city=>"Osterholz-Scharmbeck", province=>9}, + "OK"=>{city=>"Ohre-Kreis", province=>14}, + "OL"=>{city=>"Oldenburg", province=>9}, + "OLD"=>{city=>"Oldenburg/Holstein", province=>16}, + "OP"=>{city=>"Opladen", province=>10}, + "OPR"=>{city=>"Ostprignitz-Ruppin", province=>4}, + "OR"=>{city=>"Oranienburg", province=>4}, + "OS"=>{city=>"Osnabrück", province=>9}, + "OSL"=>{city=>"Oberspreewald-Lausitz", province=>4}, + "OTT"=>{city=>"Otterndorf", province=>9}, + "OTW"=>{city=>"Ottweiler", province=>12}, + "OVI"=>{city=>"Oberviechtach", province=>2}, + "OVL"=>{city=>"Obervogtland", province=>13}, + "OVP"=>{city=>"Ostvorpommern", province=>8}, + "OZ"=>{city=>"Oschatz", province=>13}, + "ÖHR"=>{city=>"Öhringen", province=>1}, + "P"=>{city=>"Potsdam", province=>4}, + "PA"=>{city=>"Passau", province=>2}, + "PAF"=>{city=>"Pfaffenhofen", province=>2}, + "PAN"=>{city=>"Rottal-Inn", province=>2}, + "PAR"=>{city=>"Parsberg", province=>2}, + "PB"=>{city=>"Paderborn", province=>10}, + "PCH"=>{city=>"Parchim", province=>8}, + "PE"=>{city=>"Peine", province=>9}, + "PEG"=>{city=>"Pegnitz", province=>2}, + "PER"=>{city=>"Perleberg", province=>4}, + "PF"=>{city=>"Pforzheim / Enzkreis", province=>1}, + "PI"=>{city=>"Pinneberg", province=>16}, + "PIR"=>{city=>"Sächsische Schweiz", province=>13}, + "PK"=>{city=>"Pritzwalk", province=>4}, + "PL"=>{city=>"Plauen", province=>13}, + "PLÖ"=>{city=>"Plön", province=>16}, + "PM"=>{city=>"Potsdam-Mittelmark", province=>4}, + "PN"=>{city=>"Pößneck", province=>15}, + "PR"=>{city=>"Prignitz", province=>4}, + "PRÜ"=>{city=>"Prüm", province=>11}, + "PS"=>{city=>"Pirmasens / Südwestpfalz", province=>11}, + "PW"=>{city=>"Pasewalk", province=>8}, + "PZ"=>{city=>"Prenzlau", province=>4}, + "QFT"=>{city=>"Querfurt", province=>14}, + "QLB"=>{city=>"Quedlinburg", province=>14}, + "R"=>{city=>"Regensburg", province=>2}, + "RA"=>{city=>"Rastatt", province=>1}, + "RC"=>{city=>"Reichenbach", province=>13}, + "RD"=>{city=>"Rendsburg-Eckernförde", province=>16}, + "RDG"=>{city=>"Ribnitz-Damgarten", province=>8}, + "RE"=>{city=>"Recklinghausen", province=>10}, + "REG"=>{city=>"Regen", province=>2}, + "REH"=>{city=>"Rehau", province=>2}, + "REI"=>{city=>"Bad Reichenhall", province=>2}, + "RG"=>{city=>"Großenhain", province=>13}, + "RH"=>{city=>"Roth", province=>2}, + "RI"=>{city=>"Rinteln", province=>9}, + "RID"=>{city=>"Riedenburg", province=>2}, + "RIE"=>{city=>"Riesa", province=>13}, + "RL"=>{city=>"Rochlitz", province=>13}, + "RM"=>{city=>"Röbel", province=>8}, + "RN"=>{city=>"Rathenow", province=>4}, + "RO"=>{city=>"Rosenheim", province=>2}, + "ROD"=>{city=>"Roding", province=>2}, + "ROF"=>{city=>"Rotenburg/Fulda", province=>7}, + "ROK"=>{city=>"Rockenhausen", province=>11}, + "ROL"=>{city=>"Rottenburg a. d. Laaber", province=>2}, + "ROS"=>{city=>"Rostock-Kreis", province=>8}, + "ROT"=>{city=>"Rothenburg o.d.Tauber", province=>2}, + "ROW"=>{city=>"Rotenburg (Wümme)", province=>9}, + "RS"=>{city=>"Remscheid", province=>10}, + "RSL"=>{city=>"Roßlau", province=>14}, + "RT"=>{city=>"Reutlingen", province=>1}, + "RU"=>{city=>"Rudolstadt", province=>15}, + "RV"=>{city=>"Ravensburg", province=>1}, + "RW"=>{city=>"Rottweil", province=>1}, + "RY"=>{city=>"Rheydt", province=>10}, + "RZ"=>{city=>"Herzogtum Lauenburg", province=>16}, + "RÜD"=>{city=>"Rheingau-Taunus-Kreis", province=>7}, + "RÜG"=>{city=>"Rügen", province=>8}, + "S"=>{city=>"Stuttgart", province=>1}, + "SAB"=>{city=>"Saarburg", province=>11}, + "SAD"=>{city=>"Schwandorf in Bayern", province=>2}, + "SAN"=>{city=>"Stadtsteinach", province=>2}, + "SAW"=>{city=>"Altmarkkreis Salzwedel", province=>14}, + "SB"=>{city=>"Saarbrücken", province=>12}, + "SBG"=>{city=>"Strasburg", province=>8}, + "SBK"=>{city=>"Schönebeck", province=>"Sachsen Anhalt"}, + "SC"=>{city=>"Schwabach", province=>2}, + "SCZ"=>{city=>"Schleiz", province=>15}, + "SDH"=>{city=>"Sondershausen", province=>15}, + "SDL"=>{city=>"Stendal", province=>14}, + "SDT"=>{city=>"Schwedt", province=>4}, + "SE"=>{city=>"Bad Segeberg", province=>16}, + "SEB"=>{city=>"Sebnitz", province=>13}, + "SEE"=>{city=>"Seelow", province=>4}, + "SEF"=>{city=>"Scheinfeld", province=>2}, + "SEL"=>{city=>"Selb", province=>2}, + "SF"=>{city=>"Sonthofen", province=>2}, + "SFA"=>{city=>"Soltau-Fallingbostel", province=>9}, + "SFB"=>{city=>"Senftenberg", province=>4}, + "SFT"=>{city=>"Staßfurt", province=>14}, + "SG"=>{city=>"Solingen", province=>10}, + "SGH"=>{city=>"Sangerhausen", province=>14}, + "SHA"=>{city=>"Schwäbisch Hall", province=>1}, + "SHG"=>{city=>"Schaumburg", province=>9}, + "SHK"=>{city=>"Saale-Holzland-Kreis", province=>15}, + "SHL"=>{city=>"Suhl", province=>15}, + "SI"=>{city=>"Siegen", province=>10}, + "SIG"=>{city=>"Sigmaringen", province=>1}, + "SIM"=>{city=>"Rhein-Hunsrück-Kreis", province=>11}, + "SK"=>{city=>"Saalkreis", province=>14}, + "SL"=>{city=>"Schleswig-Flensburg", province=>16}, + "SLE"=>{city=>"Schleiden", province=>10}, + "SLF"=>{city=>"Saalfeld-Rudolstadt", province=>15}, + "SLG"=>{city=>"Saulgau", province=>1}, + "SLN"=>{city=>"Schmölln", province=>15}, + "SLS"=>{city=>"Saarlouis", province=>12}, + "SLZ"=>{city=>"Bad Salzungen", province=>15}, + "SLÜ"=>{city=>"Schlüchtern", province=>7}, + "SM"=>{city=>"Schmalkalden-Meiningen", province=>15}, + "SMÜ"=>{city=>"Schwabmünchen", province=>2}, + "SN"=>{city=>"Schwerin", province=>8}, + "SNH"=>{city=>"Sinsheim Elsenz", province=>1}, + "SO"=>{city=>"Soest", province=>10}, + "SOB"=>{city=>"Schrobenhausen", province=>2}, + "SOG"=>{city=>"Schongau", province=>2}, + "SOK"=>{city=>"Saale-Orla-Kreis", province=>15}, + "SOL"=>{city=>"Soltau", province=>9}, + "SON"=>{city=>"Sonneberg", province=>15}, + "SP"=>{city=>"Speyer", province=>11}, + "SPB"=>{city=>"Spremberg", province=>4}, + "SPN"=>{city=>"Spree-Neiße", province=>4}, + "SPR"=>{city=>"Springe", province=>9}, + "SR"=>{city=>"Straubing (-Bogen)", province=>2}, + "SRB"=>{city=>"Strausberg", province=>4}, + "SRO"=>{city=>"Stadtroda", province=>15}, + "ST"=>{city=>"Steinfurt", province=>10}, + "STA"=>{city=>"Starnberg", province=>2}, + "STB"=>{city=>"Sternberg", province=>8}, + "STD"=>{city=>"Stade", province=>9}, + "STE"=>{city=>"Staffelstein", province=>2}, + "STH"=>{city=>"Schaumburg-Lippe", province=>9}, + "STL"=>{city=>"Stollberg", province=>13}, + "STO"=>{city=>"Stockach", province=>1}, + "SU"=>{city=>"Rhein-Sieg-Kreis", province=>10}, + "SUL"=>{city=>"Sulzbach-Rosenberg", province=>2}, + "SW"=>{city=>"Schweinfurt", province=>2}, + "SWA"=>{city=>"Bad Schwalbach", province=>7}, + "SY"=>{city=>"Syke", province=>9}, + "SZ"=>{city=>"Salzgitter", province=>9}, + "SZB"=>{city=>"Schwarzenberg", province=>13}, + "SÄK"=>{city=>"Säckingen", province=>1}, + "SÖM"=>{city=>"Sömmerda", province=>15}, + "SÜW"=>{city=>"Südliche Weinstraße", province=>11}, + "TBB"=>{city=>"Main-Tauber-Kreis", province=>1}, + "TE"=>{city=>"Tecklenburg", province=>10}, + "TET"=>{city=>"Teterow", province=>8}, + "TF"=>{city=>"Teltow-Fläming", province=>4}, + "TG"=>{city=>"Torgau", province=>13}, + "TIR"=>{city=>"Tirschenreuth", province=>2}, + "TO"=>{city=>"Torgau-Oschatz", province=>13}, + "TP"=>{city=>"Templin", province=>4}, + "TR"=>{city=>"Trier", province=>11}, + "TS"=>{city=>"Traunstein", province=>2}, + "TT"=>{city=>"Tettnang", province=>1}, + "TUT"=>{city=>"Tuttlingen", province=>1}, + "TÖL"=>{city=>"Bad Tölz-Wolfratshausen", province=>2}, + "TÖN"=>{city=>"Tönning", province=>16}, + "TÜ"=>{city=>"Tübingen", province=>1}, + "UE"=>{city=>"Uelzen", province=>9}, + "UEM"=>{city=>"Ueckermünde", province=>8}, + "UER"=>{city=>"Uecker-Randow", province=>8}, + "UFF"=>{city=>"Uffenheim", province=>2}, + "UH"=>{city=>"Unstrut-Hainich-Kreis", province=>15}, + "UL"=>{city=>"Ulm / Alb-Donau-Kreis", province=>1}, + "UM"=>{city=>"Uckermark", province=>4}, + "UN"=>{city=>"Unna", province=>10}, + "USI"=>{city=>"Usingen", province=>7}, + "ÜB"=>{city=>"Überlingen", province=>1}, + "V"=>{city=>"Vogtlandkreis", province=>13}, + "VAI"=>{city=>"Vaihingen", province=>1}, + "VB"=>{city=>"Vogelsbergkreis", province=>7}, + "VEC"=>{city=>"Vechta", province=>9}, + "VER"=>{city=>"Verden", province=>9}, + "VIB"=>{city=>"Vilsbiburg", province=>2}, + "VIE"=>{city=>"Viersen", province=>10}, + "VIT"=>{city=>"Viechtach", province=>2}, + "VK"=>{city=>"Völklingen", province=>12}, + "VL"=>{city=>"Villingen", province=>1}, + "VOF"=>{city=>"Vilshofen", province=>2}, + "VOH"=>{city=>"Vohenstrauß", province=>2}, + "VS"=>{city=>"Schwarzwald-Baar-Kreis", province=>1}, + "W"=>{city=>"Wuppertal", province=>10}, + "WA"=>{city=>"Waldeck", province=>7}, + "WAF"=>{city=>"Warendorf", province=>10}, + "WAK"=>{city=>"Wartburgkreis", province=>15}, + "WAM"=>{city=>"Westlicher Altmark-Kreis", province=>14}, + "WAN"=>{city=>"Wanne-Eickel", province=>10}, + "WAR"=>{city=>"Warburg", province=>10}, + "WAT"=>{city=>"Wattenscheid", province=>10}, + "WB"=>{city=>"Wittenberg", province=>14}, + "WBS"=>{city=>"Worbis", province=>15}, + "WD"=>{city=>"Wiedenbrück", province=>10}, + "WDA"=>{city=>"Werdau", province=>13}, + "WE"=>{city=>"Weimar", province=>15}, + "WEB"=>{city=>"Westerburg-Westerwald", province=>11}, + "WEG"=>{city=>"Wegscheid", province=>2}, + "WEL"=>{city=>"Weilburg", province=>7}, + "WEM"=>{city=>"Wesermünde", province=>9}, + "WEN"=>{city=>"Weiden", province=>2}, + "WER"=>{city=>"Wertingen", province=>2}, + "WES"=>{city=>"Wesel", province=>10}, + "WF"=>{city=>"Wolfenbüttel", province=>9}, + "WG"=>{city=>"Wangen", province=>1}, + "WHV"=>{city=>"Wilhelmshaven", province=>9}, + "WI"=>{city=>"Wiesbaden", province=>7}, + "WIL"=>{city=>"Wittlich", province=>11}, + "WIS"=>{city=>"Wismar, Kreis", province=>8}, + "WIT"=>{city=>"Witten", province=>10}, + "WIZ"=>{city=>"Witzenhausen", province=>7}, + "WK"=>{city=>"Wittstock", province=>4}, + "WL"=>{city=>"Harburg", province=>9}, + "WLG"=>{city=>"Wolgast", province=>8}, + "WM"=>{city=>"Weilheim-Schongau", province=>2}, + "WMS"=>{city=>"Wolmirstedt", province=>14}, + "WN"=>{city=>"Rems-Murr-Kreis", province=>1}, + "WND"=>{city=>"St. Wendel", province=>12}, + "WO"=>{city=>"Worms", province=>11}, + "WOB"=>{city=>"Wolfsburg", province=>9}, + "WOH"=>{city=>"Wolfhagen", province=>7}, + "WOL"=>{city=>"Wolfach", province=>1}, + "WOR"=>{city=>"Wolfratshausen", province=>2}, + "WOS"=>{city=>"Wolfstein", province=>2}, + "WR"=>{city=>"Wernigerode", province=>14}, + "WRN"=>{city=>"Waren", province=>8}, + "WS"=>{city=>"Wasserburg a. Inn", province=>2}, + "WSF"=>{city=>"Weißenfels", province=>14}, + "WST"=>{city=>"Ammerland", province=>9}, + "WSW"=>{city=>"Weißwasser", province=>13}, + "WT"=>{city=>"Waldshut", province=>1}, + "WTL"=>{city=>"Wittlage", province=>9}, + "WTM"=>{city=>"Wittmund", province=>9}, + "WUG"=>{city=>"Weißenburg-Gunzenhausen", province=>2}, + "WUN"=>{city=>"Wunsiedel", province=>2}, + "WUR"=>{city=>"Wurzen", province=>13}, + "WW"=>{city=>"Westerwald-Kreis", province=>11}, + "WZ"=>{city=>"Wetzlar", province=>7}, + "WZL"=>{city=>"Wanzleben", province=>14}, + "WÜ"=>{city=>"Würzburg", province=>2}, + "WÜM"=>{city=>"Waldmünchen", province=>2}, + "Z"=>{city=>"Zwickau (-Land)", province=>13}, + "ZE"=>{city=>"Zerbst", province=>14}, + "ZEL"=>{city=>"Zell / Mosel", province=>11}, + "ZI"=>{city=>"Löbau-Zittau", province=>13}, + "ZIG"=>{city=>"Ziegenhain", province=>7}, + "ZP"=>{city=>"Zschopau", province=>13}, + "ZR"=>{city=>"Zeulenroda", province=>15}, + "ZS"=>{city=>"Zossen", province=>4}, + "ZW"=>{city=>"Zweibrücken", province=>11}, + "ZZ"=>{city=>"Zeitz", province=>14} + ); + my ($key) = @_; + $key = $trans{lc $key} if defined $trans{lc $key}; + my %location; + $key = uc($key); + my %base = %de_kfz; + if (defined $base{$key}) { + $location{country} = 'Germany'; + $location{city} = $base{$key}{'city'}; + $location{province} = $province{$base{$key}->{province}}; + } else { + #Irssi::print $key; + foreach (keys %base) { + my $city = $base{$_}{city}; + #$city = lc($city); + #$city =~ s/ä/ae/g; + #$city =~ s/ü/ue/g; + #$city =~ s/ö/oe/g; + #$city = uc($city); + if ($city =~ /(^| |-)$key( |-|$)/i) { + $location{country} = 'Germany'; + $location{city} = $base{$_}{city}; + $location{province} = $province{$base{$_}{province}}; + } + } + } + return %location; +} + + +foreach ((352, 315)) { + Irssi::signal_add_first('event '.$_, 'process_reply'); +} + +sub pre_unload { save_cache(); } + +Irssi::signal_add('message join', 'event_message_join'); +Irssi::signal_add('query created', 'event_query_created'); +Irssi::signal_add('setup saved', 'save_cache'); + +Irssi::settings_add_bool($IRSSI{'name'}, 'localize_background', 1); + +Irssi::settings_add_str($IRSSI{'name'}, 'localize_cache_filename', Irssi::get_irssi_dir()."/localize_cache"); +Irssi::settings_add_str($IRSSI{'name'}, 'localize_trace_cmd', "/usr/sbin/traceroute -q 1 -w 2 -I"); +Irssi::settings_add_int($IRSSI{'name'}, 'localize_trace_distance', 3); + +Irssi::settings_add_str($IRSSI{'name'}, 'localize_auto_localize_channel_list', '.*'); +Irssi::settings_add_bool($IRSSI{'name'}, 'localize_auto_localize_on_join', 0); +Irssi::settings_add_bool($IRSSI{'name'}, 'localize_auto_localize_on_query', 1); +Irssi::settings_add_int($IRSSI{'name'}, 'localize_auto_localize_maxrequests', 5); +Irssi::settings_add_bool($IRSSI{'name'}, 'localize_get_coordinates', 0); +Irssi::settings_add_bool($IRSSI{'name'}, 'localize_use_databases', 1); +Irssi::settings_add_bool($IRSSI{'name'}, 'localize_use_traceroute', 1); +Irssi::settings_add_bool($IRSSI{'name'}, 'localize_show_message', 1); +Irssi::settings_add_str($IRSSI{'name'}, 'localize_ipatlas_nocache', '.*\.dip\.t-dialin\.net'); + +Irssi::settings_add_bool($IRSSI{'name'}, 'localize_xplanet_show_map', 0); +Irssi::settings_add_str($IRSSI{'name'}, 'localize_xplanet_temp_file', Irssi::get_irssi_dir()."/localize_xplanet_temp"); +Irssi::settings_add_str($IRSSI{'name'}, 'localize_xplanet_cmd', "xplanet -w"); + +Irssi::theme_register([ + auto_localize => '%B`->%n $0 ($1) has been localized in $2, $3, $4 %B[%n$5%B]%n', +]); + +Irssi::command_bind('localize', 'cmd_localize'); + +load_cache(); +print CLIENTCRAP '%B>>%n '.$IRSSI{name}.' '.$VERSION.' loaded: /localize -h for help'; |