diff options
author | Joachim Tingvold <joachim@tingvold.com> | 2014-04-06 03:11:04 +0200 |
---|---|---|
committer | Joachim Tingvold <joachim@tingvold.com> | 2014-04-06 03:11:04 +0200 |
commit | 2a0c0a3dbbdf7fa5040953c0b0d88ad6f62c011e (patch) | |
tree | 92c7cbf54272466b46f64e5dc8d1ddb429858836 /web | |
parent | fe0be5960aac1f9bb600dbf853d862a9f4e60de8 (diff) |
Initial commit. Source; TG13-goodiebag.
Diffstat (limited to 'web')
68 files changed, 5625 insertions, 0 deletions
diff --git a/web/etc/apache2/nms-public.tg13.gathering.org b/web/etc/apache2/nms-public.tg13.gathering.org new file mode 100644 index 0000000..2c6115a --- /dev/null +++ b/web/etc/apache2/nms-public.tg13.gathering.org @@ -0,0 +1,11 @@ +<VirtualHost *:80> + ServerAdmin drift@gathering.org + ServerName nms-public.tg13.gathering.org + + DocumentRoot /srv/www/nms-public.tg13.gathering.org + AddHandler cgi-script .cgi .sh .pl .py + + LogLevel warn + ErrorLog /var/log/apache2/error-nms-public.tg13.gathering.org.log + CustomLog /var/log/apache2/access-nms-public.tg13.gathering.org.log combined +</VirtualHost> diff --git a/web/etc/apache2/nms.tg13.gathering.org b/web/etc/apache2/nms.tg13.gathering.org new file mode 100644 index 0000000..cb81598 --- /dev/null +++ b/web/etc/apache2/nms.tg13.gathering.org @@ -0,0 +1,39 @@ +<VirtualHost *:80> + ServerAdmin drift@gathering.org + ServerName nms.tg13.gathering.org + ServerAlias flexus.tg13.gathering.org + + DocumentRoot /root/tgmanage/web/nms.gathering.org + <Directory "/root/tgmanage/web/nms.gathering.org"> + AllowOverride None + Options Indexes FollowSymLinks ExecCGI MultiViews + Order allow,deny + Satisfy any + Allow from ::1 + Allow from 127.0.0.1 + Allow from 151.216.125.0/24 + Allow from 151.216.124.0/24 + Allow from 2a02:ed02:124::/64 + Allow from 2a02:ed02:125::/64 + + AddHandler cgi-script .cgi .sh .pl .py + AddDefaultCharset UTF-8 + + AuthUserFile /root/tgmanage/web/.htpasswd + AuthGroupFile /dev/null + AuthName "Tech:Server Secret Volcano Lair" + AuthType Basic + + require valid-user + </Directory> + + ErrorLog /var/log/apache2/error-nms.tg13.gathering.org.log + + # Possible values include: debug, info, notice, warn, error, crit, + # alert, emerg. + LogLevel warn + + CustomLog /var/log/apache2/access-nms.tg13.gathering.org.log combined + ServerSignature On + +</VirtualHost> diff --git a/web/etc/apache2/stream.tg13.gathering.org b/web/etc/apache2/stream.tg13.gathering.org new file mode 100644 index 0000000..b184b1c --- /dev/null +++ b/web/etc/apache2/stream.tg13.gathering.org @@ -0,0 +1,25 @@ + <VirtualHost *:80> + ServerAdmin drift@gathering.org + ServerName stream.tg13.gathering.org + ServerAlias krosus.tg13.gathering.org + + DocumentRoot /srv/stream.tg13.gathering.org + <Directory "/srv/stream.tg13.gathering.org/"> + AllowOverride None + Options Indexes FollowSymLinks ExecCGI MultiViews + Order allow,deny + Allow from all + AddHandler cgi-script .cgi .sh .pl .py + AddDefaultCharset UTF-8 + + </Directory> + + ErrorLog /var/log/apache2/error-stream.tg13.gathering.org.log + + # Possible values include: debug, info, notice, warn, error, crit, + # alert, emerg. + LogLevel info + + CustomLog /var/log/apache2/access-stream.tg13.gathering.org.log combined + ServerSignature On +</VirtualHost> diff --git a/web/etc/apache2/tech.tg13.gathering.org b/web/etc/apache2/tech.tg13.gathering.org new file mode 100644 index 0000000..7ab303b --- /dev/null +++ b/web/etc/apache2/tech.tg13.gathering.org @@ -0,0 +1,12 @@ +<VirtualHost *:80> + ServerAdmin drift@gathering.org + ServerName tech.tg13.gathering.org + + DocumentRoot /srv/www/tech.tg13.gathering.org + + LogLevel warn + ErrorLog /var/log/apache2/error-tech.tg13.gathering.org.log + CustomLog /var/log/apache2/access-tech.tg13.gathering.org.log combined + + AddHandler cgi-script .pl +</VirtualHost> diff --git a/web/etc/cron/update-public-nms b/web/etc/cron/update-public-nms new file mode 100644 index 0000000..3018042 --- /dev/null +++ b/web/etc/cron/update-public-nms @@ -0,0 +1,3 @@ +# Update public nms + +* * * * * root /root/tgmanage/clients/update-public-nms.sh diff --git a/web/nms-public.gathering.org/dhcp.html b/web/nms-public.gathering.org/dhcp.html new file mode 100644 index 0000000..332ea0a --- /dev/null +++ b/web/nms-public.gathering.org/dhcp.html @@ -0,0 +1,10 @@ +<html> +<head> +<title>NMS Public - DHCP KART - The Gathering 2013</title> +<meta http-equiv="refresh" content="5;URL='/dhcp.html'"> +</head> +<body> +<img src="nettkart-dhcp.png" alt="DHCP KART" /> +<p>Sist oppdatert: Sun, 31 Mar 2013 16:03:02 +0200 +</body> +</html> diff --git a/web/nms-public.gathering.org/dhcpkart.html b/web/nms-public.gathering.org/dhcpkart.html new file mode 100644 index 0000000..77f7ad5 --- /dev/null +++ b/web/nms-public.gathering.org/dhcpkart.html @@ -0,0 +1,10 @@ +<html> + <head> + <title>DHCP-kart</title> + <meta http-equiv="refresh" content="60"> + </head> + <body> + + <p><img src="nettkart-dhcp.png" /></p> + </body> +</html> diff --git a/web/nms-public.gathering.org/index.html b/web/nms-public.gathering.org/index.html new file mode 100644 index 0000000..1917fd3 --- /dev/null +++ b/web/nms-public.gathering.org/index.html @@ -0,0 +1,15 @@ +<html> +<head> +<title>NMS Public - The Gathering 2013</title> +</head> + +<body> + +<h1>NMS Public - The Gathering 2013</h1> + +<h2><a href="dhcp.html">DHCP-kart</a></h2> +<h2><a href="trafikk.html">Trafikk-kart</a></h2> + +</body> +</html> + diff --git a/web/nms-public.gathering.org/led.pl b/web/nms-public.gathering.org/led.pl new file mode 100644 index 0000000..12b540b --- /dev/null +++ b/web/nms-public.gathering.org/led.pl @@ -0,0 +1,128 @@ +e1-3 on +e1-4 on +e3-3 on +e3-4 on +e5-3 on +e5-4 on +e7-3 on +e7-4 on +e9-3 on +e9-4 on +e11-1 on +e11-2 on +e11-3 on +e11-4 on +e13-1 on +e13-2 on +e13-3 on +e13-4 on +e15-1 on +e15-2 on +e15-3 on +e15-4 on +e17-1 on +e17-2 on +e17-3 on +e17-4 on +e19-1 on +e19-2 on +e19-3 on +e19-4 on +e21-1 on +e21-2 on +e21-3 on +e21-4 on +e23-1 on +e23-2 on +e23-3 on +e23-4 on +e25-1 on +e25-2 on +e25-3 on +e25-4 on +e27-1 on +e27-2 on +e29-1 on +e29-2 on +e31-1 on +e31-2 on +e33-1 on +e33-2 on +e35-1 on +e35-2 on +e37-1 on +e37-2 on +e39-1 on +e39-2 on +e41-1 on +e41-2 on +e43-1 on +e43-2 on +e43-3 on +e43-4 on +e45-1 on +e45-2 on +e45-3 on +e45-4 on +e47-1 on +e47-2 on +e47-3 on +e47-4 on +e49-1 on +e49-2 on +e49-3 on +e49-4 on +e51-1 on +e51-2 on +e51-3 on +e51-4 on +e53-1 on +e53-2 on +e53-3 on +e53-4 on +e55-1 on +e55-2 on +e55-3 on +e55-4 on +e57-1 on +e57-2 on +e57-3 on +e57-4 on +e59-1 on +e59-2 on +e59-3 on +e59-4 on +e61-1 on +e61-2 on +e61-3 on +e61-4 on +e63-1 on +e63-2 on +e63-3 on +e63-4 on +e65-1 on +e65-2 on +e65-3 on +e65-4 on +e67-1 on +e67-2 on +e67-3 on +e67-4 on +e69-1 on +e69-2 on +e69-3 on +e69-4 on +e71-1 on +e71-2 on +e71-3 on +e71-4 on +e73-1 on +e73-2 on +e73-3 on +e73-4 on +e75-1 on +e75-2 on +e75-3 on +e75-4 on +e77-1 on +e77-2 on diff --git a/web/nms-public.gathering.org/led.txt b/web/nms-public.gathering.org/led.txt new file mode 100644 index 0000000..42a189c --- /dev/null +++ b/web/nms-public.gathering.org/led.txt @@ -0,0 +1,256 @@ +e65-4 off +ap-e47-2 off +ap-e15-1 off +e11-4 off +e69-1 off +ap-e13-4 off +ap-e11-3 off +e23-2 off +e41-2 off +e65-1 off +ap-e25-1 off +e21-3 off +e3-3 off +e45-1 off +ap-e59-4 off +ap-e17-3 off +ap-e69-3 off +e45-2 off +e25-2 off +ap-e61-3 off +e55-1 off +ap-e49-2 off +e5-3 off +ap-e59-2 off +e15-3 off +ap-e49-1 off +e67-4 off +e21-1 off +ap-e13-3 off +ap-e59-1 off +e27-1 off +ap-e43-4 off +ap-e37-1 off +e7-3 off +ap-e77-1 off +ap-e43-3 off +ap-e65-4 off +ap-e23-2 off +ap-e5-4 off +e1-3 off +e63-4 off +ap-e19-3 off +ap-e39-1 off +e53-2 off +e13-1 off +ap-e13-1 off +ap-e63-1 off +ap-e55-3 off +e65-2 off +ap-e73-2 off +ap-e71-4 off +ap-e77-2 off +ap-e63-4 off +e25-3 off +ap-e49-4 off +ap-e43-1 off +e63-2 off +e19-2 off +e61-4 off +ap-e53-4 off +e55-4 off +ap-e69-4 off +ap-e41-2 off +e9-4 off +e43-4 off +ap-e47-4 off +ap-e15-4 off +ap-e17-1 off +ap-e19-4 off +ap-e37-2 off +ap-e67-1 off +e19-1 off +ap-e23-1 off +ap-e29-2 off +e49-4 off +ap-e7-3 off +ap-e65-3 off +e13-3 off +e57-3 off +ap-e25-3 off +e23-3 off +e37-2 off +ap-e1-3 off +ap-e75-2 off +e47-4 off +e21-4 off +e33-1 off +ap-e69-2 off +ap-e17-2 off +ap-e73-3 off +ap-e71-3 off +ap-e25-4 off +ap-e45-3 off +e69-2 off +e13-2 off +e51-1 off +ap-e7-4 off +ap-e9-3 off +e19-4 off +e17-4 off +e61-2 off +e57-2 off +ap-e63-3 off +ap-e45-2 off +e67-1 off +ap-e27-1 off +e51-2 off +e49-2 off +ap-e19-1 off +ap-e47-1 off +e59-3 off +ap-e25-2 off +ap-e65-2 off +e21-2 off +e59-4 off +e39-2 off +ap-e3-4 off +e19-3 off +ap-e29-1 off +e13-4 off +ap-e35-1 off +ap-e75-3 off +e35-1 off +ap-e13-2 off +ap-e57-3 off +ap-e73-4 off +e71-2 off +ap-e71-1 off +ap-e75-1 off +e71-1 off +ap-e41-1 off +ap-e57-4 off +e23-1 off +e77-1 off +e69-3 off +e29-1 off +ap-e49-3 off +ap-e45-1 off +e59-1 off +e73-3 off +e53-1 off +ap-e33-2 off +ap-e47-3 off +e17-1 off +e31-1 off +e55-3 off +e17-3 off +ap-e19-2 off +ap-e61-1 off +ap-e63-2 off +ap-e21-3 off +e75-1 off +ap-e61-2 off +ap-e55-1 off +ap-e33-1 off +e53-4 off +e3-4 off +ap-e9-4 off +ap-e31-1 off +e65-3 off +e75-4 off +ap-e15-2 off +ap-e35-2 off +e51-4 off +ap-e55-4 off +e51-3 off +ap-e21-1 off +e39-1 off +e63-1 off +ap-e57-1 off +ap-e11-1 off +e43-2 off +e75-3 off +e47-1 off +e25-4 off +e71-4 off +e47-2 off +e43-3 off +ap-e15-3 off +ap-e3-3 off +ap-e75-4 off +ap-e43-2 off +e15-2 off +ap-e67-3 off +ap-e59-3 off +e27-2 off +e11-1 off +ap-e23-3 off +ap-e11-2 off +ap-e51-2 off +e55-2 off +ap-e27-2 off +ap-e53-2 off +ap-e11-4 off +e69-4 off +e33-2 off +ap-e57-2 off +e11-3 off +e57-1 off +e37-1 off +e11-2 off +e53-3 off +e67-2 off +ap-e53-3 off +e67-3 off +ap-e71-2 off +e57-4 off +e73-4 off +e73-1 off +ap-e67-2 off +e61-3 off +e29-2 off +ap-e67-4 off +e15-1 off +ap-e53-1 off +ap-e55-2 off +ap-e5-3 off +ap-e51-1 off +ap-e61-4 off +ap-e45-4 off +e35-2 off +e61-1 off +e49-1 off +e43-1 off +ap-e69-1 off +ap-e39-2 off +e45-3 off +e23-4 off +e73-2 off +ap-e23-4 off +ap-e31-2 off +e71-3 off +e15-4 off +e17-2 off +e45-4 off +e47-3 off +ap-e73-1 off +e49-3 off +e63-3 off +ap-e21-2 off +ap-e51-4 off +e7-4 off +e41-1 off +ap-e17-4 off +e1-4 off +e5-4 off +ap-e1-4 off +e59-2 off +ap-e51-3 off +ap-e21-4 off +e25-1 off +e75-2 off +e77-2 off +e31-2 off +e9-3 off +ap-e65-1 off diff --git a/web/nms-public.gathering.org/nettkart-dhcp.png b/web/nms-public.gathering.org/nettkart-dhcp.png Binary files differnew file mode 100644 index 0000000..d9232de --- /dev/null +++ b/web/nms-public.gathering.org/nettkart-dhcp.png diff --git a/web/nms-public.gathering.org/nettkart-trafikk.html b/web/nms-public.gathering.org/nettkart-trafikk.html new file mode 100644 index 0000000..5675473 --- /dev/null +++ b/web/nms-public.gathering.org/nettkart-trafikk.html @@ -0,0 +1,10 @@ +<html> + <head> + <title>nettkart</title> + <meta http-equiv="refresh" content="60"> + </head> + <body> + + <p><img src="nettkart-trafikk.png" /></p> + </body> +</html> diff --git a/web/nms-public.gathering.org/nettkart-trafikk.png b/web/nms-public.gathering.org/nettkart-trafikk.png Binary files differnew file mode 100644 index 0000000..79661fc --- /dev/null +++ b/web/nms-public.gathering.org/nettkart-trafikk.png diff --git a/web/nms-public.gathering.org/trafikk.html b/web/nms-public.gathering.org/trafikk.html new file mode 100644 index 0000000..ee417a8 --- /dev/null +++ b/web/nms-public.gathering.org/trafikk.html @@ -0,0 +1,10 @@ +<html> +<head> +<title>NMS Public - TRAFIKK KART - The Gathering 2013</title> +<meta http-equiv="refresh" content="60;URL='/trafikk.html'"> +</head> +<body> +<img src="nettkart-trafikk.png" alt="TRAFIKK KART" /> +<p>Sist oppdatert: Sun, 31 Mar 2013 16:03:02 +0200 +</body> +</html> diff --git a/web/nms.gathering.org/apkart.pl b/web/nms.gathering.org/apkart.pl new file mode 100755 index 0000000..a89cb68 --- /dev/null +++ b/web/nms.gathering.org/apkart.pl @@ -0,0 +1,89 @@ +#! /usr/bin/perl +use CGI qw(fatalsToBrowser); +use GD; +use DBI; +use lib '../../include'; +use nms; +use strict; +use warnings; +my $cgi = CGI->new; + +#my $greentimeout = 7200; +my $greentimeout = 15*60; +my $maxtimeout = $greentimeout*9; + +my $dbh = nms::db_connect(); + +GD::Image->trueColor(1); + +my $img = GD::Image->new('bg07.png'); + +my $blk = $img->colorResolve(0, 0, 0); +my $red = $img->colorResolve(255, 0, 0); +my $grn = $img->colorResolve(0, 255, 0); +my $blu = $img->colorResolve(0, 0, 255); + +# Her ska' det bættre skrivas STORT jah! +my $title = new GD::Image(75,15); +$img->alphaBlending(1); +$title->alphaBlending(1); +my $titlebg = $title->colorResolve(255, 255, 255); +$title->fill(0,0,$titlebg); +$title->transparent($titlebg); +$title->string(gdGiantFont,7,0,"APEKART",$title->colorResolve(255, 0, 0)); +$img->copyResampled($title, 500, 0, 0, 0, 400, 100, 75, 15); +$img->copyResampled($title, 500, 550, 0, 0, 400, 100, 75, 15); + +$img->string(gdMediumBoldFont,0,0,"Access points",$blk); +$img->string(gdSmallFont,0,20,"Shows if a Cisco access point is plugged into the port",$blk); + +my %palette = ( 'notpolled' => $blu, 'missing' => $red, 'present' => $grn ); + +my @states = qw(present missing notpolled); + +for my $i (0..$#states) { + my $y = 60 + 20 * (4 - $i); + $img->filledRectangle(20, $y, 30, $y + 10, $palette{$states[$i]}); + $img->rectangle(20, $y, 30, $y + 10, $blk); + $img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, $y + 10, $states[$i]); +} + +my $q = $dbh->prepare("select switch,sysname,model,last_poll < now() - '30 seconds'::interval as notpolled,placement from switches natural join placements natural join ap_poll order by zorder"); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + my $sysname = $ref->{'sysname'}; + my $model = $ref->{'model'}; + my $state; + if ($ref->{'notpolled'}) { + $state = 'notpolled'; + } elsif ($model =~ /^cisco AIR-/) { + $state = 'present'; + } else { + $state = 'missing'; + $sysname .= " $model"; + } + my $clr = $palette{$state}; + + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + $img->filledRectangle($3,$4,$1,$2,$clr); + $img->rectangle($3,$4,$1,$2,$blk); + + my ($x2, $y2, $x1, $y1) = ($1, $2, $3, $4); + my $max_textlen = ($x2-$x1) > ($y2-$y1) ? $x2-$x1 : $y2-$y1; + while (length($sysname) * 6 > $max_textlen) { + # Try to abbreviate sysname if it is too long for the box + $sysname =~ s/^(.*)[a-z]~?([0-9]+)$/$1~$2/ or last; + } + if (($x2-$x1) > ($y2-$y1)) { + $img->string(gdSmallFont,$x1+2,$y1,$sysname,$blk); + } else { + $img->stringUp(gdSmallFont,$x1,$y2-3,$sysname,$blk); + } +} +$dbh->disconnect; + +if (!defined($ARGV[0])) { + print $cgi->header(-type=>'image/png', + -refresh=>'10; ' . CGI::url()); +} +print $img->png; diff --git a/web/nms.gathering.org/bg07.png b/web/nms.gathering.org/bg07.png Binary files differnew file mode 100644 index 0000000..ec54ad3 --- /dev/null +++ b/web/nms.gathering.org/bg07.png diff --git a/web/nms.gathering.org/dhcpkart.pl b/web/nms.gathering.org/dhcpkart.pl new file mode 100755 index 0000000..2af4272 --- /dev/null +++ b/web/nms.gathering.org/dhcpkart.pl @@ -0,0 +1,94 @@ +#! /usr/bin/perl +use CGI qw(fatalsToBrowser); +use GD; +use DBI; +use lib '../../include'; +use nms; +my $cgi = CGI->new; + +#my $greentimeout = 7200; +my $greentimeout = 15*60; +my $maxtimeout = $greentimeout*9; + +my $dbh = nms::db_connect(); + +GD::Image->trueColor(1); +my $map = 'bg07.png'; +die "$map does not exist" unless -e $map; +$img = GD::Image->new($map); + +my $blk = $img->colorResolve(0, 0, 0); + +$img->string(gdMediumBoldFont,0,0,"DHCP-lease status",$blk); +$img->string(gdSmallFont,0,20,"Last received DHCP-request",$blk); + +# first 1/5: green (<30 min) +# middle 3/5: yellow -> red (30 min - 6 hours) +# last 1/5: blue (>6 hours) +my $grn = $img->colorResolve(0, 255, 0); +my $blu = $img->colorResolve(0, 0, 255); + +my $l1 = 42 + (236 - 42)/5; +my $l2 = 236 - (236 - 42)/5; + +$img->filledRectangle(32, 42, 53, $l1, $grn); +$img->string(gdSmallFont,56,$l1-8,($greentimeout/60)." min",$blk); + +$img->filledRectangle(32, $l2, 53, 237, $blu); +$img->string(gdSmallFont,56,$l2-5,($maxtimeout/60)." min",$blk); + +for my $y ($l1..$l2) { + my $i = 1.0 - ($y - $l1) / ($l2 - $l1); + my $clr = get_color($i); + + $img->filledRectangle(32,$y,53,$y+1,$clr); +} + +my $q = $dbh->prepare('select switch,sysname,placement,EXTRACT(EPOCH FROM now() - last_ack) as age from switches natural join placements natural join dhcp order by sysname'); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + my $age = $ref->{'age'}; + if (!defined($age) || $age > $maxtimeout) { + $clr = $img->colorResolve(0, 0, 255); + } elsif ($age < $greentimeout) { + $clr = $img->colorResolve(0, 255, 0); + } else { + # 30 minutes = 0.0 + # 6 hours = 1.0 + + my $intensity = log($age / $greentimeout) / log($maxtimeout/$greentimeout); + $clr = get_color(1.0 - $intensity); + } + + my $sysname = $ref->{'sysname'}; + if ($sysname !~ m/d0/i) { # don't draw distro-switches + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + $img->filledRectangle($3,$4,$1,$2,$clr); + $img->rectangle($3,$4,$1,$2,$blk); + + my ($x2, $y2, $x1, $y1) = ($1, $2, $3, $4); + my $max_textlen = ($x2-$x1) > ($y2-$y1) ? $x2-$x1 : $y2-$y1; + while (length($sysname) * 6 > $max_textlen) { + # Try to abbreviate sysname if it is too long for the box + $sysname =~ s/^(.*)[a-z]~?([0-9]+)$/$1~$2/ or last; + } + if (($x2-$x1) > ($y2-$y1)) { + $img->string(gdSmallFont,$x1+2,$y1,$sysname,$blk); + } else { + $img->stringUp(gdSmallFont,$x1,$y2-3,$sysname,$blk); + } + } +} +$dbh->disconnect; + +if (!defined($ARGV[0])) { + print $cgi->header(-type=>'image/png', + -refresh=>'10; ' . CGI::url()); +} +print $img->png; + +sub get_color { + my $intensity = shift; + my $gamma = 1.0/1.90; + return $img->colorResolve(255.0, 255.0 * ($intensity ** $gamma), 0); +} diff --git a/web/nms.gathering.org/index.html b/web/nms.gathering.org/index.html new file mode 100644 index 0000000..2857377 --- /dev/null +++ b/web/nms.gathering.org/index.html @@ -0,0 +1,92 @@ +<html> + <head> + <title>snmp</title> + </head> + <body> + <p>tg light & magic. :-)</p> + + <ul> + <li><a href="dhcpkart.pl">DHCP-kart</a> + <br /><i>Oversikt over DHCP-lease etter switch</i> + </li> + + <br /> + + <li><a href="nettkart-text.pl">Nettkart</a> + <br /><i>Trafikkoversikt</i> + </li> + + <br /> + + <li><a href="nettkart-telnet.pl">Nettkart</a> + <br /><i>Trafikkoversikt /m telnetlink</i> + </li> + + <br /> +<!-- Kun moderat nyttig når vi har disablet alle webinterfacene... + <li><a href="nettkart-web.pl">Nettkart</a> + <br /><i>Trafikkoversikt /m weblink</i> + </li> + + <br /> +--> + <li><a href="portkart.pl">Nettkart, per port</a> + <br /><i>Trafikkoversikt per port</i> + </li> + + <br /> + + <li><a href="uplinkkart.pl">Uplink-kart</a> + <br /><i>Hvilke switcher har ikke to uplinker</i> + </li> + + <br /> + + <li><a href="uplinktrafikkart.pl">Uplink-trafikkart</a> + <br /><i>Hvem burde hatt mer enn to uplinker</i> + </li> + + <br /> + + <li><a href="stromkart.pl">Strømkart</a> + <br /><i>Hvilke switcher har færre enn fem tilkoblede klienter</i> + </li> + + <br /> + + <li><a href="apkart.pl">Aksesspunkt-kart</a> + <br /><i>Hvilke aksesspunkter er plugget i</i> + </li> + + <br /> + + <!--<li><a href="overlay.pl">Overlay-nettkart</a> + <br /><i>Teh magic 3D!</i> + </li> + + <br /> --> + + <li><a href="smanagement.pl">Kommander switcher</a> + <br /><i>Konfigurer switchene</i> + </li> + + <br /> + + <li><a href="sshow.pl">Utførte og køede kommandoer</a> + <br /><i>Se og håndter kommandoer som er utført og fortsatt i køen</i> + </li> + + <br /> + + <!--<li><a href="stempmap.pl">Temperaturkart</a> + <br /><i>Temperaturkart for switchene</i> + </li> + + <br /> --> + + <li><a href="mbd-status.pl">MBD-status</a> + <br /><i>Hva spiller folk mest?</i> + </li> + </ul> + </body> +</html> diff --git a/web/nms.gathering.org/led.pl b/web/nms.gathering.org/led.pl new file mode 100755 index 0000000..a05041d --- /dev/null +++ b/web/nms.gathering.org/led.pl @@ -0,0 +1,20 @@ +#! /usr/bin/perl +use CGI; +use GD; +use DBI; +use lib '../../include'; +use nms; +my $cgi = CGI->new; + +my $dbh = nms::db_connect(); + +print $cgi->header(-type=>'text/plain', -expires=>'now'); + +my $q = $dbh->prepare('select * from ( SELECT switch,sysname,sum(bytes_in) AS bytes_in,sum(bytes_out) AS bytes_out from switches natural left join get_current_datarate() group by switch,sysname) t1 natural join placements order by zorder;'); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + my $sysname = $ref->{'sysname'}; + next unless $sysname =~ /e\d+-\d+/; + printf "%s %s\n", $sysname, (defined($ref->{'bytes_in'}) ? 'on' : 'off'); +} +$dbh->disconnect; diff --git a/web/nms.gathering.org/mbd-status.pl b/web/nms.gathering.org/mbd-status.pl new file mode 100755 index 0000000..d37781f --- /dev/null +++ b/web/nms.gathering.org/mbd-status.pl @@ -0,0 +1,44 @@ +#! /usr/bin/perl +use CGI; +use DBI; +use lib '../../include'; +use nms; +my $cgi = CGI->new; + +my $dbh = nms::db_connect(); +print $cgi->header(-type=>'text/html; charset=utf-8', -refresh=>'10; ' . CGI::url()); + +print <<"EOF"; +<html> + <head> + <title>MBD status</title> + </head> + <body> + <h1>MBD status</h1> + + <p>Spill søkt etter siste 15 minutter:</p> + + <table> + <tr> + <th>Beskrivelse</th> + <th>Aktive servere</th> + </tr> +EOF + +my $q = $dbh->prepare('select description,sum(active_servers) as active_servers from (select distinct on (game,port) * from mbd_log where ts >= now() - \'10 minutes\'::interval order by game,port,ts desc ) t1 group by description order by sum(active_servers) desc, description;'); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + print <<"EOF"; + <tr> + <td>$ref->{'description'}</td> + <td>$ref->{'active_servers'}</td> + </tr> +EOF +} +$dbh->disconnect; + +print <<"EOF"; + </table> + </body> +</html> +EOF diff --git a/web/nms.gathering.org/mygraph.pl b/web/nms.gathering.org/mygraph.pl new file mode 100755 index 0000000..64104aa --- /dev/null +++ b/web/nms.gathering.org/mygraph.pl @@ -0,0 +1,179 @@ +#! /usr/bin/perl -T +use strict; +use warnings; +use GD; +use POSIX; +use Time::Zone; + +sub blendpx { + my ($gd, $x, $y, $r, $g, $b, $frac) = @_; + my ($ro, $go, $bo) = $gd->rgb($gd->getPixel($x, $y)); + + # workaround for icky 256-color graphs + # $frac = int($frac * 32) / 32; + + my $rn = $ro * (1.0 - $frac) + $r * $frac; + my $gn = $go * (1.0 - $frac) + $g * $frac; + my $bn = $bo * (1.0 - $frac) + $b * $frac; + + $gd->setPixel($x, $y, $gd->colorResolve($rn, $gn, $bn)); +} + +# Standard implementation of Wu's antialiased line algorithm. +sub wuline { + my ($gd, $x1, $y1, $x2, $y2, $r, $g, $b, $a) = @_; + $x1 = POSIX::floor($x1); + $x2 = POSIX::floor($x2); + $y1 = POSIX::floor($y1); + $y2 = POSIX::floor($y2); + + if (abs($x2 - $x1) > abs($y2 - $y1)) { + # x-directional + if ($y2 < $y1) { + ($x2, $y2, $x1, $y1) = ($x1, $y1, $x2, $y2); + } + + my $y = POSIX::floor($y1); + my $frac = $y1 - $y; + my $dx = ($x2 > $x1) ? 1 : -1; + my $dy = ($y2 - $y1) / abs($x2 - $x1); + + for (my $x = $x1; $x != $x2 + $dx; $x += $dx) { + blendpx($gd, $x, $y, $r, $g, $b, $a * (1.0 - $frac)); + blendpx($gd, $x, $y + 1, $r, $g, $b, $a * $frac); + $frac += $dy; + if ($frac > 1) { + $frac -= 1; + ++$y; + } + } + } else { + # y-directional + if ($x2 < $x1) { + ($x2, $y2, $x1, $y1) = ($x1, $y1, $x2, $y2); + } + my $x = POSIX::floor($x1); + my $frac = $x1 - $x; + my $dy = ($y2 > $y1) ? 1 : -1; + my $dx = ($x2 - $x1) / abs($y2 - $y1); + + for (my $y = $y1; $y != $y2 + $dy; $y += $dy) { + blendpx($gd, $x, $y, $r, $g, $b, $a * (1.0 - $frac)); + blendpx($gd, $x + 1, $y, $r, $g, $b, $a * $frac); + $frac += $dx; + if ($frac > 1) { + $frac -= 1; + ++$x; + } + } + } +} + +sub makegraph { + my $xoffset = 70; + my ($width, $height, $min_x, $max_x, $min_y, $max_y, $tickgran) = @_; + + # Create our base graph + my $graph = new GD::Image($width, $height, 1); + my $white = $graph->colorAllocate(255, 255, 255); + my $gray = $graph->colorAllocate(230, 230, 255); + my $black = $graph->colorAllocate(0, 0, 0); + +# $graph->fill(0, 0, $white); + $graph->filledRectangle(0, 0, $width, $height, $white); # seems to work better + + $::xs = ($width - ($xoffset+2)) / ($max_x - $min_x); + $::ys = ($height - 33) / ($min_y - $max_y); + + # Hour marks + for my $i ($xoffset+1..$width-2) { + if (((($i-($xoffset+1)) / $::xs + $min_x) / 3600) % 2 == 1) { + $graph->line($i, 0, $i, $height - 1, $gray); + } + } + + # Hour text + for my $i (0..23) { + my @bounds = GD::Image::stringFT(undef, $black, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 0, 0, $i); + my $w = $bounds[2] - $bounds[0]; + + # Determine where the center of this will be + my $starthour = POSIX::fmod(($min_x + Time::Zone::tz_local_offset()) / 3600, 24); + my $diff = POSIX::fmod($i - $starthour + 24, 24); + + my $center = ($diff * 3600 + 1800) * $::xs; + + next if ($center - $w / 2 < 1 || $center + $w / 2 > $width - ($xoffset+2)); + $graph->stringFT($black, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, $xoffset + $center - $w / 2, $height - 6, $i); + } + + # + # Y lines; we want max 11 of them (zero-line, plus five on each side, or + # whatever) but we don't want the ticks to be on minimum 50 (or + # whatever $tickgran is set to). However, if there would be + # really really few lines, go down an order of magnitude and try + # again. + # + my $ytick; + do { + $ytick = ($max_y - $min_y) / 11; + $ytick = POSIX::ceil($ytick / $tickgran) * $tickgran; + $tickgran *= 0.1; + } while (($max_y - $min_y) / $ytick < 4); + + for my $i (-11..11) { + my $y = ($i * $ytick - $max_y) * $::ys + 10; + next if ($y < 2 || $y > $height - 18); + + if ($i == 0) { + wuline($graph, $xoffset, $y, $width - 1, $y, 0, 0, 0, 1.0); + wuline($graph, $xoffset, $y + 1, $width - 1, $y + 1, 0, 0, 0, 1.0); + } else { + wuline($graph, $xoffset, $y, $width - 1, $y, 0, 0, 0, 0.2); + } + + # text + my $traf = 8 * ($i * $ytick); + my $text; + if ($traf >= 500_000_000) { + $text = (sprintf "%.1f Gbit", ($traf/1_000_000_000)); + } elsif ($traf >= 500_000) { + $text = (sprintf "%.1f Mbit", ($traf/1_000_000)); + } else { + $text = (sprintf "%.1f kbit", ($traf/1_000)); + } + + my @bounds = GD::Image::stringFT(undef, $black, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 0, 0, $text); + my $w = $bounds[2] - $bounds[0]; + my $h = $bounds[1] - $bounds[5]; + + next if ($y - $h/2 < 2 || $y + $h/2 > $height - 12); + $graph->stringFT($black, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, ($xoffset - 4) - $w, $y + $h/2, $text); + } + + # Nice border(TM) + $graph->rectangle($xoffset, 0, $width - 1, $height - 1, $black); + + return $graph; +} + +sub plotseries { + my ($graph, $xvals, $yvals, $r, $g, $b, $min_x, $max_y) = @_; + my $xoffset = 70; + + my @xvals = @{$xvals}; + my @yvals = @{$yvals}; + + my $x = $xvals[0]; + my $y = $yvals[0]; + for my $i (1..$#xvals) { + next if ($::xs * ($xvals[$i] - $x) < 2 && $::ys * ($yvals[$i] - $y) > -2); + + wuline($graph, ($x-$min_x) * $::xs + $xoffset + 1, ($y-$max_y) * $::ys + 10, + ($xvals[$i]-$min_x) * $::xs + $xoffset + 1, ($yvals[$i]-$max_y) * $::ys + 10, $r, $g, $b, 1.0); + $x = $xvals[$i]; + $y = $yvals[$i]; + } +} + +1; diff --git a/web/nms.gathering.org/nettkart-continuous.html b/web/nms.gathering.org/nettkart-continuous.html new file mode 100644 index 0000000..e51eea0 --- /dev/null +++ b/web/nms.gathering.org/nettkart-continuous.html @@ -0,0 +1,31 @@ +<html> + <body> + <div id="d"></div> + <script type="text/javascript"> + <!-- + var existing_img = null; + + function load_new() { + var i = document.createElement('img'); + i.onload = function() { loaded(i); }; + i.style.display = 'none'; + i.src = '/nettkart.pl?random=' + (new Date()).getTime(); + document.getElementById('d').appendChild(i); + } + + function loaded(i) { + i.style.display = ''; + + if (existing_img) { + existing_img.parentElement.removeChild(existing_img); + } + existing_img = i; + + setTimeout(function() { load_new(); }, 10000); + } + + load_new(); + --> + </script> + </body> +</html> diff --git a/web/nms.gathering.org/nettkart-telnet.pl b/web/nms.gathering.org/nettkart-telnet.pl new file mode 100755 index 0000000..57cac19 --- /dev/null +++ b/web/nms.gathering.org/nettkart-telnet.pl @@ -0,0 +1,47 @@ +#! /usr/bin/perl +use CGI; +use DBI; +use lib '../../include'; +use nms; +my $cgi = CGI->new; + +my $dbh = nms::db_connect(); +print $cgi->header(-type=>'text/html; charset=utf-8', -refresh=>'45; ' . CGI::url()); + +print <<"EOF"; +<html> + <head> + <title>nettkart - telnet</title> + </head> + <body> + <map name="switches"> +EOF + +my $q = $dbh->prepare("select * from switches natural join placements where ip <> inet '127.0.0.1'"); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + + my $traffic = 4.0 * $ref->{'bytes_in'} + $ref->{'bytes_out'}; # average and convert to bits (should be about the same in practice) + my $ttext; + if ($traffic >= 1_000_000_000) { + $ttext = sprintf "%.2f Gbit/port/sec", $traffic/1_000_000_000; + } elsif ($traffic => 1_000_000) { + $ttext = sprintf "%.2f Mbit/port/sec", $traffic/1_000_000; + } else { + $ttext = sprintf "%.2f kbit/port/sec", $traffic/1_000; + } + + printf " <area shape=\"rect\" coords=\"%u,%u,%u,%u\" target=\"blank\" href=\"telnet://$ref->{'ip'}\" alt=\"%s (%s)\" onmouseover=\"window.status='%s (%s)'; return true\" onmouseout=\"window.status=''\" />\n", + $3, $4, $1, $2, $ref->{'switch'}, $ref->{'sysname'}, + $ttext, $ref->{'sysname'}, $ttext; +} +$dbh->disconnect; + +print <<"EOF"; + </map> + + <p><img src="nettkart.pl" usemap="#switches" /></p> + </body> +</html> +EOF diff --git a/web/nms.gathering.org/nettkart-text.pl b/web/nms.gathering.org/nettkart-text.pl new file mode 100755 index 0000000..d3f4be7 --- /dev/null +++ b/web/nms.gathering.org/nettkart-text.pl @@ -0,0 +1,47 @@ +#! /usr/bin/perl +use CGI; +use DBI; +use lib '../../include'; +use nms; +my $cgi = CGI->new; + +my $dbh = nms::db_connect(); +print $cgi->header(-type=>'text/html; charset=utf-8', -refresh=>'10; ' . CGI::url()); + +print <<"EOF"; +<html> + <head> + <title>nettkart</title> + </head> + <body> + <map name="switches"> +EOF + +my $q = $dbh->prepare("select * from switches natural join placements where ip <> inet '127.0.0.1'"); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + + my $traffic = 4.0 * $ref->{'bytes_in'} + $ref->{'bytes_out'}; # average and convert to bits (should be about the same in practice) + my $ttext; + if ($traffic >= 1_000_000_000) { + $ttext = sprintf "%.2f Gbit/port/sec", $traffic/1_000_000_000; + } elsif ($traffic => 1_000_000) { + $ttext = sprintf "%.2f Mbit/port/sec", $traffic/1_000_000; + } else { + $ttext = sprintf "%.2f kbit/port/sec", $traffic/1_000; + } + + printf " <area shape=\"rect\" coords=\"%u,%u,%u,%u\" href=\"showswitch.pl?id=%u\" alt=\"%s (%s)\" onmouseover=\"window.status='%s (%s)'; return true\" onmouseout=\"window.status=''\" />\n", + $3, $4, $1, $2, $ref->{'switch'}, $ref->{'sysname'}, + $ttext, $ref->{'sysname'}, $ttext; +} +$dbh->disconnect; + +print <<"EOF"; + </map> + + <p><img src="nettkart.pl" usemap="#switches" /></p> + </body> +</html> +EOF diff --git a/web/nms.gathering.org/nettkart-web.pl b/web/nms.gathering.org/nettkart-web.pl new file mode 100755 index 0000000..ce76c35 --- /dev/null +++ b/web/nms.gathering.org/nettkart-web.pl @@ -0,0 +1,47 @@ +#! /usr/bin/perl +use CGI; +use DBI; +use lib '../../include'; +use nms; +my $cgi = CGI->new; + +my $dbh = nms::db_connect(); +print $cgi->header(-type=>'text/html; charset=utf-8', -refresh=>'45; ' . CGI::url()); + +print <<"EOF"; +<html> + <head> + <title>nettkart - web</title> + </head> + <body> + <map name="switches"> +EOF + +my $q = $dbh->prepare("select * from switches natural join placements where ip <> inet '127.0.0.1'"); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + + my $traffic = 4.0 * $ref->{'bytes_in'} + $ref->{'bytes_out'}; # average and convert to bits (should be about the same in practice) + my $ttext; + if ($traffic >= 1_000_000_000) { + $ttext = sprintf "%.2f Gbit/port/sec", $traffic/1_000_000_000; + } elsif ($traffic => 1_000_000) { + $ttext = sprintf "%.2f Mbit/port/sec", $traffic/1_000_000; + } else { + $ttext = sprintf "%.2f kbit/port/sec", $traffic/1_000; + } + + printf " <area shape=\"rect\" coords=\"%u,%u,%u,%u\" href=\"http://$ref->{'ip'}\" alt=\"%s (%s)\" onmouseover=\"window.status='%s (%s)'; return true\" onmouseout=\"window.status=''\" />\n", + $3, $4, $1, $2, $ref->{'switch'}, $ref->{'sysname'}, + $ttext, $ref->{'sysname'}, $ttext; +} +$dbh->disconnect; + +print <<"EOF"; + </map> + + <p><img src="nettkart.pl" usemap="#switches" /></p> + </body> +</html> +EOF diff --git a/web/nms.gathering.org/nettkart.pl b/web/nms.gathering.org/nettkart.pl new file mode 100755 index 0000000..b9517f8 --- /dev/null +++ b/web/nms.gathering.org/nettkart.pl @@ -0,0 +1,142 @@ +#! /usr/bin/perl +use CGI; +use GD; +use Image::Magick; +use DBI; +use lib '../../include'; +use nms; +my $cgi = CGI->new; + +# Sekrit night-mode +my $night = defined($cgi->param('night')); + +my $dbh = nms::db_connect(); + +GD::Image->trueColor(1); +my ($img, $text_img); + +my $img = GD::Image->new('bg07.png'); +if ($night) { + my ($width, $height) = ($img->width, $img->height); + + $img = GD::Image->new($width, $height, 1); + $img->alphaBlending(0); + $img->saveAlpha(1); + my $blank = $img->colorAllocateAlpha(0, 0, 0, 127); + $img->filledRectangle(0, 0, $img->width - 1, $img->height - 1, $blank); + + $text_img = GD::Image->new($width, $height, 1); + $text_img->alphaBlending(0); + $text_img->saveAlpha(1); + my $blank = $text_img->colorAllocateAlpha(0, 0, 0, 127); + $text_img->filledRectangle(0, 0, $text_img->width - 1, $text_img->height - 1, $blank); +} else { + $img = GD::Image->new('bg07.png'); + $text_img = $img; +} + +my $blk = $img->colorResolve(0, 0, 0); + +for my $y (42..236) { + my $i = 4.0 * ($y - 236.0) / (42.0 - 237.0); + my $clr = get_color($i); + + $img->filledRectangle(12, $y, 33, $y+1, $clr); + $text_img->filledRectangle(12, $y, 33, $y+1, $clr); +} + +$text_img->rectangle(12,42,33,236,$blk); + +my $tclr = $night ? $text_img->colorResolve(255, 255, 255) : $blk; +$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*0.0/4.0, "100 Gbit/sec"); +$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*1.0/4.0, "10 Gbit/sec"); +$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*2.0/4.0, "1 Gbit/sec"); +$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*3.0/4.0, "100 Mbit/sec"); +$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*4.0/4.0, "10 Mbit/sec"); +$text_img->stringFT($tclr, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 1000, 700, "NMS (C) 2005-2012 Tech:Server"); + +my $q = $dbh->prepare("select * from ( SELECT switch,sysname,sum(bytes_in) AS bytes_in,sum(bytes_out) AS bytes_out from switches natural left join get_current_datarate() where ip <> inet '127.0.0.1' group by switch,sysname) t1 natural join placements order by zorder;"); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + + # for now: + # 10Mbit/switch = green + # 100Mbit/switch = yellow + # 1Gbit/switch = red + # 10Gbit/switch = white + + my $clr; + + if (defined($ref->{'bytes_in'})) { + my $intensity = 0.0; + my $traffic = 4.0 * ($ref->{'bytes_in'} + $ref->{'bytes_out'}); # average and convert to bits (should be about the same in practice) + + my $max = 100_000_000_000.0; # 100Gbit + my $min = 10_000_000.0; # 10Mbit + if ($traffic >= $min) { + $intensity = log($traffic / $min) / log(10); + $intensity = 4.0 if ($intensity > 4.0); + } + $clr = get_color($intensity); + } else { + $clr = $img->colorResolve(0, 0, 255); + } + + my $sysname = $ref->{'sysname'}; + $sysname =~ s/-sekrit//; + + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + $img->filledRectangle($3,$4,$1,$2,$clr); + $text_img->filledRectangle($3,$4,$1,$2,$clr); + + $img->rectangle($3,$4,$1,$2,$blk); + $text_img->rectangle($3,$4,$1,$2,$blk); + my ($x2, $y2, $x1, $y1) = ($1, $2, $3, $4); + my $max_textlen = ($x2-$x1) > ($y2-$y1) ? $x2-$x1 : $y2-$y1; + while (length($sysname) * 6 > $max_textlen) { + # Try to abbreviate sysname if it is too long for the box + $sysname =~ s/^(.*)[a-z]~?([0-9]+)$/$1~$2/ or last; + } + if (($x2-$x1) > ($y2-$y1)) { + $text_img->string(gdSmallFont,$x1+2,$y1,$sysname,$blk); + } else { + $text_img->stringUp(gdSmallFont,$x1,$y2-3,$sysname,$blk); + } +} +$dbh->disconnect; + +print $cgi->header(-type=>'image/png', -expires=>'now'); +if ($night) { + my $magick = Image::Magick->new; + $magick->BlobToImage($img->png); + $magick->Blur(sigma=>10.0, channel=>'All'); + $magick->Gamma(gamma=>1.90); + + my $m2 = Image::Magick->new; + $m2->Read('bg07.png'); + $m2->Negate(); + $m2->Composite(image=>$magick, compose=>'Atop'); + + my $m3 = Image::Magick->new; + $m3->BlobToImage($text_img->png); + $m2->Composite(image=>$m3, compose=>'Atop'); + + $img = $m2->ImageToBlob(); + print $img; +} else { + print $img->png; +} + +sub get_color { + my $intensity = shift; + my $gamma = 1.0/1.90; + if ($intensity > 3.0) { + return $img->colorResolve(255.0 * ((4.0 - $intensity) ** $gamma), 255.0 * ((4.0 - $intensity) ** $gamma), 255.0 * ((4.0 - $intensity) ** $gamma)); + } elsif ($intensity > 2.0) { + return $img->colorResolve(255.0, 255.0 * (($intensity - 2.0) ** $gamma), 255.0 * (($intensity - 2.0) ** $gamma)); + } elsif ($intensity > 1.0) { + return $img->colorResolve(255.0, 255.0 * ((2.0 - $intensity) ** $gamma), 0); + } else { + return $img->colorResolve(255.0 * ($intensity ** $gamma), 255, 0); + } +} diff --git a/web/nms.gathering.org/portkart.pl b/web/nms.gathering.org/portkart.pl new file mode 100755 index 0000000..1269173 --- /dev/null +++ b/web/nms.gathering.org/portkart.pl @@ -0,0 +1,82 @@ +#! /usr/bin/perl +use CGI; +use GD; +use DBI; +use lib '../../include'; +use nms; +my $cgi = CGI->new; + +my $dbh = nms::db_connect(); + +GD::Image->trueColor(1); +$img = GD::Image->new('bg07.png'); + +my $blk = $img->colorResolve(0, 0, 0); + +for my $y (42..236) { + my $i = 3.0 * ($y - 236.0) / (42.0 - 237.0); + my $clr = get_color($i); + + $img->filledRectangle(12,$y,33,$y+1,$clr); +} + +$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*0.0/3.0, "1 Gbit/sec"); +$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*1.0/3.0, "100 Mbit/sec"); +$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*2.0/3.0, "10 Mbit/sec"); +$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*3.0/3.0, "1 Mbit/sec"); +$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 1000, 620, "NMS (C) 2005-2007 Tech:Server"); + +my $q = $dbh->prepare('select switch,port,bytes_in,bytes_out,placement,switchtype from switches natural join placements natural join get_datarate() where switchtype like \'%3100%\''); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + + # for now: + # 100kbit/port = all green + # 1gbit/port = all red + + my $clr; + + if (defined($ref->{'bytes_in'})) { + my $intensity = 0.0; + my $traffic = 4.0 * ($ref->{'bytes_in'} + $ref->{'bytes_out'}); # average and convert to bits (should be about the same in practice) + + my $max = 100_000_000_000.0; # 1Gbit + my $min = 1_000_000.0; # 1Mbit + if ($traffic >= $min) { + $intensity = log($traffic / $min) / log(10); + $intensity = 4.0 if ($intensity > 4.0); + } + $clr = get_color($intensity); + } else { + $clr = $img->colorResolve(0, 0, 255); + } + + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + my $npo = 48; + my $f = ($ref->{'port'} - 1) % 2; + my $po = ($ref->{'port'} - 1 - $f)/2; + my $h = 2*($2-$4)/$npo; + my $w = ($1-$3)/2; + + $img->filledRectangle($3+$w*$f,$4+$po*$h,$3+$w+$w*$f,$4+$h*($po+1),$clr); +# $img->rectangle($3+$w*$f,$4+$po*$h,$3+$w+$w*$f,$4+$h*($po+1),$blk); + $img->rectangle($3,$4,$1,$2,$blk); +} +$dbh->disconnect; + +print $cgi->header(-type=>'image/png'); +print $img->png; + +sub get_color { + my $intensity = shift; + my $gamma = 1.0/1.90; + if ($intensity > 3.0) { + return $img->colorResolve(255.0 * ((4.0 - $intensity) ** $gamma), 255.0 * ((4.0 - $intensity) ** $gamma), 255.0 * ((4.0 - $intensity) ** $gamma)); + } elsif ($intensity > 2.0) { + return $img->colorResolve(255.0, 255.0 * (($intensity - 2.0) ** $gamma), 255.0 * (($intensity - 2.0) ** $gamma)); + } elsif ($intensity > 1.0) { + return $img->colorResolve(255.0, 255.0 * ((2.0 - $intensity) ** $gamma), 0); + } else { + return $img->colorResolve(255.0 * ($intensity ** $gamma), 255, 0); + } +} diff --git a/web/nms.gathering.org/showswitch.pl b/web/nms.gathering.org/showswitch.pl new file mode 100755 index 0000000..5ed0029 --- /dev/null +++ b/web/nms.gathering.org/showswitch.pl @@ -0,0 +1,221 @@ +#! /usr/bin/perl +use CGI; +use DBI; +use Time::HiRes; +use POSIX ":sys_wait_h"; +use strict; +use warnings; +use lib '../../include'; +use nms; +my $cgi = CGI->new; +my $switch = $cgi->param('id'); +my $width = $cgi->param('width'); +my $height = $cgi->param('height'); +my @pids = (); +my $resthtml = ""; + +$width = 500 unless (defined($width)); +$height = 250 unless (defined($height)); + +require './mygraph.pl'; + +my $start = [Time::HiRes::gettimeofday]; +my $dbh = nms::db_connect(); + +# Fetch the name +my $ref = $dbh->selectrow_hashref('SELECT sysname FROM switches WHERE switch=?', undef, $switch); + +print $cgi->header(-type=>'text/html; charset=utf-8'); +print <<"EOF"; +<html> + <head> + <title>snmp</title> + </head> + <body> + <h1>Switch $switch ($ref->{'sysname'})</h1> +EOF + +my $q = $dbh->prepare('select port,coalesce(description, \'Port \' || port) as description,extract(epoch from time) as time,bytes_in,bytes_out from switches natural left join portnames natural join polls where time between now() - \'1 day\'::interval and now() and switch=? order by switch,port,time;') or die $dbh->errstr; +$q->execute($switch) or die $dbh->errstr; + +my (@totx, @toty1, @toty2) = (); + +my (@x, @y1, @y2) = (); +my $last_port = -1; +my $portname = ""; +my $min_x = time; +my $max_x = time - 86400; +my ($min_y, $max_y, $prev_time, $prev_in, $prev_out); +my ($if,$of,$ifv,$ofv); +my $idx; +my ($min_ty,$max_ty) = (0, 10_000_000/8); + +$prev_time = -1; +my $last_totx; +while (my $ref = $q->fetchrow_hashref()) { + my $time = $ref->{'time'}; + my $in = $ref->{'bytes_in'}; + my $out = $ref->{'bytes_out'}; + next if ($time == $prev_time); + + if ($ref->{'port'} != $last_port) { + if ($last_port != -1) { + my $filename = "$switch-$last_port-$width-$height.png"; + + # reap children + waitpid(-1, WNOHANG); + + my $pid = fork(); + if ($pid == 0) { +# write out the graph + my $graph = makegraph($width, $height, $min_x, $max_x, $min_y, $max_y, 5); + plotseries($graph, \@x, \@y1, 255, 0, 0, $min_x, $max_y); + plotseries($graph, \@x, \@y2, 0, 0, 255, $min_x, $max_y); + + open GRAPH, ">img/$filename" + or die "img/$filename: $!"; + print GRAPH $graph->png; + close GRAPH; + exit; + } + + push @pids, $pid; + + $resthtml .= "<div style=\"float: left;\"><h2>$portname</h2>\n"; + $resthtml .= "<p><img src=\"img/$filename\" width=\"$width\" height=\"$height\" /></p></div>\n"; + } + + # Reset all the variables + @x = (); + @y1 = (); + @y2 = (); + ($min_y,$max_y) = (0, 10_000_000/8); + $prev_time = $ref->{'time'}; + $prev_in = $ref->{'bytes_in'}; + $prev_out = $ref->{'bytes_out'}; + $last_port = $ref->{'port'}; + $portname = $ref->{'description'}; + ($if,$of,$ifv,$ofv) = (0,0,0,0); + ($prev_time,$prev_in,$prev_out) = ($time,$in,$out); + $idx = 0; + $last_totx = undef; + next; + } + + # Assume overflow (unless the switch has been down for >10 minutes) + my ($calc_in, $calc_out) = ($in, $out); + if ($in < $prev_in || $out < $prev_out) { + if ($prev_in < 4294967296 && $prev_out < 4294967296) { + # ick, heuristics + if ($prev_time - $time > 600 || ($in + 4294967296 - $prev_in) > 2147483648 || ($out + 4294967296 - $prev_out) > 2147483648) { + ($prev_time,$prev_in,$prev_out) = ($time,$in,$out); + next; + } + + $calc_in += 4294967296 if ($in < $prev_in); + $calc_out += 4294967296 if ($out < $prev_out); + } else { + $prev_in = 0; + $prev_out = 0; + } + } + + # Remove dupes + if ($in == $prev_in && $out == $prev_out) { + ($prev_time,$prev_in,$prev_out) = ($time,$in,$out); + next; + } + + # Find the current flow + my $if = ($calc_in - $prev_in) / ($time - $prev_time); + my $of = ($calc_out - $prev_out) / ($time - $prev_time); + + # Summarize (we don't care about the summed variance for now) + $min_x = $time if (!defined($min_x) || $time < $min_x); + $max_x = $time if (!defined($max_x) || $time > $max_x); + $min_y = $if if (!defined($min_y) || $if < $min_y); + $min_y = $of if ($of < $min_y); + $max_y = $if if (!defined($max_y) || $if > $max_y); + $max_y = $of if ($of > $max_y); + + my $pt = 0.5 * ($time + $prev_time); + + push @x, $pt; + push @y1, $if; + push @y2, $of; + + while ($idx < $#totx && $pt > $totx[$idx]) { + ++$idx; + } + if ($idx >= $#totx) { + push @totx, $pt; + push @toty1, $if; + push @toty2, $of; + ++$idx; + + $min_ty = $if if (!defined($min_ty) || $if < $min_ty); + $min_ty = $of if ($of < $min_ty); + $max_ty = $if if (!defined($max_ty) || $if > $max_ty); + $max_ty = $of if ($of > $max_ty); + } else { + if (!defined($last_totx) || $last_totx != $idx) { + $toty1[$idx] += $if; + $toty2[$idx] += $of; + } + $last_totx = $idx; + + $min_ty = $toty1[$idx] if (!defined($min_ty) || $toty1[$idx] < $min_ty); + $min_ty = $toty2[$idx] if ($toty2[$idx] < $min_ty); + $max_ty = $toty1[$idx] if (!defined($max_ty) || $toty1[$idx] > $max_ty); + $max_ty = $toty2[$idx] if ($toty2[$idx] > $max_ty); + } + + ($prev_time,$prev_in,$prev_out) = ($time,$in,$out); +} +$dbh->disconnect; + +# last graph +my $filename = "$switch-$last_port-$width-$height.png"; + +my $pid = fork(); +if ($pid == 0) { + my $graph = makegraph($width, $height, $min_x, $max_x, $min_y, $max_y, 5); + plotseries($graph, \@x, \@y1, 255, 0, 0, $min_x, $max_y); + plotseries($graph, \@x, \@y2, 0, 0, 255, $min_x, $max_y); + + open GRAPH, ">img/$filename" + or die "img/$filename: $!"; + print GRAPH $graph->png; + close GRAPH; + exit; +} + +push @pids, $pid; + +$resthtml .= "<div style=\"float: left;\"><h2>$portname</h2>\n"; +$resthtml .= "<p><img src=\"img/$filename\" width=\"$width\" height=\"$height\" /></p></div>\n"; + +# total graph +my $graph = makegraph($width, $height, $min_x, $max_x, $min_ty, $max_ty, 5); +plotseries($graph, \@totx, \@toty1, 255, 0, 0, $min_x, $max_ty); +plotseries($graph, \@totx, \@toty2, 0, 0, 255, $min_x, $max_ty); + +$filename = "$switch-$width-$height.png"; +open GRAPH, ">img/$filename" or die "img/$filename: $!"; +print GRAPH $graph->png; +close GRAPH; + + +# Wait for all the other graphs to be done +while (waitpid(-1, 0) != -1) { + 1; +} + +print $resthtml; + +print "<div style=\"float: left;\"><h2>Total</h2>\n"; +print "<p><img src=\"img/$filename\" width=\"$width\" height=\"$height\" /></p></div>\n"; + +my $elapsed = Time::HiRes::tv_interval($start); +printf "<p style=\"clear: both;\">Page and all graphs generated in %.2f seconds.</p>\n", $elapsed; +print "</body>\n</html>\n"; diff --git a/web/nms.gathering.org/slide.html b/web/nms.gathering.org/slide.html new file mode 100644 index 0000000..046020d --- /dev/null +++ b/web/nms.gathering.org/slide.html @@ -0,0 +1,38 @@ +<!doctype html> +<html> + <body> + <iframe id="tgview" style="border: 0; width: 1536px; height: 864px"></iframe> + + <script> + (function() { + var urls = [ + 'http://onlineclock.net/', + 'http://nms.tg13.gathering.org/dhcpkart.pl', + 'http://nms.tg13.gathering.org/nettkart-text.pl', + 'http://nms.tg13.gathering.org/nettkart-text.pl', + 'http://nms.tg13.gathering.org/uplinkkart.pl', + 'http://nms.tg13.gathering.org/uplinktrafikkart.pl', + 'http://nms.tg13.gathering.org/apkart.pl', + 'http://stats.tg13.gathering.org/' + ]; + + var view = document.getElementById('tgview'); + var fload = function( frame, url ) { + frame.src = url; + }; + + var i = 0; + (function rotation() { + //if ( i != l-1 ) { + if ( i != urls.length-1 ) { + i++ + } else { + i = 0; + } + fload( view, urls[i] ); + setTimeout( arguments.callee, 10000 ); + })(); + })(); + </script> + </body> +</html> diff --git a/web/nms.gathering.org/smanagement.pl b/web/nms.gathering.org/smanagement.pl new file mode 100755 index 0000000..c01c52d --- /dev/null +++ b/web/nms.gathering.org/smanagement.pl @@ -0,0 +1,239 @@ +#!/usr/bin/perl +use warnings; +use strict; +use CGI; +use DBI; +use Data::Dumper; +use Switch; +use lib '../../include'; +use nms; + +# Grab from .htaccess-authentication +my $user = $ENV{'REMOTE_USER'}; + +my $dbh = nms::db_connect(); +$dbh->{AutoCommit} = 0; + +# Ugly casting, found no other way +my $sinsert = $dbh->prepare( "INSERT INTO squeue + (gid, added, priority, addr, sysname, cmd, author) + VALUES(?::text::int, timeofday()::timestamptz, ?::text::int, ?::text::inet, ?, ?, ?)") + or die "Could not prepare sinsert"; +my $sgetip = $dbh->prepare("SELECT ip FROM switches WHERE sysname = ?") + or die "Could not prepare sgetip"; +my $sgid = $dbh->prepare("SELECT nextval('squeue_group_sequence') as gid"); +my $all_switches = $dbh->prepare("SELECT sysname FROM switches ORDER BY sysname"); + +sub parse_range($) { + my $switches = $_; + my @range; + + my @rangecomma = split(/\s*,\s*/, $switches); + foreach (@rangecomma) { + my ($first, $last) = $_ =~ /(e\d+\-(?:sw)?[123456])\s*\-\s*(e\d+\-(?:sw)?[123456])?/; + if (!defined($first) && $_ =~ /e\d+\-(sw)?[123456]/) { + $first = $_; + } + if (!defined($first)) { + print "<font color=\"red\">Parse error in: $_</font><br>\n"; + next; + } + my ($rowstart, $placestart) = $first =~ /e(\d+)\-(?:sw)?([123456])/; + if (!defined($rowstart) || !defined($placestart)) { + print "<font color=\"red\">Parse error in: $_</font><br>\n"; + next; + } + my ($rowend, $placeend); + if (!defined($last)) { + $rowend = $rowstart; + $placeend = $placestart; + } + else { + ($rowend, $placeend) = $last =~ /e(\d+)\-(?:sw)?([123456])/; + } + if (!defined($rowend) || !defined($placeend)) { + print "<font color=\"red\">Parse error in: $_</font><br>\n"; + next; + } + #print "e $rowstart - $placestart to e $rowend - $placeend <br>\n"; + for (my $i = $rowstart; $i <= $rowend; $i++) { + my $dostart; + if ($rowstart != $i) { + $dostart = 1; + } + else { + $dostart = $placestart; + } + for (my $j = $dostart; $j <= 6; $j++) { + last if ($i == $rowend && $j > $placeend); + push(@range, "e$i-$j"); + } + } + } +# foreach (@range) { +# print ":: $_<br>\n"; +# } + return @range; +} + +sub get_addr_from_switchnum($) { + my ($sysname) = @_; + + $sgetip->execute($sysname); + if ($sgetip->rows() < 1) { + print "Could not get the ip for: ".$sysname; + return undef; + } + my $row = $sgetip->fetchrow_hashref(); + return $row->{'ip'}; +} + +my $cgi = new CGI; + +print $cgi->header(-type=>'text/html; charset=utf-8'); + +print << "EOF"; +<html> + <head> + <title>Switch managment</title> + </head> + <body> + <p>Du er logget inn som: $user</p> + <form method="POST" action="smanagement.pl"> + <table> + <tr> + <td>Alle switchene</td> + <td><input type="radio" name="rangetype" value="all" /></td> + <td></td> + <td></td> + </tr> + <tr> + <td>Switch</td> + <td><input type="radio" checked name="rangetype" value="switch" /></td> + <td><input type="text" name="range" /></td> + <td>e1-2, e3-3 - e10-2</td> + </tr> + <tr> + <td>Regexp</td> + <td><input type="radio" name="rangetype" value="regexp" /></td> + <td><input type="text" name="regexp" /></td> + <td>Regulært uttrykk</td> + </tr> + <tr> + <td>Rad</td> + <td><input type="radio" name="rangetype" value="row" /></td> + <td><input type="text" name="range" /></td> + <td>1,3-5 (Disabled)</td> + </tr> + <tr> + <td><hr /></td> + <td><hr /></td> + <td><hr /></td> + <td><hr /></td> + </tr> + <tr> + <td>Prioritet</td> + <td></td> + <td> + <select name="priority"> + <option value="1">1 (lavest)</option> + <option value="2">2</option> + <option selected value="3">3</option> + <option value="4">4</option> + <option value="5">5 (høyest)</option> + </select> + </td> + </tr> + <tr> + <td>Kommando(er):</td> + <td></td> + <td><textarea name="cmd" cols="80" rows="24"></textarea></td> + <td>En kommando per linje. Linjer som begynner med ! sørger for at nms ikke venter på normal prompt, men fyrer av gårde neste linje umiddelbart. Kjekt for kommandoer av typen "!save\\nY"</td> + </td> + <tr> + <td><hr /></td> + <td><hr /></td> + <td><hr /></td> + <td><hr /></td> + </tr> + </table> + <input type="submit" value="Execute!" /><br /> + </form> +EOF + +print "<br />\n"; + +my @switches = (); +switch ($cgi->param('rangetype')) { + case 'all' { + print "Sender `".$cgi->param('cmd')."` til alle switchene<br />"; + @switches = (); + $all_switches->execute(); + while (my $ref = $all_switches->fetchrow_hashref) { + push @switches, $ref->{'sysname'}; + } + } + case 'switch' { +# print "Sender `".$cgi->param('cmd')."` til switchene `" +# .$cgi->param('range')."`.<br />"; + $_ = $cgi->param('range'); + @switches = parse_range($_); + } + case 'regexp' { + @switches = (); + $all_switches->execute(); + while (my $ref = $all_switches->fetchrow_hashref) { + push @switches, $ref->{'sysname'} if $ref->{'sysname'} =~ $cgi->param('regexp'); + } + } + case 'row' { +# print "Sender `".$cgi->param('cmd')."` til radene `" +# .$cgi->param('range')."`.<br />"; +# print "This function does not work yet."; +# $_ = $cgi->param('range'); +# @switches = &parse_row_range($_); +# @switches = (); + print "<font color=\"red\">Slått av!</font>\n"; + } +} + +my $gid; +if (@switches > 0) { + $sgid->execute(); + my $row = $sgid->fetchrow_hashref(); + $gid = $row->{gid}; +} + +my $pri = $cgi->param('priority'); + +print "<pre>\n"; +foreach my $switch (@switches) { + my $addr = get_addr_from_switchnum($switch); + if (!defined($addr)) { + next; + } + my $cmd = $cgi->param('cmd'); + print "$switch got addr $addr <br>\n"; + print "Queuing commands for $switch:\n"; + my $result = $sinsert->execute($gid, $pri, $addr, $switch, $cmd, $user); + if (!$result) { + print "\t<font color=\"red\">" + ."Could not execute query." + ."</font>\n"; + print "\t".$dbh->errstr."\n"; + } + else { + print "\tQueued: $cmd\n"; + } + print "\n"; +} +$dbh->commit; +if (defined($gid)) { + print "<a href=\"sshow.pl?action=showgid&gid=".$gid."\">Vis resultat</a>\n"; +} +print "</pre>\n"; + +print << "EOF"; + </body> +</html> +EOF diff --git a/web/nms.gathering.org/ssendfile.pl b/web/nms.gathering.org/ssendfile.pl new file mode 100755 index 0000000..ec2ebb8 --- /dev/null +++ b/web/nms.gathering.org/ssendfile.pl @@ -0,0 +1,48 @@ +#!/usr/bin/perl +use warnings; +use strict; +use lib '../../include'; +use POSIX; + +my $delaytime = 30; +my $poll_frequency = 60; + +sub mylog { + my $msg = shift; + my $time = POSIX::ctime(time); + $time =~ s/\n.*$//; + printf STDERR "[%s] %s\n", $time, $msg; +} + +if ($#ARGV != 1) { + die("Error in arguments passed\n". + "./ssendfile.pl addr configfile\n"); +} + +my $conn = nms::switch_connect($ARGV[0]); +if (!defined($conn)) { + die("Could not connect to switch.\n"); +} + +open(CONFIG, $ARGV[1]); +while (<CONFIG>) { + my $cmd = $_; + $cmd =~ s/[\r\n]+//g; + print "Executing: `$cmd`\n"; +# if ($cmd =~ /ip ifconfig swif0 (\d{1-3}\.\d{1-3}\.\d{1-3}\.\d{1-3})/) { +# print "New ip: $1\n"; +# $conn->cmd( String => $cmd, +# Timeout => 3); +# $conn = nms::switch_connect($1); +# if (!defined($conn)) { +# die "Could not connect to new ip: $1\n"; +# } +# } +# else { + my @data = nms::switch_exec($cmd, $conn); + foreach my $line (@data) { + $line =~ s/[\r\n]+//g; + print "$line\n"; + } +# } +} diff --git a/web/nms.gathering.org/sshow.pl b/web/nms.gathering.org/sshow.pl new file mode 100755 index 0000000..f406b69 --- /dev/null +++ b/web/nms.gathering.org/sshow.pl @@ -0,0 +1,257 @@ +#!/usr/bin/perl +use lib '../../include'; +use nms; + +use warnings; +use strict; +use Switch; +use CGI; +use DBI; + +# Grab from .htaccess-authentication +my $user = $ENV{'REMOTE_USER'}; + +my $dbh = nms::db_connect(); +$dbh->{AutoCommit} = 0; + +my $sgetdone = $dbh->prepare( +"SELECT * +FROM squeue +WHERE processed = 't' +ORDER BY updated DESC, sysname +LIMIT ?::text::int") + or die "Could not prepare sgetdone"; + +my $sgetdonegid = $dbh->prepare( +"SELECT * +FROM squeue +WHERE processed = 't' AND gid = ?::text::int +ORDER BY updated DESC, sysname") + or die "Could not prepare sgetdonegid"; + +my $slistdonegid = $dbh->prepare( +"SELECT DISTINCT gid, cmd, author, added +FROM squeue +WHERE processed = 't' +ORDER BY gid") + or die "Could not prepare slistdonegid"; + +my $slistprocgid = $dbh->prepare( +"SELECT DISTINCT gid, cmd, author, added +FROM squeue +WHERE processed = 'f' +ORDER BY gid") + or die "Could not prepare slistdonegid"; + +my $sgetgid = $dbh->prepare( +"SELECT * +FROM squeue +WHERE gid = ?") + or die "Could not prepare sgetgid"; + +my $sgetprocessing = $dbh->prepare( +"SELECT * +FROM squeue +WHERE processed = 'f' +ORDER BY updated DESC, gid, sysname") + or die "Could not prepare sgetdone"; + +my $sgetnoconnect = $dbh->prepare( +"SELECT * +FROM squeue +WHERE result = 'Could not connect to switch, delaying...'") + or die "Could not prepare sgetnoconnect"; + +my $sdisablegid = $dbh->prepare(" +UPDATE squeue SET disabled = 't' +WHERE gid = ?::text::int") + or die "Could not prepare sdisablegid"; +my $senablegid = $dbh->prepare(" +UPDATE squeue SET disabled = 'f' +WHERE gid = ?::text::int") + or die "Could not prepare sdisablegid"; + + +my $cgi = new CGI; + +print $cgi->header(-type=>'text/html; charset=utf-8'); + +print << "EOF"; +<html> + <head> + <title>Switch managment</title> + </head> + <body> + <p>Du er logget inn som: $user</p> + <form method="POST" action="sshow.pl"> + <p> + Vis <input type="text" name="count" size="4" value="10" /> siste<br /> + Vis: <select name="action" /> + <option value="listgid">Grupper</option> + <option value="done">Ferdige</option> + <option value="processing">I kø</option> + </select> + <input type="submit" value="Vis" /><br /> + </p> + </form> + <br /> +EOF + +my $limit = $cgi->param('count'); +if (!defined($limit)) { + $limit = 10; +} +my $action = $cgi->param('action'); +if (!defined($action)) { + $action = 'listgid'; +} + +if (defined($cgi->param('agid'))) { + my $gid = $cgi->param('gid'); + if (!defined($gid)) { + print "<font color=\"red\">Du har ikke valgt en gid å slette.</font>\n"; + print "<p>gid: ".$cgi->param('gid')." har blitt disablet.\n"; + } + else { + $senablegid->execute($gid); + print "<p>gid: ".$cgi->param('gid')." har blitt enablet.\n"; + } + $dbh->commit(); +} + +if ($action eq 'noconnect') { + print "<h3>Kunne ikke koble til disse switchene:</h3>\n"; + $sgetnoconnect->execute(); + print "<pre>\n"; + while ((my $row = $sgetnoconnect->fetchrow_hashref())) { + print "$row->{'sysname'} : $row->{'cmd'} : Added: $row->{'added'} : Updated: $row->{'updated'}\n"; + } + print "</pre>\n"; +} + +if ($action eq 'listgid') { + print "<pre>\n"; + print "<a href=\"sshow.pl?action=noconnect\" />Kunne ikke koble til</a>\n\n\n"; + print "<b>Ferdige:</b>\n"; + $slistdonegid->execute(); + my ($gid, $author); + $gid = -1; + while ((my $row = $slistdonegid->fetchrow_hashref())) { + $author = $row->{author}; + if ($gid != $row->{gid}) { + $gid = $row->{gid}; + print "GID: <a href=\"sshow.pl?action=showgid&gid=$gid\">$gid</a>\n"; + print "Author: $author\n"; + print "Added: ".$row->{added}."\n"; + } + my $cmd = $row->{cmd}; + print "\t$cmd\n"; + } + print "\n\n"; + print "<b>I kø:</b>\n"; + $slistprocgid->execute(); + $gid = -1; + while ((my $row = $slistprocgid->fetchrow_hashref())) { + $author = $row->{author}; + if ($gid != $row->{gid}) { + $gid = $row->{gid}; + print "GID: <a href=\"sshow.pl?action=showgid&gid=$gid\">$gid</a>\n"; + print "Author: $author\n"; + print "Added: ".$row->{added}."\n"; + } + my $cmd = $row->{cmd}; + print "\t$cmd\n"; + } + $dbh->commit(); + print "</pre>\n"; +} + +if ($action eq 'showgid') { + print "<pre>\n"; + $sgetgid->execute($cgi->param('gid')); + my $row = $sgetgid->fetchrow_hashref(); + print "GID: ".$row->{gid}."\n"; + print "Author: ".$row->{author}."\n"; + do { + print " <b>Name: ".$row->{sysname}." Addr: ".$row->{addr}."</b>\n"; + print " `<b>".$row->{cmd}."`</b>\n"; + print " <i>Added: ".$row->{added}." executed ".$row->{updated}."</i>\n"; + my $data = $row->{result}; + if (!defined($data)) { + $data = "Not executed yet!"; + } + my @lines = split(/[\n\r]+/, $data); + foreach my $line (@lines) { + print "\t$line\n"; + } + } while (($row = $sgetgid->fetchrow_hashref())); + print "</pre>\n"; +} + +if ($action eq 'done') { + print "<h3>Done</h3>\n"; + print "<pre>\n"; + + my $squery; + if (defined($cgi->param('gid'))) { + my $gid = $cgi->param('gid'); + $sgetdonegid->execute($gid); + $squery = $sgetdonegid; + } + else { + $sgetdone->execute($limit); + $squery = $sgetdone; + } + my $sysname = ''; + while (my $row = $squery->fetchrow_hashref()) { + if ($sysname ne $row->{'sysname'}) { + $sysname = $row->{'sysname'}; + print "$sysname (".$row->{addr}."):\n"; + } + print " Author: ".$row->{author}."\n"; + print " Cmd: ".$row->{cmd}."\n"; + print " Added: ".$row->{added}." Updated: ".$row->{updated}."\n"; + print " gID: ".$row->{gid}."\n"; + my @result = split(/[\n\r]+/, $row->{result}); + foreach (@result) { + print "\t".$_."\n"; + } + print "\n"; + } + $dbh->commit(); + print "</pre>\n"; +} +elsif ($action eq 'processing') { + print "<h3>Processing</h3>\n"; + print "<pre>\n"; + $sgetprocessing->execute(); + while (my $row = $sgetprocessing->fetchrow_hashref()) { + my $sysname = $row->{'sysname'}; + print "$sysname (".$row->{addr}."):\n"; + print " Author: ".$row->{author}."\n"; + print " Cmd: ".$row->{cmd}."\n"; + my $updated; + if (defined($row->{updated})) { $updated = $row->{updated}; } + else { $updated = 'never'; } + print " Added: ".$row->{added}." Updated: ".$updated."\n"; + print " Disabled: ".$row->{disabled}."\n"; + print " Locked: ".$row->{locked}."\n"; + print " gID: ".$row->{gid}; + print " <form action=\"sshow.pl\" methos=\"POST\">"; + print "<input type=\"hidden\" name=\"gid\" value=\"".$row->{gid}."\">"; + print "<input type=\"hidden\" name=\"action\" value=\"processing\">"; + if ($row->{disabled} == 0) { + print "<input type=\"submit\" name=\"agid\" value=\"Disable\">\n"; + } + else { + print "<input type=\"submit\" name=\"agid\" value=\"Enable\">\n"; + } + } + $dbh->commit(); + print "</pre>\n"; +} + +print << "EOF"; + </body> +</html> +EOF diff --git a/web/nms.gathering.org/stromkart.pl b/web/nms.gathering.org/stromkart.pl new file mode 100755 index 0000000..0aef634 --- /dev/null +++ b/web/nms.gathering.org/stromkart.pl @@ -0,0 +1,69 @@ +#! /usr/bin/perl +use CGI qw(fatalsToBrowser); +use GD; +use DBI; +use lib '../../include'; +use nms; +use strict; +use warnings; +my $cgi = CGI->new; + +#my $greentimeout = 7200; +my $greentimeout = 15*60; +my $maxtimeout = $greentimeout*9; + +my $dbh = nms::db_connect(); + +GD::Image->trueColor(1); +my $img = GD::Image->new('bg07.png'); + +my $blk = $img->colorResolve(0, 0, 0); + +$img->string(gdMediumBoldFont,0,0,"Switch uplink status",$blk); +$img->string(gdSmallFont,0,20,"Number of ports with activity",$blk); + +my $red = $img->colorResolve(255, 0, 0); +my $yel = $img->colorResolve(255, 255, 0); +my $grn = $img->colorResolve(0, 255, 0); +my $wht = $img->colorResolve(255, 255, 255); +my $gry = $img->colorResolve(127, 127, 127); + +my $q = $dbh->prepare('select switch,sysname,(select placement from placements where placements.switch=switches.switch) as placement,count((bytes_in > 0 and bytes_out > 0) or null) as active_ports,(max(last_poll_time) >= current_timestamp - interval \'2 minutes\') as fresh from switches natural left join get_current_datarate() natural join placements where switchtype like \'dlink3100%\' group by switch,sysname'); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + my $ports = $ref->{'active_ports'}; + my $sysname = $ref->{'sysname'}; + my $clr; + if ($ports < 5) { + $clr = $red; + } else { + if (!$ref->{'fresh'}) { + $clr = $yel; + } else { + $clr = $grn; + } + } + + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + $img->filledRectangle($3,$4,$1,$2,$clr); + $img->rectangle($3,$4,$1,$2,$blk); + + my ($x2, $y2, $x1, $y1) = ($1, $2, $3, $4); + my $max_textlen = ($x2-$x1) > ($y2-$y1) ? $x2-$x1 : $y2-$y1; + while (length($sysname) * 6 > $max_textlen) { + # Try to abbreviate sysname if it is too long for the box + $sysname =~ s/^(.*)[a-z]~?([0-9]+)$/$1~$2/ or last; + } + if (($x2-$x1) > ($y2-$y1)) { + $img->string(gdSmallFont,$x1+2,$y1,$sysname,$blk); + } else { + $img->stringUp(gdSmallFont,$x1,$y2-3,$sysname,$blk); + } +} +$dbh->disconnect; + +if (!defined($ARGV[0])) { + print $cgi->header(-type=>'image/png', + -refresh=>'10; ' . CGI::url()); +} +print $img->png; diff --git a/web/nms.gathering.org/uplinkkart-text.pl b/web/nms.gathering.org/uplinkkart-text.pl new file mode 100755 index 0000000..de91e92 --- /dev/null +++ b/web/nms.gathering.org/uplinkkart-text.pl @@ -0,0 +1,38 @@ +#! /usr/bin/perl +use CGI; +use DBI; +use lib '../../include'; +use nms; +my $cgi = CGI->new; + +my $dbh = nms::db_connect(); +print $cgi->header(-type=>'text/html; charset=utf-8', -refresh=>'10; ' . CGI::url()); + +print <<"EOF"; +<html> + <head> + <title>Uplinkkart</title> + </head> + <body> + <map name="switches"> +EOF + +my $q = $dbh->prepare("SELECT * FROM switches NATURAL JOIN placements WHERE switchtype = 'dlink3100'"); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + + my $ttext = 'FIXME: Put something here'; + printf " <area shape=\"rect\" coords=\"%u,%u,%u,%u\" href=\"switchdiag.pl?id=%u\" alt=\"%s (%s)\" onmouseover=\"window.status='%s (%s)'; return true\" onmouseout=\"window.status=''\" />\n", + $3, $4, $1, $2, $ref->{'switch'}, $ref->{'sysname'}, + $ttext, $ref->{'sysname'}, $ttext; +} +$dbh->disconnect; + +print <<"EOF"; + </map> + + <p><img src="uplinkkart.pl" usemap="#switches" /></p> + </body> +</html> +EOF diff --git a/web/nms.gathering.org/uplinkkart.pl b/web/nms.gathering.org/uplinkkart.pl new file mode 100755 index 0000000..32581a6 --- /dev/null +++ b/web/nms.gathering.org/uplinkkart.pl @@ -0,0 +1,70 @@ +#! /usr/bin/perl +use CGI qw(fatalsToBrowser); +use GD; +use DBI; +use lib '../../include'; +use nms; +use strict; +use warnings; +my $cgi = CGI->new; + +#my $greentimeout = 7200; +my $greentimeout = 15*60; +my $maxtimeout = $greentimeout*9; + +my $dbh = nms::db_connect(); + +GD::Image->trueColor(1); +my $img = GD::Image->new('bg07.png'); + +my $blk = $img->colorResolve(0, 0, 0); + +$img->string(gdMediumBoldFont,0,0,"Switch uplink status",$blk); +$img->string(gdSmallFont,0,20,"Number of ports with activity",$blk); + +my $red = $img->colorResolve(255, 0, 0); +my $yel = $img->colorResolve(255, 255, 0); +my $grn = $img->colorResolve(0, 255, 0); +my $blu = $img->colorResolve(0, 0, 255); +my $wht = $img->colorResolve(255, 255, 255); +my $gry = $img->colorResolve(127, 127, 127); + +my @palette = ( $blu, $red, $yel, $grn, $wht ); + +for my $ports (0..4) { + my $y = 60 + 20 * (4 - $ports); + $img->filledRectangle(20, $y, 30, $y + 10, $palette[$ports]); + $img->rectangle(20, $y, 30, $y + 10, $blk); + $img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, $y + 10, $ports); +} + +my $q = $dbh->prepare('select switch,sysname,(select placement from placements where placements.switch=switches.switch) as placement,count((bytes_in > 0 and bytes_out > 0) or null) as active_ports from switches natural left join get_current_datarate() natural join placements where port between 45 and 48 and switchtype like \'dlink3100%\' group by switch,sysname'); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + my $ports = $ref->{'active_ports'}; + my $sysname = $ref->{'sysname'}; + my $clr = $palette[$ports]; + + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + $img->filledRectangle($3,$4,$1,$2,$clr); + $img->rectangle($3,$4,$1,$2,$blk); + + my ($x2, $y2, $x1, $y1) = ($1, $2, $3, $4); + my $max_textlen = ($x2-$x1) > ($y2-$y1) ? $x2-$x1 : $y2-$y1; + while (length($sysname) * 6 > $max_textlen) { + # Try to abbreviate sysname if it is too long for the box + $sysname =~ s/^(.*)[a-z]~?([0-9]+)$/$1~$2/ or last; + } + if (($x2-$x1) > ($y2-$y1)) { + $img->string(gdSmallFont,$x1+2,$y1,$sysname,$blk); + } else { + $img->stringUp(gdSmallFont,$x1,$y2-3,$sysname,$blk); + } +} +$dbh->disconnect; + +if (!defined($ARGV[0])) { + print $cgi->header(-type=>'image/png', + -refresh=>'10; ' . CGI::url()); +} +print $img->png; diff --git a/web/nms.gathering.org/uplinktrafikkart.pl b/web/nms.gathering.org/uplinktrafikkart.pl new file mode 100755 index 0000000..32869b3 --- /dev/null +++ b/web/nms.gathering.org/uplinktrafikkart.pl @@ -0,0 +1,90 @@ +#! /usr/bin/perl +use CGI qw(fatalsToBrowser); +use GD; +use DBI; +use lib '../../include'; +use nms; +use strict; +use warnings; +my $cgi = CGI->new; + +#my $greentimeout = 7200; +my $greentimeout = 15*60; +my $maxtimeout = $greentimeout*9; + +my $dbh = nms::db_connect(); + +GD::Image->trueColor(1); +my $img = GD::Image->new('bg07.png'); + +my $blk = $img->colorResolve(0, 0, 0); + +for my $y (42..236) { + my $i = 2.0 * ($y - 236.0) / (42.0 - 237.0); + my $clr = get_color($i); + + $img->filledRectangle(12, $y, 33, $y+1, $clr); +} + +$img->string(gdMediumBoldFont,0,0,"Switch uplink traffic",$blk); +$img->string(gdSmallFont,0,20,"max of bytes in/out",$blk); + +my $red = $img->colorResolve(255, 0, 0); +my $yel = $img->colorResolve(255, 255, 0); +my $grn = $img->colorResolve(0, 255, 0); +my $wht = $img->colorResolve(255, 255, 255); + +$img->rectangle(12,42,33,236,$blk); + +$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*0.0/2.0, "4 Gbit/sec"); +$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*1.0/2.0, "2 Gbit/sec"); +$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 40, 47 + (236-42)*2.0/2.0, "1 Gbit/sec"); +$img->stringFT($blk, "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf", 10, 0, 1000, 700, "NMS (C) 2005-2012 Tech:Server"); + +my $q = $dbh->prepare('select switch,sysname,(select placement from placements where placements.switch=switches.switch) as placement,greatest(sum(bytes_in),sum(bytes_out)) as traffic from switches natural left join get_current_datarate() natural join placements where port between 45 and 48 and switchtype like \'dlink3100%\' group by switch,sysname'); +$q->execute(); +while (my $ref = $q->fetchrow_hashref()) { + my $traffic = $ref->{'traffic'} * 8.0; # convert to bits + my $sysname = $ref->{'sysname'}; + + my $max = 4_000_000_000.0; # 2Gbit + my $min = 1_000_000_000.0; # 1Gbit + $traffic = $max if ($traffic > $max); + $traffic = $min if ($traffic < $min); + my $intensity = log($traffic / $min) / log(2); + my $clr = get_color($intensity); + + $ref->{'placement'} =~ /\((\d+),(\d+)\),\((\d+),(\d+)\)/; + $img->filledRectangle($3,$4,$1,$2,$clr); + $img->rectangle($3,$4,$1,$2,$blk); + + my ($x2, $y2, $x1, $y1) = ($1, $2, $3, $4); + my $max_textlen = ($x2-$x1) > ($y2-$y1) ? $x2-$x1 : $y2-$y1; + while (length($sysname) * 6 > $max_textlen) { + # Try to abbreviate sysname if it is too long for the box + $sysname =~ s/^(.*)[a-z]~?([0-9]+)$/$1~$2/ or last; + } + if (($x2-$x1) > ($y2-$y1)) { + $img->string(gdSmallFont,$x1+2,$y1,$sysname,$blk); + } else { + $img->stringUp(gdSmallFont,$x1,$y2-3,$sysname,$blk); + } +} +$dbh->disconnect; + +if (!defined($ARGV[0])) { + print $cgi->header(-type=>'image/png', + -refresh=>'10; ' . CGI::url()); +} +print $img->png; + +sub get_color { + my $intensity = shift; + my $gamma = 1.0/1.90; + if ($intensity > 1.0) { + $intensity -= 1.0; + return $img->colorResolve(255.0, 255.0 * ($intensity ** $gamma), 255.0 * ($intensity ** $gamma)); + } else { + return $img->colorResolve(255.0 * ($intensity ** $gamma), 255.0 * (1.0 - ($intensity ** $gamma)), 0); + } +} diff --git a/web/stream.tg13.gathering.org/fix_count.pl b/web/stream.tg13.gathering.org/fix_count.pl new file mode 100755 index 0000000..aaaf42e --- /dev/null +++ b/web/stream.tg13.gathering.org/fix_count.pl @@ -0,0 +1,31 @@ +#! /usr/bin/perl + +my $lines = {}; + +open LOG, "<", "/home/techserver/count_datacube.log" + or die "count_datacube.log: $!"; + +while (<LOG>) { + chomp; + my ($date, $port, $proto, $audience, $count) = split /\s+/; + my $key = $port . ' ' . $proto . ' ' . $audience; + $lines->{$date}{$key} = $count; +} + +close LOG; + +my $last_date = undef; +for my $date (sort keys %$lines) { + for my $key (keys %{$lines->{$date}}) { + if (defined($last_date) && !exists($lines->{$last_date}{$key})) { + $lines->{$last_date}{$key} = $lines->{$date}{$key}; + } + } + $last_date = $date; +} + +for my $date (sort keys %$lines) { + for my $key (sort keys %{$lines->{$date}}) { + print "$date $key " . $lines->{$date}{$key} . "\n"; + } +} diff --git a/web/stream.tg13.gathering.org/img/cam-map.png b/web/stream.tg13.gathering.org/img/cam-map.png Binary files differnew file mode 100644 index 0000000..759641a --- /dev/null +++ b/web/stream.tg13.gathering.org/img/cam-map.png diff --git a/web/stream.tg13.gathering.org/img/icon_1.png b/web/stream.tg13.gathering.org/img/icon_1.png Binary files differnew file mode 100644 index 0000000..6d6e67e --- /dev/null +++ b/web/stream.tg13.gathering.org/img/icon_1.png diff --git a/web/stream.tg13.gathering.org/img/icon_2.png b/web/stream.tg13.gathering.org/img/icon_2.png Binary files differnew file mode 100644 index 0000000..599d5f6 --- /dev/null +++ b/web/stream.tg13.gathering.org/img/icon_2.png diff --git a/web/stream.tg13.gathering.org/img/icon_3.png b/web/stream.tg13.gathering.org/img/icon_3.png Binary files differnew file mode 100644 index 0000000..4d1de76 --- /dev/null +++ b/web/stream.tg13.gathering.org/img/icon_3.png diff --git a/web/stream.tg13.gathering.org/img/icon_camera.png b/web/stream.tg13.gathering.org/img/icon_camera.png Binary files differnew file mode 100644 index 0000000..e1bf2c3 --- /dev/null +++ b/web/stream.tg13.gathering.org/img/icon_camera.png diff --git a/web/stream.tg13.gathering.org/img/icon_event.png b/web/stream.tg13.gathering.org/img/icon_event.png Binary files differnew file mode 100644 index 0000000..9ce6df4 --- /dev/null +++ b/web/stream.tg13.gathering.org/img/icon_event.png diff --git a/web/stream.tg13.gathering.org/img/icon_hd.png b/web/stream.tg13.gathering.org/img/icon_hd.png Binary files differnew file mode 100644 index 0000000..d9086bc --- /dev/null +++ b/web/stream.tg13.gathering.org/img/icon_hd.png diff --git a/web/stream.tg13.gathering.org/img/icon_sd.png b/web/stream.tg13.gathering.org/img/icon_sd.png Binary files differnew file mode 100644 index 0000000..3bddbe9 --- /dev/null +++ b/web/stream.tg13.gathering.org/img/icon_sd.png diff --git a/web/stream.tg13.gathering.org/index-bak.pl b/web/stream.tg13.gathering.org/index-bak.pl new file mode 100755 index 0000000..3e31107 --- /dev/null +++ b/web/stream.tg13.gathering.org/index-bak.pl @@ -0,0 +1,67 @@ +#!/usr/bin/perl -I /srv/streamlib +use warnings; +use strict; +use CGI; +use Geo::IP; +use NetAddr::IP; +use Net::IP; +# apt-get install libnet-ip-perl libnetaddr-ip-perl +use HTML::Template; +use stream; +use stream::config; + +my $client = CGI->new; + +my $v4net = $stream::config::v4net; +my $v6net = $stream::config::v6net; +my $tg = $stream::config::tg; +my $tg_full = $stream::config::tg_full; +my %streams = %stream::config::streams; + +my $force_unicast = $client->param('forceunicast'); + +my $location = undef; + +print $client->header(); + +my $clip = $client->remote_addr(); +my $template = HTML::Template->new(filename => 'index.tmpl'); +my $is_local = &is_ip_local($clip, $v4net, $v6net); + +my @streams = &html_local_test(); +$template->param(TG => $tg); +$template->param(TG_FULL => $tg_full); +$template->param(STREAMS => \@streams); +print $template->output(); + + +sub html_local_test() { + my @s = (); + foreach my $name (sort { $streams{$a}->{priority} <=> $streams{$b}->{priority} } keys %streams) { + my $title_link = "http://stream.tg$tg.gathering.org/stream.pl?delivery=%s&stream=${name}&interlaced=%s"; + my $multicast_link = $streams{$name}->{has_multicast} ? "multicast" : "unicast"; + $multicast_link = "unicast" if ($force_unicast == 1 || not $is_local); + + if ($streams{$name}->{external}) { + $title_link = $streams{$name}->{url}; + } else { + $title_link = sprintf($title_link, $multicast_link, $streams{$name}->{interlaced}); + } + my %hash = ( + 'title_link' => $title_link, + 'title' => $streams{$name}->{title}, + 'source' => $streams{$name}->{source}, + 'delivery' => $multicast_link + ); + if ($multicast_link eq "multicast") { + $hash{'is_multicast'} .= 1; + my $unicast_link = $title_link; + $unicast_link=~s/multicast/unicast/g; + $hash{'unicast_link'} .= $unicast_link; + } + $hash{'description'} .= $streams{$name}->{description} if exists($streams{$name}->{description}); + push(@s, \%hash); + + } + return @s; +} diff --git a/web/stream.tg13.gathering.org/index-bak.tmpl b/web/stream.tg13.gathering.org/index-bak.tmpl new file mode 100644 index 0000000..c0aa95d --- /dev/null +++ b/web/stream.tg13.gathering.org/index-bak.tmpl @@ -0,0 +1,31 @@ +<html> +<head> + <title>The Gathering <TMPL_VAR NAME=TG_FULL></title> + <link rel="stylesheet" type="text/css" media="screen" href="superawesomeness.css"> + <link href='http://fonts.googleapis.com/css?family=Open+Sans&subset=latin,latin-ext' rel='stylesheet' type='text/css'> +</head> +<body> + <div id="spaceship"></div> + <div id="innhold"> + <h1>The Gathering <TMPL_VAR NAME=TG_FULL></h1> + <ul> + <TMPL_LOOP NAME="STREAMS"> + <li><a href="<TMPL_VAR NAME=TITLE_LINK>"><TMPL_VAR NAME=TITLE ></a> + <p> + Source: <TMPL_VAR NAME=SOURCE > + <br/>Delivery: <TMPL_VAR NAME=delivery> <TMPL_IF NAME=IS_MULTICAST>(<a href='<TMPL_VAR NAME=UNICAST_LINK>'>problems? try unicast vlc link here</a>)</TMPL_IF> + <TMPL_IF NAME="DESCRIPTION"><br /><TMPL_VAR NAME=DESCRIPTION></TMPL_IF></li> + </TMPL_LOOP> + </ul> + </div> + <footer> + <p>Problems with the non game streams? The easiest way to get hold of us is on IRC (EFNet); + one of ViD, Rockj and Sesse should be available if there's too much traffic + on #tg to be heard.</p> + <p><a href="http://stream.tg<TMPL_VAR NAME="TG">.gathering.org">http://stream.tg<TMPL_VAR NAME="TG">.gathering.org</a></p> + + </footer> +</body> +</html> + + diff --git a/web/stream.tg13.gathering.org/index.pl b/web/stream.tg13.gathering.org/index.pl new file mode 100755 index 0000000..e5f103c --- /dev/null +++ b/web/stream.tg13.gathering.org/index.pl @@ -0,0 +1,72 @@ +#!/usr/bin/perl -I /srv/streamlib +use warnings; +use strict; +use CGI; +use Geo::IP; +use NetAddr::IP; +use Net::IP; +# apt-get install libnet-ip-perl libnetaddr-ip-perl +use HTML::Template; +use stream; +use stream::config; + +my $client = CGI->new; + +my $v4net = $stream::config::v4net; +my $v6net = $stream::config::v6net; +my $tg = $stream::config::tg; +my $tg_full = $stream::config::tg_full; +my %streams = %stream::config::streams; + +my $force_unicast = $client->param('forceunicast'); +my $no_header = $client->param('noheader'); + +my $location = undef; + +print $client->header(); + +my $clip = $client->remote_addr(); +my $template = HTML::Template->new(filename => 'index.tmpl'); +my $is_local = &is_ip_local($clip, $v4net, $v6net); + +my @streams = &html_local_test(); +$template->param(TG => $tg); +$template->param(TG_FULL => $tg_full); +$template->param(STREAMS => \@streams); +$template->param(NOHEADER => $no_header); +print $template->output(); + + +sub html_local_test() { + my @s = (); + foreach my $name (sort { $streams{$a}->{priority} <=> $streams{$b}->{priority} } keys %streams) { + my $title_link = "http://stream.tg$tg.gathering.org/stream.pl?delivery=%s&stream=${name}&interlaced=%s"; + my $multicast_link = $streams{$name}->{has_multicast} ? "multicast" : "unicast"; + $multicast_link = "unicast" if ($force_unicast == 1 || not $is_local); + + if ($streams{$name}->{external}) { + $title_link = $streams{$name}->{url}; + } else { + $title_link = sprintf($title_link, $multicast_link, $streams{$name}->{interlaced}); + } + my %hash = ( + 'title_link' => $title_link, + 'title' => $streams{$name}->{title}, + 'source' => $streams{$name}->{source}, + 'quality' => $streams{$name}->{quality}, + 'location' => $streams{$name}->{location}, + 'type' => $streams{$name}->{type}, + 'delivery' => $multicast_link, + ); + if ($multicast_link eq "multicast") { + $hash{'is_multicast'} .= 1; + my $unicast_link = $title_link; + $unicast_link=~s/multicast/unicast/g; + $hash{'unicast_link'} .= $unicast_link; + } + $hash{'description'} .= $streams{$name}->{description} if exists($streams{$name}->{description}); + push(@s, \%hash); + + } + return @s; +} diff --git a/web/stream.tg13.gathering.org/index.tmpl b/web/stream.tg13.gathering.org/index.tmpl new file mode 100644 index 0000000..a565f0e --- /dev/null +++ b/web/stream.tg13.gathering.org/index.tmpl @@ -0,0 +1,35 @@ +<html> +<head> + <title>The Gathering <TMPL_VAR NAME=TG_FULL> Streams</title> + <link rel="stylesheet" type="text/css" href="singularity.css" media="all"> +</head> +<body> + <div id="innhold"> + <TMPL_UNLESS NAME=NOHEADER> + <h1>The Gathering <TMPL_VAR NAME=TG_FULL> Streams</h1> + </TMPL_UNLESS> + + <TMPL_LOOP NAME="STREAMS"> + <div class="stream-link"> + <div class="stream-icon"><img src="img/icon_<TMPL_VAR NAME=QUALITY>.png" /> <img src="img/icon_<TMPL_VAR NAME=TYPE>.png" /> <TMPL_IF NAME=LOCATION><img src="img/icon_<TMPL_VAR NAME=LOCATION>.png"></TMPL_IF></div> + <div class="stream-link-content"> + <a href="<TMPL_VAR NAME=TITLE_LINK>"><TMPL_VAR NAME=TITLE></a><br> + Source: <TMPL_VAR NAME=SOURCE><br> + Delivery: <TMPL_VAR NAME=delivery> <TMPL_IF NAME=IS_MULTICAST>(<a href='<TMPL_VAR NAME=UNICAST_LINK>'>problems? try unicast vlc link here</a>)</TMPL_IF> + + </div> + </div> + </TMPL_LOOP> + <div id="map"> + <img src="img/cam-map.png"> + </div> + + </div> + + <p>Problems with the non game streams? The easiest way to get hold of us is on IRC (EFNet); one of ViD, Rockj and Sesse should be available if there's too much traffic on #tg to be heard.</p> + <p><a href="http://stream.tg<TMPL_VAR NAME="TG">.gathering.org">http://stream.tg<TMPL_VAR NAME="TG">.gathering.org</a></p> + +</body> +</html> + + diff --git a/web/stream.tg13.gathering.org/ios/PLACEHOLDER b/web/stream.tg13.gathering.org/ios/PLACEHOLDER new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/web/stream.tg13.gathering.org/ios/PLACEHOLDER diff --git a/web/stream.tg13.gathering.org/ios/event.m3u8 b/web/stream.tg13.gathering.org/ios/event.m3u8 new file mode 100644 index 0000000..11152d3 --- /dev/null +++ b/web/stream.tg13.gathering.org/ios/event.m3u8 @@ -0,0 +1,16 @@ +#EXTM3U +#EXT-X-TARGETDURATION:5 +#EXT-X-VERSION:3 +#EXT-X-ALLOW-CACHE:NO +#EXT-X-MEDIA-SEQUENCE:27432 +#EXTINF:4.97, +http://stream.tg13.gathering.org/ios/event-00027432.ts +#EXTINF:4.04, +http://stream.tg13.gathering.org/ios/event-00027433.ts +#EXTINF:3.99, +http://stream.tg13.gathering.org/ios/event-00027434.ts +#EXTINF:3.97, +http://stream.tg13.gathering.org/ios/event-00027435.ts +#EXTINF:3.74, +http://stream.tg13.gathering.org/ios/event-00027436.ts +#EXT-X-ENDLIST diff --git a/web/stream.tg13.gathering.org/ios/stream.m3u8 b/web/stream.tg13.gathering.org/ios/stream.m3u8 new file mode 100644 index 0000000..d3d46a6 --- /dev/null +++ b/web/stream.tg13.gathering.org/ios/stream.m3u8 @@ -0,0 +1,8 @@ +#EXTM3U +#EXT-X-TARGETDURATION:5 +#EXT-X-VERSION:3 +#EXT-X-ALLOW-CACHE:NO +#EXT-X-MEDIA-SEQUENCE:1 +#EXTINF:3.84, +http://stream.tg13.gathering.org/ios/stream-00000001.ts +#EXT-X-ENDLIST diff --git a/web/stream.tg13.gathering.org/singularity.css b/web/stream.tg13.gathering.org/singularity.css new file mode 100644 index 0000000..05e1518 --- /dev/null +++ b/web/stream.tg13.gathering.org/singularity.css @@ -0,0 +1,1960 @@ +•/* http://meyerweb.com/eric/tools/css/reset/ + v2.0 | 20110126 + License: none (public domain) +*/ + +html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} +body { + line-height: 1.5; +} +ol, ul { + list-style: none; +} +blockquote, q { + quotes: none; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} + +/* @override http://www.gathering.org/tg12/files/content/design/css/typography.css */ + +/* Generic +------------------------------------------------------ */ +html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { + font-family: Arial, Sans-Serif; + font-weight: 400; +} +body { + font-size: 15px; + line-height: 20px; + color: #777; +} +/* Headings +------------------------------------------------------ */ +h1, h2, h3, h4, h5, h6 { font-weight: bold; color: #404040; } +h1 { font-size: 45px; line-height: 50px; margin-bottom: 15px; } +h2 { font-size: 25px; line-height: 31px; margin-bottom: 12px;} +h3 { font-size: 20px; line-height: 26px; } +h4 { font-size: 16px; line-height: 22px; } +h5 { font-size: 15px; line-height: 20px; } +h6 { font-size: 12px; line-height: 17px; } + +/* Text 'n stuff +------------------------------------------------------ */ +p { margin: 0 0 20px 0; } +.page p { + margin: 0 0 0.8em 0 !important; +} +blockquote { + margin: 20px; + padding: 0 0 0 40px; + color: #555; + font-style: italic; + color: #888; + position: relative; +} +blockquote p::before { + position: absolute; + top: 50px; + margin-left: -60px; + content: "\201D"; + font-size: 150px; + font-style: normal; + color: #00aaad; +} +blockquote p { + display: block; + margin-left: 40px !important; +} +blockquote small::before { + content: "\2013"; + margin: 5px; +} +blockquote small { + font-size: 13px; + margin-left: -55px; +} +strong { font-weight: bold; } + +ul { + margin: 0 0 20px 10px; + list-style-type: none; + position: relative; +} +ul.submenu ul { + margin-bottom: 0px; +} +ul li:before { + content: "\2022"; + position: absolute; + left: -17px; + width: 15px; + text-align: right; + color: #00aaad; + font-size: 13px; + line-height: 21px; +} +i, em { font-style: italic; } + +ol { + margin: 0 0 20px 15px; + list-style-type: none; + position: relative; + counter-reset: section; +} +ol > li { + counter-increment: section; +} +ol > li:before { + content: counter(section); + position: absolute; + left: -30px; + width: 23px; + text-align: right; + color: #00aaad; + font-size: 12px; + line-height: 22px; +} +dl dt { font-weight: bold; } +dd { margin: 0 0 0 20px; } + +a { color: #00aaad; text-decoration: none; } +a:hover { color: #c3027b; } +code, pre { + padding: 0 3px 2px; + font-family: Menlo, Monaco, "Courier New", monospace; + font-size: 12px; + color: #8F8F8F; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + background-color: #F8F8F8; + border: 1px solid #C0C4C5; +} +code { + padding: 3px 4px; + color: #00aaad; +} +pre { + display: block; + padding: 8.5px; + margin: 0 0 9px; + line-height: 18px; + white-space: pre; + white-space: pre-wrap; + word-break: break-all; +} +table { + margin-bottom: 20px; +} +th, td { + padding: 4px 5px; +} +td, th { + border-left: 1px solid #E2E2E2; +} +tr td:first-child, tr th:first-child { + border: none; +} +tr td { + text-align: right; +} +th { + font-weight: bold; + vertical-align: bottom; +} +th, td { + min-width: 100px; +} +th p, td p { + margin: 0; +} +tbody tr:nth-child(even) td, thead tr th { + background-color: #F2F2F2; +} +hr { + margin-top: 0.5em; + margin-bottom: 0.5em; + border: 0; + color: #D5D5D5; + background-color: #D5D5D5; + height: 1px; +} +.visible-phone { + display: none; +} +.title-container h2 { + font-family: Tahoma, Geneva, sans-serif; + font-size: 26px; + margin-bottom: 5px; + line-height: normal; +} +h2.size13 { font-size: 13px; } +h2.size14 { font-size: 14px; } +h2.size15 { font-size: 15px; } +h2.size16 { font-size: 16px; } +h2.size17 { font-size: 17px; } +h2.size18 { font-size: 18px; } +h2.size19 { font-size: 19px; } +h2.size20 { font-size: 20px; } +h2.size21 { font-size: 21px; } +h2.size22 { font-size: 22px; } +h2.size23 { font-size: 23px; } +h2.size24 { font-size: 24px; } +h2.size25 { font-size: 25px; } +h2.size26 { font-size: 26px; } +h2.size27 { font-size: 27px; } +h2.size28 { font-size: 28px; } +h2.size29 { font-size: 29px; } +h2.size30 { font-size: 30px; } +h2.size31 { font-size: 31px; } +h2.size32 { font-size: 32px; } +h2.size33 { font-size: 33px; } +h2.size34 { font-size: 34px; } +h2.size35 { font-size: 35px; } +h2.size36 { font-size: 36px; } +h2.size37 { font-size: 37px; } +h2.size38 { font-size: 38px; } +h2.size39 { font-size: 39px; } +h2.size40 { font-size: 40px; } +h2.size41 { font-size: 41px; } +h2.size42 { font-size: 42px; } +h2.size43 { font-size: 43px; } +h2.size44 { font-size: 44px; } +h2.size45 { font-size: 45px; } +h2.size46 { font-size: 46px; } +h2.size47 { font-size: 47px; } +h2.size48 { font-size: 48px; } +h2.size49 { font-size: 49px; } +h2.size50 { font-size: 50px; } +h2.size51 { font-size: 51px; } +h2.size52 { font-size: 52px; } +h2.size53 { font-size: 53px; } +h2.size54 { font-size: 54px; } +h2.size55 { font-size: 55px; } +h2.size56 { font-size: 56px; } +h2.size57 { font-size: 57px; } +h2.size58 { font-size: 58px; } +h2.size59 { font-size: 59px; } +h2.size60 { font-size: 60px; } +h2.size61 { font-size: 61px; } +h2.size62 { font-size: 62px; } +h2.size63 { font-size: 63px; } +h2.size64 { font-size: 64px; } +h2.size65 { font-size: 65px; } +h2.size66 { font-size: 66px; } +h2.size67 { font-size: 67px; } +h2.size68 { font-size: 68px; } +h2.size69 { font-size: 69px; } +h2.size70 { font-size: 70px; } +h2.size71 { font-size: 71px; } +h2.size72 { font-size: 72px; } +h2.size73 { font-size: 73px; } +h2.size74 { font-size: 74px; } +h2.size75 { font-size: 75px; } +h2.size76 { font-size: 76px; } +h2.size77 { font-size: 77px; } +h2.size78 { font-size: 78px; } +h2.size79 { font-size: 79px; } +h2.size80 { font-size: 80px; } +h2.size81 { font-size: 81px; } +h2.size82 { font-size: 82px; } +h2.size83 { font-size: 83px; } +h2.size84 { font-size: 84px; } +h2.size85 { font-size: 85px; } +h2.size86 { font-size: 86px; } +h2.size87 { font-size: 87px; } +h2.size88 { font-size: 88px; } +h2.size89 { font-size: 89px; } +h2.size90 { font-size: 90px; } +h2.size91 { font-size: 91px; } +h2.size92 { font-size: 92px; } +h2.size93 { font-size: 93px; } +h2.size94 { font-size: 94px; } +h2.size95 { font-size: 95px; } +h2.size96 { font-size: 96px; } +h2.size97 { font-size: 97px; } +h2.size98 { font-size: 98px; } +h2.size99 { font-size: 99px; } +h2.size100 { font-size: 100px; } + +.cite:before { + content: "\201C"; +} +.cite:after { + content: "\201D"; +} +.cite > .cite:before { + content: "\2018"; +} +.cite > .cite:after { + content: "\2019"; +} +.bullet:before { + content: "\2022"; +} +.dash:after { + content: "\2013"; +} +.hellip:after { + content: "\2026"; +} +.cite:lang(no):before { + content: "\00AB"; +} +.cite:lang(no):after { + content: "\00BB"; +} +/* Meta thingy +------------------------------------------------------ */ +.breadcrumbs span.delimiter:before { + content: "\25BA"; + margin-right: 8px; + font-size: 8px; + position: relative; + top: -2px; + margin: 0 5px 0 3px; + color: #00aaad; +} +.breadcrumbs { + font-size: 12px; + margin-bottom: 10px; +} +.summary, +.summary p { + font-size: 16px; + line-height: 22px; + font-weight: 600 !important; + margin-bottom: 10px; +} +.metainfo { margin: 10px 0; } +.byline, .meta { + color: #888; + display: block; + font-size: 12px; + margin-bottom: 0.8em; +} +.byline span.delimiter:before { + content: "\2022"; + margin-right: 8px; + font-size: 8px; + position: relative; + top: -2px; + margin: 0 5px 0 5px; + color: #00aaad; +} +.phototext { + margin-top: 5px; + line-height: 18px; +} +.photoline { + margin-top: 5px; + font-style: italic; + font-size: 12px; + float: right; +} +.page h1 { margin-top: 10px; } +.vignette { + background-color: #6e6e6e; + margin-top: 5px; + margin-bottom: 5px; + height: 8px; + position: relative; +} +.vignette span { + line-height: 19px; +} +div.page .vignette { + margin-bottom: 10px; +} +div.page .span11 img { + max-width: 488px; + height: auto; +} +.vignette > span { + text-transform: lowercase; + color: #6e6e6e; + display: block; + margin-left: 15px; + background-color: white; + position: absolute; + top: -6px; + font-size: 12px; + padding: 0 3px 0 3px; + font-weight: 500; +} +div.news33.category-news:nth-child(3n) { + clear: left; +} +div.portal > h1 { + font-size: 20px; + padding: 0 10px; + color: white; +} +h1.portal-creative { + background-color: #ec008c; +} +h1.portal-game { + background-color: #fba51e; +} +h1.portal-entertainmentlectures { + background-color: #819700; +} +div.portal > div.row { + margin-bottom: 40px; +} +div.category-news h2 a { + color: black; +} +/* + * CSS for The Gathering 2013. + * Copyright KANDU and contributors + */ + +/* HTML & BODY +------------------------------------------------------ */ +body { + background: url('/tg13/files/content/design/images/background.jpg') no-repeat; + background-position: top center; +} + +html, body { + height:100%; +} +body.iframe { + background-image: none; + height: auto; +} + +/* Generic styles +------------------------------------------------------ */ + +.hidden { display: none; } +menu { margin: 0; padding: 0; } + +/* Containers and rows +------------------------------------------------------ */ +.container { + width: 1320px; + margin: 0 auto; + zoom: 1; +} + +.content { + width: 840px; +} + +.container:before, +.container:after { + zoom: 1; +} +.container:before, +.container:after, +.content:before, +.content:after, +.row:before, +.row:after { + display: table; + line-height: 0; + content: ""; +} +.container:after, +.row:after { + clear: both; +} +.row { + margin-left: -40px; +} + +/* Main structure +------------------------------------------------------ */ +header, header > div.container { +} +header { + margin-bottom: 40px; +} +header > div.container { +} +header > div.container .inner { + float: left; + width: 830px; +} +footer a, footer, footer p, footer h4 { + color: #2d4f9e; +} +footer a:hover { + color: #fff; +} +header a { + color: #c3027b; +} +header a:hover { + color: #860050; +} +header > div.container .logo { + float: left; + width: 250px; +} +header .left, header .left > div { + float: right; +} +header .right { + margin-left: 10px; + float: right; + width: 180px; +} +header .when { + background-color: #5a0037; + padding: 10px; + color: white; + border-bottom-right-radius: 6px; + border-bottom-left-radius: 6px; + font-size: 11px; + line-height: 12px; + width: 110px; + text-align: center; +} +header .when-phone .when { + width: 120px; +} +header .when-phone { + float: right; +} +header .language { + margin-top: 10px; + line-height: 25px; + font-weight: 300; + margin-right: 10px; + padding-right: 10px; + border-right: 1px solid white; + font-size: 12px; +} +header ul.promo-menu { + padding-top: 40px; + margin: 0 0 0 15px; +} +header ul.promo-menu a { + font-weight: bold; + font-size: 13px; +} +header ul li:before { + margin-top: 2px; + content: "\25A0"; + position: absolute; + left: -15px; + width: 10px; + text-align: right; + color: #860050; + font-size: 18px; + line-height: 13px; +} +header .language a { + color: white; +} +header .language a:hover { + color: #2d4f9e; +} +footer { + margin-top: 80px; + background-color: #abdcff; + background-image: url('/tg13/files/content/design/images/footerbg.jpg'); + background-repeat: no-repeat; + background-position: center bottom; +} +footer > div.container { + padding: 0px 0px 150px 0px; +} +.footer-about { + margin-bottom: 40px; + height: 100px; + position: relative; +} +.footer-about > span { + position: absolute !important; + bottom: 0; left: 0; +} +footer > div.container > div.row { + margin-top: 80px; +} +footer ul { + margin: 0; +} +footer h4 { + margin-bottom: 20px; +} +footer div.full-span2 > iframe { + margin: 20px 0px; +} +footer a { + line-height: 25px; +} +footer ul li::before { + content: ""; +} +footer div.row { + margin-left: -20px; +} +footer div.row div.row { + margin-left: -40px; +} +.footnote p { + font-size: 13px; +} +.full-span9 { width: 1360px; } +.full-span8 { width: 1280px; } +.full-span7 { width: 1115px; } +.full-span6 { width: 950px; } +.full-span5 { width: 785px; } +.full-span4 { width: 620px; } +.full-span3 { width: 455px; } +.full-span2 { width: 290px; } +.full-span1 { width: 125px; } +.content, .sidebar { + float: left; +} +.content { + margin: 0 40px 0 40px; +} +.sidebar { + width: 200px; +} +.sidebar.sponsor img { + width: 200px; +} +.sidebar.sponsor img, +.sidebar.sponsor > div.vignette { + margin-bottom: 20px; +} +.sidebar.sponsor img { + filter: grayscale(100%); + -webkit-filter: grayscale(100%); -moz-filter: grayscale(100%); + -ms-filter: grayscale(100%); -o-filter: grayscale(100%); + filter: url(/tg13/files/content/design/css/filters.svg#grayscale); + filter: gray; + -webkit-filter: grayscale(1); +} +.sidebar.sponsor img:hover { + filter: none; + -webkit-filter: grayscale(0%); -moz-filter: grayscale(0%); + -ms-filter: grayscale(0%); -o-filter: grayscale(0%); +} +.fb-comments, .fb-comments *, .fb_iframe_widget, .fb_iframe_widget * {width: 100% !important;} +.span4 iframe { + width: 100%; +} +div.comments_header { + padding:8px; + background-color: #b1b1b1; + color: white; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + margin-bottom: 10px; + margin-top: 10px; +} +div.comments_header > div { + float: left; + margin-right: 8px; + content:url('/tg13/files/content/design/images/info.png'); +} +div.comments_header h4 { + line-height: 34px; + color: white; +} +div.comments_header p { + clear: both; + margin: 8px 0 0 0 !important; + font-size: 12px; + line-height: 15px; +} +.media-page { + margin-left: 40px; +} +.videoWrapper, #mediaspace { + position: relative; + padding-bottom: 56.25%; /* 16:9 */ + padding-top: 25px; + height: 0; + margin-bottom: 0.8em; +} +.videoWrapper iframe, #mediaspace embed { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} +.stream-icon { + float: left; + margin-right: 10px; +} +.stream-link { margin-bottom: 8px;} +#galleria { + width: 840px; +} + +/* Menu & Sidebar +------------------------------------------------------ */ + +menu { + list-style: none; +} +menu a { + color: #777; +} +menu a:hover, li[class^="menu-"] a:hover { + color: black; +} +li.menu-creative a, li.menu-creative span, li.menu-creative + menu.sub-menu a, li.menu-creative + menu.submenu span { + color: #ec008c; +} +li.menu-game a, li.menu-game span, li.menu-game + menu.sub-menu a, li.menu-game + menu.submenu span { + color: #fba51e; +} +li.menu-tickets a, li.menu-tickets span, li.menu-tickets + menu.sub-menu a, li.menu-tickets + menu.submenu span { + color: #00aaad; +} +li.menu-guide a, li.menu-guide span, li.menu-guide + menu.sub-menu a, li.menu-guide + menu.submenu span { + color: #034ea2; +} +li.menu-entertainment-lectures a, li.menu-entertainment-lectures span, li.menu-entertainment-lectures + menu.sub-menu a, li.menu-entertainment-lectures + menu.submenu span { + color: #819700; +} +menu.top-menu > li { + margin-bottom: 10px; +} + +div.top-menu-text > span { + color: #7595af; + font-size: 23px; + font-weight: bold; + display: table-row; + line-height: 23px; +} +div.top-menu-text > span.help-text { + font-weight: normal; + font-size: 14px; + display: table-row; + color: #a3a3a3; + line-height: 15px; +} +div.top-menu-text { + height: 38px; + padding: 6px 0 6px 0; + margin: 0 0 0 56px; +} +div.top-menu-icon { + width: 50px; + height: 50px; + float: left; + background-color: #bfd4e5; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} +menu.top-menu a:hover div.top-menu-text > span, +menu.top-menu a:hover div.top-menu-text > span.help-text { + color: #27448b; +} +menu.top-menu a:hover div.top-menu-icon { + background-color: #3d6db3; +} +div.top-menu-icon.icon-schedule { + background-image: url('/tg13/files/content/design/images/schedule.png'); +} +div.top-menu-icon.icon-tgtv { + background-image: url('/tg13/files/content/design/images/tgtv.png'); +} +div.top-menu-icon.icon-tng { + background-image: url('/tg13/files/content/design/images/tng.png'); +} +div.top-menu-icon.icon-forum { + background-image: url('/tg13/files/content/design/images/forum.png'); +} +div.top-menu-icon.icon-compo { + background-image: url('/tg13/files/content/design/images/compo.png'); +} +div.top-menu-icon.icon-news { + background-image: url('/tg13/files/content/design/images/news.png'); +} +menu.section-menu { + margin-top: 40px; + margin-left: 15px; +} +menu.section-menu li { + margin-bottom: 15px; +} +menu.sub-menu { + margin-bottom: 20px; + margin-left: 15px; +} +span.menu-expand { + display: block; + float: left; + margin-left: -15px; + cursor: pointer; +} + +/* Graphical Elements +------------------------------------------------------ */ +/* Language +------------------------------------------------------ */ +/* Search +------------------------------------------------------ */ +.search input { + vertical-align: top; + line-height: 1; +} +.search input[type="search"] { + -webkit-appearance: none; + box-sizing:content-box; + padding: 0; + padding-left: 3px; + margin: 0; + margin-top: 10px; + border: none; + color: #9dbfd9; + height: 25px; + width: 200px; + font-size: 12px; + font-style: italic; + border-radius: 3px; + line-height: 15px; +} +.search input:focus { + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + outline: 0; +} +input[type=search]::-webkit-search-decoration { + -webkit-appearance:none; +} +input::-webkit-input-placeholder, +isindex::-webkit-input-placeholder, +textarea::-webkit-input-placeholder, +input::-moz-placeholder, +textarea::-moz-placeholder { + font-style: italic; + color: silver; +} +/* News +------------------------------------------------------ */ +.news { position: relative; } + +.news100, .clearer, .span19 { width: 840px; } +.span18 { width: 796px; } +.span17 { width: 752px; } +.span16 { width: 708px; } +.span15 { width: 664px; } +.news75, .span14 { width: 620px; } +.span13 { width: 576px; } +.news66, .span-two-third { width: 547px; } +.span12 { width: 532px; } +.span11 { width: 488px; } +.span10 { width: 444px; } +.news50, .span9 { width: 400px; } +.span8 { width: 356px; } +.span7 { width: 312px; } +.span6 { width: 268px; } +.news33, .span-one-third { width: 253px; } +.span5 { width: 224px; } +.news25, .span4 { width: 180px; } +.span3 { width: 136px; } +.span2 { width: 92px; } +.span1 { width: 48px; } +.clearer { clear: both; margin: 0px 0px 0px 40px !important; } + +div[class^="news"] > span, +div[class^="full-span"] > span, +div[class^="span"] > span { + position: relative; + display: block; +} +div[class^="news"] p, +div[class^="full-span"] p, +div[class^="span"] p { + margin: 0; +} +.article { + float: left; + margin: 0px 0px 40px 40px; +} +.article a, +.article a:hover { + text-decoration: none; + color: #777; +} + +.news_img_100 { + width: 100%; + margin: 20px 0 10px 0; +} +img.news_img_right { + width: 50%; + float: right; + margin: 0 0 20px 40px; +} +.span2.social-news div { + margin-bottom: 10px; +} +.icon-more > a { + float: right; + font-size: 13px; + margin-right: 21px; +} +.icon-more { + position: relative; +} +.icon-more > a::after { + margin-top: 2px; + padding-left: 3px; + padding-top: 2px; + padding-bottom: 1px; + margin-left: 5px; + position: absolute; + content: "\25BA"; + color: white; + background-color: black; + -webkit-border-radius: 8px; + -moz-border-radius: 8px; + border-radius: 8px; + width: 13px; + height: 13px; + font-size: 11px; + line-height: 11px; +} + +/* Page +------------------------------------------------------ */ +.page { + float: left; + margin: 0px 0px 40px 40px; +} +.page .page { + margin-left: 0px; +} +.page .page.news33 { + margin-left: 40px; +} +div.news-portal-header { + width: 840px; + margin-left: 40px !important; +} +div[class^="full-span"], +.page div[class^="news"], +.page div[class^="span"]{ + float: left; + margin-left: 40px; +} +.page h3 a, +.page li a { + border: none; +} +.page-right { + float: right; + clear: right; + margin-bottom: 40px; + margin-left: 40px; +} +.page-right a { + border: none; +} +.page-sidebar { + margin-left: 40px; +} +.page-right h3, +.page-sidebar h3 { + border-bottom: solid 4px #c0c4c5; + position: relative; + margin: 0 0 10px 0; +} +.page-sidebar .meta { + text-transform: uppercase; + font-size: 10px; +} +.page-sidebar { + position: relative; +} +.related-news { + margin-bottom: 8px; +} +.img-container { + margin-bottom: -5px; +} +.img-container a { + display:block; +} +/* Article skins +------------------------------------------------------ */ +div.article.skin-important { + background-color: black; + color: white; +} +div.article.skin-important { + padding-bottom: 40px; +} +div.article.skin-important > div[class^="news"] > span.content-container, +div.article.skin-important > div[class^="news"] > span.title-container { + margin-left: 40px; + margin-right: 40px; +} +div.article.skin-important > div[class^="news"] > span.title-container { + padding-top: 40px; +} +div.article.skin-important p, +div.article.skin-important h2, +div.article.skin-important a, +div.article.skin-important a:hover, +div.article.skin-important a:visited { + color: white; +} +div.article.skin-game .vignette, +div.article.skin-creative .vignette, +div.article.skin-entertainment .vignette { + background-color: #000; + margin: 5px 0 5px 0; + height: 8px; + position: relative; +} +div.article.skin-game .vignette span, +div.article.skin-creative .vignette span, +div.article.skin-entertainment .vignette span { + text-transform: lowercase; + color: #000; + display: block; + margin-left: 15px; + background-color: white; + position: absolute; + top: -6px; + font-size: 12px; + padding: 0 3px 0 3px; + font-weight: 500; +} +div.article.skin-game .vignette, +div.vignette.category-game { + background-color: #fba51e; +} +div.article.skin-creative .vignette, +div.vignette.category-creative { + background-color: #ec008c; +} +div.article.skin-entertainment .vignette, +div.vignette.category-entertainmentlectures { + background-color: #819700; +} +div.article.skin-game .vignette span, +div.vignette.category-game span{ + color: #fba51e; +} +div.article.skin-creative .vignette span, +div.vignette.category-creative span{ + color: #ec008c; +} +div.article.skin-entertainment .vignette span, +div.vignette.category-entertainmentlectures span{ + color: #819700; +} +div.article.skin-info { + background-color: #E6E7E8; + padding-bottom: 40px; +} +div.article.skin-info > div[class^="news"] > span.content-container, +div.article.skin-info > div[class^="news"] > span.title-container { + margin-left: 40px; + margin-right: 40px; +} +div.article.skin-info > div[class^="news"] > span.title-container { + padding-top: 40px; +} +div.article.skin-important > div[class^="news"] > span.img-container, +div.article.skin-info > div[class^="news"] > span.img-container { + margin-bottom: -25px; +} + +/* Modal +------------------------------------------------------ */ +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000000; +} +.modal-backdrop.fade { + opacity: 0; +} +.modal-backdrop { + opacity: 0.8; + filter: alpha(opacity=80); +} +.modal-c { + width: 800px; +} +.modal { + position: absolute; + top: 206px; + z-index: 1050; + width: 800px; + margin: 0 auto; + background-color: #ffffff; + -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + -webkit-background-clip: padding-box; + -moz-background-clip: padding-box; + background-clip: padding-box; +} +.modal-body { + padding: 20px; + padding-top: 10px; +} +.modal-body .modal-form { + margin-bottom: 0; +} +.right { + float: right; +} + +/* Video +----------------------------------------------------- */ + +.video h2 { + margin-top: 10px; + margin-bottom: 5px; +} +.tags span { + margin-left: 5px; + padding: 3px 4px; + border: 1px solid #DDD; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} +.tags span:hover { + background-color: whiteSmoke; +} +.tags span:hover a { + color: black; +} +.tags span a { + color: #07A430; + border-bottom: none !important; +} +.tags span a:hover { + border-bottom: none !important; +} +.tags { + margin-bottom: 20px; +} + +/* Buttons +----------------------------------------------------- */ +.btn.stage, +.btn.stage.active, +.btn.stage:hover, +.btn.game, +.btn.game.active, +.btn.game:hover, +.btn.creative, +.btn.creative.active, +.btn.creative:hover, +.btn.auditorium, +.btn.auditorium.active, +.btn.auditorium:hover { + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + color: white; +} +.btn.stage { + background-color: #ff7800; + background-image: -moz-linear-gradient(top, #ff7800, #db4d00); + background-image: -ms-linear-gradient(top, #ff7800, #db4d00); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ff7800), to(#db4d00)); + background-image: -webkit-linear-gradient(top, #ff7800, #db4d00); + background-image: -o-linear-gradient(top, #ff7800, #db4d00); + background-image: linear-gradient(top, #ff7800, #db4d00); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff7800', endColorstr='#db4d00', GradientType=0); + border-color: #db4d00 #db4d00 #ca4900; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn.stage:hover, +.btn.stage:active, +.btn.stage.active, +.btn.stage.disabled, +.btn.stage[disabled] { + background-color: #db4d00; +} +.btn.stage:active, .btn.stage.active { + background-color: #e65a99 \9; +} +.btn.game { + background-color: #49afcd; + background-image: -moz-linear-gradient(top, #009cff, #0078c4); + background-image: -ms-linear-gradient(top, #009cff, #0078c4); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#009cff), to(#0078c4)); + background-image: -webkit-linear-gradient(top, #009cff, #0078c4); + background-image: -o-linear-gradient(top, #009cff, #0078c4); + background-image: linear-gradient(top, #009cff, #0078c4); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#009cff', endColorstr='#0078c4', GradientType=0); + border-color: #0078c4 #0078c4 #0062a0; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn.game:hover, +.btn.game:active, +.btn.game.active, +.btn.game.disabled, +.btn.game[disabled] { + background-color: #0078c4; +} +.btn.game:active, .btn.game.active { + background-color: #0089e0 \9; +} +.btn.auditorium { + background-color: #49afcd; + background-image: -moz-linear-gradient(top, #f33183, #dc0c64); + background-image: -ms-linear-gradient(top, #f33183, #dc0c64); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f33183), to(#dc0c64)); + background-image: -webkit-linear-gradient(top, #f33183, #dc0c64); + background-image: -o-linear-gradient(top, #f33183, #dc0c64); + background-image: linear-gradient(top, #f33183, #dc0c64); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f33183', endColorstr='#dc0c64', GradientType=0); + border-color: #dc0c64 #dc0c64 #bb004f; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn.auditorium:hover, +.btn.auditorium:active, +.btn.auditorium.active, +.btn.auditorium.disabled, +.btn.auditorium[disabled] { + background-color: #dc0c64; +} +.btn.auditorium:active, .btn.auditorium.active { + background-color: #e81f74 \9; +} +.btn.creative { + background-color: #009997; + background-image: -moz-linear-gradient(top, #009997, #007170); + background-image: -ms-linear-gradient(top, #009997, #007170); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#009997), to(#007170)); + background-image: -webkit-linear-gradient(top, #009997, #007170); + background-image: -o-linear-gradient(top, #009997, #007170); + background-image: linear-gradient(top, #009997, #007170); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#009997', endColorstr='#007170', GradientType=0); + border-color: #007170 #007170 #004e4d; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.btn.creative:hover, +.btn.creative:active, +.btn.creative.active, +.btn.creative.disabled, +.btn.creative[disabled] { + background-color: #007170; +} +.btn.creative:active, .btn.creative.active { + background-color: #007f7d \9; +} +.btn { + display: inline-block; + padding: 4px 10px 4px; + font-size: 13px; + line-height: 18px; + color: #333; + text-align: center; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + background-color: #FAFAFA; + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(white), color-stop(25%, white), to(#E6E6E6)); + background-image: -webkit-linear-gradient(white, white 25%, #E6E6E6); + background-image: -moz-linear-gradient(top, white, white 25%, #E6E6E6); + background-image: -ms-linear-gradient(white, white 25%, #E6E6E6); + background-image: -o-linear-gradient(white, white 25%, #E6E6E6); + background-image: linear-gradient(white, white 25%, #E6E6E6); + background-repeat: no-repeat; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); + border: 1px solid #CCC; + border-bottom-color: #BBB; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); + cursor: pointer; +} +.btn:first-child { + *margin-left: 0; +} +.btn:hover { + color: #333333; + text-decoration: none; + background-color: #e6e6e6; + background-position: 0 -15px; + -webkit-transition: background-position 0.1s linear; + -moz-transition: background-position 0.1s linear; + -ms-transition: background-position 0.1s linear; + -o-transition: background-position 0.1s linear; + transition: background-position 0.1s linear; +} +.btn:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn.active, .btn:active { + background-image: none; + -webkit-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + -moz-box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05); + background-color: #e6e6e6; + background-color: #d9d9d9 \9; + color: rgba(0, 0, 0, 0.5); + outline: 0; +} +.btn-group { + position: relative; + *zoom: 1; + *margin-left: .3em; +} +.btn-group:before, .btn-group:after { + display: table; + content: ""; +} +.btn-group:after { + clear: both; +} +.btn-group:first-child { + *margin-left: 0; +} +.btn-group + .btn-group { + margin-left: 5px; +} +.btn-group .btn { + position: relative; + float: left; + margin-left: -1px; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.btn-group .btn:first-child { + margin-left: 0; + -webkit-border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; + border-top-left-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + border-bottom-left-radius: 4px; +} +.btn-group .btn:last-child, .btn-group .dropdown-toggle { + -webkit-border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; + border-top-right-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -moz-border-radius-bottomright: 4px; + border-bottom-right-radius: 4px; +} +.btn-group .btn.large:first-child { + margin-left: 0; + -webkit-border-top-left-radius: 6px; + -moz-border-radius-topleft: 6px; + border-top-left-radius: 6px; + -webkit-border-bottom-left-radius: 6px; + -moz-border-radius-bottomleft: 6px; + border-bottom-left-radius: 6px; +} +.btn-group .btn.large:last-child, .btn-group .large.dropdown-toggle { + -webkit-border-top-right-radius: 6px; + -moz-border-radius-topright: 6px; + border-top-right-radius: 6px; + -webkit-border-bottom-right-radius: 6px; + -moz-border-radius-bottomright: 6px; + border-bottom-right-radius: 6px; +} +.btn-group .btn:hover, +.btn-group .btn:focus, +.btn-group .btn:active, +.btn-group .btn.active { + z-index: 2; +} +.page a.btn, +.page a.btn::hover { + border-bottom: 1px solid #CCC; +} + +/* Schedule +------------------------------------------------------ */ +a.stage { + color: white; + background-color: #819700; +} +a.game { + color: white; + background-color: #fba51e; +} +a.auditorium { + color: black; + background-color: #d8e600; +} +a.creative { + color: white; + background-color: #ec008c; +} +a.agora { + color: white; + background-color: #2e4f9e; +} +a.remove-filter { + color: white; + background-color: #CCC; +} +.filterLink { + padding: 3px 6px; + margin-right: 5px; + line-height: 28px; +} +.calendar .stage { + color: #819700; + font-size: 25px; +} +.calendar .game { + color: #fba51e; + font-size: 25px; +} +.calendar .auditorium { + color: #d8e600; + font-size: 25px; +} +.calendar .creative { + color: #ec008c; + font-size: 25px; +} +.calendar .agora { + color: #2e4f9e; + font-size: 25px; +} +.calendar tr td { + text-align: left; +} +.calendar td, .calendar td { + min-width: 0; +} +.calendar tbody tr:nth-child(even) td { + background-color: transparent; +} +.calendar tbody tr.odd td { + background-color: #F2F2F2; +} +/* Responsive +------------------------------------------------------ */ +@media (max-width: 1320px) { + footer { + width: 1320px; + } +} +@media (max-width: 1094px) { + div.news-portal-header { + width: 630px; + margin-left: 30px !important; + } + .news100, .clearer, .span19 { width: 630px; } + .span18 { width: 597px; } + .span17 { width: 564px; } + .span16 { width: 531px; } + .span15 { width: 498px; } + .news75, .span14 { width: 465px; } + .span13 { width: 432px; } + .news66, .span-two-third { width: 410px; } + .span12 { width: 399px; } + .span11 { width: 366px; } + .span10 { width: 333px; } + .news50, .span9 { width: 300px; } + .span8 { width: 267px; } + .span7 { width: 234px; } + .span6 { width: 201px; } + .news33, .span-one-third { width: 190px; } + .span5 { width: 168px; } + .news25, .span4 { width: 135px; } + .span3 { width: 102px; } + .span2 { width: 69px; } + .span1 { width: 36px; } + .clearer { margin: 0px 0px 0px 30px !important; } + .full-span9 { width: 1094px; } + .full-span8 { width: 1034x; } + .full-span7 { width: 901px; } + .full-span6 { width: 768px; } + .full-span5 { width: 635px; } + .full-span4 { width: 502px; } + .full-span3 { width: 369px; } + .full-span2 { width: 236px; } + .full-span1 { width: 103px; } + .img-container.news100 img { width: 630px; height: auto; } + .img-container.news75 img { width: 465px; height: auto; } + .img-container.news66 img { width: 410px; height: auto; } + .img-container.news50 img { width: 300px; height: auto; } + .img-container.news33 img { width: 190px; height: auto; } + .img-container.news25 img { width: 135px; height: auto; } + .title-container h2 { + margin-bottom: 4px; + font-size: 19px; + } + h2.size13 { font-size: 9px; } + h2.size14 { font-size: 10px; } + h2.size15 { font-size: 11px; } + h2.size16 { font-size: 12px; } + h2.size17 { font-size: 12px; } + h2.size18 { font-size: 13px; } + h2.size19 { font-size: 14px; } + h2.size20 { font-size: 15px; } + h2.size21 { font-size: 15px; } + h2.size22 { font-size: 16px; } + h2.size23 { font-size: 17px; } + h2.size24 { font-size: 18px; } + h2.size25 { font-size: 18px; } + h2.size26 { font-size: 19px; } + h2.size27 { font-size: 20px; } + h2.size28 { font-size: 21px; } + h2.size29 { font-size: 21px; } + h2.size30 { font-size: 22px; } + h2.size31 { font-size: 23px; } + h2.size32 { font-size: 24px; } + h2.size33 { font-size: 24px; } + h2.size34 { font-size: 25px; } + h2.size35 { font-size: 26px; } + h2.size36 { font-size: 27px; } + h2.size37 { font-size: 27px; } + h2.size38 { font-size: 28px; } + h2.size39 { font-size: 29px; } + h2.size40 { font-size: 30px; } + h2.size41 { font-size: 30px; } + h2.size42 { font-size: 31px; } + h2.size43 { font-size: 32px; } + h2.size44 { font-size: 33px; } + h2.size45 { font-size: 33px; } + h2.size46 { font-size: 34px; } + h2.size47 { font-size: 35px; } + h2.size48 { font-size: 36px; } + h2.size49 { font-size: 36px; } + h2.size50 { font-size: 37px; } + h2.size51 { font-size: 38px; } + h2.size52 { font-size: 39px; } + h2.size53 { font-size: 39px; } + h2.size54 { font-size: 40px; } + h2.size55 { font-size: 41px; } + h2.size56 { font-size: 42px; } + h2.size57 { font-size: 42px; } + h2.size58 { font-size: 43px; } + h2.size59 { font-size: 44px; } + h2.size60 { font-size: 45px; } + h2.size61 { font-size: 45px; } + h2.size62 { font-size: 46px; } + h2.size63 { font-size: 47px; } + h2.size64 { font-size: 48px; } + h2.size65 { font-size: 48px; } + h2.size66 { font-size: 49px; } + h2.size67 { font-size: 50px; } + h2.size68 { font-size: 51px; } + h2.size69 { font-size: 51px; } + h2.size70 { font-size: 52px; } + h2.size71 { font-size: 53px; } + h2.size72 { font-size: 54px; } + h2.size73 { font-size: 54px; } + h2.size74 { font-size: 55px; } + h2.size75 { font-size: 56px; } + h2.size76 { font-size: 57px; } + h2.size77 { font-size: 57px; } + h2.size78 { font-size: 58px; } + h2.size79 { font-size: 59px; } + h2.size80 { font-size: 60px; } + h2.size81 { font-size: 60px; } + h2.size82 { font-size: 61px; } + h2.size83 { font-size: 62px; } + h2.size84 { font-size: 63px; } + h2.size85 { font-size: 63px; } + h2.size86 { font-size: 64px; } + h2.size87 { font-size: 65px; } + h2.size88 { font-size: 66px; } + h2.size89 { font-size: 66px; } + h2.size90 { font-size: 67px; } + h2.size91 { font-size: 68px; } + h2.size92 { font-size: 69px; } + h2.size93 { font-size: 69px; } + h2.size94 { font-size: 70px; } + h2.size95 { font-size: 71px; } + h2.size96 { font-size: 72px; } + h2.size97 { font-size: 72px; } + h2.size98 { font-size: 73px; } + h2.size99 { font-size: 74px; } + h2.size100 { font-size: 75px; } + .content-container p { + font-size: 12px !important; + line-height: 14px !important; + font-weight: 300; + } + .article, .page, .page-right { + margin: 0px 0px 30px 30px; + } + .page div[class^="news"], + div[class^="full-span"], + .page div[class^="span"]{ + margin-left: 30px; + } + .content { + width: 630px; + margin: 0 30px 0 30px; + } + .row { + margin-left: -30px; + } + footer div.row { + margin-left: -15px; + } + .container, footer { + width: 1094px; + } + .sidebar { + width: 202px; + } + .img-container { + margin-bottom: 4px; + } + div[class^="news"] p, + div[class^="full-span"] p, + div[class^="span"] p { + line-height: 18px; + } + div.article.skin-important { + padding-bottom: 30px; + } + div.article.skin-important > div[class^="news"] > span.content-container, + div.article.skin-important > div[class^="news"] > span.title-*, + div.article.skin-info > div[class^="news"] > span.content-container, + div.article.skin-info > div[class^="news"] > span.title-container { + margin-left: 30px; + margin-right: 30px; + } + div.article.skin-important > div[class^="news"] > span.title-container, + div.article.skin-info > div[class^="news"] > span.title-container { + padding-top: 30px; + } + .row.news .page img { + width: 100%; + } + header > div.container .inner { + width: 640px; + } + div.page .span11 img { + max-width: 366px; + height: auto; + } + footer div.row div.row { + margin-left: -30px; + } + div.content > div.row > div.page > img { + width: 630px; + height: auto; + } + div.content > div.row.news > iframe.full { + width: 630px; + margin-left: 30px; + } + #galleria { + width: 630px; + } + .media-page { + margin-left: 30px; + } +} +@media (max-width: 767px) { + .media-page { + margin-left: 0px; + } + div.page.news33.category-news { + margin-bottom: 40px; + } + div.news-portal-header { + width: 100%; + margin-left: 0px !important; + } + .img-container.news100 img, + .img-container.news75 img, + .img-container.news66 img, + .img-container.news50 img, + .img-container.news33 img, + .img-container.news25 img, + div.page .span11 img { + width: 100%; + height: auto; + } + .img-container { width: 100%; } + .img-container a { display:block; width: 100%; } + div[class^="news"], + div[class^="span"], + div[class^="full-span"], + .page div[class^="news"], + .page div[class^="span"], + .clearer, .content, .container, .sidebar, .page, header > div.container .inner, footer { + width: auto; + float: none; + clear: both; + } + .content { + margin: 0px 20px 20px 20px; + } + div.article.skin-important { + padding-bottom: 20px; + } + div.article { + width: 100% !important; + margin-left: 0; + } + .row.news { + margin-left: 0; + } + div.article.skin-important > div[class^="news"] > span.content-container, + div.article.skin-important > div[class^="news"] > span.title-container, + div.article.skin-info > div[class^="news"] > span.content-container, + div.article.skin-info > div[class^="news"] > span.title-container { + width: auto; + margin-left: 10px; + margin-right: 10px; + } + div.article.skin-important > div[class^="news"] > span.title-container, + div.article.skin-info > div[class^="news"] > span.title-container { + padding-top: 20px; + } + .content > div[class^="news"], + div[class^="span"] { + margin: 0 0 0 20px; + } + h2[class^="size"] { + font-size: 15px; + } + .sidebar { + margin: 0 20px 20px 20px; + } + header, footer { + padding: 0 20px 20px 20px; + } + .sidebar.sponsor a { + margin: 0 10px 10px 0; + float: left; + } + .sidebar.sponsor div.vignette { + clear: both; + } + .footnote > div { + width: auto; + display: block; + text-align: center; + } + footer div[class^="full-span"] { + margin-bottom: 20px; + } + .social-news > div { + float: left; + margin-right: 20px; + } + menu.top-menu { + height: 100px; + } + menu.top-menu li { + width: 45%; + float: left; + background-color: #bfd4e5; + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + } + menu.top-menu li > a { + color: white; + } + menu.top-menu .top-menu-text { + text-align: center; + margin: 0; + } + menu.top-menu .top-menu-text > span:first-child { + display: block; + font-size: 15px; + line-height: 38px; + } + menu.top-menu > li:nth-child(odd) { + margin-right: 10%; + } + div.top-menu-icon { + display: none; + } + .hidden-phone { + display: none; + } + .visible-phone { + display: block; + } + menu.section-menu { + margin: 20px 0px 0px; + padding: 60px 10px 10px; + background-color: #555; + border-radius: 5px; + color: white; + } + menu.section-menu li { + padding: 6px; + border-radius: 5px; + } + menu.section-menu a, menu.section-menu a:hover { + color: white; + } + div.top-menu-text > span.help-text { + display: none; + } + th, td { + min-width: 0px; + } + .section-menu-button { + float: right; + margin-bottom: 15px; + } + .section-menu-button a { + width: 70px; + height: 50px; + line-height: 50px; + display: block; + text-align: center; + border-radius: 5px; + background-color: #555; + color: white; + } + .section-menu-button a:hover, menu.section-menu li:hover { + background-color: #6f6f6f; + } + h1 { font-size: 25px; line-height: 30px; margin-bottom: 10px; } + h2 { font-size: 20px; line-height: 25px; margin-bottom: 8px;} + h3 { font-size: 15px; line-height: 20px; } + h4 { font-size: 12px; line-height: 17px; } + h5 { font-size: 12px; line-height: 17px; } + h6 { font-size: 12px; line-height: 17px; } + .row.news .page { + margin: 0px; + } + header { + margin-bottom: 0px; + } + menu.top-menu a:hover div.top-menu-text > span, menu.top-menu a:hover div.top-menu-text > span.help-text, div.top-menu-text > span { + color: white; + } + div.logo { + width: 132px; + } + div.logo img { + height: 100px; + } + div.inner div.when { + display: none; + } + div.inner div.right { + float: left; + } + footer > div.container > div.row { + margin-top: 30px; + } + div[class^="full-span"] { + margin: 0px 0px 0px 15px; + } + footer .search input[type="search"]{ + width: 100%; + } + footer .language { + text-align: center; + } + footer > div.container { + padding: 0px 0px 90px 0px; + } + header ul.promo-menu { + padding-top: 20px; + } + footer div.row div.row { + margin-left: -20px; + } + div.content > div.row > div.page > img { + width: 100%; + height: auto; + } + div.content > div.row.news > iframe.full { + width: 100%; + margin-left: 0px; + } + #galleria { + width: 100%; + } + div.calendar table, + div.calendar table thead, + div.calendar table tbody, + div.calendar table th, + div.calendar table td, + div.calendar table tr { + display: block; + } + div.calendar table thead tr { + position: absolute; + top: -9999px; + left: -9999px; + } + div.calendar table td { + border: none; + border-bottom: 1px solid #CCC; + position: relative; + padding-left: 20%; + white-space: normal; + text-align: left; + } + div.calendar table td:before { + position: absolute; + top: 6px; + left: 6px; + width: 45%; + padding-right: 10px; + white-space: nowrap; + text-align:left; + font-weight: bold; + content: attr(data-title); + } + .filterLink { + clear: right; + display: block; + text-align: center; + } + li.menu-creative a, li.menu-creative span, li.menu-creative + menu.sub-menu a, li.menu-creative + menu.submenu span, + li.menu-game a, li.menu-game span, li.menu-game + menu.sub-menu a, li.menu-game + menu.submenu span, + li.menu-tickets a, li.menu-tickets span, li.menu-tickets + menu.sub-menu a, li.menu-tickets + menu.submenu span, + li.menu-guide a, li.menu-guide span, li.menu-guide + menu.sub-menu a, li.menu-guide + menu.submenu span, + li.menu-entertainment-lectures a, li.menu-entertainment-lectures span, li.menu-entertainment-lectures + menu.sub-menu a, li.menu-entertainment-lectures + menu.submenu span { + color: white; + } +} diff --git a/web/stream.tg13.gathering.org/singularity.png b/web/stream.tg13.gathering.org/singularity.png Binary files differnew file mode 100644 index 0000000..3a13cdf --- /dev/null +++ b/web/stream.tg13.gathering.org/singularity.png diff --git a/web/stream.tg13.gathering.org/stream.pl b/web/stream.tg13.gathering.org/stream.pl new file mode 100755 index 0000000..8ccf05c --- /dev/null +++ b/web/stream.tg13.gathering.org/stream.pl @@ -0,0 +1,87 @@ +#!/usr/bin/perl -I /srv/streamlib + +use warnings; +use strict; + +use stream; +use stream::config; +use CGI; +my $client = CGI->new; + +my $stream = $client->param('stream'); +my $interlaced = $client->param('interlaced'); +my $delivery = $client->param('delivery'); + +my $v4net = $stream::config::v4net; +my $v6net = $stream::config::v6net; +my $multicast_ip = $stream::config::multicast; +my $tg = $stream::config::tg; +my $base_url = $stream::config::vlc_base_host; +my %streams = %stream::config::streams; + + + +#default +if (not defined $delivery) { + $delivery = "multicast"; +} + +if((not defined $stream) or (not defined $delivery)) { + print $client->header(); + die "No stream and/or delivery method, robots unhappy :/\n"; +} + +my $url = ""; +my $port_del = ""; +my $port_str = ""; +my $extinf = ""; +my $flash_appendix = ""; + +my $clip = $client->remote_addr(); + +if (exists($streams{$stream})) { + my $is_multicast = 0; + # add force is_ip_local in check? + $is_multicast = 1 if (exists($streams{$stream}->{has_multicast}) && $delivery eq "multicast"); + + if ($is_multicast) { + $port_del = 20; + $extinf .= "Multicasted"; + $url = $streams{$stream}->{multicast_ip}; + } else { + $port_del = 30; + $extinf .= "Unicasted"; + $url = $base_url; + + if ($streams{$stream}->{is_flash}) { + $port_del = 50; + $flash_appendix = "/stream.flv"; + } + } + + $port_del = $streams{$stream}->{preport} if (defined($streams{$stream}->{preport})); + $port_str = $streams{$stream}->{port}; + $extinf .= " $streams{$stream}->{title}"; + +} else { + &error("No stream and/or delivery method, robots unhappy :-/"); +} + +#print out new file +print $client->header(-type => "application/vlc", + "-Content-disposition" => "attachment; filename=tg-".$delivery."-".$stream.".vlc" +); + +print "#EXTM3U\n"; +print "#EXTINF:-1,TG$tg $extinf\n"; +if(defined $interlaced && $interlaced == 1) { + print "#EXTVLCOPT:deinterlace=1\n"; + print "#EXTVLCOPT:deinterlace-mode=linear\n"; +} +print "$url:$port_del$port_str$flash_appendix\n"; + +sub error($) { + my $message = shift; + print $client->header(); + die($message."\n"); +} diff --git a/web/stream.tg13.gathering.org/streamstats-fast.pl b/web/stream.tg13.gathering.org/streamstats-fast.pl new file mode 100755 index 0000000..f4caa24 --- /dev/null +++ b/web/stream.tg13.gathering.org/streamstats-fast.pl @@ -0,0 +1,15 @@ +#! /usr/bin/perl +use strict; +use warnings; +use POSIX; +use CGI qw(fatalsToBrowser); + +my $port_spec = CGI::param('port'); +my $proto_spec = CGI::param('proto'); +my $audience_spec = CGI::param('audience'); + +print CGI::header(-type=>'image/png'); + +# I'm sure this is really safe +system("/srv/stream.tg13.gathering.org/fix_count.pl | /srv/stream.tg13.gathering.org/streamstats - $port_spec $proto_spec $audience_spec"); +#system("/srv/stream.tg13.gathering.org/streamstats", "/home/techserver/cleaned_datacube.log", $port_spec, $proto_spec, $audience_spec); diff --git a/web/stream.tg13.gathering.org/streamstats.cpp b/web/stream.tg13.gathering.org/streamstats.cpp new file mode 100644 index 0000000..e81419f --- /dev/null +++ b/web/stream.tg13.gathering.org/streamstats.cpp @@ -0,0 +1,217 @@ +#include <stdio.h> +#include <string.h> +#include <map> +#include <set> +#include <string> +#include <vector> +#include <stdlib.h> + +using namespace std; + +map<string, string> port_desc = { + { "3013", "main (3013)" }, + { "3014", "main-sd (3014)" }, + { "3015", "webcam (3015)" }, + { "3016", "webcam-south (3016)" }, + { "3017", "webcam-south-transcode (3017)" }, + { "3018", "webcam-fisheye (3018)" }, + { "5013", "main-transcode (5013)" }, + { "5015", "webcam-transcode (5015)" }, +}; + +struct Spec { + set<string> incl; + bool compare; +}; + +Spec parse_spec(const string &spec) +{ + Spec ret; + ret.compare = false; + + if (spec == "compare") { + ret.compare = true; + return ret; + } + if (spec == "dontcare") { + return ret; + } + + const char *ptr = spec.c_str(); + if (strncmp(ptr, "compare:", 8) == 0) { + ptr += 8; + ret.compare = true; + } + + for ( ;; ) { + const char *end = strchr(ptr, ','); + if (end == NULL) { + ret.incl.insert(ptr); + break; + } else { + ret.incl.insert(string(ptr, end)); + ptr = end + 1; + } + } + + return ret; +} + +bool filter(const string &entry, const Spec &spec) +{ + if (spec.incl.empty()) { + return false; + } + return spec.incl.count(entry) == 0; +} + +vector<string> get_stream_id(const string& port, const string &proto, const string &audience, + const Spec& port_spec, const Spec &proto_spec, const Spec &audience_spec) +{ + vector<string> keys; + if (port_spec.compare) { + if (port_desc.count(port)) { + keys.push_back(port_desc[port]); + } else { + char buf[256]; + sprintf(buf, "___%s___", port.c_str()); + keys.push_back(buf); + } + } + if (proto_spec.compare) { + keys.push_back(proto); + } + if (audience_spec.compare) { + keys.push_back(audience); + } + return keys; +} + +string get_stream_desc(const vector<string> &stream_id) +{ + string ret; + for (int i = 0; i < stream_id.size(); ++i) { + if (i != 0) { + ret += ","; + } + ret += stream_id[i]; + } + return ret; +} + +int main(int argc, char **argv) +{ + Spec port_spec = parse_spec(argv[2]); + Spec proto_spec = parse_spec(argv[3]); + Spec audience_spec = parse_spec(argv[4]); + + map<string, map<vector<string>, int> > lines; + map<vector<string>, int> stream_ids; + vector<string> stream_descs; + + // Parse the log. + FILE *fp; + if (strcmp(argv[1], "-") == 0) { + fp = stdin; + } else { + fp = fopen(argv[1], "r"); + } + while (!feof(fp)) { + char buf[1024]; + fgets(buf, 1024, fp); + + if (buf == NULL) { + break; + } + char *ptr = strchr(buf, '\n'); + if (ptr != NULL) { + *ptr = 0; + } + + char *date = strtok(buf, " "); + char *port = strtok(NULL, " "); + char *proto = strtok(NULL, " "); + char *audience = strtok(NULL, " "); + char *count = strtok(NULL, " "); + + if (date == NULL || port == NULL || proto == NULL || audience == NULL || count == NULL) { + continue; + } + + if (filter(port, port_spec)) { + continue; + } + if (filter(proto, proto_spec)) { + continue; + } + if (filter(audience, audience_spec)) { + continue; + } + + vector<string> stream_id = get_stream_id(port, proto, audience, port_spec, proto_spec, audience_spec); + if (stream_ids.count(stream_id) == 0) { + int stream_id_num = stream_ids.size(); + stream_ids.insert(make_pair(stream_id, stream_id_num)); + stream_descs.push_back(get_stream_desc(stream_id)); + } + lines[date][stream_id] += atoi(count); + } + fclose(fp); + + // Output. + char *data_file = tempnam(NULL, "data"); + FILE *datafp = fopen(data_file, "w"); + if (datafp == NULL) { + perror(data_file); + exit(1); + } + + vector<int> cols(stream_ids.size()); + for (auto& it : lines) { + const string& date = it.first; + + for (const auto& it2 : stream_ids) { + const vector<string>& stream_id = it2.first; + int stream_id_num = it2.second; + + cols[stream_id_num] = it.second[stream_id]; // note: might zero-initialize + } + fprintf(datafp, "%s", date.c_str()); + for (int i = 0; i < cols.size(); ++i) { + fprintf(datafp, " %d", cols[i]); + } + fprintf(datafp, "\n"); + } + fclose(datafp); + + // Make gnuplot script. + char *plot_file = tempnam(NULL, "plot"); + FILE *plotfp = fopen(plot_file, "w"); + if (plotfp == NULL) { + perror(plot_file); + exit(1); + } + + fprintf(plotfp, "set terminal png\n"); + fprintf(plotfp, "set xdata time\n"); + fprintf(plotfp, "set timefmt \"20%%y-%%m-%%d-%%H:%%M:%%S\"\n"); + fprintf(plotfp, "set xtics axis \"2000-00-00-01:00:00\"\n"); + fprintf(plotfp, "set format x \"%%H\"\n"); + + fprintf(plotfp, "plot"); + for (int i = 0; i < cols.size(); ++i) { + if (i == 0) { + fprintf(plotfp, " "); + } else { + fprintf(plotfp, ","); + } + fprintf(plotfp, "\"%s\" using 1:%d title \"%s\" with lines", data_file, i + 2, stream_descs[i].c_str()); + } + fprintf(plotfp, "\n"); + + fclose(plotfp); + + char buf[1024]; + sprintf(buf, "gnuplot < %s", plot_file); + system(buf); +} diff --git a/web/stream.tg13.gathering.org/streamstats.html b/web/stream.tg13.gathering.org/streamstats.html new file mode 100644 index 0000000..5d6adc7 --- /dev/null +++ b/web/stream.tg13.gathering.org/streamstats.html @@ -0,0 +1,81 @@ +<html> + <head> + <script> + function construct_url(name, choices) { + // port + var url = name + '='; + if (document.getElementById('split_' + name).checked) { + url += 'compare:'; + } + var choices_so_far = 0; + for (var i = 0; i < choices.length; ++i) { + var check = document.getElementById(name + '_' + choices[i]); + if (!check.checked) { + continue; + } + if (choices_so_far++ != 0) { + url += ','; + } + url += choices[i]; + } + return url; + } + + function update() { + var url = 'http://stream.tg13.gathering.org/streamstats-fast.pl?'; + url += construct_url('port', [ 3013, 3014, 3015, 3016, 3017, 3018, 5013, 5015 ]); + url += '&' + construct_url('proto', [ 'IPv4', 'IPv6' ]); + url += '&' + construct_url('audience', [ 'internal', 'external' ]); + + document.getElementById('graph').src = url; + } + </script> + </head> + <body> + <table> + <tr> + <th>Ports:</th> + <td> + <label><input type="checkbox" id="port_3013" checked="checked" onchange="update();" /> 3013 (Main)</label><br /> + <label><input type="checkbox" id="port_3014" checked="checked" onchange="update();" /> 3014 (Main SD)</label><br /> + <label><input type="checkbox" id="port_3015" checked="checked" onchange="update();" /> 3015 (Webcam)</label><br /> + <label><input type="checkbox" id="port_3016" checked="checked" onchange="update();" /> 3016 (Webcam south)</label><br /> + <label><input type="checkbox" id="port_3017" checked="checked" onchange="update();" /> 3017 (Webcam south transcode)</label><br /> + <label><input type="checkbox" id="port_3018" checked="checked" onchange="update();" /> 3018 (Fisheye)</label><br /> + <label><input type="checkbox" id="port_5013" checked="checked" onchange="update();" /> 5013 (Main LQ/Flash)</label><br /> + <label><input type="checkbox" id="port_5015" checked="checked" onchange="update();" /> 5015 (Webcam LQ/Flash)</label> + </td> + <td> + <label><input type="checkbox" id="split_port" onchange="update();" /> Split</label> + </td> + </tr> + <tr> + <th>Protocol:</th> + <td> + <label><input type="checkbox" id="proto_IPv4" checked="checked" onchange="update();" /> IPv4</label><br /> + <label><input type="checkbox" id="proto_IPv6" checked="checked" onchange="update();" /> IPv6</label><br /> + </td> + <td> + <label><input type="checkbox" id="split_proto" onchange="update();" /> Split</label> + </td> + </tr> + <tr> + <th>Audience:</th> + <td> + <label><input type="checkbox" id="audience_internal" checked="checked" onchange="update();" /> Internal</label><br /> + <label><input type="checkbox" id="audience_external" checked="checked" onchange="update();" /> External</label><br /> + </td> + <td> + <label><input type="checkbox" id="split_audience" onchange="update();" /> Split</label> + </td> + </tr> + <tr> + <td colspan="3"> + <input type="button" value="Update display" onclick="update();" /> + </td> + </tr> + </table> + <p><img src="" id="graph" /></p> + <script>update();</script> + </body> +</html> diff --git a/web/stream.tg13.gathering.org/streamstats.pl b/web/stream.tg13.gathering.org/streamstats.pl new file mode 100755 index 0000000..e4c20f9 --- /dev/null +++ b/web/stream.tg13.gathering.org/streamstats.pl @@ -0,0 +1,116 @@ +#! /usr/bin/perl +use strict; +use warnings; +use POSIX; +use CGI qw(fatalsToBrowser); + +my %port_spec = prepare_spec(CGI::param('port')); +my %proto_spec = prepare_spec(CGI::param('proto')); +my %audience_spec = prepare_spec(CGI::param('audience')); + +#open LOG, "<", "/home/techserver/count_datacube.log" +open LOG, "-|", "/home/techserver/fix_count.pl" +#open LOG, "<", "/home/techserver/cleaned_datacube.log" + or die "count_datacube.log: $!"; + +our %desc = ( + 3013 => 'main (3013)', + 3014 => 'main-sd (3014)', + 3015 => 'webcam (3015)', + 3016 => 'webcam-south (3016)', + 3017 => 'webcam-south-transcode (3017)', + 3018 => 'webcam-fisheye (3018)', + 5013 => 'main-transcode (5013)', + 5015 => 'webcam-transcode (5015)', +); + +my $lines = {}; +my %streams = (); + +while (<LOG>) { + chomp; + my ($date, $port, $proto, $audience, $count) = split /\s+/; + next if (filter($port, $proto, $audience)); + my $stream_id = get_stream_id($port, $proto, $audience); + $streams{$stream_id} = 1; + $lines->{$date}{$stream_id} += $count; +} + +close LOG; + +print CGI::header(-type=>'image/png'); + +my $tmpfile = POSIX::tmpnam(); +open GRAPH, ">", $tmpfile + or die "$tmpfile: $!"; +for my $date (sort keys %$lines) { + my @cols = (); + for my $stream (keys %streams) { + push @cols, ($lines->{$date}{$stream} // "0"); + } + print GRAPH "$date ", join(' ', @cols), "\n"; +} +close GRAPH; + +my $tmpfile2 = POSIX::tmpnam(); +open GNUPLOT, ">", $tmpfile2 + or die "$tmpfile2: $!"; +print GNUPLOT "set terminal png\n"; +print GNUPLOT "set xdata time\n"; +print GNUPLOT "set timefmt \"20%y-%m-%d-%H:%M:%S\"\n"; +print GNUPLOT "set xtics axis \"2000-00-00-01:00:00\"\n"; +print GNUPLOT "set format x \"%H\"\n"; + +my @plots = (); +my $idx = 2; +for my $stream (keys %streams) { + push @plots, "\"$tmpfile\" using 1:$idx title \"$stream\" with lines"; + ++$idx; +} +print GNUPLOT "plot ", join(', ', @plots); + +# \"$tmpfile\" using 0:2 with lines, \"$tmpfile\" using 0:3 with lines\n"; +close GNUPLOT; + +system("gnuplot < $tmpfile2"); + +sub prepare_spec { + my $spec = shift; + return () if ($spec eq 'compare' || $spec eq 'dontcare'); + $spec =~ s/^compare://; + + my %ret = (); + for my $s (split /,/, $spec) { + $ret{$s} = 1; + } + return %ret; +} + +sub filter { + my ($port, $proto, $audience) = @_; + return 1 if (filter_list(\%port_spec, $port)); + return 1 if (filter_list(\%proto_spec, $proto)); + return 1 if (filter_list(\%audience_spec, $audience)); + return 0; +} + +sub filter_list { + my ($spec, $candidate) = @_; + return 0 if ((scalar keys %$spec) == 0); + return !exists($spec->{$candidate}); +} + +sub get_stream_id { + my ($port, $proto, $audience) = @_; + my @keys = (); + if (CGI::param('port') =~ /^compare/) { + if (exists($desc{$port})) { + push @keys, $desc{$port}; + } else { + push @keys, "___" . $port . "___"; + } + } + push @keys, $proto if (CGI::param('proto') =~ /^compare/); + push @keys, $audience if (CGI::param('audience') =~ /^compare/); + return join(',', @keys); +} diff --git a/web/stream.tg13.gathering.org/superawesomeness.css b/web/stream.tg13.gathering.org/superawesomeness.css new file mode 100644 index 0000000..b8c5545 --- /dev/null +++ b/web/stream.tg13.gathering.org/superawesomeness.css @@ -0,0 +1,24 @@ +* { font-family: 'Open Sans', sans-serif; + +} + +body { + background: #fff; color: #000; opacity: 1; +} + +#spaceship { background: url('singularity.png'); width: 237px; height: 200px;position:absolute; top: 0; right: 0;z-index: -1} + +@media screen and (max-width: 1145px) { /* Min iPad size*/ + #spaceship { + background: #fff; + } +} + + +/* #innhold { position: absolute; left:0px ; top: 50px; margin: 0 50px 0 50px; z-index: 9; width: 520px; }*/ +#innhold { width: 480px; } +footer { clear: both; width:480px; } +a { color: #000; } +h4 { margin: 0; margin-top: 35px;} +p { margin: 0; padding: 0; } +li { margin-bottom: 14px; } diff --git a/web/stream.tg13.gathering.org/test.pl b/web/stream.tg13.gathering.org/test.pl new file mode 100755 index 0000000..3b440d5 --- /dev/null +++ b/web/stream.tg13.gathering.org/test.pl @@ -0,0 +1,70 @@ +#!/usr/bin/perl -I /srv/streamlib +use warnings; +use strict; +use CGI; +use Geo::IP; +use NetAddr::IP; +use Net::IP; +# apt-get install libnet-ip-perl libnetaddr-ip-perl +use HTML::Template; +use stream; +use stream::config; + +my $client = CGI->new; + +my $v4net = $stream::config::v4net; +my $v6net = $stream::config::v6net; +my $tg = $stream::config::tg; +my $tg_full = $stream::config::tg_full; +my %streams = %stream::config::streams; + +my $force_unicast = $client->param('forceunicast'); + +my $location = undef; + +print $client->header(); + +my $clip = $client->remote_addr(); +my $template = HTML::Template->new(filename => 'test.tmpl'); +my $is_local = &is_ip_local($clip, $v4net, $v6net); + +my @streams = &html_local_test(); +$template->param(TG => $tg); +$template->param(TG_FULL => $tg_full); +$template->param(STREAMS => \@streams); +print $template->output(); + + +sub html_local_test() { + my @s = (); + foreach my $name (sort { $streams{$a}->{priority} <=> $streams{$b}->{priority} } keys %streams) { + my $title_link = "http://stream.tg$tg.gathering.org/stream.pl?delivery=%s&stream=${name}&interlaced=%s"; + my $multicast_link = $streams{$name}->{has_multicast} ? "multicast" : "unicast"; + $multicast_link = "unicast" if ($force_unicast == 1 || not $is_local); + + if ($streams{$name}->{external}) { + $title_link = $streams{$name}->{url}; + } else { + $title_link = sprintf($title_link, $multicast_link, $streams{$name}->{interlaced}); + } + my %hash = ( + 'title_link' => $title_link, + 'title' => $streams{$name}->{title}, + 'source' => $streams{$name}->{source}, + 'quality' => $streams{$name}->{quality}, + 'location' => $streams{$name}->{location}, + 'type' => $streams{$name}->{type}, + 'delivery' => $multicast_link, + ); + if ($multicast_link eq "multicast") { + $hash{'is_multicast'} .= 1; + my $unicast_link = $title_link; + $unicast_link=~s/multicast/unicast/g; + $hash{'unicast_link'} .= $unicast_link; + } + $hash{'description'} .= $streams{$name}->{description} if exists($streams{$name}->{description}); + push(@s, \%hash); + + } + return @s; +} diff --git a/web/stream.tg13.gathering.org/test.tmpl b/web/stream.tg13.gathering.org/test.tmpl new file mode 100644 index 0000000..ea0eaca --- /dev/null +++ b/web/stream.tg13.gathering.org/test.tmpl @@ -0,0 +1,31 @@ +<html> +<head> + <title>The Gathering <TMPL_VAR NAME=TG_FULL> Streams</title> + <link rel="stylesheet" type="text/css" href="singularity.css" media="all"> +</head> +<body> + <div id="innhold"> + <h1>The Gathering <TMPL_VAR NAME=TG_FULL> Streams</h1> + <TMPL_LOOP NAME="STREAMS"> + <div class="stream-link"> + <div class="stream-icon"><img src="img/icon_<TMPL_VAR NAME=QUALITY>.png" /> <img src="img/icon_<TMPL_VAR NAME=TYPE>.png" /> <TMPL_IF NAME=LOCATION><img src="img/icon_<TMPL_VAR NAME=LOCATION>.png"></TMPL_IF></div> + <div class="stream-link-content"> + <a href="<TMPL_VAR NAME=TITLE_LINK>"><TMPL_VAR NAME=TITLE></a><br> + Source: <TMPL_VAR NAME=SOURCE><br> + Delivery: <TMPL_VAR NAME=delivery> <TMPL_IF NAME=IS_MULTICAST>(<a href='<TMPL_VAR NAME=UNICAST_LINK>'>problems? try unicast vlc link here</a>)</TMPL_IF> + </div> + </div> + </TMPL_LOOP> + <div id="map"> + <img src="img/cam-map.png"> + </div> + + </div> + + <p>Problems with the non game streams? The easiest way to get hold of us is on IRC (EFNet); one of ViD, Rockj and Sesse should be available if there's too much traffic on #tg to be heard.</p> + <p><a href="http://stream.tg<TMPL_VAR NAME="TG">.gathering.org">http://stream.tg<TMPL_VAR NAME="TG">.gathering.org</a></p> + +</body> +</html> + + diff --git a/web/streamlib/stream.pm b/web/streamlib/stream.pm new file mode 100644 index 0000000..c28136e --- /dev/null +++ b/web/streamlib/stream.pm @@ -0,0 +1,36 @@ +package stream; +use strict; +use warnings; + +BEGIN { + use Exporter(); + + our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS); + + @ISA = qw(Exporter); + $VERSION = 1.00; + @EXPORT = qw(&is_ip_local); + +} + +sub is_ip_local($$$) { + my $clip = shift; + my $v4net = shift; + my $v6net = shift; + return 0 unless defined($clip); + + my $is_local = 0; + if ($clip =~ m/\:/){ + if (NetAddr::IP->new($clip)->within($v6net)){ + $is_local = 1; + } + } else { + if (NetAddr::IP->new($clip)->within($v4net)){ + $is_local = 1; + } + } + return $is_local; +} + + +1; diff --git a/web/streamlib/stream/config.pm b/web/streamlib/stream/config.pm new file mode 100644 index 0000000..7c488b6 --- /dev/null +++ b/web/streamlib/stream/config.pm @@ -0,0 +1,160 @@ +package stream::config; +use strict; +use warnings; +use NetAddr::IP; + +our $v4net = NetAddr::IP->new("151.216.0.0/17"); +our $v6net = NetAddr::IP->new("2a02:ed02::/32"); +our $multicast = "udp://\@233.191.12.1"; +our $vlc_base_host = "http://stream.tg13.gathering.org"; +our $tg = 13; +our $tg_full = 2013; + + +# priority = sorting order in streaming list +# port , "post port number" +# has_external , shows on OVH/.fr reflector if set +# external , replaces static url link +# source , video source pew pew +# title , title doh \:D/ +our %streams = ( +# Deaktivert 31.mars kl 05.30 iush +# 'event-ios' => { +# 'type' => 'event', +# 'quality' => 'hd', +# 'priority' => 26, +# 'external' => 1, +# 'url' => "$vlc_base_host/ios/event.m3u8", +# 'source' => 'Event', +# 'title' => 'Event HD Stream for iOS devices (Apple)', +# }, +# 'event-hd' => { +# 'type' => 'event', +# 'quality' => 'hd', +# 'priority' => 20, +# 'port' => 13, +# 'interlaced' => 0, +# 'has_multicast' => 1, +# 'multicast_ip' => 'udp://@[ff7e:a40:2a02:ed02:ffff::13]', +# 'source' => 'Event', +# 'title' => 'Event HD (720p50)' +# }, +# 'event-sd' => { +# 'type' => 'event', +# 'quality' => 'sd', +# 'priority' => 24, +# 'port' => 14, +# 'interlaced' => 0, +# 'has_multicast' => 1, +# 'multicast_ip' => 'udp://@[ff7e:a40:2a02:ed02:ffff::14]', +# 'source' => 'Event', +# 'title' => 'Event SD (576p) (2mbps)' +# }, +# 'event-flash' => { +# 'type' => 'event', +# 'quality' => 'sd', +# 'priority' => 25, +# 'interlaced' => 0, +# 'external' => 1, +# 'url' => 'http://www.gathering.org/tg13/no/live-tv/', +# 'source' => 'Event', +# 'title' => 'Event SD (gathering.org flash player)', +# }, +# + + + 'south-raw' => { + 'type' => 'camera', + 'location' => 3, + 'quality' => 'hd', + 'priority' => 40, + 'port' => 16, + 'interlaced' => 1, + 'has_multicast' => 0, +# 'multicast_ip' => "udp://@[ff7e:a40:2a02:ed02:ffff::16]", + 'source' => 'Tech', + 'title' => 'Webcam South (HD) (1080i25)', + }, + + 'south-transcode' => { + 'type' => 'camera', + 'location' => 3, + 'quality' => 'hd', + 'priority' => 50, + 'port' => 17, + 'interlaced' => 0, + 'has_multicast' => 1, + 'multicast_ip' => "udp://@[ff7e:a40:2a02:ed02:ffff::17]", + 'source' => 'Tech', + 'title' => 'Webcam South (HD) (720p50)', + }, + + + 'fuglecam' => { + 'type' => 'camera', + 'location' => 2, + 'quality' => 'hd', + 'priority' => 118, + 'port' => 15, + 'interlaced' => 1, + 'has_multicast' => 1, + 'multicast_ip' => "udp://\@[ff7e:a40:2a02:ed02:ffff::15]", + 'source' => 'Tech', + 'title' => 'Webcam Fugleberget (HD) (1080i50)', + }, + + + + 'fuglecam-flv-sd' => { + 'location' => 2, + 'type' => 'camera', + 'quality' => 'sd', + 'priority' => 121, + 'interlaced' => 1, + 'external' => 1, + 'url' => 'http://www.gathering.org/tg13/no/webcam/', + 'title' => 'Webcam Fugleberget (SD) (gathering.org flash player)', + }, + + 'noc-fisheye' => { + 'type' => 'camera', + 'location' => 1, + 'quality' => 'hd', + 'priority' => 130, + 'port' => 18, + 'has_multicast' => 1, + 'interlaced' => 0, + 'multicast_ip' => "udp://@[ff7e:a40:2a02:ed02:ffff::18]:2018", + 'source' => "Tech", + 'title' => "Webcam NOC Fisheye (HD)" + }, + 'noc-fisheye-transcode' => { + 'type' => 'camera', + 'location' => 1, + 'quality' => 'hd', + 'priority' => 131, + 'port' => 19, + 'has_multicast' => 1, + 'interlaced' => 0, + 'multicast_ip' => "udp://@[ff7e:a40:2a02:ed02:ffff::19]:2019", + 'source' => "Tech", + 'title' => "Webcam NOC Fisheye (HD transcoded)" + }, + + + 'south-still' => { + 'location' => 3, + 'type' => 'camera', + 'quality' => 'hd', + 'priority' => 110, + 'external' => 1, + 'url' => 'http://stillcam.tg13.gathering.org/', + 'title' => 'Webcam South (Image)', + 'source' => 'Tech' + }, + + + ); + + +1; diff --git a/web/tech.gathering.org/event-720p.mp4.pl b/web/tech.gathering.org/event-720p.mp4.pl new file mode 100755 index 0000000..631e40d --- /dev/null +++ b/web/tech.gathering.org/event-720p.mp4.pl @@ -0,0 +1,11 @@ +#!/usr/bin/env +use strict; +use warnings; +use Capture::Tiny ':all'; + +$! = 1; +print "Content-Type: video/mp4\n\n"; + +my ($stdout, $stderr) = tee { + system('wget', '-qO-', 'http://stream.tg13.gathering.org:3013'); +}; diff --git a/web/tech.gathering.org/index.html b/web/tech.gathering.org/index.html new file mode 100644 index 0000000..9a5b0ad --- /dev/null +++ b/web/tech.gathering.org/index.html @@ -0,0 +1,20 @@ +<html> +<head> +<title>Tech resources - The Gathering 2013</title> +<link rel="stylesheet" type="text/css" href="/styles.css" media="all"> +</head> +<body> + +<h1>Tech resources - The Gathering 2013</h1> + +<img id="logo" src="logo.png" alt="The Gathering 2013" /> + +<h2><a href="http://stats.tg13.gathering.org">stats.tg13.gathering.org (weathermap)</a></h2> +<h2><a href="http://nms-public.tg13.gathering.org">nms-public.tg13.gathering.org</a></h2> +<h2><a href="http://stream.tg13.gathering.org">stream.tg13.gathering.org</a></h2> + +<h2><a href="http://techserver.gathering.org/ircrules">IRC rules for #tg@EFnet</a></h2> + +<p>Enjoy :-)</p> +</body> +</html> diff --git a/web/tech.gathering.org/logo.png b/web/tech.gathering.org/logo.png Binary files differnew file mode 100644 index 0000000..3a13cdf --- /dev/null +++ b/web/tech.gathering.org/logo.png diff --git a/web/tech.gathering.org/styles.css b/web/tech.gathering.org/styles.css new file mode 100644 index 0000000..e690989 --- /dev/null +++ b/web/tech.gathering.org/styles.css @@ -0,0 +1,24 @@ +* { font-family: 'Open Sans', sans-serif; + +} + +body { + background: #fff; color: #000; opacity: 1; +} + +#logo { background: url('logo.png'); width: 237px; height: 200px;position:absolute; top: 0; right: 0;z-index: -1} + +@media screen and (max-width: 1145px) { /* Min iPad size*/ + #spaceship { + background: #fff; + } +} + +/* #innhold { position: absolute; left:0px ; top: 50px; margin: 0 50px 0 50px; z-index: 9; width: 520px; }*/ +#innhold { width: 480px; } +footer { clear: both; width:480px; } +a { color: #000; } +h4 { margin: 0; margin-top: 35px;} +p { margin: 0; padding: 0; } +li { margin-bottom: 14px; } + |