start work on asset page

This commit is contained in:
Nicolas Debrigode 2018-01-12 17:21:46 +01:00
parent 5914a87835
commit 627bd7294a
15 changed files with 714 additions and 39 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
.idea
.DS_Store
*~
composer.lock
composer.phar
vendor/
var/*
web/asset/*

View File

@ -36,7 +36,7 @@ config:
rrdtool: "/usr/bin/rrdtool"
whois: "/usr/bin/whois"
## AS-SET
assetpath: false
assetpath: "asset"
asset_cache_life: 604800 # 604800 seconds = 7 days
## PEERINGDB
my_asn: 34863

View File

@ -7,7 +7,8 @@
"symfony/yaml": "^3.3",
"ddesrosiers/silex-annotation-provider": "~2.0",
"doctrine/dbal": "~2.5",
"mobiledetect/mobiledetectlib": "^2.8"
"mobiledetect/mobiledetectlib": "^2.8",
"brandonwamboldt/utilphp": "^1.0"
},
"autoload": {
"psr-4": {"": "src"}

View File

@ -9,6 +9,8 @@ use Silex\Provider\SessionServiceProvider;
use Silex\Provider\DoctrineServiceProvider;
use Application\ConfigApplication as ConfigApplication;
use DDesrosiers\SilexAnnotations\AnnotationServiceProvider;
use \utilphp\util as Util;
use \Mobile_Detect;
class ApplicationProvider implements ServiceProviderInterface
{
@ -29,6 +31,14 @@ class ApplicationProvider implements ServiceProviderInterface
$app->register(new HttpFragmentServiceProvider());
$app->register(new SessionServiceProvider());
$app['mobile_detect'] = function($app) {
return new Mobile_Detect();
};
$app['util'] = function($app) {
return new Util();
};
$app->register(new DoctrineServiceProvider(), array(
"dbs.options" => DbsProvider::Get()
));
@ -37,14 +47,14 @@ class ApplicationProvider implements ServiceProviderInterface
return new \Models\SqlLite($app['dbs']);
};
$app['whois'] = function() use($app) {
return new \Models\Whois($app);
};
$app->register(new AnnotationServiceProvider(), array(
'annot.controllerDir' => realpath(ConfigApplication::getControllerRootDirectory()),
));
$app->register(new ErrorProvider());
$app['mobile_detect'] = function($app) {
return new \Mobile_Detect();
};
}
}

View File

@ -100,4 +100,20 @@ class ConfigApplication
{
return !$app['mobile_detect']->isMobile() && !$app['mobile_detect']->isTablet() ? FALSE : TRUE;
}
public static function getASSetPath()
{
return self::getConfigASStats()['config']['assetpath'];
}
public static function getASSetCacheLife()
{
return self::getConfigASStats()['config']['asset_cache_life'];
}
public static function getWhois()
{
return self::getConfigASStats()['config']['whois'];
}
}

125
src/Controllers/Asset.php Normal file
View File

@ -0,0 +1,125 @@
<?php
namespace Controllers;
use Silex\Application;
use DDesrosiers\SilexAnnotations\Annotations as SLX;
use Symfony\Component\HttpFoundation\Request;
use Application\ConfigApplication as ConfigApplication;
use Controllers\Func;
/**
* @SLX\Controller(prefix="/asset")
*/
class Asset extends BaseController
{
/**
* @SLX\Route(
* @SLX\Request(method="GET", uri=""),
* @SLX\Bind(routeName="asset")
* )
*/
public function index(Request $request, Application $app)
{
$req = $request->query->all();
$this->data['active_page'] = Func::getRouteName($request);
if ( isset($req['asset']) ) {
$hours = 24;
$this->data['asset'] = strtoupper($req['asset']);
$whois = $app['whois']->getASSET($this->data['asset']);
$this->data['cache'] = $whois['cache'];
$this->data['aslist'] = $whois['aslist'];
$this->data['other_asset'] = $whois['other_asset'];
$this->data['knownlinks'] = Func::getKnowlinks();
$selected_links = array();
foreach($this->data['knownlinks'] as $link){
if(isset($req["link_${link['tag']}"]))
$selected_links[] = $link['tag'];
}
$this->data['selected_links'] = $selected_links;
$this->data['request'] = $req;
$topas = $this->db->GetASStatsTop(200, Func::statsFileForHours($hours), $selected_links, $this->data['aslist']);
foreach ($topas as $as => $nbytes) {
$this->data['asinfo'][$as]['info'] = Func::GetASInfo($as);
$this->data['asinfo'][$as]['v4'] = [
'in' => $nbytes[0],
'out' => $nbytes[1],
];
if ( $this->data['config']['showv6'] ) {
$this->data['asinfo'][$as]['v6'] = [
'in' => $nbytes[2],
'out' => $nbytes[3],
];
}
$this->data['customlinks'][$as] = Func::getCustomLinks($as);
}
foreach ( $this->data['aslist'] as $as ) {
if ( !array_key_exists($as, $topas) ) {
$this->data['asinfo_nodata'][$as]['info'] = Func::GetASInfo($as);
$this->data['customlinks'][$as] = Func::getCustomLinks($as);
}
}
$this->data['start'] = time() - $hours*3600;
$this->data['end'] = time();
$this->data['label'] = Func::statsLabelForHours($hours);
$this->data['hours'] = $hours;
#$app['util']::var_dump($this->data);
return $app['twig']->render('pages/asset/asset.html.twig', $this->data);
} else {
return $app['twig']->render('pages/asset/search.html.twig', $this->data);
}
}
/**
* @SLX\Route(
* @SLX\Request(method="GET", uri="/clear"),
* @SLX\Bind(routeName="asset/clear")
* )
*/
public function clear_all(Application $app)
{
$path = ConfigApplication::getASSetPath();
$ok = 0;
$fail = 0;
$files = glob($path."/*.txt");
foreach($files as $file) {
if ( unlink($file) ) { $ok++; } else { $fail++; }
}
$return = [
'ok' => $ok,
'fail' => $fail,
];
return json_encode($return);
}
/**
* @SLX\Route(
* @SLX\Request(method="GET", uri="/clear/{file}"),
* @SLX\Bind(routeName="asset/clear/one")
* )
*/
public function clear_one(Application $app, $file)
{
if (!preg_match("/^[a-zA-Z0-9:_-]+$/", $file)) return FALSE;
$file = ConfigApplication::getASSetPath() . "/" . $file . ".txt";
unlink($file);
return "";
}
}

View File

@ -26,22 +26,16 @@ class History extends BaseController
$this->data['asinfo'] = Func::GetASInfo($req['as']);
$this->data['customlinks'] = Func::getCustomLinks_History($req['as']);
$this->data['end'] = time();
$this->data['daily']['start'] = time() - 24 * 3600;
$this->data['daily']['end'] = time();
$this->data['weekly']['start'] = time() - 6.9 * 86400;
$this->data['weekly']['end'] = time();
$this->data['monthly']['start'] = time() - 30 * 86400;
$this->data['monthly']['end'] = time();
$this->data['yearly']['start'] = time() - 365 * 86400;
$this->data['yearly']['end'] = time();
return $app['twig']->render('pages/history.html.twig', $this->data);
return $app['twig']->render('pages/history/history.html.twig', $this->data);
} else {
return $app['twig']->render('pages/history_search.html.twig', $this->data);
return $app['twig']->render('pages/history/search.html.twig', $this->data);
}
}
}

View File

@ -9,7 +9,7 @@ class SqlLite
public function __construct($app)
{
$this->db = $app;
$this->db = $app;
}
public function GetASStatsTop($ntop, $statsfile, $selected_links, $list_asn = NULL)

92
src/Models/Whois.php Normal file
View File

@ -0,0 +1,92 @@
<?php
namespace Models;
use Controllers\Func;
use Application\ConfigApplication as ConfigApplication;
class Whois
{
protected $app;
public function __construct($app)
{
$this->app = $app;
}
public function getASSET($asset)
{
$aslist = NULL;
$cache = FALSE;
/* sanity check */
if (!preg_match("/^[a-zA-Z0-9:_-]+$/", $asset)) return NULL;
$assetfile = ConfigApplication::getASSetPath()."/".$asset.".txt";
if ( file_exists($assetfile) ) {
$filemtime = @filemtime($assetfile);
if (!$filemtime or (time() - $filemtime >= ConfigApplication::getASSetCacheLife())) {
$aslist = self::getWhois($asset, $assetfile);
} else {
$f = fopen($assetfile, "r");
$aslist = array();
while (!feof($f)) {
$line = trim(fgets($f));
if (!empty($line)) $aslist[] = $line;
}
$cache = TRUE;
}
} else {
$aslist = self::getWhois($asset, $assetfile);
}
$parse_aslist = self::parseOtherAsset($aslist);
return array('cache' => $cache, 'aslist' => $parse_aslist['aslist'], 'other_asset' => $parse_aslist['other_asset']);
}
private function getWhois($asset, $assetfile)
{
$cmd = ConfigApplication::getWhois() ." -h whois.radb.net '!i".$asset."'";
$return_aslist = explode("\n",shell_exec($cmd));
/* find the line that contains the AS-SET members */
$aslist = NULL;
foreach ($return_aslist as $asline) {
if (preg_match("/^AS/", $asline)) {
$aslist = explode(" ", $asline);
break;
}
}
if ( $aslist ) {
$f = fopen($assetfile,"w");
foreach ($aslist as $as) {
fputs($f,$as."\n");
}
fclose($f);
}
return $aslist;
}
private function parseOtherAsset($aslist)
{
$as_num = $as_other = NULL;
if ($aslist) {
foreach( $aslist as $as ) {
$as_tmp = substr($as, 2);
if (is_numeric($as_tmp)) {
$as_num[]=$as_tmp;
} else {
$as_other[]=$as;
}
}
}
return array('aslist' => $as_num, 'other_asset' => $as_other);
}
}

View File

@ -21,19 +21,21 @@
<li><a href="{{ path('index') }}">Top AS</a></li>
{% endif %}
<li class="{{ active_page.active_searchas }}"><a href="{{ path('history') }}">View AS</a></li>
<li class="{{ active_page.active_searchasset }}"><a href="asset.php">View AS-SET</a></li>
<li class="{{ active_page.active_searchasset }}"><a href="{{ path('asset') }}">View AS-SET</a></li>
<li class="{{ active_page.active_ix }}"><a href="ix.php">View IX Stats</a></li>
</ul>
<form class="navbar-form navbar-left" role="search">
<div class="input-group">
<input type="text" class="form-control menu-input" name="n" placeholder="Top AS" value="">
<span class="input-group-btn">
<button type="submit" class="btn btn-flat button-input">
<i class="fa fa-search"></i>
</button>
</span>
</div>
</form>
{% if active_page.active_top == "active" %}
<form class="navbar-form navbar-left" role="search">
<div class="input-group">
<input type="text" class="form-control menu-input" name="n" placeholder="Top AS" value="">
<span class="input-group-btn">
<button type="submit" class="btn btn-flat button-input">
<i class="fa fa-search"></i>
</button>
</span>
</div>
</form>
{% endif %}
</div>
</div>
</nav>

View File

@ -0,0 +1,318 @@
{% extends "base/base.html.twig" %}
{% import "macros/macros.html.twig" as macro %}
{% block refresh %}
{% endblock %}
{% block title %}
History for AS-SET: {{ asset }}
{% endblock %}
{% block css %}
<style>
.affix {
top:55px;
z-index: 1;
width: 15.04%;
}
@media (max-width:1680px) {
.affix {
width: 14.85%;
}
}
@media (max-width:1600px) {
.affix {
width: 14.85%;
}
}
@media (max-width:1440px) {
.affix {
width: 14.54%;
}
}
@media (max-width:1280px) {
.affix {
width: 14.34%;
}
}
@media (max-width:1024px) {
.affix {
width: 97%;
}
}
@media (max-width:768px) {
.affix {
width: 96%;
}
}
@media (max-width:667px) {
.affix {
width: 95.5%;
}
}
@media (max-width:375px) {
.affix {
width: 92%;
}
}
</style>
{% endblock %}
{% block content_wrapper %}
{% set title = "History for AS-SET" %}
{% set label = "#{asset} (#{label})" %}
{{ macro.content_header(title, label, config.outispositive ) }}
{% endblock %}
{% set aff_other_asset %}
{% if other_asset is not null %}
<div class="col-lg-12">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Other AS-SET</h3>
</div>
<div class="box-body">
<ul class="nav nav-stacked">
{% for o_asset in other_asset %}
<li class="li-customlinks">
<a href="{{ path('asset', { 'asset': o_asset }) }}">{{ o_asset }}</a>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endif %}
{% endset %}
{% set legend %}
<table width="100%" class='small'>
{% for link in knownlinks %}
{% set tag = "link_#{ link.tag }" %}
{% if request[tag] is defined and request[tag] == 'on' %}
{% set checked = 'checked' %}
{% else %}
{% set checked = '' %}
{% endif %}
<tr>
<td width='15%' style="border: 4px solid #fff;">
<table style="border-collapse: collapse; margin: 0; padding: 0"><tr>
{% if config.brighten_negative %}
<td width="9" height="18" style="background-color: #{{ link.color }}">&nbsp;</td>
<td width="9" height="18" style="opacity: 0.73; background-color: #{{ link.color }}">&nbsp;</td>
{% else %}
<td width="18" height="18" style="background-color: #{{ link.color }}">&nbsp;</td>
{% endif %}
</tr></table>
</td>
<td>&nbsp; {{ link.descr }}</td>
<td>&nbsp;<input type='checkbox' name='{{ tag }}' id ='{{ tag }}' {{ checked }}></td>
</tr>
{% endfor %}
</table>
{% endset %}
{% set counter = 0 %}
{% set aff_astable %}
{% for key_as, as_data in asinfo %}
{% set class %}
{% if (counter % 2) != 0 %}
even
{% endif %}
{% endset %}
<li class="li-padding {{ class }}">
<div class="row">
<div class="col-md-4 col-lg-2">
<b><img src="{{ global.request.baseUrl }}/flags/blank.gif" class="flag flag-{{ as_data.info.country|lower }}"/> AS{{ key_as }}: </b><small><i>{{ as_data.info.descr }}</i></small>
<div class="small">In the last {{ label|default('') }}</div>
<div class="small">IPv4: ~ {{ as_data.v4.in|format_bytes }} in / {{ as_data.v4.out|format_bytes }} out</div>
{% if as_data.v6 is defined %}
<div class="small">IPv6: ~ {{ as_data.v6.in|format_bytes }} in / {{ as_data.v6.out|format_bytes }} out</div>
{% endif %}
<span class="small">{{ attribute(customlinks, key_as)|raw }}</span>
<div class="rank">
{% set counter = counter + 1 %}
# {{ counter }}
</div>
</div>
{% if config.showv6 %}
<div class="col-md-12 col-lg-5">
<span class="pull-right">
{{ macro.getHTMLUrl(key_as, 4, as_data.info.descr, start, end, 0, selected_links, config.top_graph_width, config.top_graph_height) }}
</span>
</div>
<div class="col-md-12 col-lg-5">
<span class="pull-right">
{{ macro.getHTMLUrl(key_as, 6, as_data.info.descr, start, end, 0, selected_links, config.top_graph_width, config.top_graph_height) }}
</span>
</div>
{% else %}
<div class="col-md-12 col-lg-10">
<span class="pull-right">
{{ macro.getHTMLUrl(key_as, 4, as_data.info.descr, start, end, 0, selected_links, config.top_graph_width, config.top_graph_height) }}
</span>
</div>
{% endif %}
</div>
</li>
{% endfor %}
{% for key_as, as_data in asinfo_nodata %}
{% set class %}
{% if (counter % 2) != 0 %}
even
{% endif %}
{% endset %}
<li class="li-padding {{ class }}">
<div class="row">
<div class="col-md-4 col-lg-2">
<b><img src="{{ global.request.baseUrl }}/flags/blank.gif" class="flag flag-{{ as_data.info.country|lower }}"/> AS{{ key_as }}: </b><small><i>{{ as_data.info.descr }}</i></small>
<div class="small">In the last {{ label|default('') }}</div>
<span class="small">{{ attribute(customlinks, key_as)|raw }}</span>
<div class="rank">
{% set counter = counter + 1 %}
# {{ counter }}
</div>
</div>
<div class="col-md-12 col-lg-10">
<center>No data found for AS{{ key_as }}</center>
</div>
</div>
</li>
{% endfor %}
{% endset %}
{% block content %}
<div class="row">
<div class="col-md-12 col-lg-2">
<div class="row">
<div class="col-lg-12">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Search AS-SET</h3>
<div class="box-tools">
<button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
</div>
</div>
<div class="box-body">
<form class="navbar-form navbar-left" role="search" action="{{ path('asset') }}">
<div class="input-group">
<input id="asset" type="text" class="form-control menu-input" name="asset" placeholder="Search AS-SET" value="{{ asset }}">
<span class="input-group-btn">
<button type="submit" class="btn btn-flat button-input"><i class="fa fa-search"></i></button>
</span>
</div>
</form>
</div>
</div>
</div>
{# METTRE AFFICHAGE SI C'EST DU CACHE #}
{% if cache %}
<div class="col-lg-12">
<div class="alert alert-warning"><i class="icon fa fa-info"></i>&nbsp;Data from cache file.</div>
</div>
{% endif %}
<div class="col-lg-12">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Tools Box</h3>
</div>
<div class="box-body">
<div class="list-group list-group-unbordered">
<a id="clear_one" href="{{ path('asset/clear/one', { 'file': asset }) }}" class="list-group-item"><i class="fa fa-remove text-red"></i> Remove AS-SET cache file for {{ asset }}</a>
<a id="clear" href="{{ path('asset/clear') }}" class="list-group-item"><i class="fa fa-remove text-red"></i> Remove all AS-SET cache files.</a>
</div>
</div>
</div>
</div>
<div class="col-lg-12">
<form method='get'>
<input type='hidden' name='asset' value='{{ asset }}'/>
<div data-spy="affix" data-offset-top="400">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Legend</h3>
</div>
<div class="box-body">
{{ legend }}
</div>
<div class="box-footer">
<button type="submit" class="btn pull-right"><i class="fa fa-search"></i></button>
</div>
</div>
</div>
</form>
</div>
{{ aff_other_asset }}
</div>
</div>
<div class="col-md-12 col-lg-10">
<div class="box box-primary">
<div class="box-body">
<ul class="nav nav-stacked">
{{ aff_astable }}
</ul>
</div>
</div>
</div>
</div>
{% endblock %}
{% block modal %}
<div id="modal_clear" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<div id="reponse_ajax"></div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block js %}
<script>
$('#clear').click(function(event) {
event.preventDefault();
$.ajax({
url: $(this).attr('href'),
success: function(response) {
var json = $.parseJSON(response);
if ( json.fail ) {
$("#reponse_ajax").html('<div class=\"alert alert-danger alert-dismissable\"><i class=\"icon fa fa-ban\"></i>&nbsp;Unable to clear all cache files.</div>');
} else {
if ( !json.ok ) {
$("#reponse_ajax").html('<div class=\"alert alert-info alert-dismissable\"><i class=\"icon fa fa-info\"></i>&nbsp;The cache is already cleared.</div>');
} else {
$("#reponse_ajax").html("<div class=\"alert alert-success alert-dismissable\"><i class='icon fa fa-check'></i>&nbsp;Clear cache files done.</div>");
}
}
setTimeout(function () { window.location.replace("{{ path('asset') }}"); }, 2 * 1000);
},
beforeSend: function () {
$("#modal_clear").modal('show');
}
});
return false;
});
</script>
<script>
$('#clear_one').click(function(event) {
event.preventDefault();
$.ajax({
url: $(this).attr('href'),
success: function(response) {
setTimeout(function () { window.location.replace("{{ path('asset') }}"); }, 1 * 1000);
},
});
return false;
});
</script>
{% endblock %}

View File

@ -0,0 +1,105 @@
{% extends "base/base.html.twig" %}
{% import "macros/macros.html.twig" as macro %}
{% block refresh %}
{% endblock %}
{% block title %}
History for AS-SET
{% endblock %}
{% block css %}
{% endblock %}
{% block content_wrapper %}
{% set title = "History for AS-SET" %}
{{ macro.content_header(title, "", config.outispositive ) }}
{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-12 col-lg-2">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Search AS-SET</h3>
<div class="box-tools">
<button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
</div>
</div>
<div class="box-body">
<form class="navbar-form navbar-left" role="search" action="{{ path('asset') }}">
<div class="input-group">
<input id="asset" type="text" class="form-control menu-input" name="asset" placeholder="Search AS-SET">
<span class="input-group-btn">
<button type="submit" class="btn btn-flat button-input"><i class="fa fa-search"></i></button>
</span>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 col-md-2">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Tools Box</h3>
</div>
<div class="box-body">
<div class="list-group list-group-unbordered">
<a id="clear" href="{{ path('asset/clear') }}" class="list-group-item"><i class="fa fa-remove text-red"></i> Remove all AS-SET cache files.</a>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block modal %}
<div id="modal_clear" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<div id="reponse_ajax"></div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block js %}
<script>
window.onload = function() {
var input = document.getElementById("asset").focus();
}
</script>
<script>
$('#clear').click(function(event) {
event.preventDefault();
$.ajax({
url: $(this).attr('href'),
success: function(response) {
var json = $.parseJSON(response);
if ( json.fail ) {
$("#reponse_ajax").html('<div class=\"alert alert-danger alert-dismissable\"><i class=\"icon fa fa-ban\"></i>&nbsp;Unable to clear all cache files.</div>');
} else {
if ( !json.ok ) {
$("#reponse_ajax").html('<div class=\"alert alert-info alert-dismissable\"><i class=\"icon fa fa-info\"></i>&nbsp;The cache is already cleared.</div>');
} else {
$("#reponse_ajax").html("<div class=\"alert alert-success alert-dismissable\"><i class='icon fa fa-check'></i>&nbsp;Clear cache files done.</div>");
}
}
setTimeout(function () { location.reload(); }, 2 * 1000);
},
beforeSend: function () {
$("#modal_clear").modal('show');
}
});
return false;
});
</script>
{% endblock %}

View File

@ -77,12 +77,12 @@ History for AS{{request.as}}: {{ asinfo.descr }}
<div class="box-body">
<center>
<div class="col-lg-{{ col }}">
{{ macro.getHTMLImg(request.as, 4, "AS#{request.as} - #{asinfo.descr} - IPV4", daily.start, daily.end, 0, true, "", 0) }}
{{ macro.getHTMLImg(request.as, 4, "AS#{request.as} - #{asinfo.descr} - IPV4", daily.start, end, 0, true, "", 0) }}
</div>
{% if config.showv6 %}
<div class="col-lg-6">
{{ macro.getHTMLImg(request.as, 6, "AS#{request.as} - #{asinfo.descr} - IPV6", daily.start, daily.end, 0, true, "", 0) }}
{{ macro.getHTMLImg(request.as, 6, "AS#{request.as} - #{asinfo.descr} - IPV6", daily.start, end, 0, true, "", 0) }}
</div>
{% endif %}
</center>
@ -100,12 +100,12 @@ History for AS{{request.as}}: {{ asinfo.descr }}
<div class="box-body">
<center>
<div class="col-lg-{{ col }}">
{{ macro.getHTMLImg(request.as, 4, "AS#{request.as} - #{asinfo.descr} - IPV4", weekly.start, weekly.end, 0, true, "", 0) }}
{{ macro.getHTMLImg(request.as, 4, "AS#{request.as} - #{asinfo.descr} - IPV4", weekly.start, end, 0, true, "", 0) }}
</div>
{% if config.showv6 %}
<div class="col-lg-6">
{{ macro.getHTMLImg(request.as, 6, "AS#{request.as} - #{asinfo.descr} - IPV6", weekly.start, weekly.end, 0, true, "", 0) }}
{{ macro.getHTMLImg(request.as, 6, "AS#{request.as} - #{asinfo.descr} - IPV6", weekly.start, end, 0, true, "", 0) }}
</div>
{% endif %}
</center>
@ -123,12 +123,12 @@ History for AS{{request.as}}: {{ asinfo.descr }}
<div class="box-body">
<center>
<div class="col-lg-{{ col }}">
{{ macro.getHTMLImg(request.as, 4, "AS#{request.as} - #{asinfo.descr} - IPV4", monthly.start, monthly.end, 0, true, "", 0) }}
{{ macro.getHTMLImg(request.as, 4, "AS#{request.as} - #{asinfo.descr} - IPV4", monthly.start, end, 0, true, "", 0) }}
</div>
{% if config.showv6 %}
<div class="col-lg-6">
{{ macro.getHTMLImg(request.as, 6, "AS#{request.as} - #{asinfo.descr} - IPV6", monthly.start, monthly.end, 0, true, "", 0) }}
{{ macro.getHTMLImg(request.as, 6, "AS#{request.as} - #{asinfo.descr} - IPV6", monthly.start, end, 0, true, "", 0) }}
</div>
{% endif %}
</center>
@ -146,12 +146,12 @@ History for AS{{request.as}}: {{ asinfo.descr }}
<div class="box-body">
<center>
<div class="col-lg-{{ col }}">
{{ macro.getHTMLImg(request.as, 4, "AS#{request.as} - #{asinfo.descr} - IPV4", yearly.start, yearly.end, 0, true, "", 0) }}
{{ macro.getHTMLImg(request.as, 4, "AS#{request.as} - #{asinfo.descr} - IPV4", yearly.start, end, 0, true, "", 0) }}
</div>
{% if config.showv6 %}
<div class="col-lg-6">
{{ macro.getHTMLImg(request.as, 6, "AS#{request.as} - #{asinfo.descr} - IPV6", yearly.start, yearly.end, 0, true, "", 0) }}
{{ macro.getHTMLImg(request.as, 6, "AS#{request.as} - #{asinfo.descr} - IPV6", yearly.start, end, 0, true, "", 0) }}
</div>
{% endif %}
</center>

View File

@ -92,7 +92,7 @@ Top {{ ntop }} AS ({{ label }})
{% endset %}
{% set legend_small %}
<table class='small'>
<table width="100%" class='small'>
<tr>
<td>
{% for link in knownlinks %}
@ -144,7 +144,7 @@ Top {{ ntop }} AS ({{ label }})
<li class="li-padding {{ class }}">
<div class="row">
<div class="col-md-4 col-lg-2">
<b><img src="flags/blank.gif" class="flag flag-{{ as_data.info.country|lower }}"/> AS{{ key_as }}: </b><small><i>{{ as_data.info.descr }}</i></small>
<b><img src="{{ global.request.baseUrl }}/flags/blank.gif" class="flag flag-{{ as_data.info.country|lower }}"/> AS{{ key_as }}: </b><small><i>{{ as_data.info.descr }}</i></small>
<div class="small">In the last {{ label|default('') }}</div>
<div class="small">IPv4: ~ {{ as_data.v4.in|format_bytes }} in / {{ as_data.v4.out|format_bytes }} out</div>
{% if as_data.v6 is defined %}
@ -191,7 +191,11 @@ Top {{ ntop }} AS ({{ label }})
<h3 class="box-title">Legend</h3>
</div>
<div class="box-body">
{{ legend }}
{% if mobile %}
{{ legend_small }}
{% else %}
{{ legend }}
{% endif %}
</div>
<div class="box-footer">
<button type="submit" class="btn pull-right"><i class="fa fa-search"></i></button>