diff --git a/actions/admin/settings/130.webserver.php b/actions/admin/settings/130.webserver.php index 5ab57cc5..2b48d5f0 100644 --- a/actions/admin/settings/130.webserver.php +++ b/actions/admin/settings/130.webserver.php @@ -185,7 +185,7 @@ return [ 'apache2', 'nginx' ], - 'visible' => Settings::Get('system.awstats_enabled') == 1, + 'visible' => Settings::Get('system.traffictool') != 'webalizer', 'advanced_mode' => true ], 'system_logfiles_type' => [ diff --git a/actions/admin/settings/140.statistics.php b/actions/admin/settings/140.statistics.php index 4edb428c..6f4939ef 100644 --- a/actions/admin/settings/140.statistics.php +++ b/actions/admin/settings/140.statistics.php @@ -31,6 +31,19 @@ return [ 'title' => lng('admin.statisticsettings'), 'icon' => 'fa-solid fa-chart-area', 'fields' => [ + 'system_traffictool' => [ + 'label' => lng('serversettings.traffictool.toolselect'), + 'settinggroup' => 'system', + 'varname' => 'traffictool', + 'type' => 'select', + 'default' => 'goaccess', + 'select_var' => [ + 'webalizer' => lng('serversettings.traffictool.webalizer'), + 'awstats' => lng('serversettings.traffictool.awstats'), + 'goaccess' => lng('serversettings.traffictool.goaccess') + ], + 'save_method' => 'storeSettingUpdateTrafficTool', + ], 'system_webalizer_quiet' => [ 'label' => lng('serversettings.webalizer_quiet'), 'settinggroup' => 'system', @@ -43,15 +56,7 @@ return [ 2 => lng('admin.webalizer.veryquiet') ], 'save_method' => 'storeSettingField', - 'visible' => Settings::Get('system.awstats_enabled') == 0 - ], - 'system_awstats_enabled' => [ - 'label' => lng('serversettings.awstats_enabled'), - 'settinggroup' => 'system', - 'varname' => 'awstats_enabled', - 'type' => 'checkbox', - 'default' => false, - 'save_method' => 'storeSettingField' + 'visible' => Settings::Get('system.traffictool') == 'webalizer' ], 'system_awstats_path' => [ 'label' => lng('serversettings.awstats_path'), @@ -61,7 +66,7 @@ return [ 'string_type' => 'dir', 'default' => '/usr/share/awstats/tools/', 'save_method' => 'storeSettingField', - 'visible' => Settings::Get('system.awstats_enabled') == 1 + 'visible' => Settings::Get('system.traffictool') == 'awstats' ], 'system_awstats_awstatspath' => [ 'label' => lng('serversettings.awstats_awstatspath'), @@ -71,7 +76,7 @@ return [ 'string_type' => 'dir', 'default' => '/usr/lib/cgi-bin/', 'save_method' => 'storeSettingField', - 'visible' => Settings::Get('system.awstats_enabled') == 1 + 'visible' => Settings::Get('system.traffictool') == 'awstats' ], 'system_awstats_conf' => [ 'label' => lng('serversettings.awstats_conf'), @@ -81,7 +86,7 @@ return [ 'string_type' => 'dir', 'default' => '/etc/awstats/', 'save_method' => 'storeSettingField', - 'visible' => Settings::Get('system.awstats_enabled') == 1 + 'visible' => Settings::Get('system.traffictool') == 'awstats' ], 'system_awstats_icons' => [ 'label' => lng('serversettings.awstats_icons'), @@ -91,7 +96,7 @@ return [ 'string_type' => 'dir', 'default' => '/usr/share/awstats/icon/', 'save_method' => 'storeSettingField', - 'visible' => Settings::Get('system.awstats_enabled') == 1 + 'visible' => Settings::Get('system.traffictool') == 'awstats' ], 'system_awstats_logformat' => [ 'label' => lng('serversettings.awstats.logformat'), @@ -100,7 +105,7 @@ return [ 'type' => 'text', 'default' => '1', 'save_method' => 'storeSettingField', - 'visible' => Settings::Get('system.awstats_enabled') == 1, + 'visible' => Settings::Get('system.traffictool') == 'awstats', 'advanced_mode' => true ] ] diff --git a/admin_updates.php b/admin_updates.php index b91b4142..d2c928aa 100644 --- a/admin_updates.php +++ b/admin_updates.php @@ -26,7 +26,6 @@ const AREA = 'admin'; require __DIR__ . '/lib/init.php'; -use Exception; use Froxlor\Cron\TaskId; use Froxlor\Froxlor; use Froxlor\FroxlorLogger; diff --git a/install/froxlor.sql.php b/install/froxlor.sql.php index 8ec52008..3202f79f 100644 --- a/install/froxlor.sql.php +++ b/install/froxlor.sql.php @@ -575,8 +575,6 @@ opcache.validate_timestamps'), ('system', 'default_sslvhostconf', ''), ('system', 'mail_quota_enabled', '0'), ('system', 'mail_quota', '100'), - ('system', 'webalizer_enabled', '1'), - ('system', 'awstats_enabled', '0'), ('system', 'httpuser', 'www-data'), ('system', 'httpgroup', 'www-data'), ('system', 'webserver', 'apache2'), @@ -700,6 +698,7 @@ opcache.validate_timestamps'), ('system', 'update_channel', 'stable'), ('system', 'updatecheck_data', ''), ('system', 'update_notify_last', '2.0.0-beta1'), + ('system', 'traffictool', 'goaccess'), ('api', 'enabled', '0'), ('2fa', 'enabled', '1'), ('panel', 'decimal_places', '4'), @@ -743,7 +742,7 @@ opcache.validate_timestamps'), ('panel', 'logo_overridecustom', '0'), ('panel', 'settings_mode', '0'), ('panel', 'version', '2.0.0-beta1'), - ('panel', 'db_version', '202112310'); + ('panel', 'db_version', '202211030'); DROP TABLE IF EXISTS `panel_tasks`; diff --git a/install/updates/froxlor/update_2.x.inc.php b/install/updates/froxlor/update_2.x.inc.php index 405aabfd..cfe16350 100644 --- a/install/updates/froxlor/update_2.x.inc.php +++ b/install/updates/froxlor/update_2.x.inc.php @@ -176,3 +176,14 @@ if (Froxlor::isFroxlorVersion('0.10.38')) { Froxlor::updateToVersion($update_to); } + +if (Froxlor::isDatabaseVersion('202112310')) { + + Update::showUpdateStep("Adjusting traffic tool settings"); + $traffic_tool = Settings::Get('system.awstats_enabled') == 1 ? 'awstats' : 'webalizer'; + Settings::AddNew("system.traffictool", $traffic_tool); + Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'system' AND `varname` = 'awstats_enabled'"); + Update::lastStepStatus(0); + + Froxlor::updateToDbVersion('202211030'); +} diff --git a/lib/Froxlor/Api/Commands/Customers.php b/lib/Froxlor/Api/Commands/Customers.php index 23160048..7a2c82f8 100644 --- a/lib/Froxlor/Api/Commands/Customers.php +++ b/lib/Froxlor/Api/Commands/Customers.php @@ -633,10 +633,7 @@ class Customers extends ApiCommand implements ResourceEntity 'passwd' => $htpasswdPassword ]; - $stats_folder = 'webalizer'; - if (Settings::Get('system.awstats_enabled') == '1') { - $stats_folder = 'awstats'; - } + $stats_folder = Settings::Get('system.traffictool'); $ins_data['path'] = FileDir::makeCorrectDir($documentroot . '/' . $stats_folder . '/'); $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "[API] automatically added " . $stats_folder . " htpasswd for user '" . $loginname . "'"); Database::pexecute($ins_stmt, $ins_data, true, true); diff --git a/lib/Froxlor/Cron/Http/Apache.php b/lib/Froxlor/Cron/Http/Apache.php index 6a8504f2..5f3db58c 100644 --- a/lib/Froxlor/Cron/Http/Apache.php +++ b/lib/Froxlor/Cron/Http/Apache.php @@ -1032,30 +1032,17 @@ class Apache extends HttpConfigBase { $stats_text = ''; + $statTool = Settings::Get('system.traffictool'); + $statDomain = ($domain['parentdomainid'] == '0') ? $domain['domain'] : $domain['parentdomain']; if ($domain['speciallogfile'] == '1') { - $statDomain = ($domain['parentdomainid'] == '0') ? $domain['domain'] : $domain['parentdomain']; - if (Settings::Get('system.awstats_enabled') == '1') { - $stats_text .= ' Alias /awstats "' . FileDir::makeCorrectFile($domain['customerroot'] . '/awstats/' . $statDomain) . '"' . "\n"; + $statDomain = $domain['domain']; + } + $statDocroot = FileDir::makeCorrectFile($domain['customerroot'] . '/'.$statTool.'/' . $statDomain); + + $stats_text .= ' Alias /'.$statTool.' "' . $statDocroot . '"' . "\n"; + // awstats special requirement for icons + if ($statTool == 'awstats') { $stats_text .= ' Alias /awstats-icon "' . FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '"' . "\n"; - } else { - $stats_text .= ' Alias /webalizer "' . FileDir::makeCorrectFile($domain['customerroot'] . '/webalizer/' . $statDomain) . '"' . "\n"; - } - } else { - if ($domain['customerroot'] != $domain['documentroot']) { - if (Settings::Get('system.awstats_enabled') == '1') { - $stats_text .= ' Alias /awstats "' . FileDir::makeCorrectFile($domain['customerroot'] . '/awstats/' . $domain['domain']) . '"' . "\n"; - $stats_text .= ' Alias /awstats-icon "' . FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '"' . "\n"; - } else { - $stats_text .= ' Alias /webalizer "' . FileDir::makeCorrectFile($domain['customerroot'] . '/webalizer') . '"' . "\n"; - } - } elseif (Settings::Get('system.awstats_enabled') == '1') { - // if the docroots are equal, we still have to set an alias for awstats - // because the stats are in /awstats/[domain], not just /awstats/ - // also, the awstats-icons are someplace else too! - // -> webalizer does not need this! - $stats_text .= ' Alias /awstats "' . FileDir::makeCorrectFile($domain['documentroot'] . '/awstats/' . $domain['domain']) . '"' . "\n"; - $stats_text .= ' Alias /awstats-icon "' . FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '"' . "\n"; - } } return $stats_text; @@ -1138,7 +1125,7 @@ class Apache extends HttpConfigBase $logfiles_text .= ' CustomLog "' . $access_log . '" ' . $logtype . "\n"; } - if (Settings::Get('system.awstats_enabled') == '1') { + if (Settings::Get('system.traffictool') == 'awstats') { if ((int)$domain['parentdomainid'] == 0) { // prepare the aliases and subdomains for stats config files $server_alias = ''; diff --git a/lib/Froxlor/Cron/Http/ConfigIO.php b/lib/Froxlor/Cron/Http/ConfigIO.php index 740514e4..f2fed2d1 100644 --- a/lib/Froxlor/Cron/Http/ConfigIO.php +++ b/lib/Froxlor/Cron/Http/ConfigIO.php @@ -85,7 +85,7 @@ class ConfigIO */ private function cleanAwstatsFiles() { - if (Settings::Get('system.awstats_enabled') == '0') { + if (Settings::Get('system.traffictool') != 'awstats') { return; } diff --git a/lib/Froxlor/Cron/Http/Lighttpd.php b/lib/Froxlor/Cron/Http/Lighttpd.php index fbf057e1..0b480ddc 100644 --- a/lib/Froxlor/Cron/Http/Lighttpd.php +++ b/lib/Froxlor/Cron/Http/Lighttpd.php @@ -717,38 +717,18 @@ class Lighttpd extends HttpConfigBase { $stats_text = ''; + $statTool = Settings::Get('system.traffictool'); + $statDomain = ($domain['parentdomainid'] == '0') ? $domain['domain'] : $domain['parentdomain']; if ($domain['speciallogfile'] == '1') { - if ($domain['parentdomainid'] == '0') { - if (Settings::Get('system.awstats_enabled') == '1') { - $stats_text .= ' alias.url = ( "/awstats/" => "' . FileDir::makeCorrectFile($domain['customerroot'] . '/awstats/' . $domain['domain']) . '" )' . "\n"; - $stats_text .= ' alias.url += ( "/awstats-icon" => "' . FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '" )' . "\n"; - } else { - $stats_text .= ' alias.url = ( "/webalizer/" => "' . FileDir::makeCorrectFile($domain['customerroot'] . '/webalizer/' . $domain['domain']) . '/" )' . "\n"; - } - } else { - if (Settings::Get('system.awstats_enabled') == '1') { - $stats_text .= ' alias.url = ( "/awstats/" => "' . FileDir::makeCorrectFile($domain['customerroot'] . '/awstats/' . $domain['parentdomain']) . '" )' . "\n"; - $stats_text .= ' alias.url += ( "/awstats-icon" => "' . FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '" )' . "\n"; - } else { - $stats_text .= ' alias.url = ( "/webalizer/" => "' . FileDir::makeCorrectFile($domain['customerroot'] . '/webalizer/' . $domain['parentdomain']) . '/" )' . "\n"; - } - } - } else { - if ($domain['customerroot'] != $domain['documentroot']) { - if (Settings::Get('system.awstats_enabled') == '1') { - $stats_text .= ' alias.url = ( "/awstats/" => "' . FileDir::makeCorrectFile($domain['customerroot'] . '/awstats/' . $domain['domain']) . '" )' . "\n"; - $stats_text .= ' alias.url += ( "/awstats-icon" => "' . FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '" )' . "\n"; - } else { - $stats_text .= ' alias.url = ( "/webalizer/" => "' . FileDir::makeCorrectFile($domain['customerroot'] . '/webalizer/') . '" )' . "\n"; - } - } elseif (Settings::Get('system.awstats_enabled') == '1') { - // if the docroots are equal, we still have to set an alias for awstats - // because the stats are in /awstats/[domain], not just /awstats/ - // also, the awstats-icons are someplace else too! - // -> webalizer does not need this! - $stats_text .= ' alias.url = ( "/awstats/" => "' . FileDir::makeCorrectFile($domain['documentroot'] . '/awstats/' . $domain['domain']) . '" )' . "\n"; - $stats_text .= ' alias.url += ( "/awstats-icon" => "' . FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '" )' . "\n"; - } + $statDomain = $domain['domain']; + } + $statDocroot = FileDir::makeCorrectFile($domain['customerroot'] . '/'.$statTool.'/' . $statDomain); + + $stats_text .= ' alias.url = ( "/'.$statTool.'/" => "' . $statDocroot . '" )' . "\n"; + + // awstats special requirement for icons + if ($statTool == 'awstats') { + $stats_text .= ' alias.url += ( "/awstats-icon" => "' . FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '" )' . "\n"; } return $stats_text; @@ -837,7 +817,7 @@ class Lighttpd extends HttpConfigBase $logfiles_text .= ' accesslog.filename = "' . $access_log . '"' . "\n"; } - if (Settings::Get('system.awstats_enabled') == '1') { + if (Settings::Get('system.traffictool') == 'awstats') { if ((int)$domain['parentdomainid'] == 0) { // prepare the aliases and subdomains for stats config files $server_alias = ''; diff --git a/lib/Froxlor/Cron/Http/Nginx.php b/lib/Froxlor/Cron/Http/Nginx.php index 6b1e9c70..177ba636 100644 --- a/lib/Froxlor/Cron/Http/Nginx.php +++ b/lib/Froxlor/Cron/Http/Nginx.php @@ -725,7 +725,7 @@ class Nginx extends HttpConfigBase $logfiles_text .= "\t" . 'access_log ' . $access_log . ' ' . $logtype . ';' . "\n"; $logfiles_text .= "\t" . 'error_log ' . $error_log . ' ' . Settings::Get('system.errorlog_level') . ';' . "\n"; - if (Settings::Get('system.awstats_enabled') == '1') { + if (Settings::Get('system.traffictool') == 'awstats') { if ((int)$domain['parentdomainid'] == 0) { // prepare the aliases and subdomains for stats config files $server_alias = ''; @@ -962,6 +962,7 @@ class Nginx extends HttpConfigBase switch ($single['path']) { case '/awstats/': case '/webalizer/': + case '/goaccess/': // no stats-alias in "location /"-context break; default: @@ -1023,6 +1024,7 @@ class Nginx extends HttpConfigBase switch ($single['path']) { case '/awstats/': case '/webalizer/': + case '/goaccess/': $path_options .= $this->getStats($domain, $single); unset($htpasswds[$idx]); break; @@ -1115,35 +1117,21 @@ class Nginx extends HttpConfigBase { $stats_text = ''; - // define basic path to the stats - if (Settings::Get('system.awstats_enabled') == '1') { - $alias_dir = FileDir::makeCorrectFile($domain['customerroot'] . '/awstats/'); - } else { - $alias_dir = FileDir::makeCorrectFile($domain['customerroot'] . '/webalizer/'); + $statTool = Settings::Get('system.traffictool'); + $statDomain = ($domain['parentdomainid'] == '0') ? $domain['domain'] : $domain['parentdomain']; + if ($domain['speciallogfile'] == '1') { + $statDomain = $domain['domain']; } + $statDocroot = FileDir::makeCorrectFile($domain['customerroot'] . '/'.$statTool.'/' . $statDomain); - // if this is a parentdomain, we use this domain-name - if ($domain['parentdomainid'] == '0') { - $alias_dir = FileDir::makeCorrectDir($alias_dir . '/' . $domain['domain']); - } else { - $alias_dir = FileDir::makeCorrectDir($alias_dir . '/' . $domain['parentdomain']); - } - - if (Settings::Get('system.awstats_enabled') == '1') { - // awstats - $stats_text .= "\t" . 'location ^~ /awstats/ {' . "\n"; - } else { - // webalizer - $stats_text .= "\t" . 'location ^~ /webalizer {' . "\n"; - } - - $stats_text .= "\t\t" . 'alias ' . $alias_dir . ';' . "\n"; + $stats_text .= "\t" . 'location ^~ /'.$statTool.' {' . "\n"; + $stats_text .= "\t\t" . 'alias ' . $statDocroot . '/;' . "\n"; $stats_text .= "\t\t" . 'auth_basic "' . $single['authname'] . '";' . "\n"; $stats_text .= "\t\t" . 'auth_basic_user_file ' . FileDir::makeCorrectFile($single['usrf']) . ';' . "\n"; $stats_text .= "\t" . '}' . "\n\n"; - // awstats icons - if (Settings::Get('system.awstats_enabled') == '1') { + // awstats special requirement for icons + if ($statTool == 'awstats') { $stats_text .= "\t" . 'location ~ ^/awstats-icon/(.*)$ {' . "\n"; $stats_text .= "\t\t" . 'alias ' . FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '$1;' . "\n"; $stats_text .= "\t" . '}' . "\n\n"; diff --git a/lib/Froxlor/Cron/System/TasksCron.php b/lib/Froxlor/Cron/System/TasksCron.php index 8deff792..fb205b4d 100644 --- a/lib/Froxlor/Cron/System/TasksCron.php +++ b/lib/Froxlor/Cron/System/TasksCron.php @@ -205,21 +205,16 @@ class TasksCron extends FroxlorCron $usermaildir = FileDir::makeCorrectDir(Settings::Get('system.vmail_homedir') . '/' . $row['data']['loginname'] . '/'); // stats directory - if (Settings::Get('system.awstats_enabled') == '1') { - FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: mkdir -p ' . escapeshellarg($userhomedir . 'awstats')); - FileDir::safe_exec('mkdir -p ' . escapeshellarg($userhomedir . 'awstats')); + $statsdir = FileDir::makeCorrectDir($userhomedir . '/' . Settings::Get('system.traffictool')); + FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: mkdir -p ' . escapeshellarg($statsdir)); + FileDir::safe_exec('mkdir -p ' . escapeshellarg($statsdir)); + + foreach (['webalizer', 'awstats', 'goaccess'] as $statstools) { + $statsdir = FileDir::makeCorrectDir($userhomedir . '/' . $statstool); // in case we changed from the other stats -> remove old - // (yes i know, the stats are lost - that's why you should not change all the time!) - if (file_exists($userhomedir . 'webalizer')) { - FileDir::safe_exec('rm -rf ' . escapeshellarg($userhomedir . 'webalizer')); - } - } else { - FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: mkdir -p ' . escapeshellarg($userhomedir . 'webalizer')); - FileDir::safe_exec('mkdir -p ' . escapeshellarg($userhomedir . 'webalizer')); - // in case we changed from the other stats -> remove old - // (yes i know, the stats are lost - that's why you should not change all the time!) - if (file_exists($userhomedir . 'awstats')) { - FileDir::safe_exec('rm -rf ' . escapeshellarg($userhomedir . 'awstats')); + if (Settings::Get('system.traffictool') != $statstools && file_exists($statsdir)) { + // (yes i know, the stats are lost - that's why you should not change all the time!) + FileDir::safe_exec('rm -rf ' . escapeshellarg($statsdir)); } } diff --git a/lib/Froxlor/Cron/Traffic/TrafficCron.php b/lib/Froxlor/Cron/Traffic/TrafficCron.php index cb79996b..cf15777e 100644 --- a/lib/Froxlor/Cron/Traffic/TrafficCron.php +++ b/lib/Froxlor/Cron/Traffic/TrafficCron.php @@ -185,6 +185,8 @@ class TrafficCron extends FroxlorCron $current_stamp = time(); $current_year = date('Y', $current_stamp); $current_month = date('m', $current_stamp); + // @todo locale? + $current_month_short = date('M', $current_stamp); $current_day = date('d', $current_stamp); while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { @@ -215,11 +217,17 @@ class TrafficCron extends FroxlorCron $httptraffic = 0; reset($domainlist[$row['customerid']]); + $statsTool = Settings::Get('system.traffictool'); + if (isset($speciallogfile_domainlist[$row['customerid']]) && is_array($speciallogfile_domainlist[$row['customerid']]) && count($speciallogfile_domainlist[$row['customerid']]) != 0) { reset($speciallogfile_domainlist[$row['customerid']]); - if (Settings::Get('system.awstats_enabled') == '0') { + if ($statsTool != 'awstats') { foreach ($speciallogfile_domainlist[$row['customerid']] as $domainid => $domain) { - $httptraffic += floatval(self::callWebalizerGetTraffic($row['loginname'] . '-' . $domain, $row['documentroot'] . '/webalizer/' . $domain . '/', $domain, $domainlist[$row['customerid']])); + if ($statsTool == 'goaccess') { + $httptraffic += floatval(self::callGoaccessGetTraffic($row['loginname'] . '-' . $domain, $row['documentroot'] . '/goaccess/' . $domain . '/', $domain, $domainlist[$row['customerid']], ['month' => $current_month_short, 'year' => $current_year])); + } else { + $httptraffic += floatval(self::callWebalizerGetTraffic($row['loginname'] . '-' . $domain, $row['documentroot'] . '/webalizer/' . $domain . '/', $domain, $domainlist[$row['customerid']])); + } } } } @@ -230,8 +238,10 @@ class TrafficCron extends FroxlorCron // *not* also in the special-logfiles-loop, because the function // will iterate through all customer-domains and the awstats-configs // know the logfile-name, #246 - if (Settings::Get('system.awstats_enabled') == '1') { + if ($statsTool == 'awstats') { $httptraffic += floatval(self::callAwstatsGetTraffic($row['customerid'], $row['documentroot'] . '/awstats/', $domainlist[$row['customerid']], $current_stamp)); + } elseif ($statsTool == 'goaccess') { + $httptraffic += floatval(self::callGoaccessGetTraffic($row['loginname'], $row['documentroot'] . '/goaccess/', $caption, $domainlist[$row['customerid']], ['month' => $current_month_short, 'year' => $current_year])); } else { $httptraffic += floatval(self::callWebalizerGetTraffic($row['loginname'], $row['documentroot'] . '/webalizer/', $caption, $domainlist[$row['customerid']])); } @@ -608,19 +618,59 @@ class TrafficCron extends FroxlorCron } } + /** + * Run goaccess to create statistics and return used traffic since last run + * + * @param string $logfile Name of logfile + * @param string $outputdir Place where stats should be build + * @param string $caption Caption for webalizer output + * @param array $usersdomainlist + * + * @return int Used traffic + */ + private static function callGoaccessGetTraffic($logfile, $outputdir, $caption, array $usersdomainlist = [], array $monthyear_arr = []) + { + $returnval = 0; + + $logfile = FileDir::makeCorrectFile(Settings::Get('system.logfiles_directory') . $logfile . '-access.log'); + if (file_exists($logfile)) { + + $outputdir = FileDir::makeCorrectDir($outputdir); + if (!file_exists($outputdir)) { + FileDir::safe_exec('mkdir -p ' . escapeshellarg($outputdir)); + } + + if (file_exists($outputdir . '.tmp.json')) { + @unlink($outputdir . '.tmp.json'); + } + + $format = Settings::Get('system.logfiles_type') == '2' ? 'VCOMBINED' : 'COMBINED'; + $monthyear = $monthyear_arr['month'] . '/' . $monthyear_arr['year']; + $return_value = false; + FileDir::safe_exec("grep '" . $monthyear . "' " . escapeshellarg($logfile) . " | goaccess -o " . escapeshellarg($outputdir . '.tmp.json') . " -o " . escapeshellarg($outputdir . 'index.html') . " --html-report-title=" . escapeshellarg($caption) . " --log-format=" . $format . " - ", $return_value, ['|']); + + if (file_exists($outputdir . '.tmp.json')) { + $statscontent = json_decode(file_get_contents($outputdir . '.tmp.json'), true); + if ($statscontent) { + $returnval = $statscontent['general']['bandwidth'] ?? 0; + } + @unlink($outputdir . '.tmp.json'); + } + } + return $returnval; + } + /** * Function which make webalizer statistics and returns used traffic since last run * - * @param - * string Name of logfile - * @param - * string Place where stats should be build - * @param - * string Caption for webalizer output - * @return int Used traffic - * @author Florian Lippert (2003-2009) + * @param string $logfile Name of logfile + * @param string $outputdir Place where stats should be build + * @param string $caption Caption for webalizer output + * @param array $usersdomainlist + * + * @return float Used traffic */ - private static function callWebalizerGetTraffic($logfile, $outputdir, $caption, $usersdomainlist) + private static function callWebalizerGetTraffic($logfile, $outputdir, $caption, array $usersdomainlist = []) { $returnval = 0; @@ -738,7 +788,7 @@ class TrafficCron extends FroxlorCron // as we check for the config-model awstats will only parse // 'real' domains and no subdomains which are aliases in the // model-config-file. - $returnval += self::awstatsDoSingleDomain($singledomain, $outputdir); + $returnval += self::awstatsDoSingleDomain($singledomain, $outputdir, $current_stamp); } /** @@ -774,7 +824,7 @@ class TrafficCron extends FroxlorCron return floatval($returnval); } - private static function awstatsDoSingleDomain($domain, $outputdir) + private static function awstatsDoSingleDomain($domain, $outputdir, $current_stamp) { $returnval = 0; @@ -799,7 +849,7 @@ class TrafficCron extends FroxlorCron } FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Running awstats_buildstaticpages.pl for domain '" . $domain . "' (Output: '" . $staticOutputdir . "')"); - FileDir::safe_exec($awbsp . ' -awstatsprog=' . escapeshellarg($awprog) . ' -update -month=' . date('m') . ' -year=' . date('Y') . ' -config=' . $domain . ' -dir=' . escapeshellarg($staticOutputdir)); + FileDir::safe_exec($awbsp . ' -awstatsprog=' . escapeshellarg($awprog) . ' -update -month=' . date('m', $current_stamp) . ' -year=' . date('Y', $current_stamp) . ' -config=' . $domain . ' -dir=' . escapeshellarg($staticOutputdir)); // update our awstats index files self::awstatsGenerateIndex($domain, $outputdir); diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php index bed653b4..01297934 100644 --- a/lib/Froxlor/Froxlor.php +++ b/lib/Froxlor/Froxlor.php @@ -34,7 +34,7 @@ final class Froxlor const VERSION = '2.0.0-beta1'; // Database version (YYYYMMDDC where C is a daily counter) - const DBVERSION = '202112310'; + const DBVERSION = '202211030'; // Distribution branding-tag (used for Debian etc.) const BRANDING = ''; diff --git a/lib/Froxlor/Http/Statistics.php b/lib/Froxlor/Http/Statistics.php index 48cf7e77..33dacbf4 100644 --- a/lib/Froxlor/Http/Statistics.php +++ b/lib/Froxlor/Http/Statistics.php @@ -148,12 +148,7 @@ class Statistics } // get correct directory - $dir = $row['documentroot']; - if (Settings::Get('system.awstats_enabled') == '1') { - $dir .= '/awstats/'; - } else { - $dir .= '/webalizer/'; - } + $dir = $row['documentroot'] . '/' . Settings::Get('system.traffictool') . '/'; // only run chown if directory exists if (file_exists($dir)) { diff --git a/lib/Froxlor/Install/Install/Core.php b/lib/Froxlor/Install/Install/Core.php index bbc9b5dc..95cd118f 100644 --- a/lib/Froxlor/Install/Install/Core.php +++ b/lib/Froxlor/Install/Install/Core.php @@ -661,7 +661,7 @@ class Core private function createJsonArray() { - $system_params = ["cron", "libnssextrausers", "logrotate"]; + $system_params = ["cron", "libnssextrausers", "logrotate", "goaccess"]; if ($this->validatedData['webserver_backend'] == 'php-fpm') { $system_params[] = 'php-fpm'; } elseif ($this->validatedData['webserver_backend'] == 'fcgid') { diff --git a/lib/Froxlor/Settings/Store.php b/lib/Froxlor/Settings/Store.php index dc855220..43252f81 100644 --- a/lib/Froxlor/Settings/Store.php +++ b/lib/Froxlor/Settings/Store.php @@ -469,4 +469,23 @@ class Store } return $value; } + + public static function storeSettingUpdateTrafficTool($fieldname, $fielddata, $newfieldvalue) + { + $returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue); + + if ($returnvalue !== false && is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] == 'system' && isset($fielddata['varname']) && $fielddata['varname'] == 'traffictool' && $newfieldvalue != $fielddata['value']) { + $oldpath = '/'.$fielddata['value'].'/'; + $newpath = '/'.$newfieldvalue.'/'; + $upd_stmt = Database::query(" + UPDATE `" . TABLE_PANEL_HTPASSWDS . "` SET `path` = :newpath WHERE `path` = :oldpath + "); + Database::pexecute($upd_stmt, [ + 'newpath' => $newpath, + 'oldpath' => $oldpath + ]); + } + + return $returnvalue; + } } diff --git a/lib/Froxlor/UI/Callbacks/Domain.php b/lib/Froxlor/UI/Callbacks/Domain.php index 4ea22f7b..0bac2390 100644 --- a/lib/Froxlor/UI/Callbacks/Domain.php +++ b/lib/Froxlor/UI/Callbacks/Domain.php @@ -81,11 +81,8 @@ class Domain $result .= '' . $attributes['data'] . ''; // check for statistics if parentdomainid==0 to show stats-link for customers if ((int)UI::getCurrentUser()['adminsession'] == 0 && $attributes['fields']['parentdomainid'] == 0) { - $statsapp = 'webalizer'; - if (Settings::Get('system.awstats_enabled') == '1') { - $statsapp = 'awstats'; - } - $result .= ' '; + $statsapp = Settings::Get('system.traffictool'); + $result .= ' '; } if ($attributes['fields']['registration_date'] != '') { $result .= '
' . lng('domains.registration_date') . ': ' . $attributes['fields']['registration_date'] . ''; diff --git a/lib/configfiles/bionic.xml b/lib/configfiles/bionic.xml index db899f82..79778f4a 100644 --- a/lib/configfiles/bionic.xml +++ b/lib/configfiles/bionic.xml @@ -4579,9 +4579,19 @@ UPLOADGID= + + + + + + + + + title="Awstats (traffic analyzer)"> diff --git a/lib/configfiles/bookworm.xml b/lib/configfiles/bookworm.xml index a99fd877..1ae98a31 100644 --- a/lib/configfiles/bookworm.xml +++ b/lib/configfiles/bookworm.xml @@ -3218,9 +3218,19 @@ UPLOADGID= + + + + + + + + + title="Awstats (traffic analyzer)"> diff --git a/lib/configfiles/bullseye.xml b/lib/configfiles/bullseye.xml index 64433043..bcaf8463 100644 --- a/lib/configfiles/bullseye.xml +++ b/lib/configfiles/bullseye.xml @@ -4790,9 +4790,19 @@ UPLOADGID= + + + + + + + + + title="Awstats (traffic analyzer)"> diff --git a/lib/configfiles/buster.xml b/lib/configfiles/buster.xml index ab76b0b0..c94b14b3 100644 --- a/lib/configfiles/buster.xml +++ b/lib/configfiles/buster.xml @@ -4781,9 +4781,19 @@ UPLOADGID= + + + + + + + + + title="Awstats (traffic analyzer)"> diff --git a/lib/configfiles/focal.xml b/lib/configfiles/focal.xml index 6831c6ef..51f9d590 100644 --- a/lib/configfiles/focal.xml +++ b/lib/configfiles/focal.xml @@ -3996,9 +3996,19 @@ UPLOADGID= + + + + + + + + + title="Awstats (traffic analyzer)"> diff --git a/lib/configfiles/gentoo.xml b/lib/configfiles/gentoo.xml index ddf594a3..e14792c4 100644 --- a/lib/configfiles/gentoo.xml +++ b/lib/configfiles/gentoo.xml @@ -3664,9 +3664,19 @@ account required pam_mysql.so user= passwd= + + + + + + + + + title="Awstats (traffic analyzer)"> diff --git a/lib/configfiles/jammy.xml b/lib/configfiles/jammy.xml index 5311eefe..8c960709 100644 --- a/lib/configfiles/jammy.xml +++ b/lib/configfiles/jammy.xml @@ -3996,9 +3996,19 @@ UPLOADGID= + + + + + + + + + title="Awstats (traffic analyzer)"> diff --git a/lng/de.lng.php b/lng/de.lng.php index 7e83832e..d9fb7d06 100644 --- a/lng/de.lng.php +++ b/lng/de.lng.php @@ -1535,8 +1535,6 @@ Vielen Dank, Ihr Administrator', 'description' => 'Der Inhalt dieses Feldes wird in die 05_froxlor_dirfix_nofcgid.conf Apache Konfigurationsdatei eingefügt. Wenn leer werden folgende Standardwerte verwendet:

apache >=2.4
Require all granted
AllowOverride All


apache <=2.2
Order allow,deny
allow from all
', ], 'decimal_places' => 'Nachkommastellen bei der Ausgabe von Traffic/Webspace', - 'webalizer_enabled' => 'Nutze Webalizer-Statistiken', - 'awstats_enabled' => 'Nutze AWStats-Statistiken', 'selfdns' => [ 'title' => 'Manuelle DNS-Einstellungen für Domains', ], @@ -2040,6 +2038,9 @@ Vielen Dank, Ihr Administrator', 'title' => 'froxlor Update Kanal', 'description' => 'Wähle den bevorzugten Update Kanal. Standard ist "stable"', ], + 'traffictool' => [ + 'toolselect' => 'Traffic Analyzer', + ], ], 'spf' => [ 'use_spf' => 'Aktiviere SPF für Domains?', diff --git a/lng/en.lng.php b/lng/en.lng.php index 658a38e2..b54196f4 100644 --- a/lng/en.lng.php +++ b/lng/en.lng.php @@ -1652,8 +1652,6 @@ Yours sincerely, your administrator', 'description' => 'The content of this field will be included into the domain vHost container directly. You can use the following variables:
{DOMAIN}, {DOCROOT}, {CUSTOMER}, {IP}, {PORT}, {SCHEME}, {FPMSOCKET} (if applicable)
Attention: The code won\'t be checked for any errors. If it contains errors, webserver might not start again!', ], 'decimal_places' => 'Number of decimal places in traffic/webspace output', - 'webalizer_enabled' => 'Enable webalizer statistics', - 'awstats_enabled' => 'Enable AWstats statistics', 'selfdns' => [ 'title' => 'Customer domain dns settings', ], @@ -2159,6 +2157,12 @@ Yours sincerely, your administrator', ], 'uc_stable' => 'stable', 'uc_testing' => 'testing', + 'traffictool' => [ + 'toolselect' => 'Traffic analyzer', + 'webalizer' => 'Webalizer', + 'awstats' => 'AWStats', + 'goaccess' => 'goacccess' + ], ], 'spf' => [ 'use_spf' => 'Activate SPF for domains?', diff --git a/templates/Froxlor/settings/configuration.html.twig b/templates/Froxlor/settings/configuration.html.twig index a4ec1d64..2e31b3d4 100644 --- a/templates/Froxlor/settings/configuration.html.twig +++ b/templates/Froxlor/settings/configuration.html.twig @@ -46,7 +46,7 @@
{% set recommended = false %} {% if - (dtype == 'awstats' and get_setting('system.awstats_enabled') == '1') or + (dtype == get_setting('system.traffictool')) or (dtype == 'libnssextrausers' and (get_setting('system.mod_fcgid') == '1' or get_setting('phpfpm.enabled') == '1' or get_setting('system.apacheitksupport') == '1')) or (dtype == 'logrotate') or (dtype == 'fcgid' and get_setting('system.mod_fcgid') == '1') or