Skip to content

Instantly share code, notes, and snippets.

@Lucent
Created August 18, 2018 17:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Lucent/261228723d3d2af6e9429d84106b07a4 to your computer and use it in GitHub Desktop.
Save Lucent/261228723d3d2af6e9429d84106b07a4 to your computer and use it in GitHub Desktop.
Custom logprism for Ptable
#!/usr/bin/perl -w
#=============================================================================
#
# Copyright (C) 2005 - 2007, Matti Tukiainen, http://ktmatu.com/mt/
#
# Program name : LogPrism (logprism.pl)
# Version : 2.03
# Purpose : LogPrism turns Apache access log files (combined) into
# easy to read color highlighted format where user
# sessions, error status codes, external referrers and
# traffic from search engine spiders can be easily
# distinguished. To make log files more informative
# LogPrism can be configured to ignore log entries,
# resolve numeric IP addresses into symbolic host names
# and show the register (RIPE, ARIN, etc.) of
# unresolvable IP addresses. LogPrism supports console
# type ANSI colors and HTML.
#
# Platforms : All platforms where Perl is available should be OK. Tested
# with Solaris Perl 5.8.0 and Linux Perl 5.6.1.
# Requires Term::ANSIColor which comes with Perl 5.6 and
# later.
# Date : 2007-01-26
# Updates : 1.00 Initial release. (2005-01-26)
# 1.01 Added new IANA IP address assignments. (2005-03-31)
# 1.02 Added new IANA IP address assignments, (2005-05-09)
# AfriNIC.
# 1.03 Added new IANA IP address assignments. (2005-07-04)
# 1.04 Added new IANA IP address assignments. (2006-01-09)
# 2.00 Suppors HTML. Added all IANA IP address (2006-02-06)
# assignments. Small modification to
# parser.
# 2.01 Added new IANA IP address assignments. (2006-09-13)
# 2.02 Added new IANA IP address assignments. (2006-10-06)
# 2.03 Added new IANA IP address assignments. (2007-01-26)
#
# Author : Matti Tukiainen, http://ktmatu.com/mt/
#
# Homepage : http://ktmatu.com/software/logprism/
#
# Copying : This program may be used under the terms of GNU General
# Public License, http://www.gnu.org/copyleft/gpl.html .
#
# Usage : % perl logprism.pl -h
# % ./logprism.pl access_log -dns -sessions
# -local-url "^http://www.example.com/" | less -R
# % ./logprism.pl access_log -dns -sessions -html
# -local-url "^http://www.example.com/" -output log.html
# % tail -f access_log | ./logprism.pl -dns -sessions
# -local-url "^http://www.example.com/"
# -exclude "\.(?:ico|gif|png)$" -registry
#
#=============================================================================
use strict;
use Socket qw (AF_INET);
use Getopt::Long;
use Term::ANSIColor;
eval "use Win32::Console::ANSI;"; # Works without this on Windows also!
# Foreground colors: black, red, green, yellow, blue, magenta, cyan, white
# Background colors: on_black, on_red, on_green, on_yellow, on_blue,
# on_magenta, on_cyan
# Other attributes: clear, reset, dark, bold, underline, underscore,
# blink, reverse, concealed
#
# See also: get_html_head
my (%COLORS) = (
"ip" => {
"ansi" => "white",
"css" => "i"
},
"identd" => {
"ansi" => "red",
"css" => "n"
},
"username" => {
"ansi" => "red",
"css" => "u"
},
"date" => {
"ansi" => "blue",
"css" => "d"
},
"time" => {
"ansi" => "bold blue",
"css" => "t"
},
"time-zone" => {
"ansi" => "blue",
"css" => "z"
},
# Try entries until the regular expression matches.
"method" => [
[
'^(GET|HEAD)$',
{
"ansi" => "yellow",
"css" => "mg"
}
],
[
'^POST$',
{
"ansi" => "bold yellow",
"css" => "mp"
}
],
[
".*",
{
"ansi" => "underline yellow",
"css" => "mo"
}
],
],
"file" => {
"ansi" => "bold red",
"css" => "f"
},
"protocol" => {
"ansi" => "yellow",
"css" => "p"
},
"status" => [
[
"^2",
{
"ansi" => "blue",
"css" => "s2"
}
],
[
"^[45]",
{
"ansi" => "underline red",
"css" => "s4"
}
],
[
"^30[123]",
{
"ansi" => "underline blue",
"css" => "s3"
}
],
[
".*",
{
"ansi" => "blue",
"css" => "so"
}
]
],
"bytes" => {
"ansi" => "bold red",
"css" => "b"
},
# Use -local-url
"local-referrer" => {
"ansi" => "cyan",
"css" => "rl"
},
"referrer" => [
[
".*",
{
"ansi" => "underline cyan",
"css" => "re"
}
]
],
"client" => [
[
"(?i:" .
"Googlebot|" . # Google
"Slurp|" . # Yahoo!
"Almaden|" . # IBM
"Ask Jeeves|" . # Ask Jeeves/Teoma
"Gigabot|" . # Gigablast
"Mediapartners|" . # Google
"msnbot|" . # Microsoft
"ZyBorg|" . # WiseNut
"ichiro|" . # Goo
"geourl|" . # geourl.org
"Nutch|" . # Apache Nutch
"ia_archiver|" . # Alexa
"psbot" . # Picsearch
")",
{
"ansi" => "underline magenta",
"css" => "cr"
}
],
# Webmasterworld's A Close to perfect .htaccess ban list
[
"(?i:" .
"BlackWidow|" .
"Bot\ mailto:craftbot\@yahoo.com|" .
"ChinaClaw|" .
"DISCo|" .
"Download\ Demon|" .
"eCatch|" .
"EirGrabber|" .
"EmailSiphon|" .
"Express\ WebPictures|" .
"ExtractorPro|" .
"EyeNetIE|" .
"FlashGet|" .
"GetRight|" .
"Go!Zilla|" .
"Go-Ahead-Got-It|" .
"GrabNet|" .
"Grafula|" .
"HMView|" .
"HTTrack|" .
"Image\ Stripper|" .
"Image\ Sucker|" .
"InterGET|" .
"Internet\ Ninja|" .
"JetCar|" .
"JOC\ Web\ Spider|" .
"larbin|" .
"LeechFTP|" .
"Mass\ Downloader|" .
"MIDown\ tool|" .
"Mister\ PiX|" .
"Navroad|" .
"NearSite|" .
"NetAnts|" .
"NetSpider|" .
"Net\ Vampire|" .
"NetZIP|" .
"Octopus|" .
"Offline\ Explorer|" .
"Offline\ Navigator|" .
"PageGrabber|" .
"Papa\ Foto|" .
"pcBrowser|" .
"RealDownload|" .
"ReGet|" .
"Siphon|" .
"SiteSnagger|" .
"SmartDownload|" .
"SuperBot|" .
"SuperHTTP|" .
"Surfbot|" .
"tAkeOut|" .
"Teleport\ Pro|" .
"VoidEYE|" .
"Web\ Image\ Collector|" .
"Web\ Sucker|" .
"WebAuto|" .
"webcopier|" .
"WebFetch|" .
"WebReaper|" .
"WebSauger|" .
"Website\ eXtractor|" .
"WebStripper|" .
"WebWhacker|" .
"WebZIP|" .
"Wget|" .
"Widow|" .
"Xaldon\ WebSpider|" .
"Zeus" .
")",
{
"ansi" => "bold magenta",
"css" => "cb"
}
],
[
".*",
{
"ansi" => "magenta",
"css" => "cg"
}
]
],
"other" => {
"ansi" => "bold red",
"css" => "e"
},
# '[', ']', '"'
"[]" => {
"ansi" => "white",
"css" => "s"
}
);
# http://www.iana.org/assignments/ipv4-address-space
# 16 January 2007
my (%IP_BLOCK_REGISTRY) = (
"0" => "IANA_-_Reserved",
"1" => "IANA_-_Reserved",
"2" => "IANA_-_Reserved",
"3" => "General_Electric_Company",
"4" => "Bolt_Beranek_and_Newman_Inc.",
"5" => "IANA_-_Reserved",
"6" => "Army_Information_Systems_Center",
"7" => "IANA_-_Reserved",
"8" => "Bolt_Beranek_and_Newman_Inc.",
"9" => "IBM",
"10" => "IANA_-_Private_Use",
"11" => "DoD_Intel_Information_Systems",
"12" => "AT&T_Bell_Laboratories",
"13" => "Xerox_Corporation",
"14" => "IANA_-_Public_Data_Network",
"15" => "Hewlett-Packard_Company",
"16" => "Digital_Equipment_Corporation",
"17" => "Apple_Computer_Inc.",
"18" => "MIT",
"19" => "Ford_Motor_Company",
"20" => "Computer_Sciences_Corporation",
"21" => "DDN-RVN",
"22" => "Defense_Information_Systems_Agency",
"23" => "IANA_-_Reserved",
"24" => "ARIN_-_Cable_Block",
"25" => "UK_Ministry_of_Defense",
"26" => "Defense_Information_Systems_Agency",
"27" => "IANA_-_Reserved",
"28" => "DSI-North",
"29" => "Defense_Information_Systems_Agency",
"30" => "Defense_Information_Systems_Agency",
"31" => "IANA_-_Reserved",
"32" => "Norsk_Informasjonsteknology",
"33" => "DLA_Systems_Automation_Center",
"34" => "Halliburton_Company",
"35" => "MERIT_Computer_Network",
"36" => "IANA_-_Reserved",
"37" => "IANA_-_Reserved",
"38" => "Performance_Systems_International",
"39" => "IANA_-_Reserved",
"40" => "Eli_Lily_and_Company",
"41" => "AfriNIC",
"42" => "IANA_-_Reserved",
"43" => "Japan_Inet",
"44" => "Amateur_Radio_Digital_Communications",
"45" => "Interop_Show_Network",
"46" => "Bolt_Beranek_and_Newman_Inc.",
"47" => "Bell-Northern_Research",
"48" => "Prudential_Securities_Inc.",
"49" => "Joint_Technical_Command",
"50" => "Joint_Technical_Command",
"51" => "Deparment_of_Social_Security_of_UK",
"52" => "E.I._duPont_de_Nemours_and_Co.,_Inc.",
"53" => "Cap_Debis_CCS",
"54" => "Merck_and_Co.,_Inc.",
"55" => "Boeing_Computer_Services",
"56" => "U.S._Postal_Service",
"57" => "SITA",
"58" => "APNIC", "59" => "APNIC", "60" => "APNIC",
"61" => "APNIC", "62" => "RIPE", "63" => "ARIN", "64" => "ARIN",
"65" => "ARIN", "66" => "ARIN", "67" => "ARIN", "68" => "ARIN",
"69" => "ARIN", "70" => "ARIN", "71" => "ARIN", "72" => "ARIN",
"73" => "ARIN", "74" => "ARIN", "75" => "ARIN", "76" => "ARIN",
"77" => "RIPE", "78" => "RIPE", "79" => "RIPE", "80" => "RIPE",
"81" => "RIPE", "82" => "RIPE", "83" => "RIPE", "84" => "RIPE",
"85" => "RIPE", "86" => "RIPE", "87" => "RIPE", "88" => "RIPE",
"89" => "RIPE", "90" => "RIPE", "91" => "RIPE",
"92" => "IANA_-_Reserved",
"93" => "IANA_-_Reserved",
"94" => "IANA_-_Reserved",
"95" => "IANA_-_Reserved",
"96" => "ARIN", "97" => "ARIN", "98" => "ARIN", "99" => "ARIN",
"100" => "IANA_-_Reserved",
"101" => "IANA_-_Reserved",
"102" => "IANA_-_Reserved",
"103" => "IANA_-_Reserved",
"104" => "IANA_-_Reserved",
"105" => "IANA_-_Reserved",
"106" => "IANA_-_Reserved",
"107" => "IANA_-_Reserved",
"108" => "IANA_-_Reserved",
"109" => "IANA_-_Reserved",
"110" => "IANA_-_Reserved",
"111" => "IANA_-_Reserved",
"112" => "IANA_-_Reserved",
"113" => "IANA_-_Reserved",
"114" => "IANA_-_Reserved",
"115" => "IANA_-_Reserved",
"116" => "APNIC", "117" => "APNIC", "118" => "APNIC", "119" => "APNIC",
"120" => "APNIC", "121" => "APNIC", "122" => "APNIC", "123" => "APNIC",
"124" => "APNIC", "125" => "APNIC", "126" => "APNIC",
"127" => "IANA_-_Reserved",
"128" => "Various_Registries",
"129" => "Various_Registries",
"130" => "Various_Registries",
"131" => "Various_Registries",
"132" => "Various_Registries",
"133" => "Various_Registries",
"134" => "Various_Registries",
"135" => "Various_Registries",
"136" => "Various_Registries",
"137" => "Various_Registries",
"138" => "Various_Registries",
"139" => "Various_Registries",
"140" => "Various_Registries",
"141" => "Various_Registries",
"142" => "Various_Registries",
"143" => "Various_Registries",
"144" => "Various_Registries",
"145" => "Various_Registries",
"146" => "Various_Registries",
"147" => "Various_Registries",
"148" => "Various_Registries",
"149" => "Various_Registries",
"150" => "Various_Registries",
"151" => "Various_Registries",
"152" => "Various_Registries",
"153" => "Various_Registries",
"154" => "Various_Registries",
"155" => "Various_Registries",
"156" => "Various_Registries",
"157" => "Various_Registries",
"158" => "Various_Registries",
"159" => "Various_Registries",
"160" => "Various_Registries",
"161" => "Various_Registries",
"162" => "Various_Registries",
"163" => "Various_Registries",
"164" => "Various_Registries",
"165" => "Various_Registries",
"166" => "Various_Registries",
"167" => "Various_Registries",
"168" => "Various_Registries",
"169" => "Various_Registries",
"170" => "Various_Registries",
"171" => "Various_Registries",
"172" => "Various_Registries",
"173" => "IANA_-_Reserved",
"174" => "IANA_-_Reserved",
"175" => "IANA_-_Reserved",
"176" => "IANA_-_Reserved",
"177" => "IANA_-_Reserved",
"178" => "IANA_-_Reserved",
"179" => "IANA_-_Reserved",
"180" => "IANA_-_Reserved",
"181" => "IANA_-_Reserved",
"182" => "IANA_-_Reserved",
"183" => "IANA_-_Reserved",
"184" => "IANA_-_Reserved",
"185" => "IANA_-_Reserved",
"186" => "IANA_-_Reserved",
"187" => "IANA_-_Reserved",
"188" => "Various_Registries",
"189" => "LACNIC",
"190" => "LACNIC",
"191" => "Various_Registries",
"192" => "Various_Registries",
"193" => "RIPE",
"194" => "RIPE",
"195" => "RIPE",
"196" => "Various_Registries",
"197" => "IANA_-_Reserved",
"198" => "Various_Registries",
"199" => "ARIN", "200" => "LACNIC", "201" => "LACNIC", "202" => "APNIC",
"203" => "APNIC", "204" => "ARIN", "205" => "ARIN", "206" => "ARIN",
"207" => "ARIN", "208" => "ARIN", "209" => "ARIN", "210" => "APNIC",
"211" => "APNIC", "212" => "RIPE", "213" => "RIPE",
"214" => "US-DOD",
"215" => "US-DOD",
"216" => "ARIN",
"217" => "RIPE", "218" => "APNIC", "219" => "APNIC", "220" => "APNIC",
"221" => "APNIC", "222" => "APNIC",
"223" => "IANA_-_Reserved",
"224" => "IANA_-_Multicast",
"225" => "IANA_-_Multicast",
"226" => "IANA_-_Multicast",
"227" => "IANA_-_Multicast",
"228" => "IANA_-_Multicast",
"229" => "IANA_-_Multicast",
"230" => "IANA_-_Multicast",
"231" => "IANA_-_Multicast",
"232" => "IANA_-_Multicast",
"233" => "IANA_-_Multicast",
"234" => "IANA_-_Multicast",
"235" => "IANA_-_Multicast",
"236" => "IANA_-_Multicast",
"237" => "IANA_-_Multicast",
"238" => "IANA_-_Multicast",
"239" => "IANA_-_Multicast",
"240" => "IANA_-_Reserved",
"241" => "IANA_-_Reserved",
"242" => "IANA_-_Reserved",
"243" => "IANA_-_Reserved",
"244" => "IANA_-_Reserved",
"245" => "IANA_-_Reserved",
"246" => "IANA_-_Reserved",
"247" => "IANA_-_Reserved",
"248" => "IANA_-_Reserved",
"249" => "IANA_-_Reserved",
"250" => "IANA_-_Reserved",
"251" => "IANA_-_Reserved",
"252" => "IANA_-_Reserved",
"253" => "IANA_-_Reserved",
"254" => "IANA_-_Reserved",
"255" => "IANA_-_Reserved",
);
my ($HELP_MSG) = <<HELPMESSAGE;
LogPrism, Copyright (C) 2005-2007, Matti Tukiainen, http://ktmatu.com/mt/
Usage: $0 [-help|-dns|-sessions|-exclude <rexp>|local-url <rexp> [-logfile <file> ...|<file> ...]]
-help give this help
-dns resolve numeric IP addresses into domain names
-exclude <rexp> exclude requests to file matching <rexp>
-html create HTML output
-local-url <rexp> highlight referring URLs matching <rexp> differently
-logfile <file> Apache combined log file, glob OK (stdin if not specified)
-output <file> write log to <file> instead of stdout.
-registry show registry (e.g. ARIN) of the IP if it cannot be resolved
-sessions highlight browsing sessions
<file> Apache combined log file, glob OK (stdin if not specified)
Report bugs to http://ktmatu.com/mt/
HELPMESSAGE
sub parse_log_line {
my ($line) = shift;
my ($ok) = undef;
my ($ip, $identd, $username, $date, $time, $tz, $method, $file,
$protocol, $status, $bytes, $referer, $client, $other) = undef;
# Modified from
# groups.google.fi/groups?selm=eli%240101161337%40qz.little-neck.ny.us
if (
$line =~ m /
^
([^\s]+) # IP
\s+
(\S+) # ident check
\s+
(\S+) # auth user
\s+
\[
(\d{2}\/\w{3}\/\d{4}) # date
\:
(\d{2}\:\d{2}\:\d{2}) # time
\s+
([\+\-]\d+) # timezone
\]
\s
\"
(\w+) # GET, POST, HEAD
\s+
(\S+) # URI, URL
(?:
\s+
(HTTP\/[\d.]+) # protocol version
)?
\"
\s+
(\d{3}) # response code
\s+
(\d+|-) # bytes written
\s+
\"([^\"]*)\" # referrer
\s+
\"([^\"]*)\" # user agent
\s*
(.*) # other
/ix
) {
($ip, $identd, $username, $date, $time, $tz, $method, $file,
$protocol, $status, $bytes, $referer, $client, $other) =
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14);
$ok = 1;
};
return ($ok, $ip, $identd, $username, $date, $time, $tz, $method, $file,
$protocol, $status, $bytes, $referer, $client, $other);
};
sub number_to_domain {
my ($a, $b, $c, $d) = @_;
my ($name, $aliases, $type, $len, @addrs);
my ($addr) = pack ("C4", $a, $b, $c, $d);
($name, $aliases, $type, $len, @addrs) = gethostbyaddr ($addr, AF_INET);
return $name ? $name : join (".", ($a, $b, $c, $d));
};
sub html_ent {
my ($str) = shift;
sub encode {
my ($char) = shift;
my (%char_ent) = (
"&" => "&amp;",
"<" => "&lt;",
">" => "&gt;"
);
return $char_ent {$char};
};
$str =~ s/([\Q&><\E])/encode ($1)/ge;
return $str;
};
sub get_html_head {
my ($file_name_str) = shift;
$file_name_str = html_ent ($file_name_str);
my ($css_color_str) = "";
my (@colors) = @{get_session_colors ("css")};
my (@names) = @{get_session_colors ("cssnames")};
my ($i) = 0;
foreach my $item (@names) {
$css_color_str .= "." . $item . "{" . $colors [$i] . "}" . "\n";
$i++;
};
# See %COLORS
return <<END
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<!-- Generated by LogPrism, http://ktmatu.com/software/logprism/ -->
<!-- (c) Matti Tukiainen, http://ktmatu.com/ -->
<title>$file_name_str</title>
<meta name="robots" content="noindex,nofollow" />
<style type="text/css" media="all">
<!--
body {color: #000; background: #fff;}
/* generic container for one line */
.l {color: #000; background: #fff;}
/* ip */
.i {color: #999; background: #fff;}
/* ident, user name */
.n {color: #660099; background: #fff;}
.u {color: #990080; background: #fff;}
/* date, time, time zone */
.d {color: #1463ff; background: #fff;}
.t {color: #0047d6; background: #fff; font-weight: bold;}
.z {color: #1463ff; background: #fff;}
/* method: get, post, other */
.mg {color: #d68f00; background: #fff;}
.mp {color: #ffb114; background: #fff;}
.mo {color: #fff; background: #d68f00;}
/* file */
.f {color: #991a00; background: #fff;}
/* protocol */
.p {color: #d68f00; background: #fff;}
/* status: 2xx, 3xx, [45]xx, other */
.s2 {color: #1463ff; background: #fff;}
.s3 {color: #0047d6; background: #fff;}
.s4 {color: #fff; background: #0047d6;}
.so {color: blue; background: #fff;}
/* bytes */
.b {color: #00991a; background: #fff;}
/* referrer: local, external */
.rl {color: #0047d6; background: #fff;}
.re {color: #1463ff; background: #fff; font-weight: bold;}
/* client: good, bad, robot */
.cg {color: #809900; background: #fff;}
.cb {color: #fff; background: #00991a;}
.cr {color: #00991a; background: #fff;}
/* possible extra fields at the end */
.e {color: #660099; background: #fff;}
/* separators, ", [, etc. */
.s {color: #666; background: #fff;}
$css_color_str
-->
</style>
</head>
<body>
<pre>
END
};
sub get_html_tail {
return <<END
</pre>
</body>
</html>
END
};
sub get_session_colors {
my ($format) = shift;
my (@colors) = ();
# This is a set of colors that looks quite OK on PuTTY AND SSH Tectia AND
# new LCD display AND old CRT screen.
my (@ansi_colors) = (
"black on_green",
"black on_yellow",
"black on_cyan",
"black on_white",
"red on_green",
"red on_yellow",
"red on_cyan",
"red on_white",
"blue on_green",
"blue on_yellow",
"blue on_cyan",
"blue on_white",
"magenta on_green",
"magenta on_yellow",
"magenta on_cyan",
"magenta on_white",
"cyan on_red",
"white on_red",
"white on_blue",
"bold black on_blue",
"bold black on_white",
"bold red on_blue",
"bold red on_white",
"bold green on_red",
"bold green on_blue",
"bold green on_magenta",
"bold yellow on_red",
"bold yellow on_blue",
"bold yellow on_magenta",
"bold blue on_yellow",
"bold blue on_white",
"bold magenta on_blue",
"bold cyan on_red",
"bold white on_red",
"bold white on_green",
"bold white on_blue",
"bold white on_magenta",
);
my ($foreground_color) = "ddd";
my (@css_colors) = ();
foreach my $l ("c", "9", "f") {
foreach my $m ("c", "9", "f") {
foreach my $r ("c", "9", "f") {
my ($bacground_color) = $l . $m . $r;
#~ print ($bacground_color, "\n");
foreach my $fg ("555", "003", "360", "630") {
push (
@css_colors,
"color:#" . $fg . ";" .
"background:#" . $bacground_color . ";"
);
};
};
};
};
my (@css_color_names) = ();
my ($i) = 0;
foreach my $color (@css_colors) {
push (@css_color_names, "c" . $i);
$i++;
};
if ($format eq "ansi") {
@colors = @ansi_colors;
}
elsif ($format eq "css") {
@colors = @css_colors;
}
else {
@colors = @css_color_names;
};
return \@colors;
};
sub find_color {
my ($rules) = shift;
my ($format) = shift;
my ($str) = shift;
my ($color) = "";
foreach my $item (@{$rules}) {
# print ($str, " ", $item -> [0], "\t", $item -> [1], "\n");
my ($rexp) = $item -> [0];
if ($str =~ /$rexp/) {
$color = $item -> [1]{$format};
last;
};
};
return $color;
};
sub colorize {
my ($str) = shift;
my ($color) = shift;
my ($html) = shift;
my ($colored_str) = "";
if ($html) {
$colored_str = '<span class="' . $color . '">' .
html_ent ($str) .
"</span>";
}
else {
$colored_str = colored ($str, $color);
};
# print ("\t", $colored_str, "\n");
return $colored_str;
};
sub read_log {
my ($log_filename_str) = shift;
my ($dns) = shift;
my ($exclude_requests) = shift;
my ($local_url_str) = shift;
my ($show_sessions) = shift;
my ($show_registry) = shift;
my ($output_file) = shift;
my ($html) = shift;
my (%ip_domain) = ();
my (%session) = ();
my (%session_color) = ();
my (@session_pipe) = ();
my ($session_total) = 0;
my ($ok) = undef;
my ($ip, $identd, $username, $date, $time, $tz, $method, $file,
$protocol, $status, $bytes, $referer, $client, $other) = undef;
open (OUTPUT, ">" . $output_file) ||
die ("$0: " . "Cannot open " . $output_file . "\n");
my ($format) = "ansi";
my ($tmp_format) = $format;
if ($html) {
$format = "css";
$tmp_format = "cssnames";
#~ (print OUTPUT get_html_head (join (", ", @$log_filename_str)));
};
my (@session_colors) = @{get_session_colors ($tmp_format)};
my ($max_sessions) = scalar (@session_colors);
# shuffle colors
@session_colors = sort {rand (1) > 0.5 ? 1 : -1} @session_colors;
if ($html) {
(print OUTPUT get_html_head (join (", ", @$log_filename_str)));
};
if ($local_url_str) {
unshift (
@{$COLORS {"referrer"}}, [
$local_url_str,
$COLORS {"local-referrer"}
]
);
};
foreach my $log_file (@$log_filename_str) {
open (LOGFILE, "<" . $log_file) || die ("$0: Cannot open " .$log_file);
while (<LOGFILE>) {
my ($line) = $_;
my ($colored) = "";
# print ($line);
($ok, $ip, $identd, $username, $date, $time, $tz, $method, $file,
$protocol, $status, $bytes, $referer, $client, $other) =
parse_log_line ($line);
if ($ok) {
next if ($exclude_requests && ($file =~ /$exclude_requests/));
my ($name) = "";
my ($registry) = "";
my ($session_key) = "";
my ($session_id) = "";
if (
($dns)
&&
($ip =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/)
) {
if ($ip_domain {$ip}) {
$name = $ip_domain {$ip};
# flush cache periodically
if (scalar (keys (%ip_domain)) > 10_000) {
%ip_domain = ();
};
}
else {
$name = number_to_domain (split (/\./, $ip));
$ip_domain {$ip} = $name;
};
$ip = $name;
};
if (
($show_registry)
&&
(
($name =~ /^(\d{1,3})\.\d{1,3}\.\d{1,3}\.\d{1,3}$/)
||
($ip =~ /^(\d{1,3})\.\d{1,3}\.\d{1,3}\.\d{1,3}$/)
)
) {
$registry = $IP_BLOCK_REGISTRY {$1} || "";
};
if ($ip =~ /(\d{1,3}\.\d{1,3})\.\d{1,3}\.\d{1,3}/) {
$session_key = $1;
}
else {
my (@domain_parts) = split (/\./, $ip);
$session_key = ($domain_parts [-2] || "") .
($domain_parts [-1] || "");
};
# calc hash for user agent string
my ($short_client) = unpack ("%16C*", $client) % 65536;
$session_id = $session_key . $short_client;
$session {$session_id}++;
# print (scalar (@session_pipe), "\n");
# print ($session_total, "\t", $max_sessions, "\n");
if ($session {$session_id} == 1) {
$session_total++;
unshift (@session_pipe, $session_id);
$session_color {$session_id} =
$session_colors [$session_total % $max_sessions];
# print (join (", ", @session_pipe), "\n");
# print ($session_id, "\t", $session {$session_id}, "\n");
};
# print ($session_total % $max_sessions, " %%%\n");
if (scalar (@session_pipe) > $max_sessions) {
my ($dropped_session) = pop (@session_pipe);
delete ($session {$dropped_session});
delete ($session_color {$dropped_session});
# print ($dropped_session, "***\n");
};
my ($ses_color) = $session_color {$session_id};
my ($method_color) = find_color (
$COLORS {"method"},
$format,
$method
);
my ($status_color) = find_color (
$COLORS {"status"},
$format,
$status
);
my ($referrer_color) = find_color (
$COLORS {"referrer"},
$format,
$referer
);
my ($client_color) = find_color (
$COLORS {"client"},
$format,
$client
);
my ($ip_color) = $COLORS {"ip"}{$format};
if ($show_sessions) {
$ip_color = $session_color {$session_id};
};
my ($space) = " ";
# my ($space) = $html ? "&nbsp;" : " ";
$colored .= colorize ($ip || "", $ip_color, $html);
if ($registry) {
$colored .= colorize ("@" . $registry, $ip_color, $html);
};
$colored .= $space;
$colored .= colorize (
$identd || "",
$COLORS {"identd"}{$format},
$html
);
$colored .= $space;
$colored .= colorize (
$username || "", $COLORS {"username"}{$format},
$html
);
$colored .= $space;
$colored .= colorize ("[", $COLORS {"[]"}{$format}, $html);
$colored .= colorize (
$date || "",
$COLORS {"date"}{$format},
$html
);
$colored .= colorize (":", $COLORS {"[]"}{$format}, $html);
$colored .= colorize (
$time || "",
$COLORS {"time"}{$format},
$html
);
$colored .= $space;
$colored .= colorize (
$tz || "",
$COLORS {"time-zone"}{$format},
$html
);
$colored .= colorize ("]", $COLORS {"[]"}{$format}, $html);
$colored .= $space;
$colored .= colorize ('"', $COLORS {"[]"}{$format}, $html);
$colored .= colorize ($method || "", $method_color, $html);
$colored .= $space;
$colored .= colorize (
$file || "",
$COLORS {"file"}{$format},
$html
);
$colored .= $space;
$colored .= colorize (
$protocol || "",
$COLORS {"protocol"}{$format},
$html
);
$colored .= colorize ('"', $COLORS {"[]"}{$format}, $html);
$colored .= $space;
$colored .= colorize ($status || "", $status_color, $html);
$colored .= $space;
$colored .= colorize (
$bytes || "",
$COLORS {"bytes"}{$format},
$html
);
$colored .= $space;
$colored .= colorize ('"', $COLORS {"[]"}{$format}, $html);
$colored .= colorize ($referer || "", $referrer_color, $html);
$colored .= colorize ('"', $COLORS {"[]"}{$format}, $html);
$colored .= $space;
$colored .= colorize ('"', $COLORS {"[]"}{$format}, $html);
$colored .= colorize ($client || "", $client_color, $html);
$colored .= colorize ('"', $COLORS {"[]"}{$format}, $html);
if ($other) {
$colored .= colorize (
$other || "",
$COLORS {"other"}{$format},
$html
);
};
if ($html) {
$colored = '<span class="l">' . $colored . "</span>";
};
(print OUTPUT $colored, "\n");
}
else {
(print OUTPUT $line);
};
};
close (LOGFILE);
};
if ($html) {
(print OUTPUT get_html_tail ());
};
close (OUTPUT);
};
my ($help) = "";
my ($dns) = 0;
my ($exclude_str) = "";
my ($local_url_str) = "";
my ($output_file) = "-";
my ($registry) = 0;
my ($sessions) = 0;
my ($html) = 0;
my (@log_file_list) = ();
my ($ok) = GetOptions (
'help!' => \$help,
'dns!' => \$dns,
'exclude:s' => \$exclude_str,
'local-url:s' => \$local_url_str,
'output-file:s' => \$output_file,
'registry!' => \$registry,
'sessions!' => \$sessions,
'html!' => \$html,
'logfile:s' => \@log_file_list,
);
if ($help) {
die ($HELP_MSG);
}
else {
if (scalar (@ARGV) != 0) {
push (@log_file_list, @ARGV);
}
elsif (scalar (@log_file_list) == 0) {
push (@log_file_list, "-");
};
read_log (
\@log_file_list,
$dns,
$exclude_str,
$local_url_str,
$sessions,
$registry,
$output_file,
$html
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment