diff options
author | Sergey Dvoriancev <dv_serg@mail.ru> | 2012-05-11 23:49:43 +0400 |
---|---|---|
committer | Sergey Dvoriancev <dv_serg@mail.ru> | 2012-05-11 23:49:43 +0400 |
commit | c48bb3b4394462608eaeac925b8082865ee618e1 (patch) | |
tree | 3e92d0ce5c51e654a0f36a6c57a4145faa90aa65 | |
parent | e56c90c1453d6bc32ef0caf48f2be3f4364add13 (diff) | |
download | pfsense-packages-c48bb3b4394462608eaeac925b8082865ee618e1.tar.gz pfsense-packages-c48bb3b4394462608eaeac925b8082865ee618e1.tar.bz2 pfsense-packages-c48bb3b4394462608eaeac925b8082865ee618e1.zip |
SQStat 1
-rw-r--r-- | config/lightsquid/sqstat.class.php | 1286 |
1 files changed, 580 insertions, 706 deletions
diff --git a/config/lightsquid/sqstat.class.php b/config/lightsquid/sqstat.class.php index 1ba15c8b..228aecfe 100644 --- a/config/lightsquid/sqstat.class.php +++ b/config/lightsquid/sqstat.class.php @@ -1,708 +1,582 @@ +<?php +/* $Id$ */ +/* + sqstat.class.php + Squid Proxy Server realtime stat + + (c) Alex Samorukov, samm@os2.kiev.ua + modification by 2011 Serg Dvoriancev, dv_serg@mail.ru + Squid Proxy Server realtime stat + + part of pfSense (www.pfSense.com) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +// sqstat class +DEFINE('SQSTAT_VERSION', '1.20'); +DEFINE('SQSTAT_SHOWLEN', 60); + +class squidstat{ + var $fp; + + # conection + var $squidhost; + var $squidport; + + # hosts + var $hosts_file; + var $hosts; + + # versions + var $server_version; + var $sqstat_version; + + # other + var $group_by; + var $resolveip; + var $autorefresh; + var $use_sessions = false; + + # cache manager + var $cachemgr_passwd; + + # errors + var $errno; + var $errstr; + + function squidstat(){ + $this->sqstat_version = SQSTAT_VERSION; + + $this->squidhost = '127.0.0.1'; + $this->squidport = '3128'; + + $This->group_by = 'host'; + $this->resolveip = true; + $this->hosts_file = ''; + $this->autorefresh = 0; + $this->cachemgr_passwd = ''; + + $errno = 0; + $errstr = ''; + + if (!function_exists("preg_match")) { $this->errorMsg(5, 'You need to install <a href="http://www.php.net/pcre/" target="_blank">PHP pcre extension</a> to run this script'); + $this->showError(); + exit(5); + } + + // we need session support to gather avg. speed + if (function_exists("session_start")){ + $this->use_sessions=true; + } + + } + + function formatXHTML($body, $refresh, $use_js = false){ + $text='<?xml version="1.0" encoding="UTF-8"?>'."\n". + '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'."\n" + .'<html>' + .'<head>' + .'<link href="sqstat.css" rel="stylesheet" type="text/css"/>'; + if($refresh) $text.='<META HTTP-EQUIV=Refresh CONTENT="'.$refresh.'; URL='.$_SERVER["PHP_SELF"].'?refresh='.$refresh.'&config='.$GLOBALS["config"].'"/>'; + $text.='<title>SqStat '.SQSTAT_VERSION.'</title>' + .($use_js?'<script src="zhabascript.js" type="text/javascript"></script>':'').'</head>' + .($use_js?'<body onload="jsInit();"><div id="dhtmltooltip"></div><img id="dhtmlpointer" src="arrow.gif">':'<body>') + .$body.'</body></html>'; + return $text; + } + + function showError(){ + $text='<h1>SqStat error</h1>'. + '<h2 style="color:red">Error ('.$this->errno.'): '.$this->errstr.'</span>'; + echo $this->formatXHTML($text,0); + } + + function connect($squidhost, $squidport){ + $this->fp = false; + # connecting to the squidhost + $this->fp = @fsockopen($squidhost, $squidport, $this->errno, $this->errstr, 10); + if (!$this->fp) { + # failed to connect + return false; + } + return true; + } + + # based @ (c) moritz at barafranca dot com + function duration ($seconds) { + $takes_time = array(604800,86400,3600,60,0); + $suffixes = array("w","d","h","m","s"); + $output = ""; + foreach ($takes_time as $key=>$val) { + ${$suffixes[$key]} = ($val == 0) ? $seconds : floor(($seconds/$val)); + $seconds -= ${$suffixes[$key]} * $val; + if (${$suffixes[$key]} > 0) { + $output .= ${$suffixes[$key]}; + $output .= $suffixes[$key]." "; + } + } + return trim($output); + } + + /** + * Format a number of bytes into a human readable format. + * Optionally choose the output format and/or force a particular unit + * + * @param int $bytes The number of bytes to format. Must be positive + * @param string $format Optional. The output format for the string + * @param string $force Optional. Force a certain unit. B|KB|MB|GB|TB + * @return string The formatted file size + */ + function filesize_format($bytes, $format = '', $force = '') + { + $force = strtoupper($force); + $defaultFormat = '%01d %s'; + if (strlen($format) == 0) + $format = $defaultFormat; + $bytes = max(0, (int) $bytes); + $units = array('b', 'Kb', 'Mb', 'Gb', 'Tb', 'Pb'); + $power = array_search($force, $units); + if ($power === false) + $power = $bytes > 0 ? floor(log($bytes)/log(1024)) : 0; + return sprintf($format, $bytes / pow(1024, $power), $units[$power]); + } + + function makeQuery($pass = ""){ + $raw = array(); + # sending request + if(!$this->fp) + die("Please connect to server"); + + $out = "GET cache_object://localhost/active_requests HTTP/1.0\r\n"; + if ($pass != "") + $out .= "Authorization: Basic ".base64_encode("cachemgr:$pass")."\r\n"; + $out .= "\r\n"; + + fwrite($this->fp, $out); + + while (!feof($this->fp)) { + $raw[] = trim(fgets($this->fp, 2048)); + } + fclose($this->fp); + + if ($raw[0]!="HTTP/1.0 200 OK") { $this->errorMsg(1, "Cannot get data. Server answered: $raw[0]"); + return false; + } + + # parsing output; + $header = 1; + $connection = 0; + $parsed["server_version"] = "Unknown"; + foreach($raw as $key=>$v){ + # cutoff http header + if ($header==1 && $v=="") $header=0; + if ($header) { + if(substr(strtolower($v),0,7) == "server:") { # parsing server version + $parsed["server_version"] = substr($v,8); + } + } + else { + if(substr($v,0,11) == "Connection:") { # parsing connection + $connection = substr($v,12); + } + if ($connection) { + # username field is avaible in Squid 2.6 stable + if(substr($v,0,9) == "username ") $parsed["con"][$connection]["username"] = substr($v, 9); + if(substr($v,0,5) == "peer:") $parsed["con"][$connection]["peer"] = substr($v, 6); + if(substr($v,0,3) == "me:") $parsed["con"][$connection]["me"] = substr($v, 4); + if(substr($v,0,4) == "uri ") $parsed["con"][$connection]["uri"] = substr($v, 4); + if(substr($v,0,10) == "delay_pool") $parsed["con"][$connection]["delay_pool"] = substr($v, 11); + + if (preg_match('/out.offset \d+, out.size (\d+)/', $v, $matches)) { + $parsed["con"][$connection]["bytes"] = $matches[1]; + } + if (preg_match('/start \d+\.\d+ \((\d+).\d+ seconds ago\)/', $v, $matches)){ + $parsed["con"][$connection]["seconds"] = $matches[1]; + } + } + } + } + return $parsed; + } + + function implode_with_keys($array, $glue) { + foreach ($array as $key => $v){ + $ret[] = $key . '=' . htmlspecialchars($v); + } + return implode($glue, $ret); + } + + function makeHtmlReport($data, $resolveip = false, $hosts_array = array(), $use_js = true) { + global $group_by; + if($this->use_sessions){ + session_name('SQDATA'); + session_start(); + } + + $total_avg = $total_curr = 0; + // resort data array + $users=array(); + switch($group_by){ + case "host": + $group_by_name="Host"; + $group_by_key='return $ip;'; + break; + case "username": + $group_by_name="User"; + $group_by_key='return $v["username"];'; + break; + default: + die("wrong group_by!"); + } + + foreach($data["con"] as $key => $v){ + if(substr($v["uri"],0,13)=="cache_object:") continue; // skip myself + $ip=substr($v["peer"],0,strpos($v["peer"],":")); + if(isset($hosts_array[$ip])){ + $ip=$hosts_array[$ip]; + } + // i use ip2long() to make ip sorting work correctly + elseif($resolveip){ + $hostname=gethostbyaddr($ip); + if($hostname==$ip) $ip=ip2long($ip);// resolve failed + else $ip=$hostname; + } + else{ + $ip=ip2long(substr($v["peer"],0,strpos($v["peer"],":"))); + } + $v['connection'] = $key; + if(!isset($v["username"])) $v["username"]="N/A"; + $users[eval($group_by_key)][]=$v; + } + ksort($users); + $refresh=0; + if(isset($_GET["refresh"]) && !isset($_GET["stop"])) $refresh=(int)$_GET["refresh"]; + $text=''; + if(count($GLOBALS["configs"])==1) $servers=$GLOBALS["squidhost"].':'.$GLOBALS["squidport"]; + else{ + $servers='<select onchange="this.form.submit();" name="config">'; + foreach ($GLOBALS["configs"] as $key=>$v){ + $servers.='<option '.($GLOBALS["config"]==$key?' selected="selected" ':'').' value="'.$key.'">'.htmlspecialchars($v).'</option>'; + } + $servers.='</select>'; + } + $text.='<div class="header"><form method="get" action="'.$_SERVER["PHP_SELF"].'">'. + 'Squid RealTime stat for the '.$servers.' proxy server ('.$data["server_version"].').<br/>'. + 'Auto refresh: <input name="refresh" type="text" size="4" value="'.$refresh.'"/> sec. <input type="submit" value="Update"/> <input name="stop" type="submit" value="Stop"/> Created at: <tt>'.date("h:i:s d/m/Y").'</tt><br/>'. + '</div>'. + '<table class="result" align="center" width="100%" border="0">'. + '<tr>'. + '<th>'.$group_by_name.'</th><th>URI</th>'. + ($this->use_sessions?'<th>Curr. Speed</th><th>Avg. Speed</th>':''). + '<th>Size</th><th>Time</th>'. + '</tr>'; + $ausers=$acon=0; + unset($session_data); + if (isset($_SESSION['time']) && ((time() - $_SESSION['time']) < 3*60) && isset($_SESSION['sqdata']) && is_array($_SESSION['sqdata'])) { + //only if the latest data was less than 3 minutes ago + $session_data = $_SESSION['sqdata']; + } + $table=''; + foreach($users as $key=>$v){ + $ausers++; + $table.='<tr><td style="border-right:0;" colspan="2"><b>'.(is_int($key)?long2ip($key):$key).'</b></td>'. + '<td style="border-left:0;" colspan="5"> </td></tr>'; + $user_avg = $user_curr = $con_color = 0; + foreach ($v as $con){ + if(substr($con["uri"],0,7)=="http://" || substr($con["uri"],0,6)=="ftp://"){ + if(strlen($con["uri"])>SQSTAT_SHOWLEN) $uritext=htmlspecialchars(substr($con["uri"],0,SQSTAT_SHOWLEN)).'</a> ....'; + else $uritext=htmlspecialchars($con["uri"]).'</a>'; + $uri='<a target="_blank" href="'.htmlspecialchars($con["uri"]).'">'.$uritext; + } + else $uri=htmlspecialchars($con["uri"]); + $acon++; + //speed stuff + $con_id = $con['connection']; + $is_time = time(); + $curr_speed=0; + $avg_speed=0; + if (isset($session_data[$con_id]) && $con_data = $session_data[$con_id] ) { + // if we have info about current connection, we do analyze its data + // current speed + $was_time = $con_data['time']; + $was_size = $con_data['size']; + if ($was_time && $was_size) { + $delta = $is_time - $was_time; + if ($delta == 0) { + $delta = 1; + } + if ($con['bytes'] >= $was_size) { + $curr_speed = ($con['bytes'] - $was_size) / 1024 / $delta; + } + } else { + $curr_speed = $con['bytes'] / 1024; + } + + //avg speed + $avg_speed = $con['bytes'] / 1024; + if ($con['seconds'] > 0) { + $avg_speed /= $con['seconds']; + } + } + + $new_data[$con_id]['time'] = $is_time; + $new_data[$con_id]['size'] = $con['bytes']; + + //sum speeds + $total_avg += $avg_speed; + $user_avg += $avg_speed; + $total_curr += $curr_speed; + $user_curr += $curr_speed; + + if($use_js) $js='onMouseout="hideddrivetip()" onMouseover="ddrivetip(\''.$this->implode_with_keys($con,'<br/>').'\')"'; + else $js=''; + $table.='<tr'.( (++$con_color % 2 == 0) ? ' class="odd"' : '' ).'><td id="white"></td>'. + '<td nowrap '.$js.' width="80%" >'.$uri.'</td>'; + if($this->use_sessions){ + $table .= '<td nowrap align="right">'.( (round($curr_speed, 2) > 0) ? sprintf("%01.2f KB/s", $curr_speed) : '' ).'</td>'. + '<td nowrap align="right">'.( (round($avg_speed, 2) > 0) ? sprintf("%01.2f KB/s", $avg_speed) : '' ). '</td>'; + } + $table .= '<td nowrap align="right">'.$this->filesize_format($con["bytes"]).'</td>'. + '<td nowrap align="right">'.$this->duration($con["seconds"],"short").'</td>'. + '</tr>'; + } + if($this->use_sessions){ + $table.=sprintf("<tr><td colspan=\"2\"></td><td align=\"right\" id=\"highlight\">%01.2f KB/s</td><td align=\"right\" id=\"highlight\">%01.2f KB/s</td><td colspan=\"2\"></td>", + $user_curr, $user_avg); + } + + } + $_SESSION['time'] = time(); + if(isset($new_data)) $_SESSION['sqdata'] = $new_data; + $stat_row=''; + if($this->use_sessions){ + $stat_row.=sprintf("<tr class=\"total\"><td><b>Total:</b></td><td align=\"right\" colspan=\"5\"><b>%d</b> users and <b>%d</b> connections @ <b>%01.2f/%01.2f</b> KB/s (CURR/AVG)</td></tr>", + $ausers, $acon, $total_curr, $total_avg); + } + else { + $stat_row.=sprintf("<tr class=\"total\"><td><b>Total:</b></td><td align=\"right\" colspan=\"5\"><b>%d</b> users and <b>%d</b> connections</td></tr>", + $ausers, $acon); + } + if($ausers==0){ + $text.='<tr><td colspan=6><b>No active connections</b></td></tr>'; + } + else { + $text.=$stat_row.$table.$stat_row; + } + $text .= '</table>'. + '<p class="copyleft">© <a href="mailto:samm@os2.kiev.ua?subject=SqStat '.SQSTAT_VERSION.'">Alex Samorukov</a>, 2006</p>'; + return $this->formatXHTML($text,$refresh,$use_js); + } + + function parseRequest($data, $group_by = 'host', $resolveip = false) { $parsed = array(); + if ($this->use_sessions) { + session_name('SQDATA'); + session_start(); + } + + # resort data array + $users = array(); + switch ($group_by) { + case "username": + $group_by_name = "User"; + $group_by_key = "username"; + break; + case "host": + default: + $group_by_name = "Host"; + $group_by_key = "peer"; + break; + } + + # resolve IP & group + foreach ($data["con"] as $key => $v) { # skip myself + if (substr($v["uri"], 0, 13) == "cache_object:") continue; + + $ip = substr($v["peer"], 0, strpos($v["peer"], ":")); + $v["peer"] = $ip; + + # name from hosts + if (isset($this->hosts[$ip])) { + $ip = $this->hosts[$ip]; + } + else + # i use ip2long() to make ip sorting work correctly + if ($resolveip) { + $hostname = gethostbyaddr($ip); + if ($hostname == $ip) + $ip = ip2long($ip); # resolve failed. use (ip2long) key + else $ip = $hostname; + } + else { + $ip = ip2long(substr($v["peer"], 0, strpos($v["peer"], ":"))); + } + $v['con_id'] = $key; + $v["username"] = isset($v["username"]) ? $v["username"] : "N/A"; + + # users [key => conn_array] + $users[$v[$group_by_key]][] = $v; + } + ksort($users); + + unset($session_data); + if (isset($_SESSION['time']) && ((time() - $_SESSION['time']) < 3*60) && + isset($_SESSION['sqdata']) && is_array($_SESSION['sqdata'])) { + # only if the latest data was less than 3 minutes ago + $session_data = $_SESSION['sqdata']; + } + + # users count & con cont + $ausers = $acon = 0; + $total_avg = $total_curr = 0; + foreach ($users as $key => $v) { $ausers++; + + $user_avg = $user_curr = $con_color = 0; + foreach ($v as $con_key => $con){ $cres = array(); + $acon++; + + $uritext = $con["uri"]; + if (substr($con["uri"], 0, 7) == "http://" || substr($con["uri"], 0, 6) == "ftp://") { + if (strlen($uritext) > SQSTAT_SHOWLEN) + $uritext = htmlspecialchars(substr($uritext, 0, SQSTAT_SHOWLEN)) . ' ....'; + } + else $uritext = htmlspecialchars($uritext); + $cres['uritext'] = $uritext; + $cres['uri'] = $con["uri"]; + + # speed stuff + $con_id = $con['connection']; + $is_time = time(); + $curr_speed = $avg_speed = 0; + if (isset($session_data[$con_id]) && $con_data = $session_data[$con_id] ) { + # if we have info about current connection, we do analyze its data + # current speed + $was_time = $con_data['time']; + $was_size = $con_data['size']; + if ($was_time && $was_size) { + $delta = $is_time - $was_time; + if ($delta == 0) { + $delta = 1; + } + if ($con['bytes'] >= $was_size) { + $curr_speed = ($con['bytes'] - $was_size) / 1024 / $delta; + } + } else { + $curr_speed = $con['bytes'] / 1024; + } + + # avg speed + $avg_speed = $con['bytes'] / 1024; + if ($con['seconds'] > 0) { + $avg_speed /= $con['seconds']; + } + } + $cres['cur_speed'] = $curr_speed; + $cres['avg_speed'] = $avg_speed; + $cres['seconds'] = $con["seconds"]; + $cres['bytes'] = $con["bytes"]; + + # groupped parsed[key => conn_key] + $parsed['users'][$key]['con'][$con_key] = $cres; + + # for sessions + $new_data[$con_id]['time'] = $is_time; + $new_data[$con_id]['size'] = $con['bytes']; + + # sum speeds + $total_avg += $avg_speed; + $user_avg += $avg_speed; + $total_curr += $curr_speed; + $user_curr += $curr_speed; + } + + # total per user + $parsed['users'][$key]['user_curr'] = $user_curr; + $parsed['users'][$key]['user_avg'] = $user_avg; + } + + # total info + $parsed['ausers'] = $ausers; + $parsed['acon'] = $acon; + $parsed['total_avg'] = $total_avg; + $parsed['total_curr'] = $total_curr; + + # update session info + $_SESSION['time'] = time(); + if (isset($new_data)) $_SESSION['sqdata'] = $new_data; + + return $parsed; + } + + function errorMsg($errno, $errstr) + { $this->errno = $errno; + $this->errstr = $errstr; + } + + function load_hosts() + { + # loading hosts file + $hosts_array = array(); + + if (!empty($this->hosts_file)) { + if (is_file($this->hosts_file)) { + $handle = @fopen($this->hosts_file, "r"); + if ($handle) { + while (!feof($handle)) { + $buffer = fgets($handle, 4096); + unset($matches); + if (preg_match('/^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})[ \t]+(.+)$/i', $buffer, $matches)) { + $hosts_array[$matches[1]]=$matches[2]; + } + } + fclose($handle); + } + $this->hosts = $hosts_array; + } + else { + #error + $this->errorMsg(4, "Hosts file not found. Cant read <tt>'{$this->hosts_file}'</tt>."); + return $this->errno; + } + } + + return 0; + } + + function query_exec() + { + $data = ""; + + $this->server_version = '(unknown)'; + if ($this->connect($this->squidhost, $this->squidport)) { + $data = $this->makeQuery($this->cachemgr_passwd); + if ($this->errno == 0) { + $this->server_version = $data['server_version']; + $data = $this->parseRequest($data, 'host', true); + } + } + + return $data; + } - - -<!DOCTYPE html> -<html> - <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# githubog: http://ogp.me/ns/fb/githubog#"> - <meta charset='utf-8'> - <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <title>Downloads · dvserg/pfsense-packages · GitHub</title> - <link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub" /> - <link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub" /> - <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" /> - - - - - <meta content="authenticity_token" name="csrf-param" /> -<meta content="SaEmvr7Few28qx5SIv3J8S+GcnuZ7qhoGu3Gtmsyy8Q=" name="csrf-token" /> - - <link href="https://a248.e.akamai.net/assets.github.com/stylesheets/bundles/github-61ae1d367be26efd3260c8a23fc81353611bfa47.css" media="screen" rel="stylesheet" type="text/css" /> - <link href="https://a248.e.akamai.net/assets.github.com/stylesheets/bundles/github2-c1921b914a1a5c9fd63f1f197c5742bcc5500740.css" media="screen" rel="stylesheet" type="text/css" /> - - - - - <script src="https://a248.e.akamai.net/assets.github.com/javascripts/bundles/frameworks-31b6b84bca1e7d3f3907f63a4dd7f9bbda3a0eda.js" type="text/javascript"></script> - - <script defer="defer" src="https://a248.e.akamai.net/assets.github.com/javascripts/bundles/github-88c09a33a6ebba4abecc6d3381fddeeb6b55fb13.js" type="text/javascript"></script> - - - - - <meta property="og:title" content="pfsense-packages"/> - <meta property="og:type" content="githubog:gitrepository"/> - <meta property="og:url" content="https://github.com/dvserg/pfsense-packages"/> - <meta property="og:image" content="https://a248.e.akamai.net/assets.github.com/images/gravatars/gravatar-140.png?1329275856"/> - <meta property="og:site_name" content="GitHub"/> - <meta property="og:description" content="pfsense-packages - pfSense packages repository"/> - - <meta name="description" content="pfsense-packages - pfSense packages repository" /> - - <link href="https://github.com/dvserg/pfsense-packages/commits/master.atom" rel="alternate" title="Recent Commits to pfsense-packages:master" type="application/atom+xml" /> - - </head> - - - <body class="logged_out page-downloads vis-public fork env-production " data-blob-contribs-enabled="yes"> - <div id="wrapper"> - - - - - - <div id="header" class="true clearfix"> - <div class="container clearfix"> - <a class="site-logo" href="https://github.com"> - <!--[if IE]> - <img alt="GitHub" class="github-logo" src="https://a248.e.akamai.net/assets.github.com/images/modules/header/logov7.png?1323882716" /> - <img alt="GitHub" class="github-logo-hover" src="https://a248.e.akamai.net/assets.github.com/images/modules/header/logov7-hover.png?1324325358" /> - <![endif]--> - <img alt="GitHub" class="github-logo-4x" height="30" src="https://a248.e.akamai.net/assets.github.com/images/modules/header/logov7@4x.png?1323882716" /> - <img alt="GitHub" class="github-logo-4x-hover" height="30" src="https://a248.e.akamai.net/assets.github.com/images/modules/header/logov7@4x-hover.png?1324325358" /> - </a> - - <!-- - make sure to use fully qualified URLs here since this nav - is used on error pages on other domains - --> - <ul class="top-nav logged_out"> - <li class="pricing"><a href="https://github.com/plans">Signup and Pricing</a></li> - <li class="explore"><a href="https://github.com/explore">Explore GitHub</a></li> - <li class="features"><a href="https://github.com/features">Features</a></li> - <li class="blog"><a href="https://github.com/blog">Blog</a></li> - <li class="login"><a href="https://github.com/login?return_to=%2Fdvserg%2Fpfsense-packages%2Fdownloads">Login</a></li> - </ul> - - - - - </div> - </div> - - - - <div class="site hfeed" itemscope itemtype="http://schema.org/WebPage"> - <div class="container hentry"> - <div class="pagehead repohead instapaper_ignore readability-menu"> - <div class="title-actions-bar"> - - - - - <ul class="pagehead-actions"> - - - - <li> - <a href="/login?return_to=%2Fdvserg%2Fpfsense-packages" class="minibutton btn-i-type-i-switcher switcher count btn-watches js-toggler-target watch-button entice tooltipped leftwards" title="You must be logged in to use this feature" rel="nofollow"><span><span class="icon"></span><i>1</i> Watch</span></a> - </li> - <li> - <a href="/login?return_to=%2Fdvserg%2Fpfsense-packages" class="minibutton btn-i-type-i-switcher switcher count btn-forks js-toggler-target fork-button entice tooltipped leftwards" title="You must be logged in to use this feature" rel="nofollow"><span><span class="icon"></span><i>20</i> Fork</span></a> - </li> - - </ul> - - <h1 itemscope itemtype="http://data-vocabulary.org/Breadcrumb" class="entry-title"> - <span class="repo-label"><span class="public">public</span></span> - <span class="mega-icon public-repo"></span> - <span class="author vcard"> -<a href="/dvserg" class="url fn" itemprop="url" rel="author"> <span itemprop="title">dvserg</span> - </a></span> / - <strong><a href="/dvserg/pfsense-packages" class="js-current-repository">pfsense-packages</a></strong> - <span class="fork-flag"> - <span class="text">forked from <a href="/bsdperimeter/pfsense-packages">bsdperimeter/pfsense-packages</a></span> - </span> - </h1> - </div> - - - - <ul class="tabs"> - <li><a href="/dvserg/pfsense-packages" class="selected" highlight="repo_sourcerepo_downloadsrepo_commitsrepo_tagsrepo_branches">Code</a></li> - <li><a href="/dvserg/pfsense-packages/network" highlight="repo_network">Network</a> - <li><a href="/dvserg/pfsense-packages/pulls" highlight="repo_pulls">Pull Requests <span class='counter'>0</span></a></li> - - - - <li><a href="/dvserg/pfsense-packages/graphs" highlight="repo_graphsrepo_contributors">Graphs</a></li> - - </ul> - -<div class="frame frame-center tree-finder" style="display:none" - data-tree-list-url="/dvserg/pfsense-packages/tree-list/49d604126f311966c2e61e125064191142bd98e8" - data-blob-url-prefix="/dvserg/pfsense-packages/blob/49d604126f311966c2e61e125064191142bd98e8" - > - - <div class="breadcrumb"> - <span class="bold"><a href="/dvserg/pfsense-packages">pfsense-packages</a></span> / - <input class="tree-finder-input js-navigation-enable" type="text" name="query" autocomplete="off" spellcheck="false"> - </div> - - <div class="octotip"> - <p> - <a href="/dvserg/pfsense-packages/dismiss-tree-finder-help" class="dismiss js-dismiss-tree-list-help" title="Hide this notice forever" rel="nofollow">Dismiss</a> - <span class="bold">Octotip:</span> You've activated the <em>file finder</em> - by pressing <span class="kbd">t</span> Start typing to filter the - file list. Use <span class="kbd badmono">↑</span> and - <span class="kbd badmono">↓</span> to navigate, - <span class="kbd">enter</span> to view files. - </p> - </div> - - <table class="tree-browser" cellpadding="0" cellspacing="0"> - <tr class="js-header"><th> </th><th>name</th></tr> - <tr class="js-no-results no-results" style="display: none"> - <th colspan="2">No matching files</th> - </tr> - <tbody class="js-results-list js-navigation-container"> - </tbody> - </table> -</div> - -<div id="jump-to-line" style="display:none"> - <h2>Jump to Line</h2> - <form accept-charset="UTF-8"> - <input class="textfield" type="text"> - <div class="full-button"> - <button type="submit" class="classy"> - <span>Go</span> - </button> - </div> - </form> -</div> - - -<div class="subnav-bar"> - - <ul class="actions subnav"> - <li><a href="/dvserg/pfsense-packages/tags" class="blank" highlight="repo_tags">Tags <span class="counter">0</span></a></li> - <li><a href="/dvserg/pfsense-packages/downloads" class="selected " highlight="repo_downloads">Downloads <span class="counter">4</span></a></li> - - </ul> - - - <ul class="subnav"> - - <li><a href="/dvserg/pfsense-packages" highlight="repo_source">Files</a></li> - <li><a href="/dvserg/pfsense-packages/commits/master" highlight="repo_commits">Commits</a></li> - <li><a href="/dvserg/pfsense-packages/branches" class="" highlight="repo_branches" rel="nofollow">Branches <span class="counter">1</span></a></li> - </ul> - -</div> - - - - - - - - - </div><!-- /.repohead --> - - - - - - -<p> - <a href="/dvserg/pfsense-packages/zipball/master" class="button classy first-in-line" rel="nofollow"> - <span>Download as zip</span> - </a> - <a href="/dvserg/pfsense-packages/tarball/master" class="button classy" rel="nofollow"> - <span>Download as tar.gz</span> - </a> -</p> - - -<div id="uploaded_downloads"> - -<h3>Download Packages</h3> - -<ol class="download-list" id="manual_downloads"> - <li class="ctype-unknown"> - <span class="mini-icon download-unknown"></span> - <span class="download-stats"> - <strong>1</strong> download - </span> - <h4> - <a href="/downloads/dvserg/pfsense-packages/zhabascript.js">zhabascript.js</a> - — SQStat mon > to Lightsquid folder - </h4> - <p><strong>4KB</strong> · Uploaded <time class="js-relative-date" datetime="2012-05-09T12:32:44-07:00" title="2012-05-09 12:32:44">May 09, 2012</time></p> - </li> - <li class="ctype-unknown"> - <span class="mini-icon download-unknown"></span> - <span class="download-stats"> - <strong>0</strong> downloads - </span> - <h4> - <a href="/downloads/dvserg/pfsense-packages/sqstat.php">sqstat.php</a> - — SQStat mon > to Lightsquid folder - </h4> - <p><strong>12KB</strong> · Uploaded <time class="js-relative-date" datetime="2012-05-09T12:32:34-07:00" title="2012-05-09 12:32:34">May 09, 2012</time></p> - </li> - <li class="ctype-unknown"> - <span class="mini-icon download-unknown"></span> - <span class="download-stats"> - <strong>1</strong> download - </span> - <h4> - <a href="/downloads/dvserg/pfsense-packages/sqstat.css">sqstat.css</a> - — SQStat mon > to Lightsquid folder - </h4> - <p><strong>1KB</strong> · Uploaded <time class="js-relative-date" datetime="2012-05-09T12:32:22-07:00" title="2012-05-09 12:32:22">May 09, 2012</time></p> - </li> - <li class="ctype-unknown"> - <span class="mini-icon download-unknown"></span> - <span class="download-stats"> - <strong>0</strong> downloads - </span> - <h4> - <a href="/downloads/dvserg/pfsense-packages/sqstat.class.php">sqstat.class.php</a> - — SQStat mon > to Lightsquid folder - </h4> - <p><strong>20KB</strong> · Uploaded <time class="js-relative-date" datetime="2012-05-09T12:32:14-07:00" title="2012-05-09 12:32:14">May 09, 2012</time></p> - </li> -</ol> - -</div> - - - </div> - <div class="context-overlay"></div> - </div> - - <div id="footer-push"></div><!-- hack for sticky footer --> - </div><!-- end of wrapper - hack for sticky footer --> - - <!-- footer --> - <div id="footer" > - - <div class="upper_footer"> - <div class="container clearfix"> - - <!--[if IE]><h4 id="blacktocat_ie">GitHub Links</h4><![endif]--> - <![if !IE]><h4 id="blacktocat">GitHub Links</h4><![endif]> - - <ul class="footer_nav"> - <h4>GitHub</h4> - <li><a href="https://github.com/about">About</a></li> - <li><a href="https://github.com/blog">Blog</a></li> - <li><a href="https://github.com/features">Features</a></li> - <li><a href="https://github.com/contact">Contact & Support</a></li> - <li><a href="https://github.com/training">Training</a></li> - <li><a href="http://enterprise.github.com/">GitHub Enterprise</a></li> - <li><a href="http://status.github.com/">Site Status</a></li> - </ul> - - <ul class="footer_nav"> - <h4>Tools</h4> - <li><a href="http://get.gaug.es/">Gauges: Analyze web traffic</a></li> - <li><a href="http://speakerdeck.com">Speaker Deck: Presentations</a></li> - <li><a href="https://gist.github.com">Gist: Code snippets</a></li> - <li><a href="http://mac.github.com/">GitHub for Mac</a></li> - <li><a href="http://mobile.github.com/">Issues for iPhone</a></li> - <li><a href="http://jobs.github.com/">Job Board</a></li> - </ul> - - <ul class="footer_nav"> - <h4>Extras</h4> - <li><a href="http://shop.github.com/">GitHub Shop</a></li> - <li><a href="http://octodex.github.com/">The Octodex</a></li> - </ul> - - <ul class="footer_nav"> - <h4>Documentation</h4> - <li><a href="http://help.github.com/">GitHub Help</a></li> - <li><a href="http://developer.github.com/">Developer API</a></li> - <li><a href="http://github.github.com/github-flavored-markdown/">GitHub Flavored Markdown</a></li> - <li><a href="http://pages.github.com/">GitHub Pages</a></li> - </ul> - - </div><!-- /.site --> - </div><!-- /.upper_footer --> - -<div class="lower_footer"> - <div class="container clearfix"> - <!--[if IE]><div id="legal_ie"><![endif]--> - <![if !IE]><div id="legal"><![endif]> - <ul> - <li><a href="https://github.com/site/terms">Terms of Service</a></li> - <li><a href="https://github.com/site/privacy">Privacy</a></li> - <li><a href="https://github.com/security">Security</a></li> - </ul> - - <p>© 2012 <span title="0.09136s from fe9.rs.github.com">GitHub</span> Inc. All rights reserved.</p> - </div><!-- /#legal or /#legal_ie--> - - <div class="sponsor"> - <a href="http://www.rackspace.com" class="logo"> - <img alt="Dedicated Server" height="36" src="https://a248.e.akamai.net/assets.github.com/images/modules/footer/rackspaces_logo.png?1329521039" width="38" /> - </a> - Powered by the <a href="http://www.rackspace.com ">Dedicated - Servers</a> and<br/> <a href="http://www.rackspacecloud.com">Cloud - Computing</a> of Rackspace Hosting<span>®</span> - </div> - </div><!-- /.site --> -</div><!-- /.lower_footer --> - - </div><!-- /#footer --> - - - -<div id="keyboard_shortcuts_pane" class="instapaper_ignore readability-extra" style="display:none"> - <h2>Keyboard Shortcuts <small><a href="#" class="js-see-all-keyboard-shortcuts">(see all)</a></small></h2> - - <div class="columns threecols"> - <div class="column first"> - <h3>Site wide shortcuts</h3> - <dl class="keyboard-mappings"> - <dt>s</dt> - <dd>Focus site search</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>?</dt> - <dd>Bring up this help dialog</dd> - </dl> - </div><!-- /.column.first --> - - <div class="column middle" style='display:none'> - <h3>Commit list</h3> - <dl class="keyboard-mappings"> - <dt>j</dt> - <dd>Move selection down</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>k</dt> - <dd>Move selection up</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>c <em>or</em> o <em>or</em> enter</dt> - <dd>Open commit</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>y</dt> - <dd>Expand URL to its canonical form</dd> - </dl> - </div><!-- /.column.first --> - - <div class="column last" style='display:none'> - <h3>Pull request list</h3> - <dl class="keyboard-mappings"> - <dt>j</dt> - <dd>Move selection down</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>k</dt> - <dd>Move selection up</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>o <em>or</em> enter</dt> - <dd>Open issue</dd> - </dl> - <dl class="keyboard-mappings"> - <dt><span class="platform-mac">⌘</span><span class="platform-other">ctrl</span> <em>+</em> enter</dt> - <dd>Submit comment</dd> - </dl> - </div><!-- /.columns.last --> - - </div><!-- /.columns.equacols --> - - <div style='display:none'> - <div class="rule"></div> - - <h3>Issues</h3> - - <div class="columns threecols"> - <div class="column first"> - <dl class="keyboard-mappings"> - <dt>j</dt> - <dd>Move selection down</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>k</dt> - <dd>Move selection up</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>x</dt> - <dd>Toggle selection</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>o <em>or</em> enter</dt> - <dd>Open issue</dd> - </dl> - <dl class="keyboard-mappings"> - <dt><span class="platform-mac">⌘</span><span class="platform-other">ctrl</span> <em>+</em> enter</dt> - <dd>Submit comment</dd> - </dl> - </div><!-- /.column.first --> - <div class="column last"> - <dl class="keyboard-mappings"> - <dt>c</dt> - <dd>Create issue</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>l</dt> - <dd>Create label</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>i</dt> - <dd>Back to inbox</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>u</dt> - <dd>Back to issues</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>/</dt> - <dd>Focus issues search</dd> - </dl> - </div> - </div> - </div> - - <div style='display:none'> - <div class="rule"></div> - - <h3>Issues Dashboard</h3> - - <div class="columns threecols"> - <div class="column first"> - <dl class="keyboard-mappings"> - <dt>j</dt> - <dd>Move selection down</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>k</dt> - <dd>Move selection up</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>o <em>or</em> enter</dt> - <dd>Open issue</dd> - </dl> - </div><!-- /.column.first --> - </div> - </div> - - <div style='display:none'> - <div class="rule"></div> - - <h3>Network Graph</h3> - <div class="columns equacols"> - <div class="column first"> - <dl class="keyboard-mappings"> - <dt><span class="badmono">←</span> <em>or</em> h</dt> - <dd>Scroll left</dd> - </dl> - <dl class="keyboard-mappings"> - <dt><span class="badmono">→</span> <em>or</em> l</dt> - <dd>Scroll right</dd> - </dl> - <dl class="keyboard-mappings"> - <dt><span class="badmono">↑</span> <em>or</em> k</dt> - <dd>Scroll up</dd> - </dl> - <dl class="keyboard-mappings"> - <dt><span class="badmono">↓</span> <em>or</em> j</dt> - <dd>Scroll down</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>t</dt> - <dd>Toggle visibility of head labels</dd> - </dl> - </div><!-- /.column.first --> - <div class="column last"> - <dl class="keyboard-mappings"> - <dt>shift <span class="badmono">←</span> <em>or</em> shift h</dt> - <dd>Scroll all the way left</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>shift <span class="badmono">→</span> <em>or</em> shift l</dt> - <dd>Scroll all the way right</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>shift <span class="badmono">↑</span> <em>or</em> shift k</dt> - <dd>Scroll all the way up</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>shift <span class="badmono">↓</span> <em>or</em> shift j</dt> - <dd>Scroll all the way down</dd> - </dl> - </div><!-- /.column.last --> - </div> - </div> - - <div style='display:none'> - <div class="rule"></div> - <div class="columns threecols"> - <div class="column first" style='display:none'> - <h3>Source Code Browsing</h3> - <dl class="keyboard-mappings"> - <dt>t</dt> - <dd>Activates the file finder</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>l</dt> - <dd>Jump to line</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>w</dt> - <dd>Switch branch/tag</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>y</dt> - <dd>Expand URL to its canonical form</dd> - </dl> - </div> - </div> - </div> - - <div style='display:none'> - <div class="rule"></div> - <div class="columns threecols"> - <div class="column first"> - <h3>Browsing Commits</h3> - <dl class="keyboard-mappings"> - <dt><span class="platform-mac">⌘</span><span class="platform-other">ctrl</span> <em>+</em> enter</dt> - <dd>Submit comment</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>escape</dt> - <dd>Close form</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>p</dt> - <dd>Parent commit</dd> - </dl> - <dl class="keyboard-mappings"> - <dt>o</dt> - <dd>Other parent commit</dd> - </dl> - </div> - </div> - </div> -</div> - - <div id="markdown-help" class="instapaper_ignore readability-extra"> - <h2>Markdown Cheat Sheet</h2> - - <div class="cheatsheet-content"> - - <div class="mod"> - <div class="col"> - <h3>Format Text</h3> - <p>Headers</p> - <pre> -# This is an <h1> tag -## This is an <h2> tag -###### This is an <h6> tag</pre> - <p>Text styles</p> - <pre> -*This text will be italic* -_This will also be italic_ -**This text will be bold** -__This will also be bold__ - -*You **can** combine them* -</pre> - </div> - <div class="col"> - <h3>Lists</h3> - <p>Unordered</p> - <pre> -* Item 1 -* Item 2 - * Item 2a - * Item 2b</pre> - <p>Ordered</p> - <pre> -1. Item 1 -2. Item 2 -3. Item 3 - * Item 3a - * Item 3b</pre> - </div> - <div class="col"> - <h3>Miscellaneous</h3> - <p>Images</p> - <pre> -![GitHub Logo](/images/logo.png) -Format: ![Alt Text](url) -</pre> - <p>Links</p> - <pre> -http://github.com - automatic! -[GitHub](http://github.com)</pre> -<p>Blockquotes</p> - <pre> -As Kanye West said: - -> We're living the future so -> the present is our past. -</pre> - </div> - </div> - <div class="rule"></div> - - <h3>Code Examples in Markdown</h3> - <div class="col"> - <p>Syntax highlighting with <a href="http://github.github.com/github-flavored-markdown/" title="GitHub Flavored Markdown" target="_blank">GFM</a></p> - <pre> -```javascript -function fancyAlert(arg) { - if(arg) { - $.facebox({div:'#foo'}) - } } -```</pre> - </div> - <div class="col"> - <p>Or, indent your code 4 spaces</p> - <pre> -Here is a Python code example -without syntax highlighting: - - def foo: - if not bar: - return true</pre> - </div> - <div class="col"> - <p>Inline code for comments</p> - <pre> -I think you should use an -`<addr>` element here instead.</pre> - </div> - </div> - - </div> -</div> - - - <div class="ajax-error-message"> - <p><span class="mini-icon exclamation"></span> Something went wrong with that request. Please try again. <a href="javascript:;" class="ajax-error-dismiss">Dismiss</a></p> - </div> - - <div id="logo-popup"> - <h2>Looking for the GitHub logo?</h2> - <ul> - <li> - <h4>GitHub Logo</h4> - <a href="http://github-media-downloads.s3.amazonaws.com/GitHub_Logos.zip"><img alt="Github_logo" src="https://a248.e.akamai.net/assets.github.com/images/modules/about_page/github_logo.png?1315867479" /></a> - <a href="http://github-media-downloads.s3.amazonaws.com/GitHub_Logos.zip" class="minibutton btn-download download"><span><span class="icon"></span>Download</span></a> - </li> - <li> - <h4>The Octocat</h4> - <a href="http://github-media-downloads.s3.amazonaws.com/Octocats.zip"><img alt="Octocat" src="https://a248.e.akamai.net/assets.github.com/images/modules/about_page/octocat.png?1315867479" /></a> - <a href="http://github-media-downloads.s3.amazonaws.com/Octocats.zip" class="minibutton btn-download download"><span><span class="icon"></span>Download</span></a> - </li> - </ul> - </div> - - - - - <span id='server_response_time' data-time='0.09526' data-host='fe9'></span> - </body> -</html> - +?>
\ No newline at end of file |