1#!/usr/local/bin/perl
2#
3#
4# By Stefan 'tommie' Tomanek, stefan@kann-nix.org
5#
6#
7# This script works fine on DFN (german universities) and T-Oline sites
8#
9# 01.03.2002
10# *Changed to GPL
11#
12# 15.03.2002
13# *Now works on QUERIES as well
14#
15# 24.04.2002
16# *the nick does not have to be on the channel
17# *switched to /WHO
18#
19# 27.04.2002
20# *localization of hosts (/localize @hostname)
21#
22# 29.04.2002
23# *tweaked Design
24# *added channel statistics
25#
26# 04.05.2002
27# *added alternate database (IP Atlas)
28#
29# 05.05.2002
30# *the script is now able to use both databases simultaniously
31# */set localize_use_<database> to enable or disable them
32#
33# 10.05.2002
34# *non-blocking IO via fork()
35#
36# 13.05.2002
37# *finally improved forking and background localizing
38# *now using XML
39#
40# 26.05.2002
41# *Implemented auto-localize
42#
43# 28.05.2002
44# *major updates
45# *fixed race conditions
46#
47# 30.05.2002
48# *finally rendered traceroute support usefull
49#
50# 31.05.2002
51# *moved database to this file
52#
53# 03.07.2002
54# *switched to Data::Dumper
55#
56# 25.11.2014
57# Added utrace.de as a localizer
58# http://www.utrace.de/
59
60use strict;
61use vars qw($VERSION %IRSSI);
62
63$VERSION = "2017040101";
64%IRSSI = (
65    authors     => "Stefan 'tommie' Tomanek",
66    contact     => "stefan\@pico.ruhr.de",
67    name        => "localize",
68    description => "Localizes users using traceroute, the localizer database or IP-Atlas",
69    license     => "GPLv2",
70    url         => "",
71    changed     => "$VERSION",
72    modules     => "Data::Dumper LWP::UserAgent HTML::Entities",
73    commands	=> "localize"
74);
75
76use Irssi 20020324;
77use LWP::UserAgent;
78use HTML::Entities;
79use Data::Dumper;
80use POSIX;
81use Socket;
82
83use vars qw(%queries %cache %ipdb $procs @tracer $debug);
84$debug = 0;
85$procs = 0;
86
87
88# host regexps for trace_host
89#
90
91@tracer = (
92    { provider => 'tonline',
93      regexp   => [ '.*?-.*?\.(.*?)(\.DE|)\.net\.dtag\.de', ]
94    },
95    { provider => 'uunet',
96      regexp   => [ '.*?-\d+-\d+\..*?\.(.*?)\d?\.uunet\.de', ]
97    },
98    { provider => 'kpnqwest',
99      regexp   => [ '.*?-.*?\.(\w?)\.de\.kpnqwest\.net', ]
100    },
101    { provider => 'ewetel',
102      regexp   => [ '.*?-.*?-.*?\.rt8\.(.*?)\.ewetel\.net',
103                    '(.*?)[0-9]*-.*?\.ewetel\.net',
104		    'so\d+-\d+-\d+-bbrt\d+\.(.*?)\.ewe-ip-backbone\.de']
105    },
106    { provider => 'arcor',
107      regexp   => [ '((?!dsl)\w+)-\d+-\d+-\d+-\d+\.arcor-ip\.net',
108                    '.*?-(.*?)-.*?\d*\.arcor-online\.net']
109    },
110    { provider => 'mediaways',
111      regexp   => ['.*-(.*)-de.*-.*-.*-.*\..*\.mediaways.net', ]
112    },
113    { provider => 'mobilcom',
114      regexp   => ['.*\.(.*?)[0-9]+-.\.mcbone\.net',]
115    },
116    { provider => 'vianetworks',
117      regexp   => ['\w+\.(.*?)\.revmap\.vianetworks\.de',
118                   'rt\d{3}(.*?)\.de\.vianw\.net',]
119    },
120    { provider => 'mfnx',
121      regexp   => ['.+-\d+-\d+-\d+\..+\.(.*?)[0-9]+\.de\.mfnx\.net',]
122    },
123    { provider => 'colt',
124      regexp   => ['.+-.*\..+\.(.*?)\.DE.COLT-ISC.NET',
125                   '.+\.((?!dsl)(?!host)\w+)\.de\.colt\.net',
126		   '..\d\.(\w+)\.de\.colt\.net',]
127    },
128    { provider => 'telia',
129      regexp   => ['(.*?)-.+-.+-.+\.telia.net',]
130    },
131    { provider => 'hansanet',
132      regexp   => ['.*\.(.*?)-[0-9]+\.hansenet\.net',]
133    },
134    { provider => 'isis',
135      regexp   => ['isis-gw-(.*?)[0-9]\.de\.cw\.net', ]
136    },
137    { provider => 'cable & wireless',
138      regexp   => ['.*-\d+-\d+-\d+-.*?-(.*?)\d+\.de\.cw\.net',
139                   '.*?-.*?-(.*?)\d+\.de\.cw\.net']
140    },
141    { provider => 'NEFkom',
142      regexp   => ['nefkom-gw-(.*?)\.de\.cw\.net',]
143    },
144    { provider => 'eastlink',
145      regexp   => ['.*?-.*?-.*?-.*?-(.*?)\.eastlink.de',]
146    },
147    { provider => 'alternet',
148      regexp   => ['.*\.(.*?)\d?\.de\.alter\.net',]
149    },
150    { provider => 'CompleTel',
151      regexp   => ['.+-.+-.+-.+\.(.*)\.ipcenta\.de',]
152    },
153    { provider => 'mediascape',
154      regexp   => ['.+\..+\.(.*?)\.mediascape\.net',]
155    },
156    { provider => 'schlund',
157      regexp   => ['gw-prtr-[0-9]+-.+\.(.+)[0-9]+\.schlund.net',]
158    },
159    { provider => 'bisping',
160      regexp   => ['(.*?)-gw-pmx[0-9]*\.bisping\.net',]
161    },
162    { provider => 'gatel',
163      regexp   => ['ser[0-3]+-[0-3]+\.(.*?)[0-3]+\.de\.gatel\.net',]
164    },
165    { provider => 'qsc',
166      regexp   => ['rqsc-(.*?)-de[0-9]+-.+[0-9]+-[0-9]+-[0-9]+\.nw\.mediaways\.net',
167                   'bsn\d+\.(.*?)\.qdsl-home\.de',
168		   'bsn\d+\.(.*?)\.qsc\.de',
169		   'core1\.(.*?)\.qsc\.de']
170    },
171    { provider => 'dfn',
172      regexp   => ['.r-(.*?)[0-9]+\.g-win.dfn.de',
173                   '.*\.uni-(.*?)\.de',
174		   '.*\.fh-(.*?)\.de',
175		   '.*\.tu-(.*?)\.de',
176		   '.*\.fu-(.*?)\.de',]
177    },
178    { provider => 'mops.net',
179      regexp   => ['.*?\.core\d\.(.*?)\.mops\.net',]
180    },
181    { provider => 'schule.de',
182      regexp   => ['.*\.(.*?)\..*?\.Schule\.DE',]
183    },
184    { provider => 'belwue',
185      regexp   => ['(?:.*?-)?(.*?)\d+\.BelWue\.DE',]
186    },
187    { provider => 'lambdanet',
188      regexp   => ['.*?\.(.*?)\.de\.lambdanet\.net',]
189    }
190);
191
192%ipdb = (
193    # For utrace.de API documentation, see http://en.utrace.de/api.php
194    d1utrace=>{ name=>'utrace',
195		   active=>1,
196		   url=>'http://xml.utrace.de/?query=',
197		   city=>'<region>(.*?)<\/region>',
198		   province=>'<org>(.*?)<\/org>',
199		   country=>'<countrycode>(.*?)<\/countrycode>',
200		   provider=>'<isp>(.*?)<\/isp>',
201		   failure=>'request-limit-exceeded|Host not found'},
202    d2ipatlas=> { name=>'IP-Atlas',
203		  active=>0,
204	          url=>'http://www.xpenguin.com/plot.php?address=',
205                  city=>'is located in (.*?),',
206		  province=>'is located in.*, (.*?) \(state\),',
207		  country=>'is located in.*, (.*?)\. ',
208		  failure=>'cannot be located|does not resolve' },
209    d3netgeo => { name=>'NetGeo',
210                  active=>0,
211		  url=>'http://netgeo.caida.org/perl/netgeo.cgi?target=',
212		  city=>'CITY:\ *(\w+)<br>',
213		  province=>'STATE:.*?, (.*?) \(state\)<br>',
214		  country=>'COUNTRY:\ *(\w+)<br>',
215		  failure=> "SHOULD NOT"},
216);
217
218sub draw_box ($$$) {
219    my ($title, $text, $footer) = @_;
220    my $box = '';
221    $box .= '%R,--[%n%9%U'.$title.'%U%9%R]%n'."\n";
222    foreach (split(/\n/, $text)) {
223        $box .= '%R|%n '.$_."\n";
224    }
225    $box .= '%R`--<%n'.$footer.'%R>->%n';
226    return $box;
227}
228
229sub show_help() {
230    my $help="Localize $VERSION
231/localize <nickname>
232    Try to localize the user 'nickname'
233/localize @<hostname>
234    Try to localize the host
235/localize <#channel>
236    Create a tree of the people inside the channel
237/localize -s
238    Save the localize cache and settings
239/localize -r
240    Reload the localize cache from file
241/localize -c
242    Clear the cache
243/localize -sc
244    Shows the current content of the cache
245/localize -h
246    Display this help
247";
248    my $text = "";
249    foreach (split(/\n/, $help)) {
250	$_ =~ s/^\/(.*)$/%9\/$1%9/;
251        $text .= $_."\n";
252    }
253    print CLIENTCRAP draw_box("Localize", $text, "Help");
254}
255
256sub get ($) {
257    my ($url) = @_;
258    my $ua = LWP::UserAgent->new(env_proxy => 1,keep_alive => 1,timeout => 30);
259    $ua->agent('Irssi');
260    my $request = HTTP::Request->new('GET', $url);
261    my $response = $ua->request($request);
262    if ($response->is_success()) {
263	return $response->content();
264    } else {
265	return undef;
266    }
267}
268
269sub parse_page ($$) {
270    my ($page, $item) = @_;
271    my %empty;
272    my (%location);
273    $_ = $page;
274    my $regexp = $item->{failure};
275    return(%location) if /$regexp/;
276    foreach my $key ('city', 'province', 'country') {
277	$location{$key} = '';
278	my $regexp = $item->{$key};
279	if (/$regexp/) {
280	    $location{$key} = $1;
281	} else {
282	    return(%empty);
283	}
284    }
285    if (defined $item->{provider}) {
286	if (/$item->{provider}/) {
287	    $location{provider} = $1;
288	}
289    }
290    $location{map} = $item->{name} if (%location);
291    return (%location);
292}
293
294sub trace_host ($) {
295    my ($host) = @_;
296    my $cmd = Irssi::settings_get_str('localize_trace_cmd');
297    local *F;
298    my $pid = open(F, '-|', $cmd.' '.$host.' 2>/dev/null');
299    my $loc_host;
300    my $provider;
301    my $hops = 0;
302    my $maxhops = Irssi::settings_get_int('localize_trace_distance');
303    $_ = $host;
304    while (defined $_) {
305	print $_ if $debug;
306	$hops++;
307	if (/\*/) {
308	    kill 15, $pid;
309	    close(F);
310	    return([$loc_host, $provider]) if ($hops < $maxhops && $hops >= 0);
311	    return([undef, undef]);
312	} else {
313	    foreach my $traced (@tracer) {
314		foreach my $regexp (@{$traced->{regexp}}) {
315		    if (/[0-9]+  $regexp /i) {
316			$loc_host = $1;
317			$provider = $traced->{provider};
318			print $regexp if $debug;
319			print "$loc_host <-> $provider" if $debug;
320			$hops = 0;
321			last;
322		    }
323		}
324	    }
325	}
326	$_ = <F>;
327    }
328    close(F);
329    if ( ($hops < $maxhops) && ($hops >= 0)) {
330	if ($debug) {
331	    print $loc_host."-".$provider foreach (1..10);
332	}
333	return([$loc_host, $provider]);
334    } else {
335	print $hops." -> ".$maxhops if $debug;
336    }
337    return([undef, undef]);
338}
339
340sub localize($$) {
341    my ($nicks, $query) = @_;
342    if (Irssi::settings_get_bool('localize_background')) {
343	bg_fetch($nicks, $query);
344    } else {
345	fg_fetch($nicks, $query);
346    }
347}
348
349sub fg_fetch ($$) {
350    my ($nicks, $query) = @_;
351    my $data = create_output(@{$nicks});
352    my $auto = $queries{$query}->[0]{auto};
353    remove_request($query);
354    process_input($query, $auto, $data);
355}
356
357sub bg_fetch ($$) {
358    my ($nicks, $query) = @_;
359    my ($rh, $wh);
360    pipe($rh, $wh);
361    my $pid = fork();
362    $procs++;
363    if ($pid > 0) {
364	close $wh;
365	my $size = scalar(@{$nicks});
366	my $auto = $queries{$query}->[0]{auto};
367	remove_request($query);
368	unless ($auto ne '') {
369	    print CLIENTCRAP '%R>>%n Localizing '.$size.' host(s) in background [pid '.$pid.']...' if Irssi::settings_get_bool('localize_show_message');
370	}
371	Irssi::pidwait_add($pid);
372	my $pipetag;
373	my @args = ($rh, $query, $auto, \$pipetag);
374	$pipetag = Irssi::input_add(fileno($rh), INPUT_READ, \&pipe_input, \@args);
375    } else {
376	my $data = create_output(@{$nicks});
377	eval {
378	    print($wh $data);
379	    close($wh)
380	};
381	POSIX::_exit(1);
382    }
383}
384
385
386sub create_output(@) {
387    my (@nicks) = @_;
388    my @new_db;
389    my @stuff;
390    my @data;
391    my $i = 0;
392    foreach (@nicks) {
393	my $nick = $$_[0];
394	my $host = $$_[1];
395	my (%location);
396	if (defined $cache{$host}) {
397	    %location = %{$cache{$host}};
398	    $location{$_} = $location{$_} foreach (keys %location);
399	    $location{'map'} .= " (cached)";
400	} else {
401	    if (Irssi::settings_get_bool('localize_use_traceroute')) {
402		unless (%location) {
403		    my ($sign, $provider) = @{ trace_host($host) };
404		    print "\n\n>>>>".$sign if $debug;
405		    %location = kfz2location($sign) if $sign;
406		    $location{map} = 'traceroute' if (%location);
407		    $location{provider} = $provider if (%location);
408		}
409	    }
410	    if (Irssi::settings_get_bool('localize_use_databases')) {
411		unless (%location) {
412		    foreach (sort keys(%ipdb)) {
413			my $item = $ipdb{$_};
414			next unless $item->{active};
415			#my $ip = gethostbyname($host);
416			#next unless $ip;
417			my $url = $item->{url}.$host; #inet_ntoa($ip);
418			my $text = get($url);
419			%location = parse_page($text, $item);
420		    }
421		}
422	    }
423	    if (Irssi::settings_get_bool('localize_get_coordinates')) {
424		if (%location) {
425		    my $city = $location{city};
426		    my $ua = LWP::UserAgent->new(env_proxy=>1, keep_alive=>1, timeout=>30);
427		    my $data = $ua->get('http://www.astro.com/atlas/horoscope/?expr='.$city)->content();
428		    foreach (split /\n/, $data) {
429			decode_entities($_);
430			if (/^<li><a href="\/cgi\/ade\.cgi\?&(?:.*?)">(.*?)<\/a>, (?:.*?): <b>(\d+)n(\d+)<\/b>, <b>(\d+)e(\d+)<\/b>/i) {
431			    $location{latitude} = "$2.$3";
432			    $location{longitude} = "$4.$5";
433			    last;
434			}
435		    }
436		}
437	    }
438	}
439	$location{'nick'} = $nick if (%location);
440	$location{'host'} = $host if (%location);
441	#$location{$_} = $location{$_} foreach (keys %location);
442	push @stuff, \%location;
443	$i++;
444    }
445    my %foo = ("nicks" => \@stuff);
446    my $dumper = Data::Dumper->new([\%foo]);
447    $dumper->Purity(1)->Deepcopy(1);
448    my $data = $dumper->Dump;
449    return($data);
450}
451
452sub pipe_input ($$$$) {
453    my ($rh, $query, $auto, $pipetag) = @{$_[0]};
454    my @lines = <$rh>;
455    close($rh);
456    Irssi::input_remove($$pipetag);
457    my $text = join("", @lines);
458    process_input($query, $auto, $text);
459}
460
461sub process_input($$$) {
462    my ($query, $auto, $text) = @_;
463    my $channel_prefix = '^(\#|\+|\!)';
464    my %stuff;
465    $procs--;
466    no strict;
467    %stuff = %{ eval "$text" };
468    return(0) unless (%stuff);
469    my @items = @{$stuff{nicks}};
470    my %channel;
471    foreach (@items) {
472	my %location = %{$_};
473	if (not %location) {
474	    unless ($query =~ /$channel_prefix/) {
475		print CLIENTCRAP '%R>>%n Unable to localize '.$query if ($auto eq '');
476	    }
477	} else {
478	    my $nocache = Irssi::settings_get_str('localize_ipatlas_nocache');
479	    add_to_cache(%location) unless ($location{'map'} eq 'IP-Atlas' && $location{'host'} =~ /$nocache/);
480
481	    $location{$_} = $location{$_} foreach (keys %location);
482	    my $nick = $location{'nick'};
483	    if ($query =~ /$channel_prefix/) {
484		push @{ $channel{$location{"country"}}{$location{"province"}}{$location{"city"}} }, [$nick, $location{"map"}];
485	    } else {
486		if ($auto eq '') {
487		    show_location(%location);
488		} else {
489		    auto_localize($auto, %location);
490		}
491	    }
492	    #remove_request($query);
493	}
494    }
495    if ($query =~ /$channel_prefix/) {
496	show_cities($query, %channel);
497    }
498}
499
500sub add_to_cache (%) {
501    my (%location) = @_;
502    my $host = $location{'host'};
503    return if defined $cache{$host};
504    foreach (keys %location) {
505	next if ($_ eq 'nick' || $_ eq 'host');
506	$cache{$host}{$_} = $location{$_};
507    }
508}
509
510sub save_cache {
511    my $filename = Irssi::settings_get_str('localize_cache_filename');
512    my $data = Dumper(\%cache);
513    local *F;
514    open(F, '>',$filename);
515    print(F $data);
516    close(F);
517    print CLIENTCRAP "%R>>%n localize cache (".scalar(keys(%cache))." entries/".length($data)." bytes) saved to ".$filename;
518}
519
520sub load_cache {
521    no strict;
522    my $filename = Irssi::settings_get_str('localize_cache_filename');
523    my (%new_cache, $text);
524    local *F;
525    open F, "<",$filename || return;
526    $text .= $_ foreach (<F>);
527    close(F);
528    eval { %new_cache = %{ eval "$text" }; };
529    foreach (keys %new_cache) {
530	$cache{$_} = $new_cache{$_} unless defined $cache{$_};
531    }
532    print CLIENTCRAP "%R>>%n localize cache (".scalar(keys %new_cache)." hosts) loaded";
533}
534
535sub clear_cache {
536    foreach (keys(%cache)) {
537	delete $cache{$_};
538    }
539    print CLIENTCRAP "%R>>%n localize cache cleared";
540}
541
542sub show_location (%) {
543    my (%location) = @_;
544    my $query = Irssi::query_find($location{"nick"});
545    my $output = \&Irssi::print;
546    $output = sub { $query->print(@_); } if ($query);
547    my $text = "";
548    my $headline = '%R,--[%n%9%ULocation of '.$location{"nick"}." (".$location{"host"}.")%U%9%R]%n";
549    foreach ('Country', 'Province', 'City', 'Provider') {
550	my $fill = ' 'x(9-length($_));
551	$text .= '%B'.$fill.$_.':%n '.$location{lc $_}."\n" if defined $location{lc $_};
552    }
553    #$text .= $location{latitude}."/".$location{longitude};
554    &$output(draw_box('Location of '.$location{nick}.' ('.$location{host}.')', $text, $location{map}), MSGLEVEL_CLIENTCRAP);
555    show_map($location{latitude}, $location{longitude}, $location{nick}) if Irssi::settings_get_bool('localize_xplanet_show_map');
556}
557
558sub show_map ($$$) {
559    my ($lat, $long, $nick) = @_;
560    return unless defined $lat && defined $long;
561    my $cmd = Irssi::settings_get_str('localize_xplanet_cmd');
562    my $file = Irssi::settings_get_str('localize_xplanet_temp_file');
563    local *F;
564    open F, '>',$file;
565    print F $lat.'	'.$long.'	"'.$nick.'"';
566    close F;
567    system("$cmd -markerf $file &");
568}
569
570sub show_cities ($%) {
571    my ($channel, %cities) = @_;
572    print CLIENTCRAP "%R,---[%n%9%U".$channel."%U%9%R]%n";
573    foreach (sort keys %cities) {
574	print CLIENTCRAP "%R+-+[%n".$_."%R]%n";
575	print CLIENTCRAP "%R| | %n";
576	my $n_provs = scalar( keys %{$cities{$_}});
577	foreach my $province (sort keys %{$cities{$_}}) {
578	    my $cp = '|';
579	    $cp = ' ' if ($n_provs == 1);
580	    print CLIENTCRAP "%R| +-+%n"."%R[%n".$province."%R]%n";
581	    my $n_cities = scalar(keys %{$cities{$_}{$province}});
582	    foreach my $city (sort keys %{$cities{$_}{$province}}) {
583		my $cc = '|';
584		$cc = ' ' if ($n_cities == 1);
585		print CLIENTCRAP "%R| $cp +-+%n"."%R[%n".$city."%R]%n";
586		my $n_nicks = scalar(@{$cities{$_}{$province}{$city}});
587		foreach my $nick (sort @{$cities{$_}{$province}{$city}}) {
588		    my $cn = '|`';
589		    $cn = '`-' if ($n_nicks == 1);
590		    print CLIENTCRAP "%R| $cp $cc $cn-----%n%B[%n".$nick->[0]."%B]%n";
591		    $n_nicks--;
592		}
593		$n_cities--;
594	    }
595	    print CLIENTCRAP "%R| $cp ";
596	    $n_provs--;
597	}
598	#print CLIENTCRAP "%R|    ";
599    }
600    print CLIENTCRAP "%R`----->%n";
601}
602
603
604sub cmd_localize ($$$) {
605    my ($args, $server, $witem) = @_;
606    my @names = split(/ /, $args);
607    foreach (@names) {
608	if ( substr($_, 0, 1) eq '@' ) {
609	    my $ip = substr(lc($_), 1);
610	    new_request($server, $ip, 2, '');
611	    localize([[$ip, $ip]], $ip);
612	} elsif ($_ eq '-h') {
613	    show_help();
614	} elsif ($_ eq '-c') {
615	    clear_cache();
616	} elsif ($_ eq '-s') {
617	    save_cache();
618	} elsif ($_ eq '-r') {
619	    load_cache();
620	} elsif ($_ eq '-sc') {
621	    show_cache(@names);
622	    return();
623	} else {
624	    new_request($server, lc($_), 0, '');
625	}
626    }
627}
628
629sub show_cache (@) {
630    my (@params) = @_;
631    unless (defined $params[1] && $params[1] eq '-i_am_insane') {
632	my $entries = scalar(keys(%cache));
633	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';
634    } else {
635	my $text = "";
636	foreach my $key (sort keys %cache) {
637	    my %item = %{$cache{$key}};
638	    $item{$_} = $item{$_} foreach (keys %item);
639	    my $string .= $key;
640	    foreach ('country', 'province', 'city', 'map') {
641		$string .= ' | '.$item{$_};
642	    }
643	    $text .= $string."\n";
644	}
645	print CLIENTCRAP draw_box("Localize Cache", $text, "cache listing");
646    }
647}
648
649sub process_reply ($$$$) {
650    my ($server, $args, $sender, $address) = @_;
651    if ($args =~ /^(.*?) (.*?) (.*?) (.*?) (.*?) (.*?) (.*?)/) {
652	if (defined $queries{lc $6} && scalar(@{$queries{lc $6}}) > 0) {
653	    foreach (@{$queries{lc $6}}) {
654		my %query = %{$_};
655		next unless ($query{status} <2);
656		Irssi::signal_stop();
657		push @{${$_}{buffer}},[$6, $4];
658		${$_}{status} = 1;
659	    }
660	} elsif (defined $queries{lc $2} && scalar(@{$queries{lc $2}}) > 0) {
661	    foreach (@{$queries{lc $2}}) {
662		my %query = %{$_};
663		next unless ($query{status} <2);
664		Irssi::signal_stop();
665		push @{${$_}{buffer}},[$6, $4];
666		${$_}{status} = 1;
667	    }
668	}
669    } elsif ($args =~ /^(.*?) (.*?) :End of (|\/)WHO list\./) {
670	my ($self, $target) = ($1, $2);
671	return unless (defined $queries{lc $target} && scalar(@{$queries{lc $target}}) > 0);
672	my $needed = 0;
673	foreach (@{$queries{lc $target}}) {
674	    my %query = %{$_};
675	    $needed = 1 if $query{status} < 2;
676	    next unless ($query{status} == 1);
677	    if ($query{status} == 1) {
678		Irssi::signal_stop;
679		$query{status} = 2;
680		localize \@{$query{buffer}}, $target;
681		delete $query{buffer};
682		return();
683	    }
684	}
685	if ($needed) {
686	    Irssi::signal_stop;
687	    unless ($queries{lc $target}[0]{auto} ne '') {
688		print CLIENTCRAP '%R>>%n No such nick '.$target;
689	    }
690	    remove_request($target);
691	}
692    }
693}
694
695sub event_message_join ($$$$) {
696    my ($server, $channel, $nick, $address) = @_;
697    return() unless Irssi::settings_get_bool('localize_auto_localize_on_join');
698    my $maxreq = Irssi::settings_get_int('localize_auto_localize_maxrequests');
699    my $channels = Irssi::settings_get_str('localize_auto_localize_channel_list');
700    if ($channel =~ /$channels/i) {
701	$address =~ /(.*)@(.*)/;
702	my $host = $2;
703	if ($procs < $maxreq) {
704	    new_request($server, $nick, 2, lc($channel));
705	    localize([[lc($nick), $host]], lc($nick));
706	} else {
707	    #Irssi::print "%R>>%n Too many processes running";
708	}
709    }
710}
711
712sub event_query_created($$) {
713    my ($query, $auto) = @_;
714    my $nick = $query->{name};
715    my $server = $query->{server};
716    my $maxreq = Irssi::settings_get_int('localize_auto_localize_maxrequests');
717    return(0) unless (scalar(keys %queries) < $maxreq && Irssi::settings_get_bool('localize_auto_localize_on_query'));
718    $nick = substr($nick, 1) if (substr($nick, 0, 1) eq '=');
719    new_request($server, $nick, 0, lc($query->{name}));
720}
721
722sub auto_localize ($%) {
723    my ($auto, %location) = @_;
724    my $nick = lc($location{'nick'});
725    my $channel = Irssi::window_item_find($auto);
726    $channel->printformat(MSGLEVEL_CLIENTCRAP, 'auto_localize', $nick, $location{host}, $location{'city'}, $location{'province'}, $location{'country'}, $location{'map'}) if defined $channel;
727}
728
729sub new_request ($$$$) {
730    my ($server, $nick, $status, $auto) = @_;
731    return unless ref $server;
732    # 0 nothing done
733    # 1 started to fetch hosts
734    # 2 all hosts fetched
735    push(@{$queries{lc $nick}}, {status => $status, auto=>$auto});
736    $server->command('who '.lc($nick)) if $status == 0;
737}
738
739sub remove_request ($) {
740    my ($nick) = @_;
741    shift @{$queries{$nick}};
742    delete $queries{$nick} if scalar(@{$queries{$nick}}) == 0;
743}
744
745# Yes, I know tat this i huge
746sub kfz2location($) {
747    my %trans = (
748	"rklh"=> "RE",
749	"wstk"=> "Wk",
750	"essn"=> "E",
751	"stgt"=> "S",
752	"ffm" => "F",
753	"mnz" => "MZ",
754	"fra" => "F",
755	"esn" => "E",
756	"dtm" => "DO",
757	"kln" => "K",
758	"dus" => "D",
759	"mue" => "M",
760	"mnch"=> "M",
761	"brln"=> "B",
762	"hmb" => "HH",
763	"brmn"=> "HB",
764	"hmbg"=> "HH",
765	"han" => "H",
766	"kiel"=> "KI",
767	"lpz" => "L",
768	"bln" => "B",
769	"ber" => "B",
770	"mch" => "M",
771	"erf" => "EF",
772	"mdb" => "MD",
773	"nbg" => "N",
774	"hnv" => "H",
775	"dui" => "DU",
776	"mnhm" => "MA",
777	"mhm" => "MA",
778	"flf" => "FL",
779	"lwhf" => "LU",
780	"wue" => "W�",
781	"frnk" => "F",
782	"dsdf" => "D",
783	"sgt"  => "S",
784	"aug"  => "A",
785	"mch"  => "M",
786	"ddn"  => "DD",
787	"drs" => "DD",
788	"jen" => "J",
789	"che" => "C",
790	"nuremberg" => "N",
791	"weingarten" => "RV",
792	"munich" => "M",
793	"muc" => "M",
794	"goe" => "G�",
795	"obhs" => "OB",
796	"dus" => "D",
797    );
798
799    my %province = (
800	1=>'Baden-W�rttemberg',
801	2=>'Bayern',
802	3=>'Berlin',
803	4=>'Brandenburg',
804	5=>'Bremen',
805	6=>'Hamburg',
806	7=>'Hessen',
807	8=>'Mecklenburg-Vorpommern',
808	9=>'Niedersachsen',
809	10=>'Nordrhein-Westfalen',
810	11=>'Rheinland-Pfalz',
811	12=>'Saarland',
812	13=>'Sachsen',
813	14=>'Sachsen-Anhalt',
814	15=>'Th�ringen',
815	16=>'Schleswig-Holstein'
816    );
817
818    my %added = (
819	"PLA"=>{city=>"Plattling", province=>2},
820    );
821    my %de_kfz = (
822	"A"=>{city=>"Augsburg", province=>2},
823	"AA"=>{city=>"Ostalbkreis", province=>1},
824	"AB"=>{city=>"Aschaffenburg", province=>2},
825	"ABG"=>{city=>"Altenburger Land", province=>15},
826	"AC"=>{city=>"Aachen", province=>10},
827	"AE"=>{city=>"Auerbach", province=>13},
828	"AH"=>{city=>"Ahaus ", province=>10},
829	"AIB"=>{city=>"Bad Aibling", province=>2},
830	"AIC"=>{city=>"Aichach-Friedberg", province=>2},
831	"AK"=>{city=>"Altenkirchen", province=>11},
832	"AL"=>{city=>"Altena", province=>10},
833	"ALF"=>{city=>"Alfeld (Leine)", province=>9},
834	"ALS"=>{city=>"Alsfeld", province=>7},
835	"ALZ"=>{city=>"Alzenau", province=>2},
836	"AM"=>{city=>"Amberg", province=>2},
837	"AN"=>{city=>"Ansbach", province=>2},
838	"ANA"=>{city=>"Annaberg", province=>13},
839	"ANG"=>{city=>"Angerm�nde", province=>4},
840	"ANK"=>{city=>"Ostvorpommern, Anklam", province=>8},
841	"AP"=>{city=>"Weimarer-Land", province=>15},
842	"APD"=>{city=>"Weimarer Land, Apolda", province=>15},
843	"AR"=>{city=>"Arnsberg", province=>10},
844	"ARN"=>{city=>"Ilm-Kreis", province=>15},
845	"ART"=>{city=>"Artern", province=>15},
846	"AS"=>{city=>"Amberg-Sulzbach", province=>2},
847	"ASD"=>{city=>"Aschendorf-H�mmling", province=>9},
848	"ASL"=>{city=>"Aschersleben", province=>14},
849	"ASZ"=>{city=>"Aue-Schwarzenberg", province=>13},
850	"AT"=>{city=>"Altentreptow", province=>8},
851	"AU"=>{city=>"Aue", province=>13},
852	"AUR"=>{city=>"Aurich", province=>9},
853	"AW"=>{city=>"Ahrweiler", province=>11},
854	"AZ"=>{city=>"Alzey", province=>11},
855	"AZE"=>{city=>"Anhalt-Zerbst", province=>14},
856	"A�"=>{city=>"Alt�tting", province=>2},
857	"B"=>{city=>"Berlin", province=>"3"},
858	"BA"=>{city=>"Bamberg", province=>2},
859	"BAD"=>{city=>"Baden-Baden", province=>1},
860	"BAR"=>{city=>"Barnim", province=>4},
861	"BB"=>{city=>"B�blingen", province=>1},
862	"BBG"=>{city=>"Bernburg", province=>14},
863	"BC"=>{city=>"Biberach", province=>1},
864	"BCH"=>{city=>"Buchen", province=>1},
865	"BE"=>{city=>"Beckum", province=>10},
866	"BED"=>{city=>"Brand-Erbisdorf", province=>13},
867	"BEI"=>{city=>"Beilngries", province=>2},
868	"BEL"=>{city=>"Belzig", province=>4},
869	"BER"=>{city=>"Bernau", province=>4},
870	"BF"=>{city=>"Burgsteinfurt", province=>10},
871	"BGD"=>{city=>"Berchtesgaden", province=>2},
872	"BGL"=>{city=>"Berchtesgadener Land", province=>2},
873	"BH"=>{city=>"B�hl", province=>1},
874	"BI"=>{city=>"Bielefeld", province=>10},
875	"BID"=>{city=>"Biedenkopf", province=>7},
876	"BIN"=>{city=>"Bingen", province=>11},
877	"BIR"=>{city=>"Birkenfeld", province=>11},
878	"BIT"=>{city=>"Bitburg", province=>11},
879	"BIW"=>{city=>"Bischofswerda", province=>13},
880	"BK"=>{city=>"Backnang", province=>1},
881	"BKS"=>{city=>"Bernkastel", province=>11},
882	"BL"=>{city=>"Zollernalbkreis", province=>1},
883	"BLB"=>{city=>"Bad Berleburg", province=>10},
884	"BLK"=>{city=>"Burgenlandkreis", province=>14},
885	"BM"=>{city=>"Erftkreis", province=>10},
886	"BN"=>{city=>"Bonn", province=>10},
887	"BNA"=>{city=>"Borna", province=>13},
888	"BO"=>{city=>"Bochum", province=>10},
889	"BOG"=>{city=>"Bogen", province=>2},
890	"BOH"=>{city=>"Bocholt", province=>10},
891	"BOR"=>{city=>"Borken", province=>10},
892	"BOT"=>{city=>"Bottrop", province=>10},
893	"BR"=>{city=>"Bruchsal", province=>1},
894	"BRA"=>{city=>"Wesermarsch", province=>9},
895	"BRB"=>{city=>"Brandenburg", province=>4},
896	"BRG"=>{city=>"Burg", province=>14},
897	"BRI"=>{city=>"Brilon", province=>10},
898	"BRK"=>{city=>"Bad Br�ckenau", province=>2},
899	"BRL"=>{city=>"Braunlage", province=>9},
900	"BRV"=>{city=>"Bremerv�rde", province=>9},
901	"BS"=>{city=>"Braunschweig", province=>9},
902	"BSB"=>{city=>"Bersenbr�ck", province=>9},
903	"BSK"=>{city=>"Beeskow", province=>4},
904	"BT"=>{city=>"Bayreuth", province=>2},
905	"BTF"=>{city=>"Bitterfeld", province=>14},
906	"BU"=>{city=>"Burgdorf", province=>9},
907	"BUL"=>{city=>"Burglengenfeld", province=>2},
908	"BZ"=>{city=>"Bautzen", province=>13},
909	"BZA"=>{city=>"Bergzabern", province=>11},
910	"B�"=>{city=>"B�rdekreis", province=>14},
911	"B�D"=>{city=>"B�dingen", province=>7},
912	"B�R"=>{city=>"B�ren", province=>10},
913	"B�S"=>{city=>"B�singen", province=>1},
914	"B�Z"=>{city=>"B�tzow", province=>8},
915	"C"=>{city=>"Chemnitz", province=>13},
916	"CA"=>{city=>"Calau", province=>4},
917	"CAS"=>{city=>"Castrop-Rauxel", province=>10},
918	"CB"=>{city=>"Cottbus", province=>4},
919	"CE"=>{city=>"Celle", province=>9},
920	"CHA"=>{city=>"Cham", province=>2},
921	"CLP"=>{city=>"Cloppenburg", province=>9},
922	"CLZ"=>{city=>"Clausthal-Zellerfeld", province=>9},
923	"CO"=>{city=>"Coburg", province=>2},
924	"COC"=>{city=>"Cochem-Zell", province=>11},
925	"COE"=>{city=>"Coesfeld", province=>10},
926	"CR"=>{city=>"Crailsheim", province=>1},
927	"CUX"=>{city=>"Cuxhaven", province=>9},
928	"CW"=>{city=>"Calw", province=>1},
929	"D"=>{city=>"D�sseldorf", province=>10},
930	"DA"=>{city=>"Darmstadt", province=>7},
931	"DAH"=>{city=>"Dachau ", province=>2},
932	"DAN"=>{city=>"L�chow-Dannenberg", province=>9},
933	"DAU"=>{city=>"Daun", province=>11},
934	"DBR"=>{city=>"Bad Doberan", province=>8},
935	"DD"=>{city=>"Dresden", province=>13},
936	"DE"=>{city=>"Dessau", province=>14},
937	"DEG"=>{city=>"Deggendorf", province=>2},
938	"DEL"=>{city=>"Delmenhorst", province=>9},
939	"DGF"=>{city=>"Dingolfing-Landau", province=>2},
940	"DH"=>{city=>"Diepholz", province=>9},
941	"DI"=>{city=>"Dieburg", province=>7},
942	"DIL"=>{city=>"Dillenburg", province=>7},
943	"DIN"=>{city=>"Dinslaken", province=>10},
944	"DIZ"=>{city=>"Diez", province=>11},
945	"DKB"=>{city=>"Dinkelsb�hl", province=>2},
946	"DL"=>{city=>"D�beln", province=>13},
947	"DLG"=>{city=>"Dillingen a. d. Donau", province=>2},
948	"DM"=>{city=>"Demmin", province=>8},
949	"DN"=>{city=>"D�ren", province=>10},
950	"DO"=>{city=>"Dortmund", province=>10},
951	"DON"=>{city=>"Donau-Ries", province=>2},
952	"DS"=>{city=>"Donaueschingen", province=>1},
953	"DT"=>{city=>"Detmold", province=>10},
954	"DU"=>{city=>"Duisburg", province=>10},
955	"DUD"=>{city=>"Duderstadt", province=>9},
956	"DW"=>{city=>"Wei�eritzkreis", province=>13},
957	"DZ"=>{city=>"Delitzsch", province=>13},
958	"D�W"=>{city=>"Bad D�rkheim", province=>11},
959	"E"=>{city=>"Essen", province=>10},
960	"EA"=>{city=>"Eisenach, Stadt", province=>15},
961	"EB"=>{city=>"Eilenburg", province=>13},
962	"EBE"=>{city=>"Ebersberg", province=>2},
963	"EBN"=>{city=>"Ebern", province=>2},
964	"EBS"=>{city=>"Ebermannstadt", province=>2},
965	"ECK"=>{city=>"Eckernf�rde", province=>16},
966	"ED"=>{city=>"Erding", province=>2},
967	"EE"=>{city=>"Elbe-Elster", province=>4},
968	"EF"=>{city=>"Erfurt", province=>15},
969	"EG"=>{city=>"Eggenfelden", province=>2},
970	"EH"=>{city=>"Eisenh�ttenstadt", province=>4},
971	"EHI"=>{city=>"Ehingen", province=>1},
972	"EI"=>{city=>"Eichst�tt", province=>2},
973	"EIC"=>{city=>"Eichsfeld", province=>15},
974	"EIH"=>{city=>"Eichst�tt-Kreis", province=>2},
975	"EIL"=>{city=>"Eisleben", province=>14},
976	"EIN"=>{city=>"Einbeck", province=>9},
977	"EIS"=>{city=>"Saale-Holzlandkreis, Eisenberg", province=>15},
978	"EL"=>{city=>"Emsland", province=>9},
979	"EM"=>{city=>"Emmendingen", province=>1},
980	"EMD"=>{city=>"Emden", province=>9},
981	"EMS"=>{city=>"Rhein-Lahn-Kreis", province=>11},
982	"EN"=>{city=>"Ennepe-Ruhr-Kreis", province=>10},
983	"ER"=>{city=>"Erlangen", province=>2},
984	"ERB"=>{city=>"Odenwaldkreis", province=>7},
985	"ERH"=>{city=>"Erlangen-H�chstadt", province=>2},
986	"ERK"=>{city=>"Erkelenz", province=>10},
987	"ES"=>{city=>"Esslingen", province=>1},
988	"ESA"=>{city=>"Eisenach", province=>15},
989	"ESB"=>{city=>"Eschenbach i.d.Oberpfalz", province=>2},
990	"ESW"=>{city=>"Werra-Mei�ner-Kreis", province=>7},
991	"EU"=>{city=>"Euskirchen", province=>10},
992	"EUT"=>{city=>"Eutin", province=>16},
993	"EW"=>{city=>"Eberswalde", province=>4},
994	"F"=>{city=>"Frankfurt am Main", province=>7},
995	"FAL"=>{city=>"Fallingbostel", province=>9},
996	"FB"=>{city=>"Wetteraukreis", province=>7},
997	"FD"=>{city=>"Fulda", province=>7},
998	"FDB"=>{city=>"Friedberg", province=>2},
999	"FDS"=>{city=>"Freudenstadt", province=>1},
1000	"FEU"=>{city=>"Feuchtwangen", province=>2},
1001	"FF"=>{city=>"Frankfurt / Oder", province=>4},
1002	"FFB"=>{city=>"F�rstenfeldbruck", province=>2},
1003	"FG"=>{city=>"Freiberg", province=>13},
1004	"FH"=>{city=>"Frankfurt / Main-H�chst", province=>7},
1005	"FI"=>{city=>"Finsterwalde", province=>4},
1006	"FKB"=>{city=>"Frankenberg", province=>7},
1007	"FL"=>{city=>"Flensburg", province=>16},
1008	"FL�"=>{city=>"Fl�ha", province=>13},
1009	"FN"=>{city=>"Bodenseekreis", province=>1},
1010	"FO"=>{city=>"Forchheim", province=>2},
1011	"FOR"=>{city=>"Forst", province=>4},
1012	"FR"=>{city=>"Freiburg", province=>1},
1013	"FRG"=>{city=>"Freyung-Grafenau", province=>2},
1014	"FRI"=>{city=>"Friesland", province=>9},
1015	"FRW"=>{city=>"Bad Freienwalde", province=>4},
1016	"FS"=>{city=>"Freising", province=>2},
1017	"FT"=>{city=>"Frankenthal", province=>11},
1018	"FTL"=>{city=>"Freital", province=>13},
1019	"FW"=>{city=>"F�rstenwalde", province=>4},
1020	"FZ"=>{city=>"Fritzlar", province=>7},
1021	"F�"=>{city=>"F�rth", province=>2},
1022	"F�S"=>{city=>"F�ssen", province=>2},
1023	"G"=>{city=>"Gera", province=>15},
1024	"GA"=>{city=>"Gardelegen", province=>14},
1025	"GAN"=>{city=>"Bad Gandersheim", province=>9},
1026	"GAP"=>{city=>"Garmisch-Partenkirchen", province=>2},
1027	"GC"=>{city=>"Chemnitzer Land", province=>13},
1028	"GD"=>{city=>"Schw�bisch Gm�nd", province=>1},
1029	"GDB"=>{city=>"Gadebusch", province=>8},
1030	"GE"=>{city=>"Gelsenkirchen", province=>10},
1031	"GEL"=>{city=>"Geldern", province=>10},
1032	"GEM"=>{city=>"Gem�nden a.Main", province=>2},
1033	"GEO"=>{city=>"Gerolzhofen", province=>2},
1034	"GER"=>{city=>"Germersheim", province=>11},
1035	"GF"=>{city=>"Gifhorn", province=>9},
1036	"GG"=>{city=>"Gro�-Gerau", province=>7},
1037	"GHA"=>{city=>"Geithain", province=>13},
1038	"GHC"=>{city=>"Gr�fenhainichen", province=>14},
1039	"GI"=>{city=>"Gie�en", province=>7},
1040	"GK"=>{city=>"Geilenkirchen-Heinsberg", province=>10},
1041	"GL"=>{city=>"Rheinisch-Bergischer Kreis", province=>10},
1042	"GLA"=>{city=>"Gladbeck", province=>10},
1043	"GM"=>{city=>"Oberbergischer Kreis", province=>10},
1044	"GMN"=>{city=>"Grimmen", province=>8},
1045	"GN"=>{city=>"Gelnhausen", province=>7},
1046	"GNT"=>{city=>"Genthin", province=>14},
1047	"GOA"=>{city=>"St. Goar", province=>11},
1048	"GOH"=>{city=>"St. Goarshausen", province=>11},
1049	"GP"=>{city=>"G�ppingen", province=>1},
1050	"GR"=>{city=>"G�rlitz", province=>13},
1051	"GRA"=>{city=>"Grafenau", province=>2},
1052	"GRH"=>{city=>"Gro�enhain", province=>13},
1053	"GRI"=>{city=>"Griesbach i. Rottal", province=>2},
1054	"GRM"=>{city=>"Grimma", province=>13},
1055	"GRS"=>{city=>"Gransee", province=>4},
1056	"GRZ"=>{city=>"Greiz", province=>15},
1057	"GS"=>{city=>"Goslar", province=>9},
1058	"GT"=>{city=>"G�tersloh", province=>10},
1059	"GTH"=>{city=>"Gotha", province=>15},
1060	"GUB"=>{city=>"Guben", province=>4},
1061	"GUN"=>{city=>"Gunzenhausen", province=>2},
1062	"GV"=>{city=>"Grevenbroich", province=>10},
1063	"GVM"=>{city=>"Grevesm�hlen", province=>8},
1064	"GW"=>{city=>"Greifswald Land", province=>8},
1065	"GZ"=>{city=>"G�nzburg", province=>2},
1066	"G�"=>{city=>"G�ttingen", province=>9},
1067	"G�"=>{city=>"G�strow", province=>8},
1068	"H"=>{city=>"Hannover", province=>9},
1069	"HA"=>{city=>"Hagen", province=>10},
1070	"HAB"=>{city=>"Hammelburg", province=>2},
1071	"HAL"=>{city=>"Halle", province=>14},
1072	"HAM"=>{city=>"Hamm", province=>10},
1073	"HAS"=>{city=>"Ha�berge", province=>2},
1074	"HB"=>{city=>"Bremen", province=>5},
1075	"HBN"=>{city=>"Hildburghausen", province=>15},
1076	"HBS"=>{city=>"Halberstadt", province=>14},
1077	"HC"=>{city=>"Hainichen", province=>13},
1078	"HCH"=>{city=>"Hechingen", province=>1},
1079	"HD"=>{city=>"Rhein-Neckar-Kreis", province=>1},
1080	"HDH"=>{city=>"Heidenheim (Brenz)", province=>1},
1081	"HDL"=>{city=>"Haldensleben", province=>14},
1082	"HE"=>{city=>"Helmstedt", province=>9},
1083	"HEB"=>{city=>"Hersbruck", province=>2},
1084	"HEF"=>{city=>"Hersfeld-Rotenburg", province=>7},
1085	"HEI"=>{city=>"Dithmarschen", province=>16},
1086	"HER"=>{city=>"Herne", province=>10},
1087	"HET"=>{city=>"Hettstedt", province=>14},
1088	"HF"=>{city=>"Herford", province=>10},
1089	"HG"=>{city=>"Hochtaunus-Kreis", province=>7},
1090	"HGN"=>{city=>"Hagenow", province=>8},
1091	"HGW"=>{city=>"Greifswald", province=>8},
1092	"HH"=>{city=>"Hamburg", province=>6},
1093	"HHM"=>{city=>"Hohenm�lsen", province=>14},
1094	"HI"=>{city=>"Hildesheim", province=>9},
1095	"HIG"=>{city=>"Eichsfeld, Heiligenstadt", province=>15},
1096	"HIP"=>{city=>"Hilpoltstein", province=>2},
1097	"HL"=>{city=>"L�beck", province=>16},
1098	"HM"=>{city=>"Hameln-Pyrmont", province=>9},
1099	"HM�"=>{city=>"Hann. M�nden", province=>9},
1100	"HN"=>{city=>"Heilbronn", province=>1},
1101	"HO"=>{city=>"Hof", province=>2},
1102	"HOG"=>{city=>"Hofgeismar", province=>7},
1103	"HOH"=>{city=>"Hofheim i. Ufr.", province=>2},
1104	"HOL"=>{city=>"Holzminden", province=>9},
1105	"HOM"=>{city=>"Saarpfalz-Kreis", province=>12},
1106	"HOR"=>{city=>"Horb", province=>1},
1107	"HOT"=>{city=>"Hohenstein-Ernstthal", province=>13},
1108	"HP"=>{city=>"Bergstra�e", province=>7},
1109	"HR"=>{city=>"Schwalm-Eder-Kreis", province=>7},
1110	"HRO"=>{city=>"Rostock", province=>8},
1111	"HS"=>{city=>"Heinsberg", province=>10},
1112	"HSK"=>{city=>"Hochsauerland-Kreis", province=>10},
1113	"HST"=>{city=>"Stralsund", province=>8},
1114	"HU"=>{city=>"Main-Kinzig-Kreis", province=>7},
1115	"HUS"=>{city=>"Husum", province=>16},
1116	"HV"=>{city=>"Havelberg", province=>14},
1117	"HVL"=>{city=>"Havelland", province=>4},
1118	"HW"=>{city=>"Halle/Westfalen", province=>10},
1119	"HWI"=>{city=>"Wismar", province=>8},
1120	"HX"=>{city=>"H�xter", province=>10},
1121	"HY"=>{city=>"Hoyerswerda", province=>13},
1122	"HZ"=>{city=>"Herzberg", province=>4},
1123	"H�S"=>{city=>"H�chstadt a. d. Aisch", province=>2},
1124	"H�N"=>{city=>"H�nfeld", province=>7},
1125	"IGB"=>{city=>"St. Ingbert", province=>12},
1126	"IK"=>{city=>"Ilm-Kreis", province=>15},
1127	"IL"=>{city=>"Ilmenau", province=>15},
1128	"ILL"=>{city=>"Illertissen", province=>2},
1129	"IN"=>{city=>"Ingolstadt", province=>2},
1130	"IS"=>{city=>"Iserlohn", province=>10},
1131	"IZ"=>{city=>"Steinburg", province=>16},
1132	"J"=>{city=>"Jena", province=>15},
1133	"JB"=>{city=>"J�terbog", province=>4},
1134	"JE"=>{city=>"Jessen", province=>14},
1135	"JEV"=>{city=>"Jever", province=>9},
1136	"JL"=>{city=>"Jerichower Land", province=>14},
1137	"J�L"=>{city=>"J�lich", province=>10},
1138	"K"=>{city=>"K�ln", province=>10},
1139	"KA"=>{city=>"Karlsruhe", province=>1},
1140	"KAR"=>{city=>"Karlstadt", province=>2},
1141	"KB"=>{city=>"Waldeck-Frankenberg", province=>7},
1142	"KC"=>{city=>"Kronach", province=>2},
1143	"KE"=>{city=>"Kempten", province=>2},
1144	"KEH"=>{city=>"Kelheim", province=>2},
1145	"KEL"=>{city=>"Kehl", province=>1},
1146	"KEM"=>{city=>"Kemnath", province=>2},
1147	"KF"=>{city=>"Kaufbeuren", province=>2},
1148	"KG"=>{city=>"Bad Kissingen", province=>2},
1149	"KH"=>{city=>"Bad Kreuznach", province=>11},
1150	"KI"=>{city=>"Kiel", province=>16},
1151	"KIB"=>{city=>"Donnersberg-Kreis", province=>11},
1152	"KK"=>{city=>"Kempen-Krefeld", province=>10},
1153	"KL"=>{city=>"Kaiserslautern", province=>11},
1154	"KLE"=>{city=>"Kleve", province=>10},
1155	"KLZ"=>{city=>"Kl�tze", province=>14},
1156	"KM"=>{city=>"Kamenz", province=>13},
1157	"KN"=>{city=>"Konstanz", province=>1},
1158	"KO"=>{city=>"Koblenz", province=>11},
1159	"KR"=>{city=>"Krefeld", province=>10},
1160	"KRU"=>{city=>"Krumbach", province=>2},
1161	"KS"=>{city=>"Kassel", province=>7},
1162	"KT"=>{city=>"Kitzingen", province=>2},
1163	"KU"=>{city=>"Kulmbach", province=>2},
1164	"KUS"=>{city=>"Kusel", province=>11},
1165	"KW"=>{city=>"K�nigs-Wusterhausen", province=>4},
1166	"KY"=>{city=>"Kyritz", province=>4},
1167	"KYF"=>{city=>"Kyffh�userkreis", province=>15},
1168	"K�N"=>{city=>"Bad K�nigshofen i. Grabfeld", province=>2},
1169	"K�T"=>{city=>"K�then", province=>14},
1170	"K�Z"=>{city=>"K�tzting", province=>2},
1171	"K�N"=>{city=>"Hohenlohekreis", province=>1},
1172	"L"=>{city=>"Leipzig / Leipziger Land", province=>13},
1173	"LA"=>{city=>"Landshut", province=>2},
1174	"LAN"=>{city=>"Landau a.d.Isar", province=>2},
1175	"LAT"=>{city=>"Lauterbach", province=>7},
1176	"LAU"=>{city=>"N�rnberger Land", province=>2},
1177	"LB"=>{city=>"Ludwigsburg", province=>1},
1178	"LBS"=>{city=>"Lobenstein", province=>15},
1179	"LBZ"=>{city=>"L�bz", province=>8},
1180	"LC"=>{city=>"Luckau", province=>4},
1181	"LD"=>{city=>"Landau i. d. Pfalz", province=>11},
1182	"LDK"=>{city=>"Lahn-Dill-Kreis", province=>7},
1183	"LDS"=>{city=>"Dahme-Spreewald", province=>4},
1184	"LE"=>{city=>"Lemgo", province=>10},
1185	"LEO"=>{city=>"Leonberg", province=>1},
1186	"LER"=>{city=>"Leer", province=>9},
1187	"LEV"=>{city=>"Leverkusen", province=>10},
1188	"LF"=>{city=>"Laufen", province=>2},
1189	"LG"=>{city=>"L�neburg", province=>9},
1190	"LH"=>{city=>"L�dinghausen", province=>10},
1191	"LI"=>{city=>"Lindau", province=>2},
1192	"LIB"=>{city=>"Bad Liebenwerda", province=>4},
1193	"LIF"=>{city=>"Lichtenfels", province=>2},
1194	"LIN"=>{city=>"Lingen", province=>9},
1195	"LIP"=>{city=>"Lippe", province=>10},
1196	"LK"=>{city=>"L�bbecke", province=>10},
1197	"LL"=>{city=>"Landsberg am Lech", province=>2},
1198	"LM"=>{city=>"Limburg-Weilburg", province=>7},
1199	"LN"=>{city=>"L�bben", province=>4},
1200	"LOH"=>{city=>"Lohr a.Main", province=>2},
1201	"LOS"=>{city=>"Oder-Spree", province=>4},
1202	"LP"=>{city=>"Lippstadt", province=>10},
1203	"LR"=>{city=>"Lahr", province=>1},
1204	"LSZ"=>{city=>"Bad Langensalza", province=>15},
1205	"LU"=>{city=>"Ludwigshafen", province=>11},
1206	"LUK"=>{city=>"Luckenwalde", province=>4},
1207	"LWL"=>{city=>"Ludwigslust", province=>8},
1208	"L�"=>{city=>"L�rrach", province=>1},
1209	"L�B"=>{city=>"L�bau", province=>13},
1210	"L�D"=>{city=>"L�denscheid, Stadt", province=>10},
1211	"L�N"=>{city=>"L�nen", province=>10},
1212	"M"=>{city=>"M�nchen", province=>2},
1213	"MA"=>{city=>"Mannheim", province=>1},
1214	"MAB"=>{city=>"Marienberg", province=>13},
1215	"MAI"=>{city=>"Mainburg", province=>2},
1216	"MAK"=>{city=>"Marktredwitz", province=>2},
1217	"MAL"=>{city=>"Mallersdorf", province=>2},
1218	"MAR"=>{city=>"Marktheidenfeld", province=>2},
1219	"MB"=>{city=>"Miesbach", province=>2},
1220	"MC"=>{city=>"Malchin", province=>8},
1221	"MD"=>{city=>"Magdeburg", province=>14},
1222	"ME"=>{city=>"Mettmann", province=>10},
1223	"MED"=>{city=>"Meldorf /Suderdithmarschen", province=>16},
1224	"MEG"=>{city=>"Melsungen", province=>7},
1225	"MEI"=>{city=>"Mei�en", province=>13},
1226	"MEK"=>{city=>"Mittlerer Erzgebirgskreis", province=>13},
1227	"MEL"=>{city=>"Melle", province=>9},
1228	"MEP"=>{city=>"Meppen", province=>9},
1229	"MER"=>{city=>"Merseburg", province=>14},
1230	"MES"=>{city=>"Meschede", province=>10},
1231	"MET"=>{city=>"Mellrichstadt", province=>2},
1232	"MG"=>{city=>"M�nchengladbach", province=>10},
1233	"MGH"=>{city=>"Bad Mergentheim", province=>1},
1234	"MGN"=>{city=>"Meiningen", province=>15},
1235	"MH"=>{city=>"M�lheim an der Ruhr", province=>"Nordrhein-Westfalen."},
1236	"MHL"=>{city=>"Unstrut-Hainich-Kreis, M�hlhausen", province=>15},
1237	"MI"=>{city=>"Minden", province=>10},
1238	"MIL"=>{city=>"Miltenberg", province=>2},
1239	"MK"=>{city=>"M�rkischer Kreis", province=>10},
1240	"ML"=>{city=>"Mansfelder Land", province=>14},
1241	"MM"=>{city=>"Memmingen", province=>2},
1242	"MN"=>{city=>"Unterallg�u", province=>2},
1243	"MO"=>{city=>"Moers", province=>10},
1244	"MOD"=>{city=>"Marktoberdorf", province=>2},
1245	"MOL"=>{city=>"M�rkisch-Oderland", province=>4},
1246	"MON"=>{city=>"Monschau", province=>10},
1247	"MOS"=>{city=>"Neckar-Odenwald-Kreis", province=>1},
1248	"MQ"=>{city=>"Merseburg-Querfurt", province=>14},
1249	"MR"=>{city=>"Marburg-Biedenkopf", province=>7},
1250	"MS"=>{city=>"M�nster", province=>10},
1251	"MSP"=>{city=>"Main-Spessart", province=>2},
1252	"MST"=>{city=>"Mecklenburg-Strelitz", province=>8},
1253	"MT"=>{city=>"Montabaur", province=>11},
1254	"MTK"=>{city=>"Main-Taunus-Kreis", province=>7},
1255	"MTL"=>{city=>"Muldentalkreis", province=>13},
1256	"MW"=>{city=>"Mittweida", province=>13},
1257	"MY"=>{city=>"Mayen", province=>11},
1258	"MYK"=>{city=>"Mayen-Koblenz", province=>11},
1259	"MZ"=>{city=>"Mainz (-Bingen)", province=>11},
1260	"MZG"=>{city=>"Merzig-Saar", province=>12},
1261	"M�"=>{city=>"M�hldorf am Inn", province=>2},
1262	"M�B"=>{city=>"M�nchberg", province=>2},
1263	"M�L"=>{city=>"M�llheim", province=>1},
1264	"M�N"=>{city=>"M�nsingen", province=>1},
1265	"M�R"=>{city=>"M�ritz", province=>8},
1266	"N"=>{city=>"N�rnberg", province=>2},
1267	"NAB"=>{city=>"Nabburg", province=>2},
1268	"NAI"=>{city=>"Naila", province=>2},
1269	"NAU"=>{city=>"Nauen", province=>4},
1270	"NB"=>{city=>"Neubrandenburg", province=>8},
1271	"ND"=>{city=>"Neuburg-Schrobenhausen", province=>2},
1272	"NDH"=>{city=>"Nordhausen", province=>15},
1273	"NE"=>{city=>"Neuss", province=>10},
1274	"NEA"=>{city=>"Neustadt a. d. Aisch", province=>2},
1275	"NEB"=>{city=>"Nebra", province=>14},
1276	"NEC"=>{city=>"Neustadt b.Coburg", province=>2},
1277	"NEN"=>{city=>"Neunburg vorm Wald", province=>2},
1278	"NES"=>{city=>"Rh�n-Grabfeld", province=>2},
1279	"NEU"=>{city=>"Titisee-Neustadt im Schwarzwald", province=>1},
1280	"NEW"=>{city=>"Neustadt an der Waldnaab", province=>2},
1281	"NF"=>{city=>"Nordfriesland", province=>16},
1282	"NH"=>{city=>"Neuhaus am Rennweg", province=>15},
1283	"NI"=>{city=>"Nienburg", province=>9},
1284	"NIB"=>{city=>"Nieb�ll", province=>16},
1285	"NK"=>{city=>"Neunkirchen", province=>12},
1286	"NM"=>{city=>"Neumarkt", province=>2},
1287	"NMB"=>{city=>"Naumburg", province=>14},
1288	"NMS"=>{city=>"Neum�nster", province=>16},
1289	"NOH"=>{city=>"Bentheim", province=>9},
1290	"NOL"=>{city=>"Niederschlesische Oberlausitz", province=>13},
1291	"NOM"=>{city=>"Northeim", province=>9},
1292	"NOR"=>{city=>"Norden", province=>9},
1293	"NP"=>{city=>"Neuruppin", province=>4},
1294	"NR"=>{city=>"Neuwied", province=>11},
1295	"NR�"=>{city=>"Neustadt a.R�benberge", province=>9},
1296	"NT"=>{city=>"N�rtingen", province=>1},
1297	"NU"=>{city=>"Neu-Ulm", province=>2},
1298	"NVP"=>{city=>"Nordvorpommern", province=>8},
1299	"NW"=>{city=>"Neustadt a. d. Weinstra�e", province=>11},
1300	"NWM"=>{city=>"Nordwestmecklenburg", province=>8},
1301	"NY"=>{city=>"Niesky", province=>13},
1302	"NZ"=>{city=>"Neustrelitz", province=>8},
1303	"N�"=>{city=>"N�rdlingen", province=>2},
1304	"OA"=>{city=>"Oberallg�u", province=>2},
1305	"OAL"=>{city=>"Ostallg�u", province=>2},
1306	"OB"=>{city=>"Oberhausen", province=>10},
1307	"OBB"=>{city=>"Obernburg a. Main", province=>2},
1308	"OBG"=>{city=>"Osterburg", province=>14},
1309	"OC"=>{city=>"Oschersleben", province=>14},
1310	"OCH"=>{city=>"Ochsenfurt", province=>2},
1311	"OD"=>{city=>"Stormarn", province=>16},
1312	"OE"=>{city=>"Olpe", province=>10},
1313	"OF"=>{city=>"Offenbach", province=>7},
1314	"OG"=>{city=>"Ortenaukreis", province=>1},
1315	"OH"=>{city=>"Ostholstein", province=>16},
1316	"OHA"=>{city=>"Osterode am Harz", province=>9},
1317	"OHV"=>{city=>"Oberhavel", province=>4},
1318	"OHZ"=>{city=>"Osterholz-Scharmbeck", province=>9},
1319	"OK"=>{city=>"Ohre-Kreis", province=>14},
1320	"OL"=>{city=>"Oldenburg", province=>9},
1321	"OLD"=>{city=>"Oldenburg/Holstein", province=>16},
1322	"OP"=>{city=>"Opladen", province=>10},
1323	"OPR"=>{city=>"Ostprignitz-Ruppin", province=>4},
1324	"OR"=>{city=>"Oranienburg", province=>4},
1325	"OS"=>{city=>"Osnabr�ck", province=>9},
1326	"OSL"=>{city=>"Oberspreewald-Lausitz", province=>4},
1327	"OTT"=>{city=>"Otterndorf", province=>9},
1328	"OTW"=>{city=>"Ottweiler", province=>12},
1329	"OVI"=>{city=>"Oberviechtach", province=>2},
1330	"OVL"=>{city=>"Obervogtland", province=>13},
1331	"OVP"=>{city=>"Ostvorpommern", province=>8},
1332	"OZ"=>{city=>"Oschatz", province=>13},
1333	"�HR"=>{city=>"�hringen", province=>1},
1334	"P"=>{city=>"Potsdam", province=>4},
1335	"PA"=>{city=>"Passau", province=>2},
1336	"PAF"=>{city=>"Pfaffenhofen", province=>2},
1337	"PAN"=>{city=>"Rottal-Inn", province=>2},
1338	"PAR"=>{city=>"Parsberg", province=>2},
1339	"PB"=>{city=>"Paderborn", province=>10},
1340	"PCH"=>{city=>"Parchim", province=>8},
1341	"PE"=>{city=>"Peine", province=>9},
1342	"PEG"=>{city=>"Pegnitz", province=>2},
1343	"PER"=>{city=>"Perleberg", province=>4},
1344	"PF"=>{city=>"Pforzheim / Enzkreis", province=>1},
1345	"PI"=>{city=>"Pinneberg", province=>16},
1346	"PIR"=>{city=>"S�chsische Schweiz", province=>13},
1347	"PK"=>{city=>"Pritzwalk", province=>4},
1348	"PL"=>{city=>"Plauen", province=>13},
1349	"PL�"=>{city=>"Pl�n", province=>16},
1350	"PM"=>{city=>"Potsdam-Mittelmark", province=>4},
1351	"PN"=>{city=>"P��neck", province=>15},
1352	"PR"=>{city=>"Prignitz", province=>4},
1353	"PR�"=>{city=>"Pr�m", province=>11},
1354	"PS"=>{city=>"Pirmasens / S�dwestpfalz", province=>11},
1355	"PW"=>{city=>"Pasewalk", province=>8},
1356	"PZ"=>{city=>"Prenzlau", province=>4},
1357	"QFT"=>{city=>"Querfurt", province=>14},
1358	"QLB"=>{city=>"Quedlinburg", province=>14},
1359	"R"=>{city=>"Regensburg", province=>2},
1360	"RA"=>{city=>"Rastatt", province=>1},
1361	"RC"=>{city=>"Reichenbach", province=>13},
1362	"RD"=>{city=>"Rendsburg-Eckernf�rde", province=>16},
1363	"RDG"=>{city=>"Ribnitz-Damgarten", province=>8},
1364	"RE"=>{city=>"Recklinghausen", province=>10},
1365	"REG"=>{city=>"Regen", province=>2},
1366	"REH"=>{city=>"Rehau", province=>2},
1367	"REI"=>{city=>"Bad Reichenhall", province=>2},
1368	"RG"=>{city=>"Gro�enhain", province=>13},
1369	"RH"=>{city=>"Roth", province=>2},
1370	"RI"=>{city=>"Rinteln", province=>9},
1371	"RID"=>{city=>"Riedenburg", province=>2},
1372	"RIE"=>{city=>"Riesa", province=>13},
1373	"RL"=>{city=>"Rochlitz", province=>13},
1374	"RM"=>{city=>"R�bel", province=>8},
1375	"RN"=>{city=>"Rathenow", province=>4},
1376	"RO"=>{city=>"Rosenheim", province=>2},
1377	"ROD"=>{city=>"Roding", province=>2},
1378	"ROF"=>{city=>"Rotenburg/Fulda", province=>7},
1379	"ROK"=>{city=>"Rockenhausen", province=>11},
1380	"ROL"=>{city=>"Rottenburg a. d. Laaber", province=>2},
1381	"ROS"=>{city=>"Rostock-Kreis", province=>8},
1382	"ROT"=>{city=>"Rothenburg o.d.Tauber", province=>2},
1383	"ROW"=>{city=>"Rotenburg (W�mme)", province=>9},
1384	"RS"=>{city=>"Remscheid", province=>10},
1385	"RSL"=>{city=>"Ro�lau", province=>14},
1386	"RT"=>{city=>"Reutlingen", province=>1},
1387	"RU"=>{city=>"Rudolstadt", province=>15},
1388	"RV"=>{city=>"Ravensburg", province=>1},
1389	"RW"=>{city=>"Rottweil", province=>1},
1390	"RY"=>{city=>"Rheydt", province=>10},
1391	"RZ"=>{city=>"Herzogtum Lauenburg", province=>16},
1392	"R�D"=>{city=>"Rheingau-Taunus-Kreis", province=>7},
1393	"R�G"=>{city=>"R�gen", province=>8},
1394	"S"=>{city=>"Stuttgart", province=>1},
1395	"SAB"=>{city=>"Saarburg", province=>11},
1396	"SAD"=>{city=>"Schwandorf in Bayern", province=>2},
1397	"SAN"=>{city=>"Stadtsteinach", province=>2},
1398	"SAW"=>{city=>"Altmarkkreis Salzwedel", province=>14},
1399	"SB"=>{city=>"Saarbr�cken", province=>12},
1400	"SBG"=>{city=>"Strasburg", province=>8},
1401	"SBK"=>{city=>"Sch�nebeck", province=>"Sachsen Anhalt"},
1402	"SC"=>{city=>"Schwabach", province=>2},
1403	"SCZ"=>{city=>"Schleiz", province=>15},
1404	"SDH"=>{city=>"Sondershausen", province=>15},
1405	"SDL"=>{city=>"Stendal", province=>14},
1406	"SDT"=>{city=>"Schwedt", province=>4},
1407	"SE"=>{city=>"Bad Segeberg", province=>16},
1408	"SEB"=>{city=>"Sebnitz", province=>13},
1409	"SEE"=>{city=>"Seelow", province=>4},
1410	"SEF"=>{city=>"Scheinfeld", province=>2},
1411	"SEL"=>{city=>"Selb", province=>2},
1412	"SF"=>{city=>"Sonthofen", province=>2},
1413	"SFA"=>{city=>"Soltau-Fallingbostel", province=>9},
1414	"SFB"=>{city=>"Senftenberg", province=>4},
1415	"SFT"=>{city=>"Sta�furt", province=>14},
1416	"SG"=>{city=>"Solingen", province=>10},
1417	"SGH"=>{city=>"Sangerhausen", province=>14},
1418	"SHA"=>{city=>"Schw�bisch Hall", province=>1},
1419	"SHG"=>{city=>"Schaumburg", province=>9},
1420	"SHK"=>{city=>"Saale-Holzland-Kreis", province=>15},
1421	"SHL"=>{city=>"Suhl", province=>15},
1422	"SI"=>{city=>"Siegen", province=>10},
1423	"SIG"=>{city=>"Sigmaringen", province=>1},
1424	"SIM"=>{city=>"Rhein-Hunsr�ck-Kreis", province=>11},
1425	"SK"=>{city=>"Saalkreis", province=>14},
1426	"SL"=>{city=>"Schleswig-Flensburg", province=>16},
1427	"SLE"=>{city=>"Schleiden", province=>10},
1428	"SLF"=>{city=>"Saalfeld-Rudolstadt", province=>15},
1429	"SLG"=>{city=>"Saulgau", province=>1},
1430	"SLN"=>{city=>"Schm�lln", province=>15},
1431	"SLS"=>{city=>"Saarlouis", province=>12},
1432	"SLZ"=>{city=>"Bad Salzungen", province=>15},
1433	"SL�"=>{city=>"Schl�chtern", province=>7},
1434	"SM"=>{city=>"Schmalkalden-Meiningen", province=>15},
1435	"SM�"=>{city=>"Schwabm�nchen", province=>2},
1436	"SN"=>{city=>"Schwerin", province=>8},
1437	"SNH"=>{city=>"Sinsheim Elsenz", province=>1},
1438	"SO"=>{city=>"Soest", province=>10},
1439	"SOB"=>{city=>"Schrobenhausen", province=>2},
1440	"SOG"=>{city=>"Schongau", province=>2},
1441	"SOK"=>{city=>"Saale-Orla-Kreis", province=>15},
1442	"SOL"=>{city=>"Soltau", province=>9},
1443	"SON"=>{city=>"Sonneberg", province=>15},
1444	"SP"=>{city=>"Speyer", province=>11},
1445	"SPB"=>{city=>"Spremberg", province=>4},
1446	"SPN"=>{city=>"Spree-Nei�e", province=>4},
1447	"SPR"=>{city=>"Springe", province=>9},
1448	"SR"=>{city=>"Straubing (-Bogen)", province=>2},
1449	"SRB"=>{city=>"Strausberg", province=>4},
1450	"SRO"=>{city=>"Stadtroda", province=>15},
1451	"ST"=>{city=>"Steinfurt", province=>10},
1452	"STA"=>{city=>"Starnberg", province=>2},
1453	"STB"=>{city=>"Sternberg", province=>8},
1454	"STD"=>{city=>"Stade", province=>9},
1455	"STE"=>{city=>"Staffelstein", province=>2},
1456	"STH"=>{city=>"Schaumburg-Lippe", province=>9},
1457	"STL"=>{city=>"Stollberg", province=>13},
1458	"STO"=>{city=>"Stockach", province=>1},
1459	"SU"=>{city=>"Rhein-Sieg-Kreis", province=>10},
1460	"SUL"=>{city=>"Sulzbach-Rosenberg", province=>2},
1461	"SW"=>{city=>"Schweinfurt", province=>2},
1462	"SWA"=>{city=>"Bad Schwalbach", province=>7},
1463	"SY"=>{city=>"Syke", province=>9},
1464	"SZ"=>{city=>"Salzgitter", province=>9},
1465	"SZB"=>{city=>"Schwarzenberg", province=>13},
1466	"S�K"=>{city=>"S�ckingen", province=>1},
1467	"S�M"=>{city=>"S�mmerda", province=>15},
1468	"S�W"=>{city=>"S�dliche Weinstra�e", province=>11},
1469	"TBB"=>{city=>"Main-Tauber-Kreis", province=>1},
1470	"TE"=>{city=>"Tecklenburg", province=>10},
1471	"TET"=>{city=>"Teterow", province=>8},
1472	"TF"=>{city=>"Teltow-Fl�ming", province=>4},
1473	"TG"=>{city=>"Torgau", province=>13},
1474	"TIR"=>{city=>"Tirschenreuth", province=>2},
1475	"TO"=>{city=>"Torgau-Oschatz", province=>13},
1476	"TP"=>{city=>"Templin", province=>4},
1477	"TR"=>{city=>"Trier", province=>11},
1478	"TS"=>{city=>"Traunstein", province=>2},
1479	"TT"=>{city=>"Tettnang", province=>1},
1480	"TUT"=>{city=>"Tuttlingen", province=>1},
1481	"T�L"=>{city=>"Bad T�lz-Wolfratshausen", province=>2},
1482	"T�N"=>{city=>"T�nning", province=>16},
1483	"T�"=>{city=>"T�bingen", province=>1},
1484	"UE"=>{city=>"Uelzen", province=>9},
1485	"UEM"=>{city=>"Ueckerm�nde", province=>8},
1486	"UER"=>{city=>"Uecker-Randow", province=>8},
1487	"UFF"=>{city=>"Uffenheim", province=>2},
1488	"UH"=>{city=>"Unstrut-Hainich-Kreis", province=>15},
1489	"UL"=>{city=>"Ulm / Alb-Donau-Kreis", province=>1},
1490	"UM"=>{city=>"Uckermark", province=>4},
1491	"UN"=>{city=>"Unna", province=>10},
1492	"USI"=>{city=>"Usingen", province=>7},
1493	"�B"=>{city=>"�berlingen", province=>1},
1494	"V"=>{city=>"Vogtlandkreis", province=>13},
1495	"VAI"=>{city=>"Vaihingen", province=>1},
1496	"VB"=>{city=>"Vogelsbergkreis", province=>7},
1497	"VEC"=>{city=>"Vechta", province=>9},
1498	"VER"=>{city=>"Verden", province=>9},
1499	"VIB"=>{city=>"Vilsbiburg", province=>2},
1500	"VIE"=>{city=>"Viersen", province=>10},
1501	"VIT"=>{city=>"Viechtach", province=>2},
1502	"VK"=>{city=>"V�lklingen", province=>12},
1503	"VL"=>{city=>"Villingen", province=>1},
1504	"VOF"=>{city=>"Vilshofen", province=>2},
1505	"VOH"=>{city=>"Vohenstrau�", province=>2},
1506	"VS"=>{city=>"Schwarzwald-Baar-Kreis", province=>1},
1507	"W"=>{city=>"Wuppertal", province=>10},
1508	"WA"=>{city=>"Waldeck", province=>7},
1509	"WAF"=>{city=>"Warendorf", province=>10},
1510	"WAK"=>{city=>"Wartburgkreis", province=>15},
1511	"WAM"=>{city=>"Westlicher Altmark-Kreis", province=>14},
1512	"WAN"=>{city=>"Wanne-Eickel", province=>10},
1513	"WAR"=>{city=>"Warburg", province=>10},
1514	"WAT"=>{city=>"Wattenscheid", province=>10},
1515	"WB"=>{city=>"Wittenberg", province=>14},
1516	"WBS"=>{city=>"Worbis", province=>15},
1517	"WD"=>{city=>"Wiedenbr�ck", province=>10},
1518	"WDA"=>{city=>"Werdau", province=>13},
1519	"WE"=>{city=>"Weimar", province=>15},
1520	"WEB"=>{city=>"Westerburg-Westerwald", province=>11},
1521	"WEG"=>{city=>"Wegscheid", province=>2},
1522	"WEL"=>{city=>"Weilburg", province=>7},
1523	"WEM"=>{city=>"Weserm�nde", province=>9},
1524	"WEN"=>{city=>"Weiden", province=>2},
1525	"WER"=>{city=>"Wertingen", province=>2},
1526	"WES"=>{city=>"Wesel", province=>10},
1527	"WF"=>{city=>"Wolfenb�ttel", province=>9},
1528	"WG"=>{city=>"Wangen", province=>1},
1529	"WHV"=>{city=>"Wilhelmshaven", province=>9},
1530	"WI"=>{city=>"Wiesbaden", province=>7},
1531	"WIL"=>{city=>"Wittlich", province=>11},
1532	"WIS"=>{city=>"Wismar, Kreis", province=>8},
1533	"WIT"=>{city=>"Witten", province=>10},
1534	"WIZ"=>{city=>"Witzenhausen", province=>7},
1535	"WK"=>{city=>"Wittstock", province=>4},
1536	"WL"=>{city=>"Harburg", province=>9},
1537	"WLG"=>{city=>"Wolgast", province=>8},
1538	"WM"=>{city=>"Weilheim-Schongau", province=>2},
1539	"WMS"=>{city=>"Wolmirstedt", province=>14},
1540	"WN"=>{city=>"Rems-Murr-Kreis", province=>1},
1541	"WND"=>{city=>"St. Wendel", province=>12},
1542	"WO"=>{city=>"Worms", province=>11},
1543	"WOB"=>{city=>"Wolfsburg", province=>9},
1544	"WOH"=>{city=>"Wolfhagen", province=>7},
1545	"WOL"=>{city=>"Wolfach", province=>1},
1546	"WOR"=>{city=>"Wolfratshausen", province=>2},
1547	"WOS"=>{city=>"Wolfstein", province=>2},
1548	"WR"=>{city=>"Wernigerode", province=>14},
1549	"WRN"=>{city=>"Waren", province=>8},
1550	"WS"=>{city=>"Wasserburg a. Inn", province=>2},
1551	"WSF"=>{city=>"Wei�enfels", province=>14},
1552	"WST"=>{city=>"Ammerland", province=>9},
1553	"WSW"=>{city=>"Wei�wasser", province=>13},
1554	"WT"=>{city=>"Waldshut", province=>1},
1555	"WTL"=>{city=>"Wittlage", province=>9},
1556	"WTM"=>{city=>"Wittmund", province=>9},
1557	"WUG"=>{city=>"Wei�enburg-Gunzenhausen", province=>2},
1558	"WUN"=>{city=>"Wunsiedel", province=>2},
1559	"WUR"=>{city=>"Wurzen", province=>13},
1560	"WW"=>{city=>"Westerwald-Kreis", province=>11},
1561	"WZ"=>{city=>"Wetzlar", province=>7},
1562	"WZL"=>{city=>"Wanzleben", province=>14},
1563	"W�"=>{city=>"W�rzburg", province=>2},
1564	"W�M"=>{city=>"Waldm�nchen", province=>2},
1565	"Z"=>{city=>"Zwickau (-Land)", province=>13},
1566	"ZE"=>{city=>"Zerbst", province=>14},
1567	"ZEL"=>{city=>"Zell / Mosel", province=>11},
1568	"ZI"=>{city=>"L�bau-Zittau", province=>13},
1569	"ZIG"=>{city=>"Ziegenhain", province=>7},
1570	"ZP"=>{city=>"Zschopau", province=>13},
1571	"ZR"=>{city=>"Zeulenroda", province=>15},
1572	"ZS"=>{city=>"Zossen", province=>4},
1573	"ZW"=>{city=>"Zweibr�cken", province=>11},
1574	"ZZ"=>{city=>"Zeitz", province=>14}
1575    );
1576    my ($key) = @_;
1577    $key = $trans{lc $key} if defined $trans{lc $key};
1578    my %location;
1579    $key = uc($key);
1580    my %base = %de_kfz;
1581    if (defined $base{$key}) {
1582	$location{country} = 'Germany';
1583	$location{city} = $base{$key}{'city'};
1584	$location{province} = $province{$base{$key}->{province}};
1585    } else {
1586	#Irssi::print $key;
1587	foreach (keys %base) {
1588	    my $city = $base{$_}{city};
1589	    #$city = lc($city);
1590	    #$city =~ s/�/ae/g;
1591	    #$city =~ s/�/ue/g;
1592	    #$city =~ s/�/oe/g;
1593	    #$city = uc($city);
1594	    if ($city =~ /(^| |-)$key( |-|$)/i) {
1595		$location{country} = 'Germany';
1596		$location{city} = $base{$_}{city};
1597		$location{province} = $province{$base{$_}{province}};
1598	    }
1599	}
1600    }
1601    return %location;
1602}
1603
1604
1605foreach ((352, 315)) {
1606    Irssi::signal_add_first('event '.$_, 'process_reply');
1607}
1608
1609sub pre_unload { save_cache(); }
1610
1611Irssi::signal_add('message join', 'event_message_join');
1612Irssi::signal_add('query created', 'event_query_created');
1613Irssi::signal_add('setup saved', 'save_cache');
1614
1615Irssi::settings_add_bool($IRSSI{'name'}, 'localize_background', 1);
1616
1617Irssi::settings_add_str($IRSSI{'name'}, 'localize_cache_filename', Irssi::get_irssi_dir()."/localize_cache");
1618Irssi::settings_add_str($IRSSI{'name'}, 'localize_trace_cmd', "/usr/sbin/traceroute -q 1 -w 2 -I");
1619Irssi::settings_add_int($IRSSI{'name'}, 'localize_trace_distance', 3);
1620
1621Irssi::settings_add_str($IRSSI{'name'}, 'localize_auto_localize_channel_list', '.*');
1622Irssi::settings_add_bool($IRSSI{'name'}, 'localize_auto_localize_on_join', 0);
1623Irssi::settings_add_bool($IRSSI{'name'}, 'localize_auto_localize_on_query', 1);
1624Irssi::settings_add_int($IRSSI{'name'}, 'localize_auto_localize_maxrequests', 5);
1625Irssi::settings_add_bool($IRSSI{'name'}, 'localize_get_coordinates', 0);
1626Irssi::settings_add_bool($IRSSI{'name'}, 'localize_use_databases', 1);
1627Irssi::settings_add_bool($IRSSI{'name'}, 'localize_use_traceroute', 1);
1628Irssi::settings_add_bool($IRSSI{'name'}, 'localize_show_message', 1);
1629Irssi::settings_add_str($IRSSI{'name'}, 'localize_ipatlas_nocache', '.*\.dip\.t-dialin\.net');
1630
1631Irssi::settings_add_bool($IRSSI{'name'}, 'localize_xplanet_show_map', 0);
1632Irssi::settings_add_str($IRSSI{'name'}, 'localize_xplanet_temp_file', Irssi::get_irssi_dir()."/localize_xplanet_temp");
1633Irssi::settings_add_str($IRSSI{'name'}, 'localize_xplanet_cmd', "xplanet -w");
1634
1635Irssi::theme_register([
1636    auto_localize => '%B`->%n $0 ($1) has been localized in $2, $3, $4 %B[%n$5%B]%n',
1637]);
1638
1639Irssi::command_bind('localize', 'cmd_localize');
1640
1641load_cache();
1642print CLIENTCRAP '%B>>%n '.$IRSSI{name}.' '.$VERSION.' loaded: /localize -h for help';
1643