2
#-----------------------------------------------------------------------------
3
# GeoIp Maxmind AWStats plugin
4
# This plugin allow you to get AWStats country report with countries detected
5
# from a Geographical database (GeoIP internal database) instead of domain
7
#-----------------------------------------------------------------------------
8
# Perl Required Modules: Geo::IP (Geo::IP::PurePerl is not yet supported)
9
#-----------------------------------------------------------------------------
10
# $Revision: 1.8 $ - $Author: eldy $ - $Date: 2005/01/15 01:07:29 $
14
# ENTER HERE THE USE COMMAND FOR ALL REQUIRED PERL MODULES
15
if (!eval ('require "Geo/IP.pm";')) {
16
return $@?"Error: $@":"Error: Need Perl module Geo::IP (Geo::IP::PurePerl is not yet supported)";
19
use strict;no strict "refs";
23
#-----------------------------------------------------------------------------
25
#-----------------------------------------------------------------------------
27
# ENTER HERE THE MINIMUM AWSTATS VERSION REQUIRED BY YOUR PLUGIN
28
# AND THE NAME OF ALL FUNCTIONS THE PLUGIN MANAGE.
29
my $PluginNeedAWStatsVersion="6.2";
30
my $PluginHooksFunctions="AddHTMLMenuLink AddHTMLGraph ShowInfoHost SectionInitHashArray SectionProcessIp SectionProcessHostname SectionReadHistory SectionWriteHistory";
34
# IF YOUR PLUGIN NEED GLOBAL VARIABLES, THEY MUST BE DECLARED HERE.
48
my %countrylib=('ca'=>'Canadian Regions','us'=>'US regions');
51
'BC',"British Columbia",
58
'PE',"Prince Edward Island",
61
'NT',"Northwest Territories",
62
'YT',"Yukon Territory"
65
'AA',"Armed Forces Americas",
66
'AE',"Armed Forces Europe, Middle East, & Canada",
69
'AP',"Armed Forces Pacific",
71
'AS',"American Samoa",
76
'DC',"District of Columbia",
79
'FM',"Federated States of Micronesia",
93
'MH',"Marshall Islands",
97
'MP',"Northern Mariana Islands",
100
'NC',"North Carolina",
103
'NH',"New Hampshire",
115
'SC',"South Carolina",
121
'VI',"Virgin Islands",
124
'WV',"West Virginia",
135
#-----------------------------------------------------------------------------
136
# PLUGIN FUNCTION: Init_pluginname
137
#-----------------------------------------------------------------------------
138
sub Init_geoip_city_maxmind {
139
my $InitParams=shift;
140
my $checkversion=&Check_Plugin_Version($PluginNeedAWStatsVersion);
141
$MAXNBOFSECTIONGIR=10;
144
# ENTER HERE CODE TO DO INIT PLUGIN ACTIONS
145
debug(" Plugin geoip_city_maxmind: InitParams=$InitParams",1);
146
# if ($UpdateStats) {
147
my ($mode,$datafile)=split(/\s+/,$InitParams,2);
148
if (! $datafile) { $datafile="GeoIPCity.dat"; }
149
if ($mode eq '' || $mode eq 'GEOIP_MEMORY_CACHE') { $mode=Geo::IP::GEOIP_MEMORY_CACHE(); }
150
else { $mode=Geo::IP::GEOIP_STANDARD(); }
151
debug(" Plugin geoip_city_maxmind: GeoIP initialized in mode $mode",1);
152
$geoip_city_maxmind = Geo::IP->open($datafile, $mode);
156
return ($checkversion?$checkversion:"$PluginHooksFunctions");
160
#-----------------------------------------------------------------------------
161
# PLUGIN FUNCTION: AddHTMLMenuLink_pluginname
162
# UNIQUE: NO (Several plugins using this function can be loaded)
163
#-----------------------------------------------------------------------------
164
sub AddHTMLMenuLink_geoip_city_maxmind {
170
if ($Debug) { debug(" Plugin geoip_city_maxmind: AddHTMLMenuLink"); }
171
if ($categ eq 'who') {
172
$menu->{'plugin_geoip_city_maxmind'}=2.2; # Pos
173
$menulink->{'plugin_geoip_city_maxmind'}=2; # Type of link
174
$menutext->{'plugin_geoip_city_maxmind'}="Cities"; # Text
181
#-----------------------------------------------------------------------------
182
# PLUGIN FUNCTION: AddHTMLGraph_pluginname
183
# UNIQUE: NO (Several plugins using this function can be loaded)
184
#-----------------------------------------------------------------------------
185
sub AddHTMLGraph_geoip_city_maxmind {
193
my $total_p; my $total_h; my $total_k;
194
my $rest_p; my $rest_h; my $rest_k;
196
if ($Debug) { debug(" Plugin geoip_city_maxmind: AddHTMLGraph $categ $menu $menulink $menutext"); }
198
&tab_head("$title",19,0,'cities');
199
print "<tr bgcolor=\"#$color_TableBGRowTitle\"><th colspan=\"2\">Cities : ".((scalar keys %_city_h)-($_city_h{'unknown'}?1:0))."</th>";
200
if ($ShowCities =~ /P/i) { print "<th bgcolor=\"#$color_p\" width=\"80\">$Message[56]</th>"; }
201
if ($ShowCities =~ /P/i) { print "<th bgcolor=\"#$color_p\" width=\"80\">$Message[15]</th>"; }
202
if ($ShowCities =~ /H/i) { print "<th bgcolor=\"#$color_h\" width=\"80\">$Message[57]</th>"; }
203
if ($ShowCities =~ /H/i) { print "<th bgcolor=\"#$color_h\" width=\"80\">$Message[15]</th>"; }
204
if ($ShowCities =~ /B/i) { print "<th bgcolor=\"#$color_k\" width=\"80\">$Message[75]</th>"; }
205
if ($ShowCities =~ /L/i) { print "<th width=\"120\">$Message[9]</th>"; }
207
$total_p=$total_h=$total_k=0;
209
&BuildKeyList($MaxRowsInHTMLOutput,$MinHit{'Cities'},\%_city_h,\%_city_h);
211
# my @countrylist=('ca','us');
212
# foreach my $country (@countrylist) {
214
# print "<td class=\"aws\"><b>".$countrylib{$country}."</b></td>";
215
# if ($ShowCities =~ /P/i) { print "<td> </td>"; }
216
# if ($ShowCities =~ /P/i) { print "<td> </td>"; }
217
# if ($ShowCities =~ /H/i) { print "<td> </td>"; }
218
# if ($ShowCities =~ /H/i) { print "<td> </td>"; }
219
# if ($ShowCities =~ /B/i) { print "<td> </td>"; }
220
# if ($ShowCities =~ /L/i) { print "<td> </td>"; }
222
foreach my $key (@keylist) {
223
if ($key eq 'unknown') { next; }
224
my ($countrycode,$city)=split('_',$key,2);
226
# if ($countrycode ne $country) { next; }
228
if ($TotalPages) { $p_p=int($_city_p{$key}/$TotalPages*1000)/10; }
229
if ($TotalHits) { $p_h=int($_city_h{$key}/$TotalHits*1000)/10; }
231
print "<td class=\"aws\">".$DomainsHashIDLib{$countrycode}."</td>";
232
print "<td class=\"aws\">".ucfirst($city)."</td>";
233
if ($ShowCities =~ /P/i) { print "<td>".($_city_p{$key}?$_city_p{$key}:" ")."</td>"; }
234
if ($ShowCities =~ /P/i) { print "<td>".($_city_p{$key}?"$p_p %":' ')."</td>"; }
235
if ($ShowCities =~ /H/i) { print "<td>".($_city_h{$key}?$_city_h{$key}:" ")."</td>"; }
236
if ($ShowCities =~ /H/i) { print "<td>".($_city_h{$key}?"$p_h %":' ')."</td>"; }
237
if ($ShowCities =~ /B/i) { print "<td>".Format_Bytes($_city_k{$key})."</td>"; }
238
if ($ShowCities =~ /L/i) { print "<td>".($_city_p{$key}?Format_Date($_city_l{$key},1):'-')."</td>"; }
240
$total_p += $_city_p{$key}||0;
241
$total_h += $_city_h{$key};
242
$total_k += $_city_k{$key}||0;
246
if ($Debug) { debug("Total real / shown : $TotalPages / $total_p - $TotalHits / $total_h - $TotalBytes / $total_h",2); }
248
$rest_h=$TotalHits-$total_h;
250
if ($rest_p > 0 || $rest_h > 0 || $rest_k > 0) { # All other cities
252
# print "<td class=\"aws\"> </td>";
253
# if ($ShowCities =~ /P/i) { print "<td> </td>"; }
254
# if ($ShowCities =~ /P/i) { print "<td> </td>"; }
255
# if ($ShowCities =~ /H/i) { print "<td> </td>"; }
256
# if ($ShowCities =~ /H/i) { print "<td> </td>"; }
257
# if ($ShowCities =~ /B/i) { print "<td> </td>"; }
258
# if ($ShowCities =~ /L/i) { print "<td> </td>"; }
262
if ($TotalPages) { $p_p=int($rest_p/$TotalPages*1000)/10; }
263
if ($TotalHits) { $p_h=int($rest_h/$TotalHits*1000)/10; }
265
print "<td class=\"aws\" colspan=\"2\"><span style=\"color: #$color_other\">$Message[2]/$Message[0]</span></td>";
266
if ($ShowCities =~ /P/i) { print "<td>".($rest_p?$rest_p:" ")."</td>"; }
267
if ($ShowCities =~ /P/i) { print "<td>".($rest_p?"$p_p %":' ')."</td>"; }
268
if ($ShowCities =~ /H/i) { print "<td>".($rest_h?$rest_h:" ")."</td>"; }
269
if ($ShowCities =~ /H/i) { print "<td>".($rest_h?"$p_h %":' ')."</td>"; }
270
if ($ShowCities =~ /B/i) { print "<td>".Format_Bytes($rest_k)."</td>"; }
271
if ($ShowCities =~ /L/i) { print "<td> </td>"; }
281
#-----------------------------------------------------------------------------
282
# PLUGIN FUNCTION: ShowInfoHost_pluginname
283
# UNIQUE: NO (Several plugins using this function can be loaded)
284
# Function called to add additionnal columns to the Hosts report.
285
# This function is called when building rows of the report (One call for each
286
# row). So it allows you to add a column in report, for example with code :
287
# print "<TD>This is a new cell for $param</TD>";
288
# Parameters: Host name or ip
289
#-----------------------------------------------------------------------------
290
sub ShowInfoHost_geoip_city_maxmind {
293
if ($param eq '__title__') {
294
my $NewLinkParams=${QueryString};
295
$NewLinkParams =~ s/(^|&)update(=\w*|$)//i;
296
$NewLinkParams =~ s/(^|&)output(=\w*|$)//i;
297
$NewLinkParams =~ s/(^|&)staticlinks(=\w*|$)//i;
298
$NewLinkParams =~ s/(^|&)framename=[^&]*//i;
299
my $NewLinkTarget='';
300
if ($DetailedReportsOnNewWindows) { $NewLinkTarget=" target=\"awstatsbis\""; }
301
if (($FrameName eq 'mainleft' || $FrameName eq 'mainright') && $DetailedReportsOnNewWindows < 2) {
302
$NewLinkParams.="&framename=mainright";
303
$NewLinkTarget=" target=\"mainright\"";
305
$NewLinkParams =~ tr/&/&/s; $NewLinkParams =~ s/^&//; $NewLinkParams =~ s/&$//;
306
if ($NewLinkParams) { $NewLinkParams="${NewLinkParams}&"; }
308
print "<th width=\"80\">";
309
print "<a href=\"".($ENV{'GATEWAY_INTERFACE'} || !$StaticLinks?XMLEncode("$AWScript?${NewLinkParams}output=plugin_geoip_city_maxmind"):"$PROG$StaticLinks.plugin_geoip_city_maxmind.$StaticExt")."\"$NewLinkTarget>GeoIP<br>City</a>";
315
if ($param =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) { # IPv4 address
319
elsif ($param =~ /^[0-9A-F]*:/i) { # IPv6 address
324
if ($key && $ip==4) {
326
$record=$geoip_city_maxmind->record_by_addr($param) if $geoip_city_maxmind;
327
if ($Debug) { debug(" Plugin geoip_city_maxmind: GetCityByIp for $param: [$record]",5); }
329
$city=$record->city if $record;
330
if ($city) { print "$city"; }
331
else { print "<span style=\"color: #$color_other\">$Message[0]</span>"; }
333
if ($key && $ip==6) {
334
print "<span style=\"color: #$color_other\">$Message[0]</span>";
338
$record=$geoip_city_maxmind->record_by_name($param) if $geoip_city_maxmind;
339
if ($Debug) { debug(" Plugin geoip_city_maxmind: GetCityByHostname for $param: [$record]",5); }
341
$city=$record->city if $record;
342
if ($city) { print "$city"; }
343
else { print "<span style=\"color: #$color_other\">$Message[0]</span>"; }
348
print "<td> </td>";
355
#-----------------------------------------------------------------------------
356
# PLUGIN FUNCTION: SectionInitHashArray_pluginname
357
# UNIQUE: NO (Several plugins using this function can be loaded)
358
#-----------------------------------------------------------------------------
359
sub SectionInitHashArray_geoip_city_maxmind {
362
if ($Debug) { debug(" Plugin geoip_city_maxmind: Init_HashArray"); }
363
%_city_p = %_city_h = %_city_k = %_city_l =();
369
#-----------------------------------------------------------------------------
370
# PLUGIN FUNCTION: SectionProcessIP_pluginname
371
# UNIQUE: NO (Several plugins using this function can be loaded)
372
#-----------------------------------------------------------------------------
373
sub SectionProcessIp_geoip_city_maxmind {
374
my $param="$_[0]"; # Param must be an IP
377
$record=$geoip_city_maxmind->record_by_addr($param) if $geoip_city_maxmind;
378
if ($Debug) { debug(" Plugin geoip_city_maxmind: GetCityByIp for $param: [$record]",5); }
379
my $city=$record->city;
380
# if ($PageBool) { $_city_p{$city}++; }
382
my $countrycity=lc(($record->country_code)."_".$city);
383
$countrycity=~tr/ /_/;
384
$_city_h{$countrycity}++;
386
$_city_h{'unknown'}++;
388
# if ($timerecord > $_city_l{$city}) { $_city_l{$city}=$timerecord; }
394
#-----------------------------------------------------------------------------
395
# PLUGIN FUNCTION: SectionProcessHostname_pluginname
396
# UNIQUE: NO (Several plugins using this function can be loaded)
397
#-----------------------------------------------------------------------------
398
sub SectionProcessHostname_geoip_city_maxmind {
399
my $param="$_[0]"; # Param must be an IP
402
$record=$geoip_city_maxmind->record_by_name($param) if $geoip_city_maxmind;
403
if ($Debug) { debug(" Plugin geoip_city_maxmind: GetCityByName for $param: [$record]",5); }
404
my $city=$record->city;
405
# if ($PageBool) { $_city_p{$city}++; }
407
my $countrycity=lc(($record->country_code)."_".$city);
408
$countrycity=~tr/ /_/;
409
$_city_h{$countrycity}++;
411
$_city_h{'unknown'}++;
413
# if ($timerecord > $_city_l{$city}) { $_city_l{$city}=$timerecord; }
419
#-----------------------------------------------------------------------------
420
# PLUGIN FUNCTION: SectionReadHistory_pluginname
421
# UNIQUE: NO (Several plugins using this function can be loaded)
422
#-----------------------------------------------------------------------------
423
sub SectionReadHistory_geoip_city_maxmind {
424
my $issectiontoload=shift;
427
my $countlines=shift;
429
if ($Debug) { debug(" Plugin geoip_city_maxmind: Begin of PLUGIN_geoip_city_maxmind section"); }
431
my $count=0;my $countloaded=0;
435
if ($issectiontoload) {
437
if ($field[2]) { $_city_h{$field[0]}+=$field[2]; }
442
@field=split(/\s+/,($xmlold?CleanFromTags($_):$_));
445
until ($field[0] eq 'END_PLUGIN_geoip_city_maxmind' || $field[0] eq "${xmleb}END_PLUGIN_geoip_city_maxmind" || ! $_);
446
if ($field[0] ne 'END_PLUGIN_geoip_city_maxmind' && $field[0] ne "${xmleb}END_PLUGIN_geoip_city_maxmind") { error("History file is corrupted (End of section PLUGIN not found).\nRestore a recent backup of this file (data for this month will be restored to backup date), remove it (data for month will be lost), or remove the corrupted section in file (data for at least this section will be lost).","","",1); }
447
if ($Debug) { debug(" Plugin geoip_city_maxmind: End of PLUGIN_geoip_city_maxmind section ($count entries, $countloaded loaded)"); }
452
#-----------------------------------------------------------------------------
453
# PLUGIN FUNCTION: SectionWriteHistory_pluginname
454
# UNIQUE: NO (Several plugins using this function can be loaded)
455
#-----------------------------------------------------------------------------
456
sub SectionWriteHistory_geoip_city_maxmind {
457
my ($xml,$xmlbb,$xmlbs,$xmlbe,$xmlrb,$xmlrs,$xmlre,$xmleb,$xmlee)=(shift,shift,shift,shift,shift,shift,shift,shift,shift);
458
if ($Debug) { debug(" Plugin geoip_city_maxmind: SectionWriteHistory_geoip_city_maxmind start - ".(scalar keys %_city_h)); }
460
print HISTORYTMP "\n";
461
if ($xml) { print HISTORYTMP "<section id='plugin_geoip_city_maxmind'><sortfor>$MAXNBOFSECTIONGIR</sortfor><comment>\n"; }
462
print HISTORYTMP "# Plugin key - Pages - Hits - Bandwidth - Last access\n";
463
#print HISTORYTMP "# The $MaxNbOfExtra[$extranum] first number of hits are first\n";
464
$ValueInFile{'plugin_geoip_city_maxmind'}=tell HISTORYTMP;
465
print HISTORYTMP "${xmlbb}BEGIN_PLUGIN_geoip_city_maxmind${xmlbs}".(scalar keys %_city_h)."${xmlbe}\n";
466
&BuildKeyList($MAXNBOFSECTIONGIR,1,\%_city_h,\%_city_h);
467
my %keysinkeylist=();
469
$keysinkeylist{$_}=1;
470
#my $page=$_city_p{$_}||0;
471
#my $bytes=$_city_k{$_}||0;
472
#my $lastaccess=$_city_l{$_}||'';
473
print HISTORYTMP "${xmlrb}$_${xmlrs}0${xmlrs}", $_city_h{$_}, "${xmlrs}0${xmlrs}0${xmlre}\n"; next;
475
foreach (keys %_city_h) {
476
if ($keysinkeylist{$_}) { next; }
477
#my $page=$_city_p{$_}||0;
478
#my $bytes=$_city_k{$_}||0;
479
#my $lastaccess=$_city_l{$_}||'';
480
print HISTORYTMP "${xmlrb}$_${xmlrs}0${xmlrs}", $_city_h{$_}, "${xmlrs}0${xmlrs}0${xmlre}\n"; next;
482
print HISTORYTMP "${xmleb}END_PLUGIN_geoip_city_maxmind${xmlee}\n";
489
1; # Do not remove this line