#!/usr/bin/perl -w use strict; use NetServer::Generic; use Proc::Daemon; my $listen_port = 8080; my $logfile = '/tmp/proxy_log'; my $pageview_range = 20; # seconds my $per_page_time = 2; # minutes my $server_cb = sub { my ($s) = shift ; my $line1 = ; unless($line1 =~ m[(\w+)\s+http://([^/:]+)(:(\d+))?(\S*)\s+(\S+)]) { print STDOUT "HTTP/1.0 400 Bad Request\nConnection: close\n\n"; print STDOUT "HTTP/1.0 400 Bad Request\n"; return; } my ($method, $serv, $port, $path, $version) = ($1, $2, $4, $5, $6); if($serv !~ /stats/) { my $sock = IO::Socket::INET->new(PeerAddr => $serv, PeerPort => $port || 80, Proto => 'tcp'); print $sock "$method $path $version\n"; print $sock "Connection: close\n"; $SIG{CHLD} = 'IGNORE'; if(my $pid = fork) { while() { print $sock $_; } } else { while(<$sock>){ print STDOUT $_; } } } else { my $stats = &getStats(); print STDOUT "HTTP/1.1 200 OK\nContent-type: text/plain\n"; print STDOUT "Connection: close\n\n"; print STDOUT "Your Browsing Stats!\n\n"; print STDOUT "$stats->{DAY} page views in the last day\n"; print STDOUT "$stats->{WEEK} page views in the last week\n"; print STDOUT "$stats->{MONTH} page views in the last month\n"; print STDOUT "$stats->{YEAR} page views in the last year\n\n"; my $avg_time = ($stats->{MONTH} / 30) * $per_page_time; print STDOUT "At $per_page_time minutes per page that's $avg_time minutes per day in the last month.\n\n"; print STDOUT "Your favorite sites:\n\n"; foreach(map {$_->[0]} sort{$b->[1] <=> $a->[1]} map{[$_, $stats->{BY_SERVER}{$_}{TOTAL}]} (keys %{$stats->{BY_SERVER}})) { print STDOUT "$_\n"; print STDOUT "--------------------------------------------\n"; print STDOUT $stats->{BY_SERVER}{$_}{DAY} || 0, " page views in the last day\n"; print STDOUT $stats->{BY_SERVER}{$_}{WEEK} || 0, " page views in the last week\n"; print STDOUT $stats->{BY_SERVER}{$_}{MONTH} || 0, " page views in the last month\n"; print STDOUT $stats->{BY_SERVER}{$_}{YEAR} || 0, " page views in the last year\n\n"; } } open LOG, ">>$logfile" or die "could not open $logfile"; print LOG $serv, ' ', time, "\n"; close LOG; }; my ($foo) = new NetServer::Generic; $foo->port($listen_port); $foo->callback($server_cb); $foo->mode('forking'); print "Starting server\n"; &Proc::Daemon::Init(); $foo->run(); sub getStats { my $day_ago = time - 60 * 60 * 24; my $week_ago = time - 60 * 60 * 24 * 7; my $month_ago = time - 60 * 60 * 24 * 7 * 30; my $year_ago = time - 60 * 60 * 24 * 7 * 30 * 12; my($serv, $time, %hits); open LOG, "$logfile" or die "could not open $logfile"; while() { ($serv, $time) = split; if($time - $hits{BY_SERVER}{$serv}{LAST} > $pageview_range) { $hits{BY_SERVER}{$serv}{HITS}{$time} = 1; $hits{BY_SERVER}{$serv}{LAST} = $time; $hits{BY_SERVER}{$serv}{TOTAL}++; if($day_ago < $time) { $hits{BY_SERVER}{$serv}{DAY}++; $hits{BY_SERVER}{$serv}{WEEK}++; $hits{BY_SERVER}{$serv}{MONTH}++; $hits{BY_SERVER}{$serv}{YEAR}++; $hits{DAY}++; $hits{WEEK}++; $hits{MONTH}++; $hits{YEAR}++; } elsif ($week_ago < $time) { $hits{BY_SERVER}{$serv}{WEEK}++; $hits{BY_SERVER}{$serv}{MONTH}++; $hits{BY_SERVER}{$serv}{YEAR}++; $hits{WEEK}++; $hits{MONTH}++; $hits{YEAR}++; } elsif ($month_ago < $time) { $hits{BY_SERVER}{$serv}{MONTH}++; $hits{BY_SERVER}{$serv}{YEAR}++; $hits{MONTH}++; $hits{YEAR}++; } elsif ($year_ago < $time) { $hits{BY_SERVER}{$serv}{YEAR}++; $hits{YEAR}++; } } } close LOG; \%hits; }