diff options
Diffstat (limited to 'config/lightsquid')
-rw-r--r-- | config/lightsquid/lightsquid.inc | 631 | ||||
-rw-r--r-- | config/lightsquid/lightsquid.priv.inc | 40 | ||||
-rw-r--r-- | config/lightsquid/lightsquid.xml | 510 | ||||
-rw-r--r-- | config/lightsquid/sqstat.class.php | 819 | ||||
-rw-r--r-- | config/lightsquid/sqstat.css | 105 | ||||
-rw-r--r-- | config/lightsquid/sqstat.php | 604 | ||||
-rwxr-xr-x | config/lightsquid/tpl/novopf/index.html | 2 | ||||
-rwxr-xr-x | config/lightsquid/tpl/novopf/user_detail.html | 4 | ||||
-rwxr-xr-x | config/lightsquid/tpl/novopf/user_month.html | 4 | ||||
-rwxr-xr-x | config/lightsquid/tpl/novopf/whousesite.html | 2 | ||||
-rwxr-xr-x | config/lightsquid/tpl/novosea/index.html | 2 | ||||
-rwxr-xr-x | config/lightsquid/tpl/novosea/user_detail.html | 4 | ||||
-rwxr-xr-x | config/lightsquid/tpl/novosea/user_month.html | 4 | ||||
-rwxr-xr-x | config/lightsquid/tpl/novosea/whousesite.html | 2 | ||||
-rw-r--r-- | config/lightsquid/zhabascript.js | 190 |
15 files changed, 1466 insertions, 1457 deletions
diff --git a/config/lightsquid/lightsquid.inc b/config/lightsquid/lightsquid.inc index a5f6b77b..7decc050 100644 --- a/config/lightsquid/lightsquid.inc +++ b/config/lightsquid/lightsquid.inc @@ -1,7 +1,9 @@ <?php /* lightsquid.inc - Copyright (C) 2006 Serg Dvorianceev + part of pfSense (https://www.pfSense.org/) + Copyright (C) 2006-2012 Sergey Dvoriancev <dv_serg@mail.ru> + Copyright (C) 2015 ESF, LLC All rights reserved. Redistribution and use in source and binary forms, with or without @@ -25,7 +27,6 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - require_once('globals.inc'); require_once('config.inc'); require_once('util.inc'); @@ -34,13 +35,14 @@ require_once('pkg-utils.inc'); require_once('filter.inc'); require_once('service-utils.inc'); -if (file_exists('squid.inc')) { - require_once('squid.inc'); +if (file_exists('/usr/local/pkg/squid.inc')) { + require_once('/usr/local/pkg/squid.inc'); +} else { + echo "No squid.inc found. You must have Squid/Squid3 package installed to use LightSquid."; } -else update_log("File 'squid.inc' not found."); global $pfs_version; -$pfs_version = substr(trim(file_get_contents("/etc/version")),0,3); +$pfs_version = substr(trim(file_get_contents("/etc/version")), 0, 3); switch ($pfs_version) { case "2.1": define('LIGHTSQUID_BASE', '/usr/pbi/lightsquid-' . php_uname("m")); @@ -49,16 +51,10 @@ switch ($pfs_version) { define('LIGHTSQUID_BASE', '/usr/pbi/lightsquid-' . php_uname("m") . '/local'); break; default: - define('LIGHTSQUID_BASE','/usr/local'); + define('LIGHTSQUID_BASE', '/usr/local'); break; } -define ('CMD_PKGDELETE', 'pkg_delete lightsquid-1.7.1'); - -// enable GUI debug -define('LS_GUI_DEBUG', 'on'); -define('LS_LOG_FILE', '/tmp/lightsquid_gui.log'); - // configuration settings !-- CHECK THIS --! define('LS_CONFIGPATH', LIGHTSQUID_BASE . '/etc/lightsquid'); define('LS_CONFIGFILE', 'lightsquid.cfg'); @@ -69,20 +65,15 @@ define('LS_LANGPATH', LIGHTSQUID_BASE . '/share/lightsquid/lang'); define('LS_REPORTPATH', '/var/lightsquid/report'); global $config; -if (isset($config['installedpackages']['squid']['config'][0])) { - if (!empty($config['installedpackages']['squid']['config'][0]['log_dir'])) - define('LS_SQUIDLOGPATH', $config['installedpackages']['squid']['config'][0]['log_dir']); - else - define('LS_SQUIDLOGPATH', '/var/squid/logs'); +if (is_array($config['installedpackages']['squid']['config'][0]) && $config['installedpackages']['squid']['config'][0]['log_dir'] != "") { + define('LS_SQUIDLOGPATH', $config['installedpackages']['squid']['config'][0]['log_dir']); +} else { + define('LS_SQUIDLOGPATH', '/var/squid/logs'); } + define('LS_SQUIDLOG', 'access.log'); define('LS_IP2NAMEPATH', LIGHTSQUID_BASE . '/libexec/lightsquid'); - -define('CRONTAB_FILE', '/var/cron/tabs/root'); define('CRONTAB_LS_TEMPLATE', '/usr/bin/perl ' . LIGHTSQUID_BASE . '/www/lightsquid/lightparser.pl'); -define('CRONTAB_LS_JOBKEY', '/lightparser.pl'); -define('CRONTAB_SQUID_TEMPLATE', '/usr/local/sbin/squid -k rotate > /dev/null'); -define('CRONTAB_SQUID_JOBKEY', '/squid -k rotate'); // default values define('LS_DEF_IP2NAME', 'dns'); @@ -106,43 +97,27 @@ define('LS_VAR_IP2NAME', 'ip2name'); define('LS_VAR_TEMPLATE', 'templatename'); define('LS_VAR_BARCOLOR', 'barcolor'); -// xml variables +// XML GUI variables define('LS_XML_LANG', 'lightsquid_lang'); define('LS_XML_SKIPURL', 'lightsquid_skipurl'); define('LS_XML_IP2NAME', 'lightsquid_ip2name'); define('LS_XML_TEMPLATE', 'lightsquid_template'); define('LS_XML_BARCOLOR', 'lightsquid_barcolor'); define('LS_XML_SHEDULERTIME', 'lightsquid_refreshsheduler_time'); -define('LS_XML_SQUID_SHEDULERTIME', 'lightsquid_squidrotatelog_sheduler_time'); - -function lightsquid_install() { - global $pfs_version; - - update_log("lightsquid_install: started"); - // create lightsquid report catalog - if (!file_exists(LS_REPORTPATH)) { - update_log("lightsquid_install: Create report dir " . LS_REPORTPATH); - mwexec("/bin/mkdir -p " . LS_REPORTPATH); - } +/* + * Package install/uninstall + */ - if ($pfs_version == "2.1" || $pfs_version == "2.2") { - # check perl - $perl_path = '/usr/bin/perl'; +function lightsquid_install() { + // create lightsquid reports directory + lightsquid_create_reportdir(); - /* Clean up a bad perl link. */ - ls_cleanup_bad_link($perl_path); + // ugly PBI hacks + if (LIGHTSQUID_BASE != '/usr/local') { + // check and fix perl paths + lightsquid_fix_perl(); - if (!file_exists("/usr/bin/perl")) { - if (is_executable('/usr/local/bin/perl')) { - symlink('/usr/local/bin/perl', '/usr/bin/perl'); - } elseif (is_executable(LIGHTSQUID_BASE . '/bin/perl')) { - symlink(LIGHTSQUID_BASE . '/bin/perl', '/usr/bin/perl'); - } - } - if (!is_dir('/usr/local/lib/perl5') && is_dir(LIGHTSQUID_BASE . '/lib/perl5')) { - symlink(LIGHTSQUID_BASE . '/lib/perl5', '/usr/local/lib/perl5'); - } if (!is_dir('/usr/local/etc/lightsquid') && is_dir(LS_CONFIGPATH)) { symlink(LS_CONFIGPATH, '/usr/local/etc/lightsquid'); } @@ -155,332 +130,358 @@ function lightsquid_install() { } } + // template symlinks foreach (array('novopf', 'novosea') as $tpl) { - if (file_exists(LS_TEMPLATEPATH . '/' . $tpl)) + if (is_dir(LS_TEMPLATEPATH . '/' . $tpl)) { $_gc = exec('rm -rf ' . LS_TEMPLATEPATH . '/' . $tpl); + } symlink('/usr/local/share/lightsquid/tpl/' . $tpl, LS_TEMPLATEPATH . '/' . $tpl); } - - update_log("lightsquid_install: stopped"); + symlink("/usr/local/www/themes", "/usr/local/www/sqstat/themes"); } function lightsquid_deinstall() { - update_log("lightsquid_deinstall: started"); - - // delete cron task's - ls_setup_cron("lightsquid_squid_rotate", "", "", false); - ls_setup_cron("lightsquid_parser", "", "", false); + // remove cronjobs + lightsquid_setup_cron(false); + // undo PBI hacks + lightsquid_unfix_perl(); + if (is_dir("/usr/local/www/sqstat/")) { + mwexec("/bin/rm -rf /usr/local/www/sqstat/"); + } +} - update_log("lightsquid_deinstall: stopped"); +/* + * Ugly PBI hacks around perl paths; only needed for pfSense <2.3 + */ +/* Create perl links on package install */ +function lightsquid_fix_perl() { + if (LIGHTSQUID_BASE != '/usr/local') { + /* Clean up a broken perl link first if needed. */ + $perl_path = '/usr/bin/perl'; + if (file_exists($perl_path) && is_link($perl_path)) { + $target = readlink($perl_path); + if (!file_exists($target) || !is_executable($target)) { + unlink($target); + } + } + /* Find usable perl and create perl symlink to $perl_path */ + if (!file_exists($perl_path)) { + if (is_executable("/usr/local/bin/perl")) { + symlink("/usr/local/bin/perl", "{$perl_path}"); + } elseif (is_executable(LIGHTSQUID_BASE . "/bin/perl")) { + symlink(LIGHTSQUID_BASE . "/bin/perl", "{$perl_path}"); + } + } + if (!is_dir("/usr/local/lib/perl5") && is_dir(LIGHTSQUID_BASE . "/lib/perl5")) { + symlink(LIGHTSQUID_BASE . "/lib/perl5", "/usr/local/lib/perl5"); + } + } +} +/* Remove perl links on package uninstall */ +function lightsquid_unfix_perl() { + if (LIGHTSQUID_BASE != '/usr/local') { + $perl_path = '/usr/bin/perl'; + if (file_exists($perl_path) && is_link($perl_path)) { + $target = readlink($perl_path); + $ls_target = LIGHTSQUID_BASE . "/bin/perl"; + if ($target === $ls_target) { + unlink($perl_path); + } + } + $perl_libpath = "/usr/local/lib/perl5"; + if (is_dir($perl_libpath) && is_link($perl_libpath)) { + $target = readlink($perl_libpath); + $ls_target = LIGHTSQUID_BASE . "/lib/perl5"; + if ($target === $ls_target) { + unlink($perl_libpath); + } + } + } } +/* + * Package configuration routines + */ function lightsquid_resync() { global $config, $pfs_version; - $tm = ''; - $tm_squid = ''; - if ($pfs_version == "2.1" || $pfs_version == "2.2") { - # check perl - if (!file_exists("/usr/bin/perl")) - mwexec("ln -s /usr/local/bin/perl /usr/bin/perl"); + // Ugly PBI hacks + if (LIGHTSQUID_BASE != '/usr/local') { + // check perl paths + if (!file_exists("/usr/bin/perl")) { + lightsquid_fix_perl(); + } // Fixup library path so GD can find its libraries for graphs. mwexec("/sbin/ldconfig -m " . LIGHTSQUID_BASE . "/lib/"); } - // create lightsquid report catalog - if (!file_exists(LS_REPORTPATH)) { - update_log("lightsquid_install: Create report dir " . LS_REPORTPATH); - mwexec("mkdir -p " . LS_REPORTPATH); - } - + lightsquid_create_reportdir(); mwexec("/bin/chmod -R u+w " . LIGHTSQUID_BASE . "/etc/lightsquid"); - // debug - $light_test = array(); - if (($_POST['Submit'] === 'Save') or !isset($_POST['Submit'])) { - $lsconf_var = array(); + // Set up variables for configuration update + $lsconf_var = array(); + $lsconf_var[LS_VAR_CFGPATH] = "\"" . LS_CONFIGPATH . "\""; + $lsconf_var[LS_VAR_LOGPATH] = "\"" . LS_SQUIDLOGPATH . "\""; - // variables for update - $lsconf_var[LS_VAR_CFGPATH] = "\"" . LS_CONFIGPATH . "\""; - if (isset($config['installedpackages']['squid']['config'][0])) { - $lsconf_var[LS_VAR_LOGPATH] = "\"" . LS_SQUIDLOGPATH . "\""; - } - $lsconf_var[LS_VAR_TPLPATH] = "\"" . LS_TEMPLATEPATH . "\""; - $lsconf_var[LS_VAR_LANGPATH] = "\"" . LS_LANGPATH . "\""; - $lsconf_var[LS_VAR_REPORTPATH] = "\"" . LS_REPORTPATH . "\""; - $lsconf_var[LS_VAR_IP2NAMEPATH] = "\"" . LS_IP2NAMEPATH . "\""; - - $lsconf_var[LS_VAR_LANG] = "\"" . LS_DEF_LANG . "\""; - $lsconf_var[LS_VAR_TEMPLATE] = "\"" . LS_DEF_TEMPLATE . "\""; - $lsconf_var[LS_VAR_IP2NAME] = "\"" . LS_DEF_IP2NAME . "\""; - $lsconf_var[LS_VAR_SKIPURL] = "\"" . LS_DEF_SKIPURL . "\""; - $lsconf_var[LS_VAR_SQUIDLOGTYPE]= LS_DEF_SQUIDLOGTYPE; - - // update variables from package GUI config - if (isset($config['installedpackages']['lightsquid']['config'][0])) { - $cfg = $config['installedpackages']['lightsquid']['config'][0]; - - $tm = $cfg[LS_XML_SHEDULERTIME]; - $tm_squid = $cfg[LS_XML_SQUID_SHEDULERTIME]; - - if (isset($cfg[LS_XML_LANG]) and !empty($cfg[LS_XML_LANG])) - $lsconf_var[LS_VAR_LANG] = "\"" . $cfg[LS_XML_LANG] . "\";"; - - if (isset($cfg[LS_XML_SKIPURL]) and !empty($cfg[LS_XML_SKIPURL])) - $lsconf_var[LS_VAR_SKIPURL] = "\"" . $cfg[LS_XML_SKIPURL] . "\";"; - - if (isset($cfg[LS_XML_IP2NAME]) and !empty($cfg[LS_XML_IP2NAME] )) - $lsconf_var[LS_VAR_IP2NAME] = "\"" . $cfg[LS_XML_IP2NAME] . "\";"; - - if (isset($cfg[LS_XML_TEMPLATE]) and !empty($cfg[LS_XML_TEMPLATE])) { - $tpl_val = $cfg[LS_XML_TEMPLATE]; - // check template path - if (!file_exists(LS_TEMPLATEPATH."/$tpl_val")) $tpl_val = 'base'; - $lsconf_var[LS_VAR_TEMPLATE] = "\"" . $tpl_val . "\";"; - } + $lsconf_var[LS_VAR_TPLPATH] = "\"" . LS_TEMPLATEPATH . "\""; + $lsconf_var[LS_VAR_LANGPATH] = "\"" . LS_LANGPATH . "\""; + $lsconf_var[LS_VAR_REPORTPATH] = "\"" . LS_REPORTPATH . "\""; + $lsconf_var[LS_VAR_IP2NAMEPATH] = "\"" . LS_IP2NAMEPATH . "\""; - if (isset($cfg[LS_XML_BARCOLOR]) and !empty($cfg[LS_XML_BARCOLOR])) - $lsconf_var[LS_VAR_BARCOLOR] = "\"" . $cfg[LS_XML_BARCOLOR] . "\";"; - } + $lsconf_var[LS_VAR_LANG] = "\"" . LS_DEF_LANG . "\""; + $lsconf_var[LS_VAR_TEMPLATE] = "\"" . LS_DEF_TEMPLATE . "\""; + $lsconf_var[LS_VAR_IP2NAME] = "\"" . LS_DEF_IP2NAME . "\""; + $lsconf_var[LS_VAR_SKIPURL] = "'" . LS_DEF_SKIPURL . "'"; + $lsconf_var[LS_VAR_SQUIDLOGTYPE]= LS_DEF_SQUIDLOGTYPE; - $lsconf = ""; - $lsconf_file = LS_CONFIGPATH . "/" . LS_CONFIGFILE; - // open lightsquid config - if (file_exists($lsconf_file)) { - $lsconf = file_get_contents($lsconf_file); - update_log("Load config file $lsconf_file"); - } else { - update_log("Error loading config file $lsconf_file"); - // or open from 'lightsquid.cfg.dist' - $lsconf_dist_file = LS_CONFIGPATH . "/" . LS_CONFIGFILE_DIST; - if (file_exists($lsconf_dist_file)) { - $lsconf = file_get_contents($lsconf_dist_file); - update_log("Load config dist. file $lsconf_dist_file"); - } else update_log("Error loading config dist. file $lsconf_dist_file"); + // Update variables from package GUI config + if (is_array($config['installedpackages']['lightsquid']['config'][0])) { + $lightsquid_config = $config['installedpackages']['lightsquid']['config'][0]; + + if (isset($lightsquid_config[LS_XML_LANG]) and !empty($lightsquid_config[LS_XML_LANG])) { + $lsconf_var[LS_VAR_LANG] = "\"" . $lightsquid_config[LS_XML_LANG] . "\""; } - // update lightsquid config - if (!empty($lsconf)) { - $lsconf = explode("\n", $lsconf); - foreach ($lsconf_var as $key => $val) { - for($i = 0; $i < count($lsconf); $i++) { - $s = trim($lsconf[$i]); - $e_key = "/^[$]" . $key . "[ ]*[=]+/i"; -# update_log("Regular: preg_match(\"$e_key," . "'$s')"); // debug regular template - if (preg_match($e_key, $s)) { -# update_log("Regular PASSED: preg_match(\"$e_key," . "'$s')"); // debug regular template - $lsconf[$i] = '$' . "$key = $val;"; - update_log("Update config: $key=$val"); - } - } - } + if (isset($lightsquid_config[LS_XML_SKIPURL]) and !empty($lightsquid_config[LS_XML_SKIPURL])) { + $lsconf_var[LS_VAR_SKIPURL] = "'" . str_replace(".", "\\.", $lightsquid_config[LS_XML_SKIPURL]) . "'"; + } - $lsconf = implode("\n", $lsconf); - $fl = file_put_contents($lsconf_file, $lsconf); - update_log("Save config file $lsconf_file ($fl)"); + if (isset($lightsquid_config[LS_XML_IP2NAME]) and !empty($lightsquid_config[LS_XML_IP2NAME] )) { + $lsconf_var[LS_VAR_IP2NAME] = "\"" . $lightsquid_config[LS_XML_IP2NAME] . "\""; } - // set shedule - refresh data job - if ($tm) { - $on = false; - $opt = array("*", "*", "*", "*", "*", "root", CRONTAB_LS_TEMPLATE . " today"); - switch($tm) { - case 'lhp_none': $on = false; break; - case 'lhp_10m': $on = true; $opt[0]= "*/10"; break; - case 'lhp_20m': $on = true; $opt[0]= "*/20"; break; - case 'lhp_30m': $on = true; $opt[0]= "*/30"; break; - case 'lhp_40m': $on = true; $opt[0]= "*/40"; break; - case 'lhp_50m': $on = true; $opt[0]= "*/50"; break; - case 'lhp_60m': $on = true; $opt[0]= "*/60"; break; - case 'lhp_2h': $on = true; $opt[0]= "0"; $opt[1]= "*/2"; break; - case 'lhp_3h': $on = true; $opt[0]= "0"; $opt[1]= "*/3"; break; - case 'lhp_4h': $on = true; $opt[0]= "0"; $opt[1]= "*/4"; break; - case 'lhp_6h': $on = true; $opt[0]= "0"; $opt[1]= "*/6"; break; - case 'lhp_8h': $on = true; $opt[0]= "0"; $opt[1]= "*/8"; break; - case 'lhp_12h': $on = true; $opt[0]= "0"; $opt[1]= "*/12"; break; - case 'lhp_24h': $on = true; $opt[0]= "45"; $opt[1]= "23"; break; # dayly at 23:45 + if (isset($lightsquid_config[LS_XML_TEMPLATE]) and !empty($lightsquid_config[LS_XML_TEMPLATE])) { + $tpl_val = $lightsquid_config[LS_XML_TEMPLATE]; + // check template path + if (!file_exists(LS_TEMPLATEPATH."/$tpl_val")) { + $tpl_val = 'base'; } - ls_setup_cron("lightsquid_parser_today", $opt, CRONTAB_LS_JOBKEY, $on); - - # fix possible data lost with 00:00 script start - rescan yesterday - $opt = array("15", "0", "*", "*", "*", "root", CRONTAB_LS_TEMPLATE . " yesterday"); - ls_setup_cron("lightsquid_parser_yesterday", $opt, CRONTAB_LS_JOBKEY, $on); - - } else { - ls_setup_cron("lightsquid_parser_today", "", "", false); - ls_setup_cron("lightsquid_parser_yesterday", "", "", false); + $lsconf_var[LS_VAR_TEMPLATE] = "\"" . $tpl_val . "\""; } - - ls_setup_cron("lightsquid_squid_rotate", "", "", false); - - // update squid conf - if (isset($config['installedpackages']['squid']['config'][0])) { - $squid_settings = $config['installedpackages']['squid']['config'][0]; - $squid_settings['log_enabled'] = 'on'; - if (empty($squid_settings['log_dir'])) - $squid_settings['log_dir'] = LS_SQUIDLOGPATH; - - # sqstat - $ifmgr = "127.0.0.1;"; - $iface = ($squid_settings['active_interface'] ? $squid_settings['active_interface'] : 'lan'); - $iface = explode(",", $iface); - foreach ($iface as $i => $if) { - $realif = ls_get_real_interface_address($if); - if ($realif[0]) - $ifmgr = $ifmgr . $realif[0] . ";"; - } - /* Only save and resync if we're actually making any changes. */ - if (strpos($config['installedpackages']['squidnac']['config'][0]['ext_cachemanager'], $ifmgr) === FALSE) { - $config['installedpackages']['squidnac']['config'][0]['ext_cachemanager'] = $ifmgr; - write_config(); - if (function_exists('squid_resync')) - squid_resync(); - else - update_log("Function 'squid_resync' not found."); - } + if (isset($lightsquid_config[LS_XML_BARCOLOR]) and !empty($lightsquid_config[LS_XML_BARCOLOR])) { + $lsconf_var[LS_VAR_BARCOLOR] = "\"" . $lightsquid_config[LS_XML_BARCOLOR] . "\""; } } - if ($_POST['Submit'] === 'Refresh now') refresh_now(); - if ($_POST['Submit'] === 'Refresh full') refresh_full(); -} - -// setup cron tasks -// original source from '/etc/inc/pfsense-utils.inc' function 'tdr_install_cron' -// this function safe for other tasks -// ***************************************************************************** -// - $task_name: cron task name (for config identification) /for searching my cron tasks/ -// - $options: array=[0:minute][1:hour][2:mday][3:month][4:wday][5:who][6:cmd] -// - $task_key: cron command key for searching -// - $on_off: true-'on task', false-'off' task -// required: $task_nameand $on_off -// ***************************************************************************** -define('FIELD_TASKNAME', 'task_name'); - -function ls_setup_cron($task_name, $options, $task_key, $on_off) { - global $config; - update_log("ls_setup_cron: start task_name=$task_name, task_key=$task_key, on_off=$on_off"); - - // check input params - if(!$task_name) { - update_log("ls_setup_cron: exit - uncomplete input params."); - return; + // Create or update lightsquid.cfg + $lsconf = ""; + $lsconf_file = LS_CONFIGPATH . "/" . LS_CONFIGFILE; + // Always use the lightsquid.cfg.dist template to avoid issues with GUI values reconfiguration + $lsconf_dist_file = LS_CONFIGPATH . "/" . LS_CONFIGFILE_DIST; + if (file_exists($lsconf_dist_file)) { + $lsconf = file_get_contents($lsconf_dist_file); + log_error("[lightsquid] Loaded default '{$lsconf_dist_file}' configuration file."); + } else { + log_error("[lightsquid] Error: Could not load default '{$lsconf_dist_file}' configuration file."); } - // delete old task(s) - if (is_array($config['cron']['item'])) { - foreach ($config['cron']['item'] as $key => $item) { - # unset crontask by name - if (!empty($task_name) && ($item[FIELD_TASKNAME] == $task_name)) { - unset($config['cron']['item'][$key]); - } else - # unset crontask by cmd - if ($options[6] && (strpos($item['command'], $options[6]) !== false)) { - unset($config['cron']['item'][$key]); - } + // Update lightsquid.cfg + if (!empty($lsconf)) { + $lsconf = explode("\n", $lsconf); + foreach ($lsconf_var as $key => $val) { + for ($i = 0; $i < count($lsconf); $i++) { + $s = trim($lsconf[$i]); + $e_key = "/^[$]" . $key . "[ ]*[=]+/i"; + if (preg_match($e_key, $s)) { + $lsconf[$i] = '$' . "$key = $val;"; + } + } } - } - # install cron task - if ($on_off) { - if ($task_key) { - if (is_array($options)) { - # add new - $cron_item = array(); - $cron_item[FIELD_TASKNAME] = $task_name; - $cron_item['minute'] = $options[0]; - $cron_item['hour'] = $options[1]; - $cron_item['mday'] = $options[2]; - $cron_item['month'] = $options[3]; - $cron_item['wday'] = $options[4]; - $cron_item['who'] = $options[5]; - $cron_item['command'] = $options[6]; - - # check options - if (!$cron_item['who']) $cron_item['who'] = "nobody"; - - $config['cron']['item'][] = $cron_item; - update_log("ls_setup_cron: add cron task '{$task_name}'='{$cron_item['command']}'"); + $lsconf = implode("\n", $lsconf); + if (file_put_contents($lsconf_file, $lsconf)) { + log_error("[lightsquid] Successfully created '{$lsconf_file}' configuration file."); + } else { + log_error("[lightsquid] Error: Could not create '{$lsconf_file}' configuration file."); } - } else - // log - update_log("ls_setup_cron: input prm 'task_key' not defined"); + } else { + log_error("[lightsquid] Error: Could not create '{$lsconf_file}' configuration file."); } - write_config("Installed cron task '$task_name' for 'lightsquid' package"); - configure_cron(); - update_log("ls_setup_cron: Apply new cron settings."); + // Set up scheduled reports updates + lightsquid_setup_cron(true); } -function update_log($log) { - if (LS_GUI_DEBUG === 'on') { - $t_ls_log = ''; - if (file_exists(LS_LOG_FILE)) - $t_ls_log = file_get_contents(LS_LOG_FILE); - $t_ls_log .= "\n$log"; - file_put_contents(LS_LOG_FILE, $t_ls_log); +/* + * Reports + */ + +/* Configure scheduled reports updates via cron */ +function lightsquid_setup_cron($active=false) { + global $config; + if (is_array($config['installedpackages']['lightsquid']['config'][0])) { + $cron_schedule = $config['installedpackages']['lightsquid']['config'][0][LS_XML_SHEDULERTIME]; + } else { + $cron_schedule = ''; + } + $lightsquid_parser_today = CRONTAB_LS_TEMPLATE . " today"; + $lightsquid_parser_yesterday = CRONTAB_LS_TEMPLATE . " yesterday"; + + if ($active && $cron_schedule) { + $on = false; + $opt = array("*", "*", "*", "*", "*", "root"); + // remove old cronjobs first ... + log_error("[lightsquid] Removing old cronjobs..."); + install_cron_job($lightsquid_parser_today, false); + install_cron_job($lightsquid_parser_yesterday, false); + // ... and configure updated cronjobs if needed + switch($cron_schedule) { + case 'lhp_none': $on = false; break; + case 'lhp_10m': $on = true; $opt[0]= "*/10"; break; + case 'lhp_20m': $on = true; $opt[0]= "*/20"; break; + case 'lhp_30m': $on = true; $opt[0]= "*/30"; break; + case 'lhp_40m': $on = true; $opt[0]= "*/40"; break; + case 'lhp_50m': $on = true; $opt[0]= "*/50"; break; + case 'lhp_60m': $on = true; $opt[0]= "*/60"; break; + case 'lhp_2h': $on = true; $opt[0]= "0"; $opt[1]= "*/2"; break; + case 'lhp_3h': $on = true; $opt[0]= "0"; $opt[1]= "*/3"; break; + case 'lhp_4h': $on = true; $opt[0]= "0"; $opt[1]= "*/4"; break; + case 'lhp_6h': $on = true; $opt[0]= "0"; $opt[1]= "*/6"; break; + case 'lhp_8h': $on = true; $opt[0]= "0"; $opt[1]= "*/8"; break; + case 'lhp_12h': $on = true; $opt[0]= "0"; $opt[1]= "*/12"; break; + case 'lhp_24h': $on = true; $opt[0]= "45"; $opt[1]= "23"; break; // daily at 23:45 + } + if ($on) { + log_error("[lightsquid] Updating cronjobs..."); + install_cron_job($lightsquid_parser_today, $on, $opt[0], $opt[1], $opt[2], $opt[3], $opt[4], $opt[5]); + // fix possible data lost with 00:00 script start - rescan yesterday + install_cron_job($lightsquid_parser_yesterday, true, "15", "0", "*", "*", "*", "root"); + } + } else { + log_error("[lightsquid] Removing all cronjobs..."); + install_cron_job($lightsquid_parser_today, false); + install_cron_job($lightsquid_parser_yesterday, false); } } -function refresh_now() { +/* Parse today's entires only in access.log via the GUI button */ +function lightsquid_refresh_now() { $cmd = CRONTAB_LS_TEMPLATE . " today"; - update_log("refresh_now: execute command '$cmd'"); - // create lightsquid report catalog - if (!file_exists(LS_REPORTPATH)) { - update_log("lightsquid_install: Create report dir " . LS_REPORTPATH); - mwexec("mkdir -p " . LS_REPORTPATH); + $lg = LS_SQUIDLOG; + lightsquid_create_reportdir(); + + if (file_exists(LS_SQUIDLOGPATH . "/{$lg}")) { + log_error("[lightsquid] Parsing today's entries in access.log using '{$cmd}'"); + mwexec_bg($cmd); + } else { + log_error("[lightsquid] Could not parse '{$lg}' - log does not exist!"); } - mwexec_bg($cmd); } -function refresh_full() { +/* Parse all entries in all access logs, including the rotated ones via the GUI button */ +function lightsquid_refresh_full() { $cmd = CRONTAB_LS_TEMPLATE; - $log_name = LS_SQUIDLOG; - update_log("refresh_full: start"); - - // create lightsquid report catalog - if (!file_exists(LS_REPORTPATH)) { - update_log("lightsquid_install: Create report dir " . LS_REPORTPATH); - mwexec("mkdir -p " . LS_REPORTPATH); - } + lightsquid_create_reportdir(); + log_error("[lightsquid] Parsing all access log(s) entries using '{$cmd}'..."); // parse access.log - update_log("refresh_full: execute command '$cmd'"); - mwexec_bg("$cmd $log_name"); - // parse access.log.x - if (isset($config['installedpackages']['squid']['config'][0])) { - for ($i=0; $i<100; $i++) { - $lg = LS_SQUIDLOG . ".$i"; - if (file_exists(LS_SQUIDLOGPATH . "/$lg")) { - update_log("refresh_full: execute command '$cmd $lg'"); - mwexec_bg("$cmd $lg"); - } else - // really go <= 10 cycles - break; + $lg = LS_SQUIDLOG; + if (file_exists(LS_SQUIDLOGPATH . "/{$lg}")) { + log_error("[lightsquid] Parsing log entries in '{$lg}'..."); + mwexec_bg("{$cmd} {$lg}"); + } else { + log_error("[lightsquid] Could not parse '{$lg}' - log does not exist!"); + } + // parse access.log.x; if user configured some insane amount of rotated logs, only parse the first 100 of them + for ($i = 0; $i < 100; $i++) { + $lg = LS_SQUIDLOG . ".{$i}"; + if (file_exists(LS_SQUIDLOGPATH . "/{$lg}")) { + log_error("[lightsquid] Parsing log entries in '{$lg}'..."); + mwexec_bg("{$cmd} {$lg}"); + } else { + break; } } - update_log("refresh_full: stop"); } -function ls_get_real_interface_address($iface) -{ +/* Helper function to create lightsquid reports directory if needed */ +function lightsquid_create_reportdir() { + if (!is_dir(LS_REPORTPATH)) { + log_error("[lightsquid] Creating report dir " . LS_REPORTPATH); + safe_mkdir(LS_REPORTPATH); + } +} + + +/* + * Input validation + * Check required Squid configuration and provide instructions to users, + * instead of trying to mess with Squid's settings directly. + */ +function lightsquid_validate_input($post, &$input_errors) { global $config; + /* Manual reports refresh; only allow to run if the configuration file exists already! */ + if ($post['refreshnow'] == 'Refresh now' || $post['refreshfull'] == 'Refresh full') { + $lsconf_file = LS_CONFIGPATH . "/" . LS_CONFIGFILE; + if (file_exists($lsconf_file)) { + if ($post['refreshnow'] == 'Refresh now') { + lightsquid_refresh_now(); + return; + } elseif ($post['refreshfull'] == 'Refresh full') { + lightsquid_refresh_full(); + return; + } + } else { + $input_errors[] = "Please, configure LightSquid package first and Save settings before trying to manually refresh reports."; + } + } - $iface = convert_friendly_interface_to_real_interface_name($iface); - $line = trim(shell_exec("ifconfig $iface | grep inet | grep -v inet6")); - list($dummy, $ip, $dummy2, $netmask) = explode(" ", $line); + /* Check whether Squid is configured at all */ + if (is_array($config['installedpackages']['squid']['config'][0])) { + $squid_settings = $config['installedpackages']['squid']['config'][0]; + } else { + $input_errors[] = "Please, configure Squid package 'General' settings first."; + $squid_settings = array(); + } - return array($ip, long2ip(hexdec($netmask))); -} + /* Check whether logging is enabled in Squid */ + if ($squid_settings['log_enabled'] != "on") { + $input_errors[] = "Please, enable Access Logging in Squid package 'General' settings first."; + } + + /* Check whether log directory is configured in Squid */ + if ($squid_settings['log_dir'] == "") { + $input_errors[] = "Please, configure Log Store Directory in Squid package 'General' settings first."; + } -/* If a path is a symlink but the target is missing, remove the link. */ -function ls_cleanup_bad_link($link) { - if (file_exists($link) && is_link($link)) { - $target = readlink($link); - if (!file_exists($target) || !is_executable($target)) { - unlink($link); + /* SqStat - check external cache managers + * This check is only needed for Squid 2.7 packages, any Squid 3.x package allows localhost as cache manager by default + */ + $ifmgr = "127.0.0.1"; + if (get_pkg_id("squid") !== -1) { + if (is_array($config['installedpackages']['squidnac']['config'])) { + $ext_cachemanager = ($config['installedpackages']['squidnac']['config'][0]['ext_cachemanager'] ?: ""); + } else { + $ext_cachemanager = ""; + } + if (strpos($ext_cachemanager, $ifmgr) === false) { + $input_errors[] = "Please, add '{$ifmgr}' to Squid - Access Control - External Cache-Managers first."; + } + } + /* SqStat - check that Squid listens on loopback unless the proxy is set as transparent (which makes it listen on localhost automatically) */ + if (is_array($config['installedpackages']['squid']['config'])) { + $active_interfaces = ($config['installedpackages']['squid']['config'][0]['active_interface'] ?: ""); + $transparent = ($config['installedpackages']['squid']['config'][0]['transparent_proxy'] == "on" ? true : false); + } else { + $active_interfaces = ""; + $transparent = false; + } + if (!$transparent) { + if (strpos($active_interfaces, "lo0") === false) { + $input_errors[] = "Please, configure Squid - General - Proxy Interface(s) to include 'loopback' interface."; + } + } + + /* 'Skip URL(s)' validation */ + if ($post['lightsquid_skipurl'] != "") { + $hosts = explode("|", $post['lightsquid_skipurl']); + foreach ($hosts as $host) { + $host = trim($host); + if (!is_ipaddr($host) && !is_hostname($host) && !is_domain($host)) { + $input_errors[] = "'Skip URL(s)' entry '{$host}' is not a valid IP address, hostname, domain or subnet."; + } } } } diff --git a/config/lightsquid/lightsquid.priv.inc b/config/lightsquid/lightsquid.priv.inc new file mode 100644 index 00000000..f228ad1e --- /dev/null +++ b/config/lightsquid/lightsquid.priv.inc @@ -0,0 +1,40 @@ +<?php +/* + lightsquid.priv.inc + part of pfSense (http://www.pfSense.org/) + Copyright (C) 2015 ESF, LLC + All rights reserved. + + 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. +*/ +global $priv_list; + +$priv_list['page-status-lightsquid'] = array(); +$priv_list['page-status-lightsquid']['name'] = "WebCfg - Status: LightSquid package"; +$priv_list['page-status-lightsquid']['descr'] = "Allow access to LightSquid package GUI"; +$priv_list['page-status-lightsquid']['match'] = array(); + +$priv_list['page-status-lightsquid']['match'][] = "pkg.php?xml=lightsquid.xml*"; +$priv_list['page-status-lightsquid']['match'][] = "pkg_edit.php?xml=lightsquid.xml*"; +$priv_list['page-status-lightsquid']['match'][] = "sqstat/sqstat.php*"; + +?> diff --git a/config/lightsquid/lightsquid.xml b/config/lightsquid/lightsquid.xml index f5f09b94..834efd46 100644 --- a/config/lightsquid/lightsquid.xml +++ b/config/lightsquid/lightsquid.xml @@ -2,453 +2,429 @@ <!DOCTYPE packagegui SYSTEM "../schema/packages.dtd"> <?xml-stylesheet type="text/xsl" href="../xsl/package.xsl"?> <packagegui> - <copyright> - <![CDATA[ + <copyright> +<![CDATA[ /* $Id$ */ -/* ========================================================================== */ +/* ====================================================================================== */ /* - lightsquid.xml - part of pfSense (http://www.pfSense.com) - Copyright (C) 2007 to whom it may belong - All rights reserved. - - Based on m0n0wall (http://m0n0.ch/wall) - Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>. - All rights reserved. - */ -/* ========================================================================== */ + lightsquid.xml + part of pfSense (https://www.pfSense.org/) + Copyright (C) 2006-2012 Sergey Dvoriancev <dv_serg@mail.ru> + Copyright (C) 2015 ESF, LLC + All rights reserved. +*/ +/* ====================================================================================== */ /* - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: + 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. + 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. + 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. - */ -/* ========================================================================== */ - ]]> - </copyright> - <description>Describe your package here</description> - <requirements>Describe your package requirements here</requirements> - <faq>Currently there are no FAQ items provided.</faq> + + 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. +*/ +/* ====================================================================================== */ + ]]> + </copyright> <name>lightsquid</name> - <version>2.41</version> - <title>Services: Proxy Reports (LightSquid, SQStat) -> Settings</title> + <version>2.42</version> + <title>Squid Proxy Reports: Settings</title> <category>Status</category> <include_file>/usr/local/pkg/lightsquid.inc</include_file> <menu> - <name>Proxy report</name> - <tooltiptext>Proxy server statistic report</tooltiptext> + <name>Squid Proxy Reports</name> + <tooltiptext>Proxy Server Statistic Reports</tooltiptext> <section>Status</section> - <url>/pkg_edit.php?xml=lightsquid.xml&id=0</url> + <url>/pkg_edit.php?xml=lightsquid.xml</url> </menu> - <tabs> - <tab> - <text>Settings</text> - <url>/pkg_edit.php?xml=lightsquid.xml&id=0</url> - <active/> - </tab> - <tab> - <text>Lightsquid Report</text> - <url>/lightsquid/index.cgi</url> - </tab> - <tab> - <text>Proxy State</text> - <url>/sqstat/sqstat.php</url> - </tab> - </tabs> - <additional_files_needed> - <prefix>/usr/local/pkg/</prefix> - <chmod>0755</chmod> - <item>https://packages.pfsense.org/packages/config/lightsquid/lightsquid.inc</item> - </additional_files_needed> - <additional_files_needed> - <prefix>/usr/local/www/sqstat/</prefix> - <chmod>0644</chmod> - <item>https://packages.pfsense.org/packages/config/lightsquid/sqstat.class.php</item> - </additional_files_needed> - <additional_files_needed> - <prefix>/usr/local/www/sqstat/</prefix> - <chmod>0644</chmod> - <item>https://packages.pfsense.org/packages/config/lightsquid/sqstat.php</item> - </additional_files_needed> - <additional_files_needed> - <prefix>/usr/local/www/sqstat/</prefix> - <chmod>0644</chmod> - <item>https://packages.pfsense.org/packages/config/lightsquid/sqstat.css</item> - </additional_files_needed> - <additional_files_needed> - <prefix>/usr/local/www/sqstat/</prefix> - <chmod>0644</chmod> - <item>https://packages.pfsense.org/packages/config/lightsquid/zhabascript.js</item> - </additional_files_needed> + <tabs> + <tab> + <text>Settings</text> + <url>/pkg_edit.php?xml=lightsquid.xml</url> + <active/> + </tab> + <tab> + <text>Lightsquid Report</text> + <url>/lightsquid/index.cgi</url> + </tab> + <tab> + <text>Proxy Status</text> + <url>/sqstat/sqstat.php</url> + </tab> + </tabs> + <additional_files_needed> + <prefix>/usr/local/pkg/</prefix> + <item>https://packages.pfsense.org/packages/config/lightsquid/lightsquid.inc</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/etc/inc/priv/</prefix> + <item>https://packages.pfsense.org/packages/config/lightsquid/lightsquid.priv.inc</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/sqstat/</prefix> + <item>https://packages.pfsense.org/packages/config/lightsquid/sqstat.class.php</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/sqstat/</prefix> + <item>https://packages.pfsense.org/packages/config/lightsquid/sqstat.php</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/sqstat/</prefix> + <item>https://packages.pfsense.org/packages/config/lightsquid/sqstat.css</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/www/sqstat/</prefix> + <item>https://packages.pfsense.org/packages/config/lightsquid/zhabascript.js</item> + </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/bigfiles.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/day_detail.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/graph.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/group_detail.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/images/datetime.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/images/flag_red.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/images/graph.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/images/groups.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/images/printer.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/images/users.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/index.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/month_detail.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/print.css</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/screen.css</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/topsites.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/user_detail.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/user_month.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/user_time.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novopf/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novopf/whousesite.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/bigfiles.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/day_detail.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/graph.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/group_detail.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/images/datetime.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/images/flag_red.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/images/graph.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/images/groups.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/images/printer.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/images/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/images/users.png</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/index.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/month_detail.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/print.css</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/screen.css</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/topsites.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/user_detail.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/user_month.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/user_time.html</item> </additional_files_needed> <additional_files_needed> <prefix>/usr/local/share/lightsquid/tpl/novosea/</prefix> - <chmod>0444</chmod> <item>https://packages.pfsense.org/packages/config/lightsquid/tpl/novosea/whousesite.html</item> </additional_files_needed> - <fields> - <field> - <fielddescr>Language</fielddescr> - <fieldname>lightsquid_lang</fieldname> - <description>Select report language</description> - <type>select</type> - <value>eng</value> - <options> - <option><name>Bulgarian</name><value>bg</value></option> - <option><name>Czech</name><value>cz</value></option> - <option><name>English</name><value>eng</value></option> - <option><name>French</name><value>fr</value></option> - <option><name>Hungarian</name><value>hu</value></option> - <option><name>Italian</name><value>it</value></option> - <option><name>Portuguese - Brazil</name><value>pt_br</value></option> - <option><name>Russian</name><value>ru</value></option> - <option><name>Russian KOI-8</name><value>ru-koi8</value></option> - <option><name>Spanish</name><value>sp</value></option> - <option><name>Ukrainian</name><value>ua</value></option> - </options> - </field> - <field> - <fielddescr>Bar color</fielddescr> - <fieldname>lightsquid_barcolor</fieldname> - <description>Select bar color</description> - <type>select</type> - <value>orange</value> - <options> - <option><name>Orange</name><value>orange</value></option> - <option><name>Blue</name><value>blue</value></option> - <option><name>Green</name><value>green</value></option> - <option><name>Yellow</name><value>yellow</value></option> - <option><name>Brown</name><value>brown</value></option> - <option><name>Red</name><value>red</value></option> - </options> - </field> - <field> - <fielddescr>Report scheme</fielddescr> - <fieldname>lightsquid_template</fieldname> - <description>Select report scheme</description> - <type>select</type> - <value>base</value> - <options> - <option><name>Base</name><value>base</value></option> - <option><name>Text</name><value>text</value></option> - <option><name>NovoSea</name><value>novosea</value></option> - <option><name>NovoPf</name><value>novopf</value></option> - </options> - </field> - <field> - <fielddescr>IP resolve method (future)</fielddescr> - <fieldname>lightsquid_ip2name</fieldname> - <description> - <table cellpadding=1 cellspacing=0 style="text-align: left;"> <tbody> - <tr><th colspan=2> Select IP to Name resolve method (take effect only on new data): </th><tr> - <tr><th> IP </th><td> - return IP </td><tr> - <tr><th> Demo </th><td> - return AUTHNAME, else DNSNAME, else IP </td><tr> - <tr><th> DNS </th><td> - return DNSNAME </td><tr> - <tr><th> Simple </th><td> - return AUTHNAME else IP </td><tr> - <tr><th> SMB </th><td> - return SMB name of pc </td><tr> - <tr><th> Squidauth </th><td> - return AUTHNAME else IP, allow cyrilyc name </td><tr> - </tbody> </table> - </description> - <type>select</type> - <value>dns</value> - <options> - <option><name>IP</name><value>ip</value></option> - <option><name>Demo</name><value>demo</value></option> - <option><name>DNS</name><value>dns</value></option> - <option><name>Simple</name><value>simple</value></option> - <option><name>SMB</name><value>smb</value></option> - <option><name>Squidauth</name><value>squidauth</value></option> - </options> - </field> - <field> - <fielddescr>Refresh sheduler</fielddescr> - <fieldname>lightsquid_refreshsheduler_time</fieldname> - <description> - Select data refresh period. System will execute task every XX time as from 00:00 hours. <br> - For example: if selected 2h - system wil start task at 0-2-4-..-24h. <br> - Note: (!),(*) - use only for powerful system; (+) - recomended. <br><br> - <input type="submit" name="Submit" value="Refresh now"><br> - <input type="submit" name="Submit" value="Refresh full"> - <br> Press button for start background refresh (this take some time). - <br> <span style="color: rgb(153, 51, 0);"> Note after installation: - <br> Firstly - enable log in squid package with "/var/squid/logs" path. - <br> Secondly - press Refresh button to create lightsquid reports, else you will have an error diagnostic page.</span> + <fields> + <field> + <name>Instructions</name> + <type>listtopic</type> + </field> + <field> + <type>info</type> + <fielddescr> + <![CDATA[ + <span class="errmsg">IMPORTANT: Perform these steps after install:</span> + ]]> + </fielddescr> + <description> + <![CDATA[ + 1/ <strong>Enable 'Access Logging' in the Squid package!</strong> It is strongly suggested to leave the 'Log Store Directory' in Squid package at default '/var/squid/logs' value.<br/><br/> + 2a/ <strong>ONLY if Squid is NOT set up as transparent proxy:</strong><br/> + - Configure Squid - General - Proxy Interface(s) to include <strong>'loopback'</strong> interface (in addition to any other interfaces you want Squid to bind on).<br/> + 2b/ <strong>ONLY if using Squid 2.7 package</strong> (this is not needed for Squid 3.x.):<br/> + - Add '127.0.0.1' to Squid - Access Control - External Cache-Managers.<br/><br/> + 3/ <strong>Configure 'Report Template Settings' and 'Reporting Settings and Scheduler' below and Save when finished.</strong><br/><br/> + 4/ <strong>Use the Refresh buttons in the 'Manual Refresh' section below to create initial LightSquid reports</strong>; otherwise you will get an error diagnostic page.<br/> + - <em>"Refresh now"</em> will (re)parse today's entries only in Squid's current access.log.<br/> + - <em>"Refresh full"</em> will (re)parse all entries in all Squid's access logs, including the rotated ones. <strong>Note: This may take long time to finish!</strong><br/> + ]]> </description> - <type>select</type> - <value>lhp_none</value> - <options> - <option><name>none</name><value>lhp_none</value></option> - <option><name>10min(!)</name><value>lhp_10m</value></option> - <option><name>20min(!)</name><value>lhp_20m</value></option> - <option><name>30min(*)</name><value>lhp_30m</value></option> - <option><name>40min(*)</name><value>lhp_40m</value></option> - <option><name>50min(+)</name><value>lhp_50m</value></option> - <option><name>60min(+)</name><value>lhp_60m</value></option> - <option><name>2h</name><value>lhp_2h</value></option> - <option><name>3h</name><value>lhp_3h</value></option> - <option><name>4h</name><value>lhp_4h</value></option> - <option><name>6h</name><value>lhp_6h</value></option> - <option><name>8h</name><value>lhp_8h</value></option> - <option><name>12h</name><value>lhp_12h</value></option> - <option><name>24(00)h</name><value>lhp_24h</value></option> - </options> - </field> - <!--field> - <fielddescr>Squid rotate log sheduler</fielddescr> - <fieldname>lightsquid_squidrotatelog_sheduler_time</fieldname> + </field> + <field> + <name>Report Template Settings</name> + <type>listtopic</type> + </field> + <field> + <fielddescr>Language</fielddescr> + <fieldname>lightsquid_lang</fieldname> + <description>Select report language.</description> + <type>select</type> + <default_value>eng</default_value> + <options> + <option><name>Bulgarian</name><value>bg</value></option> + <option><name>Czech</name><value>cz</value></option> + <option><name>English</name><value>eng</value></option> + <option><name>French</name><value>fr</value></option> + <option><name>Hungarian</name><value>hu</value></option> + <option><name>Italian</name><value>it</value></option> + <option><name>Portuguese (Brazilian)</name><value>pt_br</value></option> + <option><name>Russian</name><value>ru</value></option> + <option><name>Russian (KOI-8)</name><value>ru-koi8</value></option> + <option><name>Spanish</name><value>sp</value></option> + <option><name>Ukrainian</name><value>ua</value></option> + </options> + </field> + <field> + <fielddescr>Report Template</fielddescr> + <fieldname>lightsquid_template</fieldname> + <description>Select report template.</description> + <type>select</type> + <default_value>base</default_value> + <options> + <option><name>Base</name><value>base</value></option> + <option><name>Text</name><value>text</value></option> + <option><name>NovoSea</name><value>novosea</value></option> + <option><name>NovoPf</name><value>novopf</value></option> + </options> + </field> + <field> + <fielddescr>Bar Color</fielddescr> + <fieldname>lightsquid_barcolor</fieldname> + <description>Select bar color.</description> + <type>select</type> + <default_value>orange</default_value> + <options> + <option><name>Orange</name><value>orange</value></option> + <option><name>Blue</name><value>blue</value></option> + <option><name>Green</name><value>green</value></option> + <option><name>Yellow</name><value>yellow</value></option> + <option><name>Brown</name><value>brown</value></option> + <option><name>Red</name><value>red</value></option> + </options> + </field> + <field> + <name>Reporting Settings and Scheduler</name> + <type>listtopic</type> + </field> + <field> + <fielddescr>IP Resolve Method</fielddescr> + <fieldname>lightsquid_ip2name</fieldname> <description> - Select squid log rotate period. System will execute task every XX time as from 00:00 hours. <br> - This option will allow the updating of the faster <br> - For example: if selected '2 day' - system wil start task every 2 day of month. <br> - This option will allow the updating of the faster <br> - Note: You must choose from that the rate of filling dialogue access.log squid; <br> - The more customers, the more often it should be the job. + <![CDATA[ + <table cellpadding=1 cellspacing=0 style="text-align: left;"> + <tbody> + <tr><th colspan=2>Select which method(s) should be attempted (in the order listed below) to resolve IPs to hostnames:</th></tr> + <tr><th>IP </th><td> - Do not resolve IP addresses.</td></tr> + <tr><th>Demo </th><td> - Use Squid AUTHNAME, then DNSNAME, then IP.</td></tr> + <tr><th>DNS </th><td> - Use DNSNAME.</td></tr> + <tr><th>Simple </th><td> - Use Squid AUTHNAME, then IP address.</td></tr> + <tr><th>SMB </th><td> - Use NetBIOS name.</td></tr> + <tr><th>Squidauth </th><td> - Use Squid AUTHNAME, then IP address (allow international characters).</td></tr> + </tbody> + </table> + ]]> </description> <type>select</type> - <value>lsr_none</value> - <options> - <option><name>none</name><value>lsr_none</value></option> - <option><name>every 1 day</name><value>lsr_d1</value></option> - <option><name>every 2 day</name><value>lsr_d2</value></option> - <option><name>every 3 day</name><value>lsr_d3</value></option> - <option><name>every 4 day</name><value>lsr_d4</value></option> - <option><name>every 5 day</name><value>lsr_d5</value></option> - <option><name>every 6 day</name><value>lsr_d6</value></option> - <option><name>weekly at Monday</name><value>lsr_w1</value></option> - <option><name>weekly at Tuesday</name><value>lsr_w2</value></option> - <option><name>weekly at Wednesday</name><value>lsr_w3</value></option> - <option><name>weekly at Thursday</name><value>lsr_w4</value></option> - <option><name>weekly at Friday</name><value>lsr_w5</value></option> - <option><name>weekly at Saturday</name><value>lsr_w6</value></option> - <option><name>weekly at Sunday</name><value>lsr_w7</value></option> - <option><name>every 10 day</name><value>lsr_d10</value></option> - <option><name>every 15 day</name><value>lsr_d15</value></option> - <option><name>every 20 day</name><value>lsr_d20</value></option> - <option><name>every 25 day</name><value>lsr_d25</value></option> - <option><name>every 30 day</name><value>lsr_d30</value></option> - </options> - </field--> + <default_value>dns</default_value> + <options> + <option><name>IP</name><value>ip</value></option> + <option><name>Demo</name><value>demo</value></option> + <option><name>DNS</name><value>dns</value></option> + <option><name>Simple</name><value>simple</value></option> + <option><name>SMB</name><value>smb</value></option> + <option><name>Squidauth</name><value>squidauth</value></option> + </options> + </field> <field> - <fielddescr>Skip url</fielddescr> - <fieldname>lightsquid_skipurl</fieldname> + <fielddescr>Skip URL(s)</fielddescr> + <fieldname>lightsquid_skipurl</fieldname> <description> - If you want skip some sites from stat, example our local www server - Example, if you want skip LOCAL site, put it here - zdd.com|192.168.1.|cnn.com + <![CDATA[ + If you want to omit some sites from statistics (e.g., a local webserver), specify the URL(s) here.<br/> + Separate multiple entries by <strong>|</strong> character.<br/><br/> + Example: example.com|192.168.1.|example.net + ]]> </description> <type>textarea</type> <cols>60</cols> <rows>5</rows> </field> + <field> + <fielddescr>Refresh Scheduler</fielddescr> + <fieldname>lightsquid_refreshsheduler_time</fieldname> + <description> + <![CDATA[ + Select data refresh period. The reporting task will be executed every XX minutes/hours.<br/> + <strong>Legend:</strong> (!),(*) - use only with fast hardware; (+) - recommended values.<br/> + ]]> + </description> + <type>select</type> + <default_value>lhp_none</default_value> + <options> + <option><name>none</name><value>lhp_none</value></option> + <option><name>10min(!)</name><value>lhp_10m</value></option> + <option><name>20min(!)</name><value>lhp_20m</value></option> + <option><name>30min(*)</name><value>lhp_30m</value></option> + <option><name>40min(*)</name><value>lhp_40m</value></option> + <option><name>50min(+)</name><value>lhp_50m</value></option> + <option><name>60min(+)</name><value>lhp_60m</value></option> + <option><name>2h</name><value>lhp_2h</value></option> + <option><name>3h</name><value>lhp_3h</value></option> + <option><name>4h</name><value>lhp_4h</value></option> + <option><name>6h</name><value>lhp_6h</value></option> + <option><name>8h</name><value>lhp_8h</value></option> + <option><name>12h</name><value>lhp_12h</value></option> + <option><name>24h</name><value>lhp_24h</value></option> + </options> + </field> + <field> + <type>info</type> + <fielddescr>Manual Refresh</fielddescr> + <description> + <![CDATA[ + <input type="submit" name="refreshnow" id="refreshnow" value="Refresh now" /> will (re)parse today's entries only in Squid's current access.log.<br/><br/> + <input type="submit" name="refreshfull" id="refreshfull" value="Refresh full" /> will (re)parse all entries in all Squid's access logs, including the rotated ones. + <strong>Note: This may take long time to finish!</strong><br/><br/> + Press a button above to start background refresh (this will take some time).<br/> + ]]> + </description> + </field> </fields> - <custom_php_resync_config_command> - lightsquid_resync(); - </custom_php_resync_config_command> <custom_php_install_command> lightsquid_install(); - lightsquid_resync(); </custom_php_install_command> <custom_php_deinstall_command> lightsquid_deinstall(); </custom_php_deinstall_command> + <custom_php_resync_config_command> + <![CDATA[ + // Do not resync configuration on manual reports refresh + if ($_POST['refreshnow'] == "Refresh now" || $_POST['refreshfull'] == "Refresh full") { + return; + } + lightsquid_resync(); + ]]> + </custom_php_resync_config_command> + <custom_php_validation_command> + lightsquid_validate_input($_POST, $input_errors); + </custom_php_validation_command> </packagegui> diff --git a/config/lightsquid/sqstat.class.php b/config/lightsquid/sqstat.class.php index 88a5cfce..2f1dc9ba 100644 --- a/config/lightsquid/sqstat.class.php +++ b/config/lightsquid/sqstat.class.php @@ -1,133 +1,129 @@ <?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.php + part of pfSense (https://www.pfSense.org/) + Copyright (C) 2006 Alex Samorukov <samm@os2.kiev.ua> + Copyright (C) 2011 Sergey Dvoriancev <dv_serg@mail.ru> + Copyright (C) 2015 ESF, LLC + All rights reserved. + + 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 +/* Squid Proxy Server realtime stats */ DEFINE('SQSTAT_VERSION', '1.20'); DEFINE('SQSTAT_SHOWLEN', 60); -class squidstat{ - var $fp; +class squidstat { + var $fp; - # conection - var $squidhost; - var $squidport; + // conection + var $squidhost; + var $squidport; - # hosts - var $hosts_file; + // hosts + var $hosts_file; var $hosts; - # versions + // versions var $server_version; var $sqstat_version; - # other - var $group_by; + // other + var $group_by; var $resolveip; var $autorefresh; var $use_sessions = false; - # cache manager + // cache manager var $cachemgr_passwd; - # errors + // errors var $errno; var $errstr; - function squidstat(){ - $this->sqstat_version = SQSTAT_VERSION; + function squidstat() { + $this->sqstat_version = SQSTAT_VERSION; - $this->squidhost = '127.0.0.1'; - $this->squidport = '3128'; + $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 = ''; + $this->group_by = 'host'; + $this->resolveip = true; + $this->hosts_file = ''; + $this->autorefresh = 0; + $this->cachemgr_passwd = ''; - $errno = 0; - $errstr = ''; + $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'); + 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; + 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>'; + 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 showError() { + $text = '<h1>SqStat error</h1>' . '<h2 style="color:red">Error (' . $this->errno . ') : ' . $this->errstr . '</h2>'; + echo $this->formatXHTML($text, 0); } - function connect($squidhost, $squidport){ + function connect($squidhost, $squidport) { $this->fp = false; - # connecting to the squidhost + // connecting to the squidhost $this->fp = @fsockopen($squidhost, $squidport, $this->errno, $this->errstr, 10); if (!$this->fp) { - # failed to connect + // failed to connect return false; } return true; } - # based @ (c) moritz at barafranca dot com + // 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"); + $takes_time = array(604800, 86400, 3600, 60, 0); + $suffixes = array("w", "d", "h", "m", "s"); $output = ""; - foreach ($takes_time as $key=>$val) { + foreach ($takes_time as $key => $val) { ${$suffixes[$key]} = ($val == 0) ? $seconds : floor(($seconds/$val)); $seconds -= ${$suffixes[$key]} * $val; if (${$suffixes[$key]} > 0) { @@ -145,31 +141,34 @@ class squidstat{ * @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 + * @return string The formatted file size */ - function filesize_format($bytes, $format = '', $force = '') - { + function filesize_format($bytes, $format = '', $force = '') { $force = strtoupper($force); $defaultFormat = '%01d %s'; - if (strlen($format) == 0) - $format = $defaultFormat; + 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; + if ($power === false) { + $power = $bytes > 0 ? floor(log($bytes)/log(1024)) : 0; + } return sprintf($format, $bytes / pow(1024, $power), $units[$power]); } - function makeQuery($pass = ""){ + function makeQuery($pass = "") { $raw = array(); - # sending request - if(!$this->fp) - die("Please connect to server"); + // 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"; + if ($pass != "") { + $out .= "Authorization: Basic ". base64_encode("cachemgr:$pass") . "\r\n"; + } $out .= "\r\n"; fwrite($this->fp, $out); @@ -184,38 +183,56 @@ class squidstat{ return false; } - # parsing output; + // parsing output; $header = 1; $connection = 0; $parsed["server_version"] = "Unknown"; - foreach($raw as $key=>$v){ - # cutoff http header - if ($header==1 && $v=="") $header=0; + 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); + 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); + } else { + if (substr($v, 0, 11) == "Connection:") { + // parsing connection + $connection = substr($v, 12); } if ($connection) { - # username field is avaible in Squid 2.6 stable - # peer changed to remote in Squid 3.2 or later - # me changed to local in Squid 3.2 or later - if(substr($v,0,9) == "username ") $parsed["con"][$connection]["username"] = substr($v, 9); - if(substr($v,0,7) == "remote:") $parsed["con"][$connection]["peer"] = substr($v, 8); - if(substr($v,0,5) == "peer:") $parsed["con"][$connection]["peer"] = substr($v, 6); - if(substr($v,0,6) == "local:") $parsed["con"][$connection]["me"] = substr($v, 7); - 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); + /* username field is avaible in Squid 2.6+ + * peer changed to remote in Squid 3.2+ + * me changed to local in Squid 3.2+ + */ + if (substr($v, 0, 9) == "username ") { + $parsed["con"][$connection]["username"] = substr($v, 9); + } + if (substr($v, 0, 7) == "remote:") { + $parsed["con"][$connection]["peer"] = substr($v, 8); + } + if (substr($v, 0, 5) == "peer:") { + $parsed["con"][$connection]["peer"] = substr($v, 6); + } + if (substr($v, 0, 6) == "local:") { + $parsed["con"][$connection]["me"] = substr($v, 7); + } + 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)){ + if (preg_match('/start \d+\.\d+ \((\d+).\d+ seconds ago\)/', $v, $matches)) { $parsed["con"][$connection]["seconds"] = $matches[1]; } } @@ -225,7 +242,7 @@ class squidstat{ } function implode_with_keys($array, $glue) { - foreach ($array as $key => $v){ + foreach ($array as $key => $v) { $ret[] = $key . '=' . htmlspecialchars($v); } return implode($glue, $ret); @@ -233,96 +250,107 @@ class squidstat{ function makeHtmlReport($data, $resolveip = false, $hosts_array = array(), $use_js = true) { global $group_by; - if($this->use_sessions){ + if ($this->use_sessions) { session_name('SQDATA'); session_start(); } $total_avg = $total_curr = 0; // resort data array - $users=array(); - switch($group_by){ + $users = array(); + switch ($group_by) { case "host": - $group_by_name="Host"; - $group_by_key='return $ip;'; - break; + $group_by_name="Host"; + $group_by_key='return $ip;'; + break; case "username": - $group_by_name="User"; - $group_by_key='return $v["username"];'; - break; + $group_by_name="User"; + $group_by_key='return $v["username"];'; + break; default: - die("wrong group_by!"); + 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; + foreach ($data["con"] as $key => $v) { + if (substr($v["uri"], 0, 13) == "cache_object:") { + continue; // skip myself } - else{ - $ip=ip2long(substr($v["peer"],0,strpos($v["peer"],":"))); + $ip = substr($v["peer"], 0, strpos($v["peer"], ":")); + if (isset($hosts_array[$ip])) { + $ip = $hosts_array[$ip]; + // 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; + 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>'; + $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>'; + $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; + $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 + // only if the latest data was less than 3 minutes ago $session_data = $_SESSION['sqdata']; } - $table=''; - foreach($users as $key=>$v){ + $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; + $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"]); } - else $uri=htmlspecialchars($con["uri"]); $acon++; - //speed stuff + // 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 + $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) { @@ -337,7 +365,7 @@ class squidstat{ $curr_speed = $con['bytes'] / 1024; } - //avg speed + // avg speed $avg_speed = $con['bytes'] / 1024; if ($con['seconds'] > 0) { $avg_speed /= $con['seconds']; @@ -347,241 +375,244 @@ class squidstat{ $new_data[$con_id]['time'] = $is_time; $new_data[$con_id]['size'] = $con['bytes']; - //sum speeds + // 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>'; + 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>'; + $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); + 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); + if (isset($new_data)) { + $_SESSION['sqdata'] = $new_data; } - 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); + $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>'; + 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]; + } elseif ($resolveip) { + // use ip2long() to make ip sorting work correctly + $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 count + $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"]; + + // grouped 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; } - else { - $text.=$stat_row.$table.$stat_row; + + // 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; } - $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); + + return $parsed; } - 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 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 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; - } + 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; + } } ?> diff --git a/config/lightsquid/sqstat.css b/config/lightsquid/sqstat.css index 7575933e..c29adad2 100644 --- a/config/lightsquid/sqstat.css +++ b/config/lightsquid/sqstat.css @@ -1,68 +1,73 @@ /* "connections" table */ -TABLE.result{ - border:1px solid #ccccdd;border-collapse:collapse; +table.result { + border: 1px solid #ccccdd; + border-collapse: collapse; } -TABLE.result TH{ - font-family: Verdana;font-size:14px; +table.result th { + font-family: Verdana; + font-size: 14px; } -TABLE.result TD{ - font-family: Verdana;font-size:11px;border:1px solid #c0c0c0;padding:2px; +table.result td { + font-family: Verdana; + font-size: 11px; + border: 1px solid #c0c0c0; + padding: 2px; } -TABLE.result TR.total TD{ - background-color:#DCDAD5; +table.result tr.total td { + background-color: #DCDAD5; } - -TABLE.result TH{ - background-color:#ccccdd; - white-space: nowrap; padding: 0px 2px; +table.result th { + background-color: #ccccdd; + white-space: nowrap; + padding: 0px 2px; } - -TABLE.result tr.odd td { - background-color: #eef; +table.result tr.odd td { + background-color: #eef; } -TABLE.result tr.odd td#white { - background-color: #fff; +table.result tr.odd td#white { + background-color: #fff; } -TABLE.result td#highlight { - background-color: #e9e9e9; +table.result td#highlight { + background-color: #e9e9e9; } - /* top header */ -DIV.header{ - border:3px solid #ccccdd;margin-bottom:10px;padding:3px; - font-family: Verdana;font-size:12pt; +div.header { + border: 3px solid #ccccdd; + margin-bottom: 10px; + padding: 3px; + font-family: Verdana; + font-size: 12pt; } -.copyleft,SELECT{ - font-family: Verdana;font-size:10px; +.copyleft, select { + font-family: Verdana; + font-size: 10px; } -.copyleft A{ - text-decoration:none +.copyleft a { + text-decoration: none } -.copyleft A:HOVER{ - text-decoration:underline +.copyleft a:hover { + text-decoration: underline } -FORM{ - margin:0;padding:0; +form { + margin: 0; + padding: 0; } - -#dhtmltooltip{ - position: absolute; - /* width: 350px; */ - border: 2px solid black; - padding: 2px; - background-color: lightyellow; - visibility: hidden; - z-index: 100; - font-family: Verdana; font-size: 10px; +#dhtmltooltip { + position: absolute; + /* width: 350px; */ + + border: 2px solid black; + padding: 2px; + background-color: lightyellow; + visibility: hidden; + z-index: 100; + font-family: Verdana; + font-size: 10px; } - - -#dhtmlpointer{ - position:absolute; - left: -300px; - z-index: 101; - visibility: hidden; +#dhtmlpointer { + position: absolute; + left: -300px; + z-index: 101; + visibility: hidden; } - - diff --git a/config/lightsquid/sqstat.php b/config/lightsquid/sqstat.php index 7b12b970..5d3a0e83 100644 --- a/config/lightsquid/sqstat.php +++ b/config/lightsquid/sqstat.php @@ -1,417 +1,385 @@ <?php -/* $Id$ */ /* - sqstat.php - Squid Proxy Server realtime stat - - (c) Alex Samorukov, samm@os2.kiev.ua - modification by 2011 Serg Dvoriancev, dv_serg@mail.ru - - 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.php + part of pfSense (https://www.pfSense.org/) + Copyright (C) 2006 Alex Samorukov <samm@os2.kiev.ua> + Copyright (C) 2011 Sergey Dvoriancev <dv_serg@mail.ru> + Copyright (C) 2015 ESF, LLC + All rights reserved. + + 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 - Squid Proxy Server realtime stat *** -(c) Alex Samorukov, samm@os2.kiev.ua -*/ - +/* Squid Proxy Server realtime stats */ require_once('guiconfig.inc'); require_once('sqstat.class.php'); -# init +// init $squidclass = new squidstat(); -# ------------------------------------------------------------------------------ -# Requests -# ------------------------------------------------------------------------------ - -# AJAX responce -if ($_REQUEST['getactivity']) -{ - header("Content-type: text/javascript"); - echo sqstat_AJAX_response( $_REQUEST ); - exit; +/* + * Requests + */ + +/* AJAX response */ +if ($_REQUEST['getactivity']) { + header("Content-type: text/javascript"); + echo sqstat_AJAX_response( $_REQUEST ); + exit; } -# ------------------------------------------------------------------------------ -# HTML Page -# ------------------------------------------------------------------------------ +/* + * HTML Page + */ -$pgtitle = "Proxy Squid: Realtime stat (sqstat)"; +$pgtitle = "Squid Proxy Server: Realtime Stats (SQStat)"; require_once("head.inc"); -$csrf_token= csrf_get_tokens(); +$csrf_token = csrf_get_tokens(); ?> -<link href="sqstat.css" rel="stylesheet" type="text/css"/> +<link href="sqstat.css" rel="stylesheet" type="text/css"/> <script type="text/javascript" src="/javascript/scriptaculous/prototype.js"></script> <script type="text/javascript" src="zhabascript.js"></script> -<!-- Ajax Script --> +<!-- AJAX script --> <script type="text/javascript"> - +//<![CDATA[ var intervalID = 0; function el(id) { - return document.getElementById(id); + return document.getElementById(id); } function getactivity(action) { - var url = "<?php echo ($_SERVER["PHP_SELF"]); ?>"; - var pars = "getactivity=yes" + "<? echo '&__csrf_magic='.$csrf_token ?>"; - - var myAjax = new Ajax.Request( url, - { - method: 'post', - parameters: pars, - onComplete: activitycallback - }); + var url = "<?php echo ($_SERVER["PHP_SELF"]); ?>"; + var pars = "getactivity=yes" + "<? echo '&__csrf_magic='.$csrf_token ?>"; + + var myAjax = new Ajax.Request(url, { + method: 'post', + parameters: pars, + onComplete: activitycallback + }); } function activitycallback(transport) { - - if (200 == transport.status) { - result = transport.responseText; - } + if (200 == transport.status) { + result = transport.responseText; + } } function update_start() { - var cmax = parseInt(el('refresh').value); + var cmax = parseInt(el('refresh').value); - update_stop(); + update_stop(); - if (cmax > 0) { - intervalID = window.setInterval('getactivity();', cmax * 1000); - } + if (cmax > 0) { + intervalID = window.setInterval('getactivity();', cmax * 1000); + } } function update_stop() { - window.clearInterval(intervalID); - intervalID = 0; + window.clearInterval(intervalID); + intervalID = 0; } // pre-call window.setTimeout('update_start()', 150); +//]]> </script> -<!-- HTML --> - -<!-- begin --> +<!-- HTML start --> <body link="#0000CC" vlink="#0000CC" alink="#0000CC"> <?php include("fbegin.inc"); ?> <?php - # prepare page data - $data = ''; - sqstat_loadconfig(); - if (sqstat_loadconfig() == 0) { - $data = $squidclass->query_exec(); - } - - if ($squidclass->errno == 0) { - $data = sqstat_resultHTML($data); - } - else { - # error - $data = sqstat_errorHTML(); - } + // Prepare page data + $data = ''; + sqstat_loadconfig(); + if (sqstat_loadconfig() == 0) { + $data = $squidclass->query_exec(); + } + + if ($squidclass->errno == 0) { + $data = sqstat_resultHTML($data); + } else { + // error + $data = sqstat_errorHTML(); + } ?> -<!-- form --> -<div id="sqstat_header" class="header" > - <?php echo ( sqstat_headerHTML() ); ?> +<!-- Form --> +<div id="sqstat_header" class="header"> + <?php echo ( sqstat_headerHTML() ); ?> </div> -<!-- result table --> +<!-- Result table --> <div id="sqstat_result" class="result"> - <?php echo ($data); ?> + <?php echo ($data); ?> </div> -<!-- end --> +<!-- HTML end --> <?php include("fend.inc"); ?> </body> </html> + <?php -# ------------------------------------------------------------------------------ -# Functions -# ------------------------------------------------------------------------------ +/* + * Functions + */ -function sqstat_AJAX_response( $request ) -{ - global $squidclass, $data; - $res = ''; +function sqstat_AJAX_response( $request ) { + global $squidclass, $data; + $res = ''; - if (sqstat_loadconfig() != 0) { - return sqstat_AJAX_error(sqstat_errorHTML()); - } + if (sqstat_loadconfig() != 0) { + return sqstat_AJAX_error(sqstat_errorHTML()); + } - # Actions - $data = $squidclass->query_exec(); + // Actions + $data = $squidclass->query_exec(); - $ver = sqstat_serverInfoHTML(); - $res .= "el('sqstat_serverver').innerHTML = '$ver';"; + $ver = sqstat_serverInfoHTML(); + $res .= "el('sqstat_serverver').innerHTML = '$ver';"; - $time = date("h:i:s d/m/Y"); - $res .= "el('sqstat_updtime').innerHTML = '$time';"; + $time = date("h:i:s d/m/Y"); + $res .= "el('sqstat_updtime').innerHTML = '$time';"; - $data = sqstat_resultHTML( $data ); - if ($squidclass->errno == 0) { - $data = sqstat_AJAX_prep($data); - $res .= "el('sqstat_result').innerHTML = '$data';"; - } - else { - # error - $res .= sqstat_AJAX_error(sqstat_errorHTML()); - } + $data = sqstat_resultHTML( $data ); + if ($squidclass->errno == 0) { + $data = sqstat_AJAX_prep($data); + $res .= "el('sqstat_result').innerHTML = '$data';"; + } else { + // error + $res .= sqstat_AJAX_error(sqstat_errorHTML()); + } - return $res; + return $res; } -function sqstat_AJAX_prep($text) -{ - $text = str_replace("'", "\'", $text); - $text = str_replace("\n", "\\r\\n", $text); - return $text; +function sqstat_AJAX_prep($text) { + $text = str_replace("'", "\'", $text); + $text = str_replace("\n", "\\r\\n", $text); + return $text; } -function sqstat_AJAX_error($err) -{ - $err = sqstat_AJAX_prep($err); - $t .= "el('sqstat_result').innerHTML = '$err';"; - return $t; +function sqstat_AJAX_error($err) { + $err = sqstat_AJAX_prep($err); + $t .= "el('sqstat_result').innerHTML = '$err';"; + return $t; } -# ------------------------------------------------------------------------------ -# Reports -# ------------------------------------------------------------------------------ +/* + *Reports + */ -function sqstat_headerHTML() -{ - global $squidclass; +function sqstat_headerHTML() { + global $squidclass; - $date = date("h:i:s d/m/Y"); - $squidinfo = sqstat_serverInfoHTML(); + $date = date("h:i:s d/m/Y"); + $squidinfo = sqstat_serverInfoHTML(); - if (empty($squidclass->autorefresh)) $squidclass->autorefresh = 0; + if (empty($squidclass->autorefresh)) { + $squidclass->autorefresh = 0; + } - return -<<<EOD + return <<< EOD <form method="get" action="{$_SERVER["PHP_SELF"]}"> - <input id="counter" name="counter" type="hidden" value=0/> + <input id="counter" name="counter" type="hidden" value=0 /> Squid RealTime stat {$squidclass->sqstat_version} for the {$servers} proxy server <a id='sqstat_serverver'>{$squidinfo}</a>.<br/> Auto refresh: <input id="refresh" name="refresh" type="text" size="4" value="{$squidclass->autorefresh}"/> sec. - <input type="button" value="Update" onclick="update_start();"/> - <input type="button" value="Stop" onclick="update_stop();"/> Created at: <tt id='sqstat_updtime'>{$date}</tt><br/> + <input type="button" value="Update" onclick="update_start();" /> + <input type="button" value="Stop" onclick="update_stop();" /> Created at: <tt id='sqstat_updtime'>{$date}</tt><br/> </form> EOD; } -function sqstat_serverInfoHTML() -{ - global $squidclass; - return $squidclass->server_version . " ({$squidclass->squidhost}:{$squidclass->squidport})"; +function sqstat_serverInfoHTML() { + global $squidclass; + return $squidclass->server_version . " ({$squidclass->squidhost}:{$squidclass->squidport})"; } -function sqstat_resultHTML($data) -{ - global $squidclass; - - $group_by_name = $squidclass->group_by_name; - $use_js = true; - - $t = array(); - - # table header - $t[] = "<table class='result' align='center' width='100%' border='0'>"; - $t[] = "<tr>"; - $t[] = "<th>{$group_by_name}</th><th>URI</th>"; - if ($squidclass->use_sessions) - $t[] = "<th>Curr. Speed</th><th>Avg. Speed</th>"; - $t[] = "<th>Size</th><th>Time</th>"; - $t[] = "</tr>"; - - # table body - if (is_array($data['users'])) { - $tbl = array(); - - $con_color = 0; - foreach($data['users'] as $key => $v) { - # skeep total info - if ($key == 'total') continue; - # group row - $tbl[] = "<tr>"; - $tbl[] = "<td style='border-right:0;' colspan='2'><b>" . (is_int($key) ? long2ip($key) : $key) . "</b></td>"; - $tbl[] = "<td style='border-left:0;' colspan='5'> </td>"; - $tbl[] = "</tr>"; - - # connections row - foreach ($v['con'] as $con) { - if ($use_js) - $js = "onMouseout='hideddrivetip()' onMouseover='ddrivetip(\"" . $squidclass->implode_with_keys($con,"<br/>") . "\")'"; - else $js=''; - - # begin new row - $class = (++$con_color % 2 == 0) ? " class='odd'" : ""; - $tbl[] = "<tr ($class)>"; - - # URL - $uri = "<a target='_blank' href='" . htmlspecialchars($con["uri"]) ."'>{$con['uritext']}</a>"; - $tbl[] = "<td id='white'></td>"; - $tbl[] = "<td nowrap {$js} width='80%'>{$uri}</td>"; - - # speed - if ($squidclass->use_sessions) { - $cur_s = round($con['cur_speed'], 2) > 0 ? sprintf("%01.2f KB/s", $con['cur_speed']) : ''; - $avg_s = round($con['avg_speed'], 2) > 0 ? sprintf("%01.2f KB/s", $con['avg_speed']) : ''; - $tbl[] = "<td nowrap align='right'>{$cur_s}</td>"; - $tbl[] = "<td nowrap align='right'>{$avg_s}</td>"; - } - - # file size - $filesize = $squidclass->filesize_format($con["bytes"]); - $duration = $squidclass->duration($con["seconds"], "short"); - $tbl[] = "<td nowrap align='right'>{$filesize}</td>"; - $tbl[] = "<td nowrap align='right'>{$duration}</td>"; - - # end row - $tbl[] = "</tr>"; - } - - # total user speed - if ($squidclass->use_sessions) { - $user_curr = sprintf("%01.2f KB/s", $v['user_curr']); - $user_avg = sprintf("%01.2f KB/s", $v['user_avg']); - $tbl[] ="<tr>"; - $tbl[] ="<td colspan='2'></td>"; - $tbl[] ="<td align='right' id='highlight'>{$user_curr}</td>"; - $tbl[] ="<td align='right' id='highlight'>{$user_avg}</td>"; - $tbl[] ="<td colspan='2'></td>"; - } - } - - - # status row - $stat = array(); - $ausers = sprintf("%d", $data['ausers']); - $acon = sprintf("%d", $data['acon']); - $stat[] = "<tr class='total'><td><b>Total:</b></td>"; - if ($squidclass->use_sessions) { - $total_curr = sprintf("%01.2f", $data['total_curr']); - $total_avg = sprintf("%01.2f", $data['total_avg']); - $stat[] = "<td align='right' colspan='5'><b>{$ausers}</b> users and <b>{$acon}</b> connections @ <b>{$total_curr}/{$total_avg}</b> KB/s (CURR/AVG)</td>"; - } - else { - $stat[] = "<td align='right' colspan='5'><b>{$ausers}</b> users and <b>{$acon}</b> connections</td>"; - } - $t[] = "</tr>"; - } - - if ($ausers == 0) { - $t[] = "<tr><td colspan=6><b>No active connections</b></td></tr>"; - } - else { - $stat = implode("\n", $stat); - $tbl = implode("\n", $tbl); - $t[] = $stat . $tbl . $stat; - } - - $t[] = "</table>"; - $t[] = "<p class='copyleft'>Report based on SQStat © <a href='mailto:samm@os2.kiev.ua?subject=SqStat '" . SQSTAT_VERSION . "'>Alex Samorukov</a>, 2006</p>"; - - return implode("\n", $t); +function sqstat_resultHTML($data) { + global $squidclass; + + $group_by_name = $squidclass->group_by_name; + $use_js = true; + + $t = array(); + + // table header + $t[] = "<table class='result' align='center' width='100%' border='0'>"; + $t[] = "<tr>"; + $t[] = "<th>{$group_by_name}</th><th>URI</th>"; + if ($squidclass->use_sessions) { + $t[] = "<th>Curr. Speed</th><th>Avg. Speed</th>"; + } + $t[] = "<th>Size</th><th>Time</th>"; + $t[] = "</tr>"; + + // table body + if (is_array($data['users'])) { + $tbl = array(); + + $con_color = 0; + foreach($data['users'] as $key => $v) { + // skip total info + if ($key == 'total') { + continue; + } + // group row + $tbl[] = "<tr>"; + $tbl[] = "<td style='border-right:0;' colspan='2'><b>" . (is_int($key) ? long2ip($key) : $key) . "</b></td>"; + $tbl[] = "<td style='border-left:0;' colspan='5'> </td>"; + $tbl[] = "</tr>"; + + // connections row + foreach ($v['con'] as $con) { + if ($use_js) { + $js = "onMouseout='hideddrivetip()' onMouseover='ddrivetip(\"" . $squidclass->implode_with_keys($con,"<br/>") . "\")'"; + } else { + $js=''; + } + + // begin new row + $class = (++$con_color % 2 == 0) ? " class='odd'" : ""; + $tbl[] = "<tr ($class)>"; + + // URL + $uri = "<a target='_blank' href='" . htmlspecialchars($con["uri"]) ."'>{$con['uritext']}</a>"; + $tbl[] = "<td id='white'></td>"; + $tbl[] = "<td nowrap {$js} width='80%'>{$uri}</td>"; + + // speed + if ($squidclass->use_sessions) { + $cur_s = round($con['cur_speed'], 2) > 0 ? sprintf("%01.2f KB/s", $con['cur_speed']) : ''; + $avg_s = round($con['avg_speed'], 2) > 0 ? sprintf("%01.2f KB/s", $con['avg_speed']) : ''; + $tbl[] = "<td nowrap align='right'>{$cur_s}</td>"; + $tbl[] = "<td nowrap align='right'>{$avg_s}</td>"; + } + + // file size + $filesize = $squidclass->filesize_format($con["bytes"]); + $duration = $squidclass->duration($con["seconds"], "short"); + $tbl[] = "<td nowrap align='right'>{$filesize}</td>"; + $tbl[] = "<td nowrap align='right'>{$duration}</td>"; + + // end row + $tbl[] = "</tr>"; + } + + // total user speed + if ($squidclass->use_sessions) { + $user_curr = sprintf("%01.2f KB/s", $v['user_curr']); + $user_avg = sprintf("%01.2f KB/s", $v['user_avg']); + $tbl[] ="<tr>"; + $tbl[] ="<td colspan='2'></td>"; + $tbl[] ="<td align='right' id='highlight'>{$user_curr}</td>"; + $tbl[] ="<td align='right' id='highlight'>{$user_avg}</td>"; + $tbl[] ="<td colspan='2'></td>"; + } + } + + + // status row + $stat = array(); + $ausers = sprintf("%d", $data['ausers']); + $acon = sprintf("%d", $data['acon']); + $stat[] = "<tr class='total'><td><b>Total:</b></td>"; + if ($squidclass->use_sessions) { + $total_curr = sprintf("%01.2f", $data['total_curr']); + $total_avg = sprintf("%01.2f", $data['total_avg']); + $stat[] = "<td align='right' colspan='5'><b>{$ausers}</b> users and <b>{$acon}</b> connections @ <b>{$total_curr}/{$total_avg}</b> KB/s (CURR/AVG)</td>"; + } else { + $stat[] = "<td align='right' colspan='5'><b>{$ausers}</b> users and <b>{$acon}</b> connections</td>"; + } + $t[] = "</tr>"; + } // ENDIF (is_array($data['users'])) + + if ($ausers == 0) { + $t[] = "<tr><td colspan=6><b>No active connections</b></td></tr>"; + } else { + $stat = implode("\n", $stat); + $tbl = implode("\n", $tbl); + $t[] = $stat . $tbl . $stat; + } + + $t[] = "</table>"; + $t[] = "<p class='copyleft'>Report based on SQStat © <a href='mailto:samm@os2.kiev.ua?subject=SqStat '" . SQSTAT_VERSION . "'>Alex Samorukov</a>, 2006</p>"; + + return implode("\n", $t); } -function sqstat_errorHTML() -{ - global $squidclass; - $t = array(); +function sqstat_errorHTML() { + global $squidclass; + $t = array(); - # table header - $t[] = "<table class='result' align='center' width='100%' border='0'>"; - $t[] = "<tr><th align='left'>SqStat error</th></tr>"; - $t[] = "<tr><td>"; - $t[] = '<p style="color:red">Error (' . $squidclass->errno . '): ' . $squidclass->errstr . '</p>'; - $t[] = "</td></tr>"; - $t[] = "</table>"; + // table header + $t[] = "<table class='result' align='center' width='100%' border='0'>"; + $t[] = "<tr><th align='left'>SqStat error</th></tr>"; + $t[] = "<tr><td>"; + $t[] = '<p style="color:red">Error (' . $squidclass->errno . '): ' . $squidclass->errstr . '</p>'; + $t[] = "</td></tr>"; + $t[] = "</table>"; - return implode ("\n", $t); + return implode ("\n", $t); } -function sqstat_loadconfig() -{ - global $squidclass, $config; - - $squidclass->errno = 0; - $squidclass->errstr = ''; - - $squidclass->sqstat_version = SQSTAT_VERSION; - - # === load config from pfSense === - $iface = '127.0.0.1'; - $iport = 3128; - $squid_settings = $config['installedpackages']['squid']['config'][0]; - if (!empty($squid_settings)) { - # squid interface IP & port - $realif = array(); - $iface = ($squid_settings['active_interface'] ? $squid_settings['active_interface'] : 'lan'); - $iface = explode(",", $iface); - foreach ($iface as $i => $if) { - $realif[] = sqstat_get_real_interface_address($if); - $iface = $realif[$i][0] ? $realif[$i][0] : '127.0.0.1'; - } - $iport = $squid_settings['proxy_port'] ? $squid_settings['proxy_port'] : 3128; - } - $squidclass->squidhost = $iface; - $squidclass->squidport = $iport; - - $squidclass->group_by = "host"; - $squidclass->resolveip = true; - $squidclass->hosts_file = ''; # hosts file not used - $squidclass->autorefresh = 3; # refresh 3 sec by default - $squidclass->cachemgr_passwd = ''; - - # load hosts file, if defined - if (!empty($squidclass->hosts_file)) { - $squidclass->load_hosts(); - } - - return $squidclass->errno; -} +function sqstat_loadconfig() { + global $squidclass, $config; + + $squidclass->errno = 0; + $squidclass->errstr = ''; + + $squidclass->sqstat_version = SQSTAT_VERSION; + + $iface = '127.0.0.1'; + /* Load config from pfSense and find proxy port */ + $iport = 3128; + if (is_array($config['installedpackages']['squid']['config'][0])) { + $squid_settings = $config['installedpackages']['squid']['config'][0]; + } else { + $squid_settings = array(); + } + $iport = $squid_settings['proxy_port'] ? $squid_settings['proxy_port'] : 3128; + + $squidclass->squidhost = $iface; + $squidclass->squidport = $iport; -function sqstat_get_real_interface_address($iface) -{ - global $config; + $squidclass->group_by = "host"; + $squidclass->resolveip = true; + $squidclass->hosts_file = ''; // hosts file not used + $squidclass->autorefresh = 3; // refresh 3 secs by default + $squidclass->cachemgr_passwd = ''; - $iface = convert_friendly_interface_to_real_interface_name($iface); - $line = trim(shell_exec("ifconfig $iface | grep inet | grep -v inet6")); - list($dummy, $ip, $dummy2, $netmask) = explode(" ", $line); + // Load hosts file if defined + if (!empty($squidclass->hosts_file)) { + $squidclass->load_hosts(); + } - return array($ip, long2ip(hexdec($netmask))); + return $squidclass->errno; } ?> diff --git a/config/lightsquid/tpl/novopf/index.html b/config/lightsquid/tpl/novopf/index.html index 5680866c..9d8ca329 100755 --- a/config/lightsquid/tpl/novopf/index.html +++ b/config/lightsquid/tpl/novopf/index.html @@ -97,7 +97,7 @@ <TR class=total> <TD align="left">##MSG_TOTAL_AVERAGE##:</Td> <!-- HIDE group start --> - <TD> </TD> + <TD> </TD> <!-- HIDE group end --> <TD align="center">##USERAVERAGE##</TD> <!-- HIDE oversize start--> diff --git a/config/lightsquid/tpl/novopf/user_detail.html b/config/lightsquid/tpl/novopf/user_detail.html index b3a7b168..8a8ff2cb 100755 --- a/config/lightsquid/tpl/novopf/user_detail.html +++ b/config/lightsquid/tpl/novopf/user_detail.html @@ -45,8 +45,8 @@ <tbody> <tr class=total> <th align="left" >##MSG_TOTAL##</th> - <th> </th> - <th> </th> + <th> </th> + <th> </th> <th align="right" nowrap="true">##TOTAL##</th> <th colspan=2> </th> </tr> diff --git a/config/lightsquid/tpl/novopf/user_month.html b/config/lightsquid/tpl/novopf/user_month.html index de7d8cab..f51e051e 100755 --- a/config/lightsquid/tpl/novopf/user_month.html +++ b/config/lightsquid/tpl/novopf/user_month.html @@ -63,8 +63,8 @@ <TR class="total"> <TD align="center">##MSG_TOTAL##</TD> <TD align="right" nowrap="true"><FONT size="-1">##TOTALBYTES##</FONT></TD> - <td align="right" nowrap="true"> </td> - <td align="right" nowrap="true"> </td> + <td align="right" nowrap="true"> </td> + <td align="right" nowrap="true"> </td> </TR> </tbody> </table> diff --git a/config/lightsquid/tpl/novopf/whousesite.html b/config/lightsquid/tpl/novopf/whousesite.html index ffd288f4..5da69edc 100755 --- a/config/lightsquid/tpl/novopf/whousesite.html +++ b/config/lightsquid/tpl/novopf/whousesite.html @@ -61,7 +61,7 @@ <tr class=total> <th align="left">##MSG_TOTAL##</th> <!-- HIDE realname start--> - <td> </td> + <td> </td> <!-- HIDE realname end--> <th align="right">##TOTALCONNECT##</th> <th align="right">##TOTAL##</th> diff --git a/config/lightsquid/tpl/novosea/index.html b/config/lightsquid/tpl/novosea/index.html index cf68c86d..874f196e 100755 --- a/config/lightsquid/tpl/novosea/index.html +++ b/config/lightsquid/tpl/novosea/index.html @@ -97,7 +97,7 @@ <TR class=total> <TD align="left">##MSG_TOTAL_AVERAGE##:</Td> <!-- HIDE group start --> - <TD> </TD> + <TD> </TD> <!-- HIDE group end --> <TD align="center">##USERAVERAGE##</TD> <!-- HIDE oversize start--> diff --git a/config/lightsquid/tpl/novosea/user_detail.html b/config/lightsquid/tpl/novosea/user_detail.html index b3a7b168..8a8ff2cb 100755 --- a/config/lightsquid/tpl/novosea/user_detail.html +++ b/config/lightsquid/tpl/novosea/user_detail.html @@ -45,8 +45,8 @@ <tbody> <tr class=total> <th align="left" >##MSG_TOTAL##</th> - <th> </th> - <th> </th> + <th> </th> + <th> </th> <th align="right" nowrap="true">##TOTAL##</th> <th colspan=2> </th> </tr> diff --git a/config/lightsquid/tpl/novosea/user_month.html b/config/lightsquid/tpl/novosea/user_month.html index de7d8cab..f51e051e 100755 --- a/config/lightsquid/tpl/novosea/user_month.html +++ b/config/lightsquid/tpl/novosea/user_month.html @@ -63,8 +63,8 @@ <TR class="total"> <TD align="center">##MSG_TOTAL##</TD> <TD align="right" nowrap="true"><FONT size="-1">##TOTALBYTES##</FONT></TD> - <td align="right" nowrap="true"> </td> - <td align="right" nowrap="true"> </td> + <td align="right" nowrap="true"> </td> + <td align="right" nowrap="true"> </td> </TR> </tbody> </table> diff --git a/config/lightsquid/tpl/novosea/whousesite.html b/config/lightsquid/tpl/novosea/whousesite.html index ffd288f4..5da69edc 100755 --- a/config/lightsquid/tpl/novosea/whousesite.html +++ b/config/lightsquid/tpl/novosea/whousesite.html @@ -61,7 +61,7 @@ <tr class=total> <th align="left">##MSG_TOTAL##</th> <!-- HIDE realname start--> - <td> </td> + <td> </td> <!-- HIDE realname end--> <th align="right">##TOTALCONNECT##</th> <th align="right">##TOTAL##</th> diff --git a/config/lightsquid/zhabascript.js b/config/lightsquid/zhabascript.js index 311e5fe9..7cdd898a 100644 --- a/config/lightsquid/zhabascript.js +++ b/config/lightsquid/zhabascript.js @@ -1,118 +1,106 @@ /*********************************************** -* Cool DHTML tooltip script- © Dynamic Drive DHTML code library (www.dynamicdrive.com) -* This notice MUST stay intact for legal use -* Visit Dynamic Drive at http://www.dynamicdrive.com/ for full source code -***********************************************/ + * Cool DHTML tooltip script II- © Dynamic Drive DHTML code library (www.dynamicdrive.com) + * This notice MUST stay intact for legal use + * Visit Dynamic Drive at http://www.dynamicdrive.com/ for full source code + ***********************************************/ +var offsetxpoint = -60; //Customize x offset of tooltip +var offsetypoint = 20; //Customize y offset of tooltip +var ie = document.all; +var ns6 = document.getElementById && !document.all; +var enabletip = false; +var tipobj = false; -var offsetxpoint=-60 //Customize x offset of tooltip -var offsetypoint=20 //Customize y offset of tooltip -var ie=document.all -var ns6=document.getElementById && !document.all -var enabletip=false -var tipobj=false; - -function jsInit(){ - - if (ie||ns6) - tipobj=document.all? document.all["dhtmltooltip"] : document.getElementById? document.getElementById("dhtmltooltip") : "" - //alert(tipobj); +function jsInit() { + if (ie || ns6) { + tipobj = document.all ? document.all.dhtmltooltip : document.getElementById ? document.getElementById("dhtmltooltip") : ""; + //alert(tipobj); + } } -/*********************************************** -* Cool DHTML tooltip script II- © Dynamic Drive DHTML code library (www.dynamicdrive.com) -* This notice MUST stay intact for legal use -* Visit Dynamic Drive at http://www.dynamicdrive.com/ for full source code -***********************************************/ - -var offsetfromcursorX=12 //Customize x offset of tooltip -var offsetfromcursorY=10 //Customize y offset of tooltip +var offsetfromcursorX = 12; //Customize x offset of tooltip +var offsetfromcursorY = 10; //Customize y offset of tooltip -var offsetdivfrompointerX=10 //Customize x offset of tooltip DIV relative to pointer image -var offsetdivfrompointerY=14 //Customize y offset of tooltip DIV relative to pointer image. Tip: Set it to (height_of_pointer_image-1). +var offsetdivfrompointerX = 10; //Customize x offset of tooltip DIV relative to pointer image +var offsetdivfrompointerY = 14; //Customize y offset of tooltip DIV relative to pointer image. Tip: Set it to (height_of_pointer_image-1). -//document.write('<div id="dhtmltooltip"></div>') //write out tooltip DIV -document.write('<img id="dhtmlpointer" src="arrow.gif">') //write out pointer image +document.write('<div id="dhtmltooltip"></div>'); //write out tooltip DIV +document.write('<img id="dhtmlpointer" src="arrow.gif">'); //write out pointer image -var ie=document.all -var ns6=document.getElementById && !document.all -var enabletip=false -if (ie||ns6) - var tipobj=document.all? document.all["dhtmltooltip"] : document.getElementById? document.getElementById("dhtmltooltip") : "" +if (ie || ns6) { + var tipobj = document.all ? document.all.dhtmltooltip : document.getElementById ? document.getElementById("dhtmltooltip") : ""; +} -var pointerobj=document.all? document.all["dhtmlpointer"] : document.getElementById? document.getElementById("dhtmlpointer") : "" +var pointerobj = document.all ? document.all.dhtmlpointer : document.getElementById ? document.getElementById("dhtmlpointer") : ""; -function ietruebody(){ - return (document.compatMode && document.compatMode!="BackCompat")? document.documentElement : document.body +function ietruebody() { + return (document.compatMode && document.compatMode !== "BackCompat") ? document.documentElement : document.body; } -function ddrivetip(thetext, thewidth, thecolor){ - if(!tipobj) return false; - if (ns6||ie){ - if (typeof thewidth!="undefined") tipobj.style.width=thewidth+"px" - if (typeof thecolor!="undefined" && thecolor!="") tipobj.style.backgroundColor=thecolor - tipobj.innerHTML=thetext - enabletip=true - return false - } +function ddrivetip(thetext, thewidth, thecolor) { + if (!tipobj) { + return false; + } + if (ns6 || ie) { + if (thewidth !== undefined) { + tipobj.style.width = thewidth + "px"; + } + if (thecolor !== undefined && thecolor !== "") { + tipobj.style.backgroundColor = thecolor; + } + tipobj.innerHTML = thetext; + enabletip = true; + return false; + } } -function positiontip(e){ - if (enabletip){ - var nondefaultpos=false - var curX=(ns6)?e.pageX : event.clientX+ietruebody().scrollLeft; - var curY=(ns6)?e.pageY : event.clientY+ietruebody().scrollTop; - //Find out how close the mouse is to the corner of the window - var winwidth=ie&&!window.opera? ietruebody().clientWidth : window.innerWidth-20 - var winheight=ie&&!window.opera? ietruebody().clientHeight : window.innerHeight-20 - - var rightedge=ie&&!window.opera? winwidth-event.clientX-offsetfromcursorX : winwidth-e.clientX-offsetfromcursorX - var bottomedge=ie&&!window.opera? winheight-event.clientY-offsetfromcursorY : winheight-e.clientY-offsetfromcursorY - - var leftedge=(offsetfromcursorX<0)? offsetfromcursorX*(-1) : -1000 - - //if the horizontal distance isn't enough to accomodate the width of the context menu -/* if (rightedge<tipobj.offsetWidth){ - //move the horizontal position of the menu to the left by it's width - tipobj.style.left=curX-tipobj.offsetWidth+"px" - nondefaultpos=true - alert(1); - } - else */ - if (curX<leftedge) - tipobj.style.left="5px" - else{ - //position the horizontal position of the menu where the mouse is positioned - tipobj.style.left=curX+offsetfromcursorX-offsetdivfrompointerX+"px" - pointerobj.style.left=curX+offsetfromcursorX+"px" - } - - //same concept with the vertical position - if (bottomedge<tipobj.offsetHeight){ - tipobj.style.top=curY-tipobj.offsetHeight-offsetfromcursorY+"px" - nondefaultpos=true - } - else{ - tipobj.style.top=curY+offsetfromcursorY+offsetdivfrompointerY+"px" - pointerobj.style.top=curY+offsetfromcursorY+"px" - } - tipobj.style.visibility="visible" - if (!nondefaultpos) - pointerobj.style.visibility="visible" - else - pointerobj.style.visibility="hidden" - } -} +function positiontip(e) { + if (enabletip) { + var nondefaultpos = false; + var curX = (ns6) ? e.pageX : event.clientX + ietruebody().scrollLeft; + var curY = (ns6) ? e.pageY : event.clientY + ietruebody().scrollTop; + //Find out how close the mouse is to the corner of the window + var winwidth = (ie && !window.opera) ? ietruebody().clientWidth : window.innerWidth - 20; + var winheight = (ie && !window.opera) ? ietruebody().clientHeight : window.innerHeight - 20; -function hideddrivetip(){ - if (ns6||ie){ - enabletip=false - tipobj.style.visibility="hidden" - pointerobj.style.visibility="hidden" - tipobj.style.left="-1000px" - tipobj.style.backgroundColor='' - tipobj.style.width='' - } + var rightedge = (ie && !window.opera) ? winwidth - event.clientX - offsetfromcursorX : winwidth - e.clientX - offsetfromcursorX; + var bottomedge = (ie && !window.opera) ? winheight - event.clientY - offsetfromcursorY : winheight - e.clientY - offsetfromcursorY; + + var leftedge = (offsetfromcursorX < 0) ? offsetfromcursorX * (-1) : -1000; + + if (curX < leftedge) { + tipobj.style.left = "5px"; + } else { + //position the horizontal position of the menu where the mouse is positioned + tipobj.style.left = curX + offsetfromcursorX - offsetdivfrompointerX + "px"; + pointerobj.style.left = curX + offsetfromcursorX + "px"; + } + + //same concept with the vertical position + if (bottomedge < tipobj.offsetHeight) { + tipobj.style.top = curY - tipobj.offsetHeight - offsetfromcursorY + "px"; + nondefaultpos = true; + } else { + tipobj.style.top = curY + offsetfromcursorY + offsetdivfrompointerY + "px"; + pointerobj.style.top = curY + offsetfromcursorY + "px"; + } + tipobj.style.visibility = "visible"; + if (!nondefaultpos) { + pointerobj.style.visibility = "visible"; + } else { + pointerobj.style.visibility = "hidden"; + } + } } -document.onmousemove=positiontip +function hideddrivetip() { + if (ns6 || ie) { + enabletip = false; + tipobj.style.visibility = "hidden"; + pointerobj.style.visibility = "hidden"; + tipobj.style.left = "-1000px"; + tipobj.style.backgroundColor = ''; + tipobj.style.width = ''; + } +} +document.onmousemove = positiontip; |