From 5de2af21516f28817ff0a7d6274142e26e3e1253 Mon Sep 17 00:00:00 2001
From: mcramer <m.cramer@pixcept.de>
Date: Thu, 22 Aug 2013 08:42:24 -0400
Subject: [PATCH] - Implemented: New cron class and split up cron_daily - Implemented: FS#3110 - Turn monitoring module into cron jobs
---
server/lib/classes/monitor_tools.inc.php | 1406 ---------
server/lib/classes/functions.inc.php | 398 ++
server/lib/classes/cron.d/100-monitor_mem_usage.inc.php | 124
server/lib/classes/cronjob.inc.php | 158 +
server/lib/classes/cron.d/100-monitor_server.inc.php | 133
server/lib/classes/cron.d/100-monitor_mail_log.inc.php | 181 +
server/lib/classes/cron.d/100-monitor_os_version.inc.php | 112
server/lib/classes/cron.d/200-logfiles.inc.php | 271 +
server/cron.php | 90
install/sql/ispconfig3.sql | 16
server/lib/classes/cron.d/100-monitor_hd_quota.inc.php | 162 +
server/lib/classes/cron.d/100-monitor_mail_queue.inc.php | 138
server/lib/classes/cron.d/100-monitor_rkhunter.inc.php | 127
server/lib/classes/cron.d/100-monitor_raid.inc.php | 263 +
server/lib/classes/cron.d/100-monitor_clamav_log.inc.php | 179 +
server/lib/classes/cron.d/300-quota_notify.inc.php | 479 +++
server/cron_daily.sh | 15
server/lib/classes/cron.d/100-monitor_openvz.inc.php | 183 +
server/lib/classes/cron.d/150-webalizer.inc.php | 142
server/lib/classes/cron.d/100-monitor_disk_usage.inc.php | 166 +
server/lib/classes/cron.d/150-awstats.inc.php | 183 +
server/lib/classes/cron.d/500-backup.inc.php | 330 ++
server/lib/classes/cron.d/100-monitor_system_update.inc.php | 208 +
server/lib/classes/cron.inc.php | 271 +
server/lib/classes/cron.d/100-monitor_iptables.inc.php | 132
server/lib/classes/cron.d/100-monitor_syslog.inc.php | 153 +
server/cron.sh | 12
server/lib/classes/cron.d/100-monitor_ispconfig_log.inc.php | 146 +
server/lib/classes/libdatetime.inc.php | 479 +++
server/lib/classes/cron.d/100-monitor_email_quota.inc.php | 149 +
server/lib/classes/cron.d/100-monitor_services.inc.php | 94
server/lib/classes/cron.d/400-openvz.inc.php | 83
/dev/null | 870 ------
server/lib/classes/cron.d/100-monitor_mongodb.inc.php | 127
server/lib/classes/cron.d/100-mailbox_stats.inc.php | 269 +
server/lib/classes/cron.d/100-monitor_cpu.inc.php | 136
server/lib/classes/cron.d/100-monitor_fail2ban.inc.php | 127
server/lib/classes/cron.d/100-monitor_ispconfig_version.inc.php | 110
38 files changed, 6,373 insertions(+), 2,249 deletions(-)
diff --git a/install/sql/ispconfig3.sql b/install/sql/ispconfig3.sql
index 8480e76..c562c07 100644
--- a/install/sql/ispconfig3.sql
+++ b/install/sql/ispconfig3.sql
@@ -1429,6 +1429,22 @@
`value` varchar(255) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `sys_cron`
+--
+
+CREATE TABLE IF NOT EXISTS `sys_cron` (
+ `name` varchar(50) NOT NULL,
+ `last_run` datetime NULL DEFAULT NULL,
+ `next_run` datetime NULL DEFAULT NULL,
+ `running` tinyint(1) UNSIGNED NOT NULL DEFAULT '0',
+ PRIMARY KEY (`name`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+
-- --------------------------------------------------------
--
diff --git a/server/cron.php b/server/cron.php
new file mode 100644
index 0000000..ce7a26f
--- /dev/null
+++ b/server/cron.php
@@ -0,0 +1,90 @@
+<?php
+
+/*
+Copyright (c) 2007-2012, Till Brehm, projektfarm Gmbh
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+define('SCRIPT_PATH', dirname($_SERVER["SCRIPT_FILENAME"]));
+require(SCRIPT_PATH."/lib/config.inc.php");
+require(SCRIPT_PATH."/lib/app.inc.php");
+
+set_time_limit(0);
+ini_set('error_reporting', E_ALL & ~E_NOTICE);
+
+// make sure server_id is always an int
+$conf['server_id'] = intval($conf['server_id']);
+
+
+// Load required base-classes
+$app->uses('ini_parser,file,services,getconf,system,cron,functions');
+$app->load('libdatetime,cronjob');
+
+
+// read all cron jobs
+$path = SCRIPT_PATH . '/lib/classes/cron.d';
+if(!is_dir($path)) die('Cron path missing!');
+$files = array();
+$d = opendir($path);
+while($f = readdir($d)) {
+ $file_path = $path . '/' . $f;
+ if($f === '.' || $f === '..' || !is_file($file_path)) continue;
+ if(substr($f, strrpos($f, '.')) !== '.php') continue;
+ $files[] = $f;
+}
+closedir($d);
+
+// sort in alphabetical order, so we can use prefixes like 000-xxx
+sort($files);
+
+foreach($files as $f) {
+ $name = substr($f, 0, strpos($f, '.'));
+ if(preg_match('/^\d+\-(.*)$/', $name, $match)) $name = $match[1]; // strip numerical prefix from file name
+
+ include($path . '/' . $f);
+ $class_name = 'cronjob_' . $name;
+
+ if(class_exists($class_name, false)) {
+ $cronjob = new $class_name();
+ if(get_parent_class($cronjob) !== 'cronjob') {
+ print 'Invalid class ' . $class_name . ' not extending class cronjob (' . get_parent_class($cronjob) . ')!' . "\n";
+ unset($cronjob);
+ continue;
+ }
+ print 'Included ' . $class_name . ' from ' . $file_path . ' -> will now run job.' . "\n";
+
+ $cronjob->run();
+
+ print 'run job (' . $class_name . ') done.' . "\n";
+
+ unset($cronjob);
+ }
+}
+unset($files);
+
+die("finished.\n");
+
+?>
diff --git a/server/cron.sh b/server/cron.sh
new file mode 100644
index 0000000..281bb13
--- /dev/null
+++ b/server/cron.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin
+
+if [ -f /usr/local/ispconfig/server/lib/php.ini ]; then
+ PHPINIOWNER=`stat -c %U /usr/local/ispconfig/server/lib/php.ini`
+ if [ $PHPINIOWNER == 'root' ] || [ $PHPINIOWNER == 'ispconfig' ]; then
+ export PHPRC=/usr/local/ispconfig/server/lib
+ fi
+fi
+
+/usr/bin/php -q /usr/local/ispconfig/server/cron.php
diff --git a/server/cron_daily.php b/server/cron_daily.php
deleted file mode 100644
index 029c4f3..0000000
--- a/server/cron_daily.php
+++ /dev/null
@@ -1,1346 +0,0 @@
-<?php
-
-/*
-Copyright (c) 2007-2012, Till Brehm, projektfarm Gmbh
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- * 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.
- * Neither the name of ISPConfig nor the names of its contributors
- may be used to endorse or promote products derived from this software without
- specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
-*/
-
-define('SCRIPT_PATH', dirname($_SERVER["SCRIPT_FILENAME"]));
-require(SCRIPT_PATH."/lib/config.inc.php");
-require(SCRIPT_PATH."/lib/app.inc.php");
-
-set_time_limit(0);
-ini_set('error_reporting', E_ALL & ~E_NOTICE);
-
-// make sure server_id is always an int
-$conf['server_id'] = intval($conf['server_id']);
-
-
-// Load required base-classes
-$app->uses('ini_parser,file,services,getconf,system');
-
-
-#######################################################################################################
-// store the mailbox statistics in the database
-#######################################################################################################
-
-$parse_mail_log = false;
-$sql = "SELECT mailuser_id,maildir FROM mail_user WHERE server_id = ".$conf['server_id'];
-$records = $app->db->queryAllRecords($sql);
-if(count($records) > 0) $parse_mail_log = true;
-
-foreach($records as $rec) {
- if(@is_file($rec['maildir'].'/ispconfig_mailsize')) {
- $parse_mail_log = false;
-
- // rename file
- rename($rec['maildir'].'/ispconfig_mailsize',$rec['maildir'].'/ispconfig_mailsize_save');
-
- // Read the file
- $lines = file($rec['maildir'].'/ispconfig_mailsize_save');
- $mail_traffic = 0;
- foreach($lines as $line) {
- $mail_traffic += intval($line);
- }
- unset($lines);
-
- // Delete backup file
- if(@is_file($rec['maildir'].'/ispconfig_mailsize_save')) unlink($rec['maildir'].'/ispconfig_mailsize_save');
-
- // Save the traffic stats in the sql database
- $tstamp = date('Y-m');
-
- $sql = "SELECT * FROM mail_traffic WHERE month = '$tstamp' AND mailuser_id = ".$rec['mailuser_id'];
- $tr = $app->dbmaster->queryOneRecord($sql);
-
- $mail_traffic += $tr['traffic'];
- if($tr['traffic_id'] > 0) {
- $sql = "UPDATE mail_traffic SET traffic = $mail_traffic WHERE traffic_id = ".$tr['traffic_id'];
- } else {
- $sql = "INSERT INTO mail_traffic (month,mailuser_id,traffic) VALUES ('$tstamp',".$rec['mailuser_id'].",$mail_traffic)";
- }
- $app->dbmaster->query($sql);
- //echo $sql;
-
- }
-
-}
-
-if($parse_mail_log == true) {
- $mailbox_traffic = array();
- $mail_boxes = array();
- $mail_rewrites = array(); // we need to read all mail aliases and forwards because the address in amavis is not always the mailbox address
-
- function parse_mail_log_line($line) {
- //Oct 31 17:35:48 mx01 amavis[32014]: (32014-05) Passed CLEAN, [IPv6:xxxxx] [IPv6:xxxxx] <xxx@yyyy> -> <aaaa@bbbb>, Message-ID: <xxxx@yyyyy>, mail_id: xxxxxx, Hits: -1.89, size: 1591, queued_as: xxxxxxx, 946 ms
-
- if(preg_match('/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+[^ ]+\s+amavis.* <([^>]+)>\s+->\s+((<[^>]+>,)+) .*Message-ID:\s+<([^>]+)>.* size:\s+(\d+),.*$/', $line, $matches) == false) return false;
-
- $timestamp = strtotime($matches[1]);
- if(!$timestamp) return false;
-
- $to = array();
- $recipients = explode(',', $matches[3]);
- foreach($recipients as $recipient) {
- $recipient = substr($recipient, 1, -1);
- if(!$recipient || $recipient == $matches[2]) continue;
- $to[] = $recipient;
- }
-
- return array('line' => $line, 'timestamp' => $timestamp, 'size' => $matches[6], 'from' => $matches[2], 'to' => $to, 'message-id' => $matches[5]);
- }
-
- function add_mailbox_traffic(&$traffic_array, $address, $traffic) {
- global $mail_boxes, $mail_rewrites;
-
- $address = strtolower($address);
-
- if(in_array($address, $mail_boxes) == true) {
- if(!isset($traffic_array[$address])) $traffic_array[$address] = 0;
- $traffic_array[$address] += $traffic;
- } elseif(array_key_exists($address, $mail_rewrites)) {
- foreach($mail_rewrites[$address] as $address) {
- if(!isset($traffic_array[$address])) $traffic_array[$address] = 0;
- $traffic_array[$address] += $traffic;
- }
- } else {
- // this is not a local address - skip it
- }
- }
-
- $sql = "SELECT email FROM mail_user WHERE server_id = ".$conf['server_id'];
- $records = $app->db->queryAllRecords($sql);
- foreach($records as $record) {
- $mail_boxes[] = $record['email'];
- }
- $sql = "SELECT source, destination FROM mail_forwarding WHERE server_id = ".$conf['server_id'];
- $records = $app->db->queryAllRecords($sql);
- foreach($records as $record) {
- $targets = preg_split('/[\n,]+/', $record['destination']);
- foreach($targets as $target) {
- if(in_array($target, $mail_boxes)) {
- if(isset($mail_rewrites[$record['source']])) $mail_rewrites[$record['source']][] = $target;
- else $mail_rewrites[$record['source']] = array($target);
- }
- }
- }
-
- $state_file = dirname(__FILE__) . '/mail_log_parser.state';
- $prev_line = false;
- $last_line = false;
- $cur_line = false;
-
- if(file_exists($state_file)) {
- $prev_line = parse_mail_log_line(trim(file_get_contents($state_file)));
- //if($prev_line) echo "continuing from previous run, log position: " . $prev_line['message-id'] . " at " . strftime('%d.%m.%Y %H:%M:%S', $prev_line['timestamp']) . "\n";
- }
-
- if(file_exists('/var/log/mail.log')) {
- $fp = fopen('/var/log/mail.log', 'r');
- //echo "Parsing mail.log...\n";
- $l = 0;
- while($line = fgets($fp, 8192)) {
- $l++;
- //if($l % 1000 == 0) echo "\rline $l";
- $cur_line = parse_mail_log_line($line);
- if(!$cur_line) continue;
-
- if($prev_line) {
- // check if this line has to be processed
- if($cur_line['timestamp'] < $prev_line['timestamp']) {
- $parse_mail_log = false; // we do not need to parse the second file!
- continue; // already processed
- } elseif($cur_line['timestamp'] == $prev_line['timestamp'] && $cur_line['message-id'] == $prev_line['message-id']) {
- $parse_mail_log = false; // we do not need to parse the second file!
- $prev_line = false; // this line has already been processed but the next one has to be!
- continue;
- }
- }
-
- add_mailbox_traffic($mailbox_traffic, $cur_line['from'], $cur_line['size']);
- foreach($cur_line['to'] as $to) {
- add_mailbox_traffic($mailbox_traffic, $to, $cur_line['size']);
- }
- $last_line = $line; // store for the state file
- }
- fclose($fp);
- //echo "\n";
- }
-
- if($parse_mail_log == true && file_exists('/var/log/mail.log.1')) {
- $fp = fopen('/var/log/mail.log.1', 'r');
- //echo "Parsing mail.log.1...\n";
- $l = 0;
- while($line = fgets($fp, 8192)) {
- $l++;
- //if($l % 1000 == 0) echo "\rline $l";
- $cur_line = parse_mail_log_line($line);
- if(!$cur_line) continue;
-
- if($prev_line) {
- // check if this line has to be processed
- if($cur_line['timestamp'] < $prev_line['timestamp']) continue; // already processed
- if($cur_line['timestamp'] == $prev_line['timestamp'] && $cur_line['message-id'] == $prev_line['message-id']) {
- $prev_line = false; // this line has already been processed but the next one has to be!
- continue;
- }
- }
-
- add_mailbox_traffic($mailbox_traffic, $cur_line['from'], $cur_line['size']);
- foreach($cur_line['to'] as $to) {
- add_mailbox_traffic($mailbox_traffic, $to, $cur_line['size']);
- }
- }
- fclose($fp);
- //echo "\n";
- }
- unset($mail_rewrites);
- unset($mail_boxes);
-
- // Save the traffic stats in the sql database
- $tstamp = date('Y-m');
- $sql = "SELECT mailuser_id,email FROM mail_user WHERE server_id = ".$conf['server_id'];
- $records = $app->db->queryAllRecords($sql);
- foreach($records as $rec) {
- if(array_key_exists($rec['email'], $mailbox_traffic)) {
- $sql = "SELECT * FROM mail_traffic WHERE month = '$tstamp' AND mailuser_id = ".$rec['mailuser_id'];
- $tr = $app->dbmaster->queryOneRecord($sql);
-
- $mail_traffic = $tr['traffic'] + $mailbox_traffic[$rec['email']];
- if($tr['traffic_id'] > 0) {
- $sql = "UPDATE mail_traffic SET traffic = $mail_traffic WHERE traffic_id = ".$tr['traffic_id'];
- } else {
- $sql = "INSERT INTO mail_traffic (month,mailuser_id,traffic) VALUES ('$tstamp',".$rec['mailuser_id'].",$mail_traffic)";
- }
- $app->dbmaster->query($sql);
- //echo $sql;
- }
- }
-
- unset($mailbox_traffic);
- if($last_line) file_put_contents($state_file, $last_line);
-}
-
-#######################################################################################################
-// Create webalizer statistics
-#######################################################################################################
-
-function setConfigVar( $filename, $varName, $varValue, $append = 0 ) {
- if($lines = @file($filename)) {
- $out = '';
- $found = 0;
- foreach($lines as $line) {
- @list($key, $value) = preg_split('/[\t= ]+/', $line, 2);
- if($key == $varName) {
- $out .= $varName.' '.$varValue."\n";
- $found = 1;
- } else {
- $out .= $line;
- }
- }
- if($found == 0) {
- //* add \n if the last line does not end with \n or \r
- if(substr($out,-1) != "\n" && substr($out,-1) != "\r") $out .= "\n";
- //* add the new line at the end of the file
- if($append == 1) $out .= $varName.' '.$varValue."\n";
- }
-
- file_put_contents($filename,$out);
- }
-}
-
-
-$sql = "SELECT domain_id, domain, document_root, web_folder, type, parent_domain_id FROM web_domain WHERE (type = 'vhost' or type = 'vhostsubdomain') and stats_type = 'webalizer' AND server_id = ".$conf['server_id'];
-$records = $app->db->queryAllRecords($sql);
-
-foreach($records as $rec) {
- //$yesterday = date('Ymd',time() - 86400);
- $yesterday = date('Ymd',strtotime("-1 day", time()));
-
- $log_folder = 'log';
- if($rec['type'] == 'vhostsubdomain') {
- $tmp = $app->db->queryOneRecord('SELECT `domain` FROM web_domain WHERE domain_id = '.intval($rec['parent_domain_id']));
- $subdomain_host = preg_replace('/^(.*)\.' . preg_quote($tmp['domain'], '/') . '$/', '$1', $rec['domain']);
- if($subdomain_host == '') $subdomain_host = 'web'.$rec['domain_id'];
- $log_folder .= '/' . $subdomain_host;
- unset($tmp);
- }
- $logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/'.$yesterday.'-access.log');
- if(!@is_file($logfile)) {
- $logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/'.$yesterday.'-access.log.gz');
- if(!@is_file($logfile)) {
- continue;
- }
- }
-
- $domain = escapeshellcmd($rec['domain']);
- $statsdir = escapeshellcmd($rec['document_root'].'/'.($rec['type'] == 'vhostsubdomain' ? $rec['web_folder'] : 'web').'/stats');
- $webalizer = '/usr/bin/webalizer';
- $webalizer_conf_main = '/etc/webalizer/webalizer.conf';
- $webalizer_conf = escapeshellcmd($rec['document_root'].'/log/webalizer.conf');
-
- if(is_file($statsdir.'/index.php')) unlink($statsdir.'/index.php');
-
- if(!@is_file($webalizer_conf)) {
- copy($webalizer_conf_main,$webalizer_conf);
- }
-
- if(@is_file($webalizer_conf)) {
- setConfigVar($webalizer_conf, 'Incremental', 'yes');
- setConfigVar($webalizer_conf, 'IncrementalName', $statsdir.'/webalizer.current');
- setConfigVar($webalizer_conf, 'HistoryName', $statsdir.'/webalizer.hist');
- }
-
-
- if(!@is_dir($statsdir)) mkdir($statsdir);
- exec("$webalizer -c $webalizer_conf -n $domain -s $domain -r $domain -q -T -p -o $statsdir $logfile");
-}
-
-#######################################################################################################
-// Create awstats statistics
-#######################################################################################################
-
-$sql = "SELECT domain_id, domain, document_root, web_folder, type, system_user, system_group, parent_domain_id FROM web_domain WHERE (type = 'vhost' or type = 'vhostsubdomain') and stats_type = 'awstats' AND server_id = ".$conf['server_id'];
-$records = $app->db->queryAllRecords($sql);
-
-$web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
-
-foreach($records as $rec) {
- //$yesterday = date('Ymd',time() - 86400);
- $yesterday = date('Ymd',strtotime("-1 day", time()));
-
- $log_folder = 'log';
- if($rec['type'] == 'vhostsubdomain') {
- $tmp = $app->db->queryOneRecord('SELECT `domain` FROM web_domain WHERE domain_id = '.intval($rec['parent_domain_id']));
- $subdomain_host = preg_replace('/^(.*)\.' . preg_quote($tmp['domain'], '/') . '$/', '$1', $rec['domain']);
- if($subdomain_host == '') $subdomain_host = 'web'.$rec['domain_id'];
- $log_folder .= '/' . $subdomain_host;
- unset($tmp);
- }
- $logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/'.$yesterday.'-access.log');
- if(!@is_file($logfile)) {
- $logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/'.$yesterday.'-access.log.gz');
- if(!@is_file($logfile)) {
- continue;
- }
- }
- $web_folder = ($rec['type'] == 'vhostsubdomain' ? $rec['web_folder'] : 'web');
- $domain = escapeshellcmd($rec['domain']);
- $statsdir = escapeshellcmd($rec['document_root'].'/'.$web_folder.'/stats');
- $awstats_pl = $web_config['awstats_pl'];
- $awstats_buildstaticpages_pl = $web_config['awstats_buildstaticpages_pl'];
-
- $awstats_conf_dir = $web_config['awstats_conf_dir'];
- $awstats_website_conf_file = $web_config['awstats_conf_dir'].'/awstats.'.$domain.'.conf';
-
- if(is_file($awstats_website_conf_file)) unlink($awstats_website_conf_file);
-
- $sql = "SELECT domain FROM web_domain WHERE (type = 'alias' OR type = 'subdomain') AND parent_domain_id = ".$rec['domain_id'];
- $aliases = $app->db->queryAllRecords($sql);
- $aliasdomain = '';
-
- if(is_array($aliases)) {
- foreach ($aliases as $alias) {
- $aliasdomain.= ' '.$alias['domain']. ' www.'.$alias['domain'];
- }
- }
-
- if(!is_file($awstats_website_conf_file)) {
- $awstats_conf_file_content = 'Include "'.$awstats_conf_dir.'/awstats.conf"
-LogFile="/var/log/ispconfig/httpd/'.$domain.'/yesterday-access.log"
-SiteDomain="'.$domain.'"
-HostAliases="www.'.$domain.' localhost 127.0.0.1'.$aliasdomain.'"';
- file_put_contents($awstats_website_conf_file,$awstats_conf_file_content);
- }
-
- if(!@is_dir($statsdir)) mkdir($statsdir);
- if(is_link('/var/log/ispconfig/httpd/'.$domain.'/yesterday-access.log')) unlink('/var/log/ispconfig/httpd/'.$domain.'/yesterday-access.log');
- symlink($logfile,'/var/log/ispconfig/httpd/'.$domain.'/yesterday-access.log');
-
- $awmonth = date("n");
- $awyear = date("Y");
-
- if (date("d") == 1) {
- $awmonth = date("m")-1;
- if (date("m") == 1) {
- $awyear = date("Y")-1;
- $awmonth = "12";
- }
- }
-
- // awstats_buildstaticpages.pl -update -config=mydomain.com -lang=en -dir=/var/www/domain.com/'.$web_folder.'/stats -awstatsprog=/path/to/awstats.pl
- // $command = "$awstats_buildstaticpages_pl -update -config='$domain' -lang=".$conf['language']." -dir='$statsdir' -awstatsprog='$awstats_pl'";
-
- $command = "$awstats_buildstaticpages_pl -month='$awmonth' -year='$awyear' -update -config='$domain' -lang=".$conf['language']." -dir='$statsdir' -awstatsprog='$awstats_pl'";
-
- if (date("d") == 2) {
- $awmonth = date("m")-1;
- if (date("m") == 1) {
- $awyear = date("Y")-1;
- $awmonth = "12";
- }
-
- $statsdirold = $statsdir."/".$awyear."-".$awmonth."/";
- mkdir($statsdirold);
- $files = scandir($statsdir);
- foreach ($files as $file) {
- if (substr($file,0,1) != "." && !is_dir("$statsdir"."/"."$file") && substr($file,0,1) != "w" && substr($file,0,1) != "i") copy("$statsdir"."/"."$file","$statsdirold"."$file");
- }
- }
-
-
- if($awstats_pl != '' && $awstats_buildstaticpages_pl != '' && fileowner($awstats_pl) == 0 && fileowner($awstats_buildstaticpages_pl) == 0) {
- exec($command);
- if(is_file($rec['document_root'].'/'.$web_folder.'/stats/index.html')) unlink($rec['document_root'].'/'.$web_folder.'/stats/index.html');
- rename($rec['document_root'].'/'.$web_folder.'/stats/awstats.'.$domain.'.html',$rec['document_root'].'/'.$web_folder.'/stats/awsindex.html');
- if(!is_file($rec['document_root']."/".$web_folder."/stats/index.php")) {
- if(file_exists("/usr/local/ispconfig/server/conf-custom/awstats_index.php.master")) {
- copy("/usr/local/ispconfig/server/conf-custom/awstats_index.php.master",$rec['document_root']."/".$web_folder."/stats/index.php");
- } else {
- copy("/usr/local/ispconfig/server/conf/awstats_index.php.master",$rec['document_root']."/".$web_folder."/stats/index.php");
- }
- }
-
- $app->log('Created awstats statistics with command: '.$command,LOGLEVEL_DEBUG);
- } else {
- $app->log("No awstats statistics created. Either $awstats_pl or $awstats_buildstaticpages_pl is not owned by root user.",LOGLEVEL_WARN);
- }
-
- if(is_file($rec['document_root']."/".$web_folder."/stats/index.php")) {
- chown($rec['document_root']."/".$web_folder."/stats/index.php",$rec['system_user']);
- chgrp($rec['document_root']."/".$web_folder."/stats/index.php",$rec['system_group']);
- }
-
-}
-
-
-#######################################################################################################
-// Make the web logfiles directories world readable to enable ftp access
-#######################################################################################################
-
-if(is_dir('/var/log/ispconfig/httpd')) exec('chmod +r /var/log/ispconfig/httpd/*');
-
-#######################################################################################################
-// Manage and compress web logfiles and create traffic statistics
-#######################################################################################################
-
-$sql = "SELECT domain_id, domain, type, document_root, web_folder, parent_domain_id FROM web_domain WHERE (type = 'vhost' or type = 'vhostsubdomain') AND server_id = ".$conf['server_id'];
-$records = $app->db->queryAllRecords($sql);
-foreach($records as $rec) {
-
- //* create traffic statistics based on yesterdays access log file
- $yesterday = date('Ymd',time() - 86400);
-
- $log_folder = 'log';
- if($rec['type'] == 'vhostsubdomain') {
- $tmp = $app->db->queryOneRecord('SELECT `domain` FROM web_domain WHERE domain_id = '.intval($rec['parent_domain_id']));
- $subdomain_host = preg_replace('/^(.*)\.' . preg_quote($tmp['domain'], '/') . '$/', '$1', $rec['domain']);
- if($subdomain_host == '') $subdomain_host = 'web'.$rec['domain_id'];
- $log_folder .= '/' . $subdomain_host;
- unset($tmp);
- }
-
- $logfile = $rec['document_root'].'/' . $log_folder . '/'.$yesterday.'-access.log';
- $total_bytes = 0;
-
- $handle = @fopen($logfile, "r");
- if ($handle) {
- while (($line = fgets($handle, 4096)) !== false) {
- if (preg_match('/^\S+ \S+ \S+ \[.*?\] "\S+.*?" \d+ (\d+) ".*?" ".*?"/', $line, $m)) {
- $total_bytes += intval($m[1]);
- }
- }
-
- //* Insert / update traffic in master database
- $traffic_date = date('Y-m-d',time() - 86400);
- $tmp = $app->dbmaster->queryOneRecord("select hostname from web_traffic where hostname='".$rec['domain']."' and traffic_date='".$traffic_date."'");
- if(is_array($tmp) && count($tmp) > 0) {
- $sql = "update web_traffic set traffic_bytes=traffic_bytes+"
- . $total_bytes
- . " where hostname='" . $rec['domain']
- . "' and traffic_date='" . $traffic_date . "'";
- } else {
- $sql = "insert into web_traffic (hostname, traffic_date, traffic_bytes) values ('".$rec['domain']."', '".$traffic_date."', '".$total_bytes."')";
- }
- $app->dbmaster->query($sql);
-
- fclose($handle);
- }
-
- $yesterday2 = date('Ymd',time() - 86400*2);
- $logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/'.$yesterday2.'-access.log');
-
- //* Compress logfile
- if(@is_file($logfile)) {
- // Compress yesterdays logfile
- exec("gzip -c $logfile > $logfile.gz");
- unlink($logfile);
- }
-
- // rotate and compress the error.log when it exceeds a size of 10 MB
- $logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/error.log');
- if(is_file($logfile) && filesize($logfile) > 10000000) {
- exec("gzip -c $logfile > $logfile.1.gz");
- exec("cat /dev/null > $logfile");
- }
-
- // delete logfiles after 30 days
- $month_ago = date('Ymd',time() - 86400 * 30);
- $logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/'.$month_ago.'-access.log.gz');
- if(@is_file($logfile)) {
- unlink($logfile);
- }
-
- //* Delete older Log files, in case that we missed them before due to serverdowntimes.
- $datepart = date('Ym',time() - 86400 * 31 * 2);
-
- $logfile = escapeshellcmd($rec['document_root']).'/' . $log_folder . '/'.$datepart.'*-access.log.gz';
- exec('rm -f '.$logfile);
-
- $logfile = escapeshellcmd($rec['document_root']).'/' . $log_folder . '/'.$datepart.'*-access.log';
- exec('rm -f '.$logfile);
-}
-
-//* Delete old logfiles in /var/log/ispconfig/httpd/ that were created by vlogger for the hostname of the server
-exec('hostname -f', $tmp_hostname);
-if($tmp_hostname[0] != '' && is_dir('/var/log/ispconfig/httpd/'.$tmp_hostname[0])) {
- exec('cd /var/log/ispconfig/httpd/'.$tmp_hostname[0]."; find . -mtime +30 -name '*.log' | xargs rm > /dev/null 2> /dev/null");
-}
-unset($tmp_hostname);
-
-#######################################################################################################
-// Rotate the ispconfig.log file
-#######################################################################################################
-
-// rotate the ispconfig.log when it exceeds a size of 10 MB
-$logfile = $conf['ispconfig_log_dir'].'/ispconfig.log';
-if(is_file($logfile) && filesize($logfile) > 10000000) {
- exec("gzip -c $logfile > $logfile.1.gz");
- exec("cat /dev/null > $logfile");
-}
-
-// rotate the cron.log when it exceeds a size of 10 MB
-$logfile = $conf['ispconfig_log_dir'].'/cron.log';
-if(is_file($logfile) && filesize($logfile) > 10000000) {
- exec("gzip -c $logfile > $logfile.1.gz");
- exec("cat /dev/null > $logfile");
-}
-
-// rotate the auth.log when it exceeds a size of 10 MB
-$logfile = $conf['ispconfig_log_dir'].'/auth.log';
-if(is_file($logfile) && filesize($logfile) > 10000000) {
- exec("gzip -c $logfile > $logfile.1.gz");
- exec("cat /dev/null > $logfile");
-}
-
-#######################################################################################################
-// Cleanup website tmp directories
-#######################################################################################################
-
-$sql = "SELECT domain_id, domain, document_root, system_user FROM web_domain WHERE server_id = ".$conf['server_id'];
-$records = $app->db->queryAllRecords($sql);
-$app->uses('system');
-if(is_array($records)) {
- foreach($records as $rec){
- $tmp_path = realpath(escapeshellcmd($rec['document_root'].'/tmp'));
- if($tmp_path != '' && strlen($tmp_path) > 10 && is_dir($tmp_path) && $app->system->is_user($rec['system_user'])){
- exec('cd '.$tmp_path."; find . -mtime +1 -name 'sess_*' | grep -v -w .no_delete | xargs rm > /dev/null 2> /dev/null");
- }
- }
-}
-
-#######################################################################################################
-// Cleanup logs in master database (only the "master-server")
-#######################################################################################################
-
-if ($app->dbmaster == $app->db) {
- /** 7 days */
- $tstamp = time() - (60*60*24*7);
-
- /*
- * Keep 7 days in sys_log
- * (we can delete the old items, because if they are OK, they don't interrest anymore
- * if they are NOT ok, the server will try to process them in 1 minute and so the
- * error appears again after 1 minute. So it is no problem to delete the old one!
- */
- $sql = "DELETE FROM sys_log WHERE tstamp < " . $tstamp . " AND server_id != 0";
- $app->dbmaster->query($sql);
-
- /*
- * Delete all remote-actions "done" and older than 7 days
- * ATTENTION: We have the same problem as described in cleaning the datalog. We must not
- * delete the last entry
- */
- $sql = "SELECT max(action_id) FROM sys_remoteaction";
- $res = $app->dbmaster->queryOneRecord($sql);
- $maxId = $res['max(action_id)'];
- $sql = "DELETE FROM sys_remoteaction " .
- "WHERE tstamp < " . $tstamp . " " .
- " AND action_state = 'ok' " .
- " AND action_id <" . intval($maxId);
- $app->dbmaster->query($sql);
-
- /*
- * The sys_datalog is more difficult.
- * 1) We have to keet ALL entries with
- * server_id=0, because they depend on ALL servers (even if they are not
- * actually in the system (and will be insered in 3 days or so).
- * 2) We have to keey ALL entries which are not actually precessed by the
- * server never mind how old they are!
- * 3) We have to keep the entry with the highest autoinc-id, because mysql calculates the
- * autoinc-id as "new value = max(row) +1" and does not store this in a separate table.
- * This means, if we delete to entry with the highest autoinc-value then this value is
- * reused as autoinc and so there are more than one entries with the same value (over
- * for example 4 Weeks). This is confusing for our system.
- * ATTENTION 2) and 3) is in some case NOT the same! so we have to check both!
- */
-
- /* First we need all servers and the last sys_datalog-id they processed */
- $sql = "SELECT server_id, updated FROM server ORDER BY server_id";
- $records = $app->dbmaster->queryAllRecords($sql);
-
- /* Then we need the highest value ever */
- $sql = "SELECT max(datalog_id) FROM sys_datalog";
- $res = $app->dbmaster->queryOneRecord($sql);
- $maxId = $res['max(datalog_id)'];
-
- /* Then delete server by server */
- foreach($records as $server) {
- $tmp_server_id = intval($server['server_id']);
- if($tmp_server_id > 0) {
- $sql = "DELETE FROM sys_datalog " .
- "WHERE tstamp < " . $tstamp .
- " AND server_id = " . intval($server['server_id']) .
- " AND datalog_id < " . intval($server['updated']) .
- " AND datalog_id < " . intval($maxId);
- }
-// echo $sql . "\n";
- $app->dbmaster->query($sql);
- }
-}
-
-#########
-// function for sending notification emails
-#########
-function send_notification_email($template, $placeholders, $recipients) {
- global $conf;
-
- if(!is_array($recipients) || count($recipients) < 1) return false;
- if(!is_array($placeholders)) $placeholders = array();
-
- if(file_exists($conf['rootpath'].'/conf-custom/mail/' . $template . '_'.$conf['language'].'.txt')) {
- $lines = file($conf['rootpath'].'/conf-custom/mail/' . $template . '_'.$conf['language'].'.txt');
- } elseif(file_exists($conf['rootpath'].'/conf-custom/mail/' . $template . '_en.txt')) {
- $lines = file($conf['rootpath'].'/conf-custom/mail/' . $template . '_en.txt');
- } elseif(file_exists($conf['rootpath'].'/conf/mail/' . $template . '_'.$conf['language'].'.txt')) {
- $lines = file($conf['rootpath'].'/conf/mail/' . $template . '_'.$conf['language'].'.txt');
- } else {
- $lines = file($conf['rootpath'].'/conf/mail/' . $template . '_en.txt');
- }
-
- //* get mail headers, subject and body
- $mailHeaders = '';
- $mailBody = '';
- $mailSubject = '';
- $inHeader = true;
- for($l = 0; $l < count($lines); $l++) {
- if($lines[$l] == '') {
- $inHeader = false;
- continue;
- }
- if($inHeader == true) {
- $parts = explode(':', $lines[$l], 2);
- if(strtolower($parts[0]) == 'subject') $mailSubject = trim($parts[1]);
- unset($parts);
- $mailHeaders .= trim($lines[$l]) . "\n";
- } else {
- $mailBody .= trim($lines[$l]) . "\n";
- }
- }
- $mailBody = trim($mailBody);
-
- //* Replace placeholders
- $mailHeaders = strtr($mailHeaders, $placeholders);
- $mailSubject = strtr($mailSubject, $placeholders);
- $mailBody = strtr($mailBody, $placeholders);
-
- for($r = 0; $r < count($recipients); $r++) {
- mail($recipients[$r], $mailSubject, $mailBody, $mailHeaders);
- }
-
- unset($mailSubject);
- unset($mailHeaders);
- unset($mailBody);
- unset($lines);
-
- return true;
-}
-
-
-#######################################################################################################
-// enforce traffic quota (run only on the "master-server")
-#######################################################################################################
-
-if ($app->dbmaster == $app->db) {
-
- $global_config = $app->getconf->get_global_config('mail');
-
- $current_month = date('Y-m');
-
- //* Check website traffic quota
- $sql = "SELECT sys_groupid,domain_id,domain,traffic_quota,traffic_quota_lock FROM web_domain WHERE (traffic_quota > 0 or traffic_quota_lock = 'y') and (type = 'vhost' OR type = 'vhostsubdomain')";
- $records = $app->db->queryAllRecords($sql);
- if(is_array($records)) {
- foreach($records as $rec) {
-
- $web_traffic_quota = $rec['traffic_quota'];
- $domain = $rec['domain'];
-
- // get the client
- /*
- $client_group_id = $rec["sys_groupid"];
- $client = $app->db->queryOneRecord("SELECT limit_traffic_quota,parent_client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
- $reseller = $app->db->queryOneRecord("SELECT limit_traffic_quota FROM client WHERE client_id = ".intval($client['parent_client_id']));
-
- $client_traffic_quota = intval($client['limit_traffic_quota']);
- $reseller_traffic_quota = intval($reseller['limit_traffic_quota']);
- */
-
- //* get the traffic
- $tmp = $app->db->queryOneRecord("SELECT SUM(traffic_bytes) As total_traffic_bytes FROM web_traffic WHERE traffic_date like '$current_month%' AND hostname = '$domain'");
- $web_traffic = round($tmp['total_traffic_bytes']/1024/1024);
-
- //* Website is over quota, we will disable it
- /*if( ($web_traffic_quota > 0 && $web_traffic > $web_traffic_quota) ||
- ($client_traffic_quota > 0 && $web_traffic > $client_traffic_quota) ||
- ($reseller_traffic_quota > 0 && $web_traffic > $reseller_traffic_quota)) {*/
- if($web_traffic_quota > 0 && $web_traffic > $web_traffic_quota) {
- $app->dbmaster->datalogUpdate('web_domain', "traffic_quota_lock = 'y',active = 'n'", 'domain_id', $rec['domain_id']);
- $app->log('Traffic quota for '.$rec['domain'].' exceeded. Disabling website.',LOGLEVEL_DEBUG);
-
- //* Send traffic notifications
- if($rec['traffic_quota_lock'] != 'y' && ($web_config['overtraffic_notify_admin'] == 'y' || $web_config['overtraffic_notify_client'] == 'y')) {
-
- $placeholders = array('{domain}' => $rec['domain'],
- '{admin_mail}' => ($global_config['admin_mail'] != ''? $global_config['admin_mail'] : 'root'));
-
- $recipients = array();
- //* send email to admin
- if($global_config['admin_mail'] != '' && $web_config['overtraffic_notify_admin'] == 'y') {
- $recipients[] = $global_config['admin_mail'];
- }
-
- //* Send email to client
- if($web_config['overtraffic_notify_client'] == 'y') {
- $client_group_id = $rec["sys_groupid"];
- $client = $app->db->queryOneRecord("SELECT client.email FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
- if($client['email'] != '') {
- $recipients[] = $client['email'];
- }
- }
-
- send_notification_email('web_traffic_notification', $placeholders, $recipients);
- }
-
- } else {
- //* unlock the website, if traffic is lower then quota
- if($rec['traffic_quota_lock'] == 'y') {
- $app->dbmaster->datalogUpdate('web_domain', "traffic_quota_lock = 'n',active = 'y'", 'domain_id', $rec['domain_id']);
- $app->log('Traffic quota for '.$rec['domain'].' ok again. Re-enabling website.',LOGLEVEL_DEBUG);
- }
- }
- }
- }
-
-
-}
-
-
-#######################################################################################################
-// send website quota warnings by email
-#######################################################################################################
-
-if ($app->dbmaster == $app->db) {
-
- $global_config = $app->getconf->get_global_config('mail');
-
- //* Check website disk quota
- $sql = "SELECT domain_id,sys_groupid,domain,system_user,last_quota_notification,DATEDIFF(CURDATE(), last_quota_notification) as `notified_before` FROM web_domain WHERE (type = 'vhost' OR type = 'vhostsubdomain')";
- $records = $app->db->queryAllRecords($sql);
- if(is_array($records) && !empty($records)) {
-
- $tmp_rec = $app->db->queryAllRecords("SELECT data from monitor_data WHERE type = 'harddisk_quota' ORDER BY created DESC");
- $monitor_data = array();
- if(is_array($tmp_rec)) {
- foreach ($tmp_rec as $tmp_mon) {
- $monitor_data = array_merge_recursive($monitor_data,unserialize($app->db->unquote($tmp_mon['data'])));
- }
- }
-
- foreach($records as $rec) {
-
- //$web_hd_quota = $rec['hd_quota'];
- $domain = $rec['domain'];
-
- $username = $rec['system_user'];
- $rec['used'] = $monitor_data['user'][$username]['used'];
- $rec['soft'] = $monitor_data['user'][$username]['soft'];
- $rec['hard'] = $monitor_data['user'][$username]['hard'];
- $rec['files'] = $monitor_data['user'][$username]['files'];
-
- if (!is_numeric($rec['used'])){
- if ($rec['used'][0] > $rec['used'][1]){
- $rec['used'] = $rec['used'][0];
- } else {
- $rec['used'] = $rec['used'][1];
- }
- }
- if (!is_numeric($rec['soft'])) $rec['soft']=$rec['soft'][1];
- if (!is_numeric($rec['hard'])) $rec['hard']=$rec['hard'][1];
- if (!is_numeric($rec['files'])) $rec['files']=$rec['files'][1];
-
- // used space ratio
- if($rec['soft'] > 0){
- $used_ratio = $rec['used']/$rec['soft'];
- } else {
- $used_ratio = 0;
- }
-
- $rec['ratio'] = number_format($used_ratio * 100, 2, '.', '').'%';
-
- if($rec['used'] > 1024) {
- $rec['used'] = round($rec['used'] / 1024,2).' MB';
- } else {
- if ($rec['used'] != '') $rec['used'] .= ' KB';
- }
-
- if($rec['soft'] > 1024) {
- $rec['soft'] = round($rec['soft'] / 1024,2).' MB';
- } elseif($rec['soft'] == 0){
- $rec['soft'] = '----';
- } else {
- $rec['soft'] .= ' KB';
- }
-
- if($rec['hard'] > 1024) {
- $rec['hard'] = round($rec['hard'] / 1024,2).' MB';
- } elseif($rec['hard'] == 0){
- $rec['hard'] = '----';
- } else {
- $rec['hard'] .= ' KB';
- }
-
- // send notifications only if 90% or more of the quota are used
- if($used_ratio < 0.9) {
- // reset notification date
- if($rec['last_quota_notification']) $app->dbmaster->datalogUpdate('web_domain', "last_quota_notification = NULL", 'domain_id', $rec['domain_id']);
-
- // send notification - everything ok again
- if($rec['last_quota_notification'] && $web_config['overquota_notify_onok'] == 'y' && ($web_config['overquota_notify_admin'] == 'y' || $web_config['overquota_notify_client'] == 'y')) {
- $placeholders = array('{domain}' => $rec['domain'],
- '{admin_mail}' => ($global_config['admin_mail'] != ''? $global_config['admin_mail'] : 'root'),
- '{used}' => $rec['used'],
- '{soft}' => $rec['soft'],
- '{hard}' => $rec['hard'],
- '{ratio}' => $rec['ratio']);
-
- $recipients = array();
-
- //* send email to admin
- if($global_config['admin_mail'] != '' && $web_config['overquota_notify_admin'] == 'y') {
- $recipients[] = $global_config['admin_mail'];
- }
-
- //* Send email to client
- if($web_config['overquota_notify_client'] == 'y') {
- $client_group_id = $rec["sys_groupid"];
- $client = $app->db->queryOneRecord("SELECT client.email FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
- if($client['email'] != '') {
- $recipients[] = $client['email'];
- }
- }
- send_notification_email('web_quota_ok_notification', $placeholders, $recipients);
- }
-
- continue;
- }
-
- // could a notification be sent?
- $send_notification = false;
- if(!$rec['last_quota_notification']) $send_notification = true; // not yet notified
- elseif($web_config['overquota_notify_freq'] > 0 && $rec['notified_before'] >= $web_config['overquota_notify_freq']) $send_notification = true;
-
- //* Send quota notifications
- if(($web_config['overquota_notify_admin'] == 'y' || $web_config['overquota_notify_client'] == 'y') && $send_notification == true) {
- $app->dbmaster->datalogUpdate('web_domain', "last_quota_notification = CURDATE()", 'domain_id', $rec['domain_id']);
-
- $placeholders = array('{domain}' => $rec['domain'],
- '{admin_mail}' => ($global_config['admin_mail'] != ''? $global_config['admin_mail'] : 'root'),
- '{used}' => $rec['used'],
- '{soft}' => $rec['soft'],
- '{hard}' => $rec['hard'],
- '{ratio}' => $rec['ratio']);
-
- $recipients = array();
-
- //* send email to admin
- if($global_config['admin_mail'] != '' && $web_config['overquota_notify_admin'] == 'y') {
- $recipients[] = $global_config['admin_mail'];
- }
-
- //* Send email to client
- if($web_config['overquota_notify_client'] == 'y') {
- $client_group_id = $rec["sys_groupid"];
- $client = $app->db->queryOneRecord("SELECT client.email FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
- if($client['email'] != '') {
- $recipients[] = $client['email'];
- }
- }
- send_notification_email('web_quota_notification', $placeholders, $recipients);
- }
- }
- }
-}
-
-
-#######################################################################################################
-// send mail quota warnings by email
-#######################################################################################################
-
-if ($app->dbmaster == $app->db) {
-
- $global_config = $app->getconf->get_global_config('mail');
- $mail_config = $app->getconf->get_server_config($conf['server_id'], 'mail');
-
- //* Check email quota
- $sql = "SELECT mailuser_id,sys_groupid,email,name,quota,last_quota_notification,DATEDIFF(CURDATE(), last_quota_notification) as `notified_before` FROM mail_user";
- $records = $app->db->queryAllRecords($sql);
- if(is_array($records) && !empty($records)) {
-
- $tmp_rec = $app->db->queryAllRecords("SELECT data from monitor_data WHERE type = 'email_quota' ORDER BY created DESC");
- $monitor_data = array();
- if(is_array($tmp_rec)) {
- foreach ($tmp_rec as $tmp_mon) {
- //$monitor_data = array_merge_recursive($monitor_data,unserialize($app->db->unquote($tmp_mon['data'])));
- $tmp_array = unserialize($app->db->unquote($tmp_mon['data']));
- if(is_array($tmp_array)) {
- foreach($tmp_array as $username => $data) {
- if(@!$monitor_data[$username]['used']) $monitor_data[$username]['used'] = $data['used'];
- }
- }
- }
- }
-
- foreach($records as $rec) {
-
- $email = $rec['email'];
-
- $rec['used'] = isset($monitor_data[$email]['used']) ? $monitor_data[$email]['used'] : array(1 => 0);
-
- if (!is_numeric($rec['used'])) $rec['used']=$rec['used'][1];
-
- // used space ratio
- if($rec['quota'] > 0){
- $used_ratio = $rec['used']/$rec['quota'];
- } else {
- $used_ratio = 0;
- }
-
- $rec['ratio'] = number_format($used_ratio * 100, 2, '.', '').'%';
-
- if($rec['quota'] > 0){
- $rec['quota'] = round($rec['quota'] / 1048576,4).' MB';
- } else {
- $rec['quota'] = '----';
- }
-
- if($rec['used'] < 1544000) {
- $rec['used'] = round($rec['used'] / 1024,4).' KB';
- } else {
- $rec['used'] = round($rec['used'] / 1048576,4).' MB';
- }
-
- // send notifications only if 90% or more of the quota are used
- if($used_ratio < 0.9) {
- // reset notification date
- if($rec['last_quota_notification']) $app->dbmaster->datalogUpdate('mail_user', "last_quota_notification = NULL", 'mailuser_id', $rec['mailuser_id']);
-
- // send notification - everything ok again
- if($rec['last_quota_notification'] && $mail_config['overquota_notify_onok'] == 'y' && ($mail_config['overquota_notify_admin'] == 'y' || $mail_config['overquota_notify_client'] == 'y')) {
- $placeholders = array('{email}' => $rec['email'],
- '{admin_mail}' => ($global_config['admin_mail'] != ''? $global_config['admin_mail'] : 'root'),
- '{used}' => $rec['used'],
- '{name}' => $rec['name'],
- '{quota}' => $rec['quota'],
- '{ratio}' => $rec['ratio']);
-
- $recipients = array();
- //* send email to admin
- if($global_config['admin_mail'] != '' && $mail_config['overquota_notify_admin'] == 'y') {
- $recipients[] = $global_config['admin_mail'];
- }
-
- //* Send email to client
- if($mail_config['overquota_notify_client'] == 'y') {
- $client_group_id = $rec["sys_groupid"];
- $client = $app->db->queryOneRecord("SELECT client.email FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
- if($client['email'] != '') {
- $recipients[] = $client['email'];
- }
- }
-
- send_notification_email('mail_quota_ok_notification', $placeholders, $recipients);
- }
-
- continue;
- }
-
- //* Send quota notifications
- // could a notification be sent?
- $send_notification = false;
- if(!$rec['last_quota_notification']) $send_notification = true; // not yet notified
- elseif($mail_config['overquota_notify_freq'] > 0 && $rec['notified_before'] >= $mail_config['overquota_notify_freq']) $send_notification = true;
-
- if(($mail_config['overquota_notify_admin'] == 'y' || $mail_config['overquota_notify_client'] == 'y') && $send_notification == true) {
- $app->dbmaster->datalogUpdate('mail_user', "last_quota_notification = CURDATE()", 'mailuser_id', $rec['mailuser_id']);
-
- $placeholders = array('{email}' => $rec['email'],
- '{admin_mail}' => ($global_config['admin_mail'] != ''? $global_config['admin_mail'] : 'root'),
- '{used}' => $rec['used'],
- '{name}' => $rec['name'],
- '{quota}' => $rec['quota'],
- '{ratio}' => $rec['ratio']);
-
- $recipients = array();
- //* send email to admin
- if($global_config['admin_mail'] != '' && $mail_config['overquota_notify_admin'] == 'y') {
- $recipients[] = $global_config['admin_mail'];
- }
-
- //* Send email to client
- if($mail_config['overquota_notify_client'] == 'y') {
- $client_group_id = $rec["sys_groupid"];
- $client = $app->db->queryOneRecord("SELECT client.email FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
- if($client['email'] != '') {
- $recipients[] = $client['email'];
- }
- }
-
- send_notification_email('mail_quota_notification', $placeholders, $recipients);
- }
- }
- }
-}
-
-
-#######################################################################################################
-// deactivate virtual servers (run only on the "master-server")
-#######################################################################################################
-
-if ($app->dbmaster == $app->db) {
- $current_date = date('Y-m-d');
-
- //* Check which virtual machines have to be deactivated
- $sql = "SELECT * FROM openvz_vm WHERE active = 'y' AND active_until_date != '0000-00-00' AND active_until_date < '$current_date'";
- $records = $app->db->queryAllRecords($sql);
- if(is_array($records)) {
- foreach($records as $rec) {
- $app->dbmaster->datalogUpdate('openvz_vm', "active = 'n'", 'vm_id', $rec['vm_id']);
- $app->log('Virtual machine active date expired. Disabling VM '.$rec['veid'],LOGLEVEL_DEBUG);
- }
- }
-
-
-}
-
-#######################################################################################################
-// Create website backups
-#######################################################################################################
-function formatBytes($size, $precision = 2) {
- $base=log($size)/log(1024);
- $suffixes=array('','k','M','G','T');
- return round(pow(1024,$base-floor($base)),$precision).$suffixes[floor($base)];
-}
-
-$server_config = $app->getconf->get_server_config($conf['server_id'], 'server');
-$backup_dir = $server_config['backup_dir'];
-$backup_mode = $server_config['backup_mode'];
-if($backup_mode == '') $backup_mode = 'userzip';
-
-$web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
-$http_server_user = $web_config['user'];
-
-if($backup_dir != '') {
-
- if(isset($server_config['backup_dir_ftpread']) && $server_config['backup_dir_ftpread'] == 'y') {
- $backup_dir_permissions = 0755;
- } else {
- $backup_dir_permissions = 0750;
- }
-
- if(!is_dir($backup_dir)) {
- mkdir(escapeshellcmd($backup_dir), $backup_dir_permissions, true);
- } else {
- chmod(escapeshellcmd($backup_dir), $backup_dir_permissions);
- }
-
- $sql = "SELECT * FROM web_domain WHERE server_id = '".$conf['server_id']."' AND (type = 'vhost' OR type = 'vhostsubdomain') AND backup_interval != 'none'";
- $records = $app->db->queryAllRecords($sql);
- if(is_array($records)) {
- foreach($records as $rec) {
-
- //* Do the website backup
- if($rec['backup_interval'] == 'daily' or ($rec['backup_interval'] == 'weekly' && date('w') == 0) or ($rec['backup_interval'] == 'monthly' && date('d') == '01')) {
-
- $web_path = $rec['document_root'];
- $web_user = $rec['system_user'];
- $web_group = $rec['system_group'];
- $web_id = $rec['domain_id'];
- $web_backup_dir = $backup_dir.'/web'.$web_id;
- if(!is_dir($web_backup_dir)) mkdir($web_backup_dir, 0750);
- chmod($web_backup_dir, 0750);
- //if(isset($server_config['backup_dir_ftpread']) && $server_config['backup_dir_ftpread'] == 'y') {
- chown($web_backup_dir, $rec['system_user']);
- chgrp($web_backup_dir, $rec['system_group']);
- /*} else {
- chown($web_backup_dir, 'root');
- chgrp($web_backup_dir, 'root');
- }*/
- if($backup_mode == 'userzip') {
- //* Create a .zip backup as web user and include also files owned by apache / nginx user
- $web_backup_file = 'web'.$web_id.'_'.date('Y-m-d_H-i').'.zip';
- exec('cd '.escapeshellarg($web_path).' && sudo -u '.escapeshellarg($web_user).' find . -group '.escapeshellarg($web_group).' -print 2> /dev/null | zip -b /tmp --exclude=backup\* --symlinks '.escapeshellarg($web_backup_dir.'/'.$web_backup_file).' -@', $tmp_output, $retval);
- if($retval == 0) exec('cd '.escapeshellarg($web_path).' && sudo -u '.escapeshellarg($web_user).' find . -user '.escapeshellarg($http_server_user).' -print 2> /dev/null | zip -b /tmp --exclude=backup\* --update --symlinks '.escapeshellarg($web_backup_dir.'/'.$web_backup_file).' -@', $tmp_output, $retval);
- } else {
- //* Create a tar.gz backup as root user
- $web_backup_file = 'web'.$web_id.'_'.date('Y-m-d_H-i').'.tar.gz';
- exec('tar pczf '.escapeshellarg($web_backup_dir.'/'.$web_backup_file).' --exclude=backup\* --directory '.escapeshellarg($web_path).' .', $tmp_output, $retval);
- }
- if($retval == 0){
- chown($web_backup_dir.'/'.$web_backup_file, 'root');
- chgrp($web_backup_dir.'/'.$web_backup_file, 'root');
- chmod($web_backup_dir.'/'.$web_backup_file, 0750);
-
- //* Insert web backup record in database
- //$insert_data = "(server_id,parent_domain_id,backup_type,backup_mode,tstamp,filename) VALUES (".$conf['server_id'].",".$web_id.",'web','".$backup_mode."',".time().",'".$app->db->quote($web_backup_file)."')";
- //$app->dbmaster->datalogInsert('web_backup', $insert_data, 'backup_id');
- $sql = "INSERT INTO web_backup (server_id,parent_domain_id,backup_type,backup_mode,tstamp,filename) VALUES (".$conf['server_id'].",".$web_id.",'web','".$backup_mode."',".time().",'".$app->db->quote($web_backup_file)."')";
- $app->db->query($sql);
- if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql);
- } else {
- if(is_file($web_backup_dir.'/'.$web_backup_file)) unlink($web_backup_dir.'/'.$web_backup_file);
- }
-
- //* Remove old backups
- $backup_copies = intval($rec['backup_copies']);
-
- $dir_handle = dir($web_backup_dir);
- $files = array();
- while (false !== ($entry = $dir_handle->read())) {
- if($entry != '.' && $entry != '..' && substr($entry,0,3) == 'web' && is_file($web_backup_dir.'/'.$entry)) {
- $files[] = $entry;
- }
- }
- $dir_handle->close();
-
- rsort($files);
-
- for ($n = $backup_copies; $n <= 10; $n++) {
- if(isset($files[$n]) && is_file($web_backup_dir.'/'.$files[$n])) {
- unlink($web_backup_dir.'/'.$files[$n]);
- //$sql = "SELECT backup_id FROM web_backup WHERE server_id = ".$conf['server_id']." AND parent_domain_id = $web_id AND filename = '".$app->db->quote($files[$n])."'";
- //$tmp = $app->dbmaster->queryOneRecord($sql);
- //$app->dbmaster->datalogDelete('web_backup', 'backup_id', $tmp['backup_id']);
- //$sql = "DELETE FROM web_backup WHERE backup_id = ".intval($tmp['backup_id']);
- $sql = "DELETE FROM web_backup WHERE server_id = ".$conf['server_id']." AND parent_domain_id = $web_id AND filename = '".$app->db->quote($files[$n])."'";
- $app->db->query($sql);
- if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql);
- }
- }
-
- unset($files);
- unset($dir_handle);
-
- //* Remove backupdir symlink and create as directory instead
- $app->uses('system');
- $app->system->web_folder_protection($web_path,false);
-
- if(is_link($web_path.'/backup')) {
- unlink($web_path.'/backup');
- }
- if(!is_dir($web_path.'/backup')) {
- mkdir($web_path.'/backup');
- chown($web_path.'/backup', $rec['system_user']);
- chgrp($web_path.'/backup', $rec['system_group']);
- }
-
- $app->system->web_folder_protection($web_path,true);
-
- }
-
- /* If backup_interval is set to none and we have a
- backup directory for the website, then remove the backups */
- if($rec['backup_interval'] == 'none') {
- $web_id = $rec['domain_id'];
- $web_user = $rec['system_user'];
- $web_backup_dir = realpath($backup_dir.'/web'.$web_id);
- if(is_dir($web_backup_dir)) {
- exec('sudo -u '.escapeshellarg($web_user).' rm -f '.escapeshellarg($web_backup_dir.'/*'));
- }
- }
- }
- }
-
- $sql = "SELECT * FROM web_database WHERE server_id = '".$conf['server_id']."' AND backup_interval != 'none'";
- $records = $app->db->queryAllRecords($sql);
- if(is_array($records)) {
-
- include('lib/mysql_clientdb.conf');
-
- foreach($records as $rec) {
-
- //* Do the database backup
- if($rec['backup_interval'] == 'daily' or ($rec['backup_interval'] == 'weekly' && date('w') == 0) or ($rec['backup_interval'] == 'monthly' && date('d') == '01')) {
-
- $web_id = $rec['parent_domain_id'];
- $db_backup_dir = $backup_dir.'/web'.$web_id;
- if(!is_dir($db_backup_dir)) mkdir($db_backup_dir, 0750);
- chmod($db_backup_dir, 0750);
- chown($db_backup_dir, 'root');
- chgrp($db_backup_dir, 'root');
-
- //* Do the mysql database backup with mysqldump or mongodump
- $db_id = $rec['database_id'];
- $db_name = $rec['database_name'];
-
- if ($rec['type'] == 'mysql') {
- $db_backup_file = 'db_'.$db_name.'_'.date('Y-m-d_H-i').'.sql';
- //$command = "mysqldump -h '".escapeshellcmd($clientdb_host)."' -u '".escapeshellcmd($clientdb_user)."' -p'".escapeshellcmd($clientdb_password)."' -c --add-drop-table --create-options --quick --result-file='".$db_backup_dir.'/'.$db_backup_file."' '".$db_name."'";
- $command = "mysqldump -h ".escapeshellarg($clientdb_host)." -u ".escapeshellarg($clientdb_user)." -p".escapeshellarg($clientdb_password)." -c --add-drop-table --create-options --quick --result-file='".$db_backup_dir.'/'.$db_backup_file."' '".$db_name."'";
- exec($command, $tmp_output, $retval);
-
- //* Compress the backup with gzip
- if($retval == 0) exec("gzip -c '".escapeshellcmd($db_backup_dir.'/'.$db_backup_file)."' > '".escapeshellcmd($db_backup_dir.'/'.$db_backup_file).".gz'", $tmp_output, $retval);
-
- if($retval == 0){
- chmod($db_backup_dir.'/'.$db_backup_file.'.gz', 0750);
- chown($db_backup_dir.'/'.$db_backup_file.'.gz', fileowner($db_backup_dir));
- chgrp($db_backup_dir.'/'.$db_backup_file.'.gz', filegroup($db_backup_dir));
-
- //* Insert web backup record in database
- //$insert_data = "(server_id,parent_domain_id,backup_type,backup_mode,tstamp,filename) VALUES (".$conf['server_id'].",$web_id,'mysql','sqlgz',".time().",'".$app->db->quote($db_backup_file).".gz')";
- //$app->dbmaster->datalogInsert('web_backup', $insert_data, 'backup_id');
- $sql = "INSERT INTO web_backup (server_id,parent_domain_id,backup_type,backup_mode,tstamp,filename) VALUES (".$conf['server_id'].",$web_id,'mysql','sqlgz',".time().",'".$app->db->quote($db_backup_file).".gz')";
- $app->db->query($sql);
- if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql);
-
- } else {
- if(is_file($db_backup_dir.'/'.$db_backup_file.'.gz')) unlink($db_backup_dir.'/'.$db_backup_file.'.gz');
- }
- //* Remove the uncompressed file
- if(is_file($db_backup_dir.'/'.$db_backup_file)) unlink($db_backup_dir.'/'.$db_backup_file);
- } else if ($rec['type'] == 'mongo') {
- $db_backup_file = 'db_'.$db_name.'_'.date('Y-m-d_H-i');
-
- try {
- $connection = new MongoClient("mongodb://root:123456@127.0.0.1:27017/admin");
- $db = $connection->selectDB($db_name);
- // exclude not supported by mongodump, only get user collections
- $collections = $db->getCollectionNames(false);
-
- foreach ($collections as $collection) {
- // mongodump -h 127.0.0.1 --port 27017 -u root -p 123456 --authenticationDatabase admin -d <db> -c <table> -o /tmp/test
- $command = "mongodump -h 127.0.0.1 --port 27017 -u root -p 123456 --authenticationDatabase admin -d ".escapeshellcmd($db_name)." -c ".escapeshellcmd($collection)." -o ".escapeshellcmd($db_backup_dir.'/'.$db_backup_file);
- exec($command);
- }
-
- if (is_dir(escapeshellcmd($db_backup_dir.'/'.$db_backup_file))) {
- //* Compress the backup with gzip
- exec("cd ".escapeshellcmd($db_backup_dir)." && tar -pczf ".escapeshellcmd($db_backup_dir.'/'.$db_backup_file).".tar.gz ".escapeshellcmd($db_backup_file));
- chmod($db_backup_dir.'/'.$db_backup_file.'.tar.gz', 0750);
- chown($db_backup_dir.'/'.$db_backup_file.'.tar.gz', fileowner($db_backup_dir));
- chgrp($db_backup_dir.'/'.$db_backup_file.'.tar.gz', filegroup($db_backup_dir));
-
- //* Insert web backup record in database
- $sql = "INSERT INTO web_backup (server_id,parent_domain_id,backup_type,backup_mode,tstamp,filename) VALUES (".$conf['server_id'].",$web_id,'mongodb','rootgz',".time().",'".$app->db->quote($db_backup_file).".tar.gz')";
- $app->db->query($sql);
-
- if ($app->db->dbHost != $app->dbmaster->dbHost) {
- $app->dbmaster->query($sql);
- }
-
- //* Remove the uncompressed file
- exec("rm -rf ".escapeshellcmd($db_backup_dir.'/'.$db_backup_file));
- }
- } catch (MongoConnnectionException $e) {
- // connecting to MongoDB failed - cannot create backup
- }
- }
-
- //* Remove old backups
- $backup_copies = intval($rec['backup_copies']);
-
- $dir_handle = dir($db_backup_dir);
- $files = array();
- while (false !== ($entry = $dir_handle->read())) {
- if($entry != '.' && $entry != '..' && (preg_match('/^db_(.*?)_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}\.sql.gz$/', $entry, $matches) || preg_match('/^db_(.*?)_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}\.tar.gz$/', $entry, $matches)) && is_file($db_backup_dir.'/'.$entry)) {
- if(array_key_exists($matches[1], $files) == false) $files[$matches[1]] = array();
- $files[$matches[1]][] = $entry;
- }
- }
- $dir_handle->close();
-
- reset($files);
- foreach($files as $db_name => $filelist) {
- rsort($filelist);
- for ($n = $backup_copies; $n <= 10; $n++) {
- if(isset($filelist[$n]) && is_file($db_backup_dir.'/'.$filelist[$n])) {
- unlink($db_backup_dir.'/'.$filelist[$n]);
- //$sql = "SELECT backup_id FROM web_backup WHERE server_id = ".$conf['server_id']." AND parent_domain_id = $web_id AND filename = '".$app->db->quote($filelist[$n])."'";
- //$tmp = $app->dbmaster->queryOneRecord($sql);
- //$sql = "DELETE FROM web_backup WHERE backup_id = ".intval($tmp['backup_id']);
- $sql = "DELETE FROM web_backup WHERE server_id = ".$conf['server_id']." AND parent_domain_id = $web_id AND filename = '".$app->db->quote($filelist[$n])."'";
- $app->db->query($sql);
- if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql);
- }
- }
- }
-
- unset($files);
- unset($dir_handle);
- }
- }
-
- unset($clientdb_host);
- unset($clientdb_user);
- unset($clientdb_password);
-
- }
-}
-
-
-die("finished.\n");
-?>
diff --git a/server/cron_daily.sh b/server/cron_daily.sh
old mode 100644
new mode 100755
index 9ffedae..a96da2f
--- a/server/cron_daily.sh
+++ b/server/cron_daily.sh
@@ -1,16 +1,3 @@
#!/bin/sh
-PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin
-
-if [ -f /usr/local/ispconfig/server/lib/php.ini ]; then
- PHPINIOWNER=`stat -c %U /usr/local/ispconfig/server/lib/php.ini`
- if [ $PHPINIOWNER == 'root' ] || [ $PHPINIOWNER == 'ispconfig' ]; then
- export PHPRC=/usr/local/ispconfig/server/lib
- fi
-fi
-
-/usr/bin/php -q /usr/local/ispconfig/server/cron_daily.php
-
-if [ -f /usr/local/ispconfig/server/cron_daily_billing.sh ]; then
- /usr/local/ispconfig/server/cron_daily_billing.sh
-fi
+echo "This script is no longer used. Use the cron.sh instead."
diff --git a/server/lib/classes/cron.d/100-mailbox_stats.inc.php b/server/lib/classes/cron.d/100-mailbox_stats.inc.php
new file mode 100644
index 0000000..ed43e4e
--- /dev/null
+++ b/server/lib/classes/cron.d/100-mailbox_stats.inc.php
@@ -0,0 +1,269 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_mailbox_stats extends cronjob {
+
+ // job schedule
+ protected $_schedule = '0 0 * * *';
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ // cronjob code here
+
+ #######################################################################################################
+ // store the mailbox statistics in the database
+ #######################################################################################################
+
+ $parse_mail_log = false;
+ $sql = "SELECT mailuser_id,maildir FROM mail_user WHERE server_id = ".$conf['server_id'];
+ $records = $app->db->queryAllRecords($sql);
+ if(count($records) > 0) $parse_mail_log = true;
+
+ foreach($records as $rec) {
+ if(@is_file($rec['maildir'].'/ispconfig_mailsize')) {
+ $parse_mail_log = false;
+
+ // rename file
+ rename($rec['maildir'].'/ispconfig_mailsize',$rec['maildir'].'/ispconfig_mailsize_save');
+
+ // Read the file
+ $lines = file($rec['maildir'].'/ispconfig_mailsize_save');
+ $mail_traffic = 0;
+ foreach($lines as $line) {
+ $mail_traffic += intval($line);
+ }
+ unset($lines);
+
+ // Delete backup file
+ if(@is_file($rec['maildir'].'/ispconfig_mailsize_save')) unlink($rec['maildir'].'/ispconfig_mailsize_save');
+
+ // Save the traffic stats in the sql database
+ $tstamp = date('Y-m');
+
+ $sql = "SELECT * FROM mail_traffic WHERE month = '$tstamp' AND mailuser_id = ".$rec['mailuser_id'];
+ $tr = $app->dbmaster->queryOneRecord($sql);
+
+ $mail_traffic += $tr['traffic'];
+ if($tr['traffic_id'] > 0) {
+ $sql = "UPDATE mail_traffic SET traffic = $mail_traffic WHERE traffic_id = ".$tr['traffic_id'];
+ } else {
+ $sql = "INSERT INTO mail_traffic (month,mailuser_id,traffic) VALUES ('$tstamp',".$rec['mailuser_id'].",$mail_traffic)";
+ }
+ $app->dbmaster->query($sql);
+ //echo $sql;
+
+ }
+
+ }
+
+ if($parse_mail_log == true) {
+ $mailbox_traffic = array();
+ $mail_boxes = array();
+ $mail_rewrites = array(); // we need to read all mail aliases and forwards because the address in amavis is not always the mailbox address
+
+ function parse_mail_log_line($line) {
+ //Oct 31 17:35:48 mx01 amavis[32014]: (32014-05) Passed CLEAN, [IPv6:xxxxx] [IPv6:xxxxx] <xxx@yyyy> -> <aaaa@bbbb>, Message-ID: <xxxx@yyyyy>, mail_id: xxxxxx, Hits: -1.89, size: 1591, queued_as: xxxxxxx, 946 ms
+
+ if(preg_match('/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+[^ ]+\s+amavis.* <([^>]+)>\s+->\s+((<[^>]+>,)+) .*Message-ID:\s+<([^>]+)>.* size:\s+(\d+),.*$/', $line, $matches) == false) return false;
+
+ $timestamp = strtotime($matches[1]);
+ if(!$timestamp) return false;
+
+ $to = array();
+ $recipients = explode(',', $matches[3]);
+ foreach($recipients as $recipient) {
+ $recipient = substr($recipient, 1, -1);
+ if(!$recipient || $recipient == $matches[2]) continue;
+ $to[] = $recipient;
+ }
+
+ return array('line' => $line, 'timestamp' => $timestamp, 'size' => $matches[6], 'from' => $matches[2], 'to' => $to, 'message-id' => $matches[5]);
+ }
+
+ function add_mailbox_traffic(&$traffic_array, $address, $traffic) {
+ global $mail_boxes, $mail_rewrites;
+
+ $address = strtolower($address);
+
+ if(in_array($address, $mail_boxes) == true) {
+ if(!isset($traffic_array[$address])) $traffic_array[$address] = 0;
+ $traffic_array[$address] += $traffic;
+ } elseif(array_key_exists($address, $mail_rewrites)) {
+ foreach($mail_rewrites[$address] as $address) {
+ if(!isset($traffic_array[$address])) $traffic_array[$address] = 0;
+ $traffic_array[$address] += $traffic;
+ }
+ } else {
+ // this is not a local address - skip it
+ }
+ }
+
+ $sql = "SELECT email FROM mail_user WHERE server_id = ".$conf['server_id'];
+ $records = $app->db->queryAllRecords($sql);
+ foreach($records as $record) {
+ $mail_boxes[] = $record['email'];
+ }
+ $sql = "SELECT source, destination FROM mail_forwarding WHERE server_id = ".$conf['server_id'];
+ $records = $app->db->queryAllRecords($sql);
+ foreach($records as $record) {
+ $targets = preg_split('/[\n,]+/', $record['destination']);
+ foreach($targets as $target) {
+ if(in_array($target, $mail_boxes)) {
+ if(isset($mail_rewrites[$record['source']])) $mail_rewrites[$record['source']][] = $target;
+ else $mail_rewrites[$record['source']] = array($target);
+ }
+ }
+ }
+
+ $state_file = dirname(__FILE__) . '/mail_log_parser.state';
+ $prev_line = false;
+ $last_line = false;
+ $cur_line = false;
+
+ if(file_exists($state_file)) {
+ $prev_line = parse_mail_log_line(trim(file_get_contents($state_file)));
+ //if($prev_line) echo "continuing from previous run, log position: " . $prev_line['message-id'] . " at " . strftime('%d.%m.%Y %H:%M:%S', $prev_line['timestamp']) . "\n";
+ }
+
+ if(file_exists('/var/log/mail.log')) {
+ $fp = fopen('/var/log/mail.log', 'r');
+ //echo "Parsing mail.log...\n";
+ $l = 0;
+ while($line = fgets($fp, 8192)) {
+ $l++;
+ //if($l % 1000 == 0) echo "\rline $l";
+ $cur_line = parse_mail_log_line($line);
+ if(!$cur_line) continue;
+
+ if($prev_line) {
+ // check if this line has to be processed
+ if($cur_line['timestamp'] < $prev_line['timestamp']) {
+ $parse_mail_log = false; // we do not need to parse the second file!
+ continue; // already processed
+ } elseif($cur_line['timestamp'] == $prev_line['timestamp'] && $cur_line['message-id'] == $prev_line['message-id']) {
+ $parse_mail_log = false; // we do not need to parse the second file!
+ $prev_line = false; // this line has already been processed but the next one has to be!
+ continue;
+ }
+ }
+
+ add_mailbox_traffic($mailbox_traffic, $cur_line['from'], $cur_line['size']);
+ foreach($cur_line['to'] as $to) {
+ add_mailbox_traffic($mailbox_traffic, $to, $cur_line['size']);
+ }
+ $last_line = $line; // store for the state file
+ }
+ fclose($fp);
+ //echo "\n";
+ }
+
+ if($parse_mail_log == true && file_exists('/var/log/mail.log.1')) {
+ $fp = fopen('/var/log/mail.log.1', 'r');
+ //echo "Parsing mail.log.1...\n";
+ $l = 0;
+ while($line = fgets($fp, 8192)) {
+ $l++;
+ //if($l % 1000 == 0) echo "\rline $l";
+ $cur_line = parse_mail_log_line($line);
+ if(!$cur_line) continue;
+
+ if($prev_line) {
+ // check if this line has to be processed
+ if($cur_line['timestamp'] < $prev_line['timestamp']) continue; // already processed
+ if($cur_line['timestamp'] == $prev_line['timestamp'] && $cur_line['message-id'] == $prev_line['message-id']) {
+ $prev_line = false; // this line has already been processed but the next one has to be!
+ continue;
+ }
+ }
+
+ add_mailbox_traffic($mailbox_traffic, $cur_line['from'], $cur_line['size']);
+ foreach($cur_line['to'] as $to) {
+ add_mailbox_traffic($mailbox_traffic, $to, $cur_line['size']);
+ }
+ }
+ fclose($fp);
+ //echo "\n";
+ }
+ unset($mail_rewrites);
+ unset($mail_boxes);
+
+ // Save the traffic stats in the sql database
+ $tstamp = date('Y-m');
+ $sql = "SELECT mailuser_id,email FROM mail_user WHERE server_id = ".$conf['server_id'];
+ $records = $app->db->queryAllRecords($sql);
+ foreach($records as $rec) {
+ if(array_key_exists($rec['email'], $mailbox_traffic)) {
+ $sql = "SELECT * FROM mail_traffic WHERE month = '$tstamp' AND mailuser_id = ".$rec['mailuser_id'];
+ $tr = $app->dbmaster->queryOneRecord($sql);
+
+ $mail_traffic = $tr['traffic'] + $mailbox_traffic[$rec['email']];
+ if($tr['traffic_id'] > 0) {
+ $sql = "UPDATE mail_traffic SET traffic = $mail_traffic WHERE traffic_id = ".$tr['traffic_id'];
+ } else {
+ $sql = "INSERT INTO mail_traffic (month,mailuser_id,traffic) VALUES ('$tstamp',".$rec['mailuser_id'].",$mail_traffic)";
+ }
+ $app->dbmaster->query($sql);
+ //echo $sql;
+ }
+ }
+
+ unset($mailbox_traffic);
+ if($last_line) file_put_contents($state_file, $last_line);
+ }
+
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/100-monitor_clamav_log.inc.php b/server/lib/classes/cron.d/100-monitor_clamav_log.inc.php
new file mode 100644
index 0000000..fc28bfb
--- /dev/null
+++ b/server/lib/classes/cron.d/100-monitor_clamav_log.inc.php
@@ -0,0 +1,179 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_monitor_clamav_log extends cronjob {
+
+ // job schedule
+ protected $_schedule = '*/5 * * * *';
+ protected $_run_at_new = true;
+
+ private $_tools = null;
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ /* used for all monitor cronjobs */
+ $app->load('monitor_tools');
+ $this->_tools = new monitor_tools();
+ /* end global section for monitor cronjobs */
+
+ /* the id of the server as int */
+ $server_id = intval($conf['server_id']);
+
+ /** The type of the data */
+ $type = 'log_clamav';
+
+ /* Get the data of the log */
+ $data = $this->_tools->_getLogData($type);
+
+ // Todo: the state should be calculated.
+ $state = 'ok';
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+
+ /** The type of the data */
+ $type = 'log_freshclam';
+
+ /* Get the data of the log */
+ $data = $this->_tools->_getLogData($type);
+
+ /* Get the data from the LAST log-Entry.
+ * if there can be found:
+ * WARNING: Your ClamAV installation is OUTDATED!
+ * then the clamav is outdated. This is a warning!
+ */
+ $state = 'ok';
+
+ $tmp = explode("\n", $data);
+ $lastLog = array();
+ if ($tmp[sizeof($tmp) - 1] == '') {
+ /* the log ends with an empty line remove this */
+ array_pop($tmp);
+ }
+ if (strpos($tmp[sizeof($tmp) - 1], '-------------') !== false) {
+ /* the log ends with "-----..." remove this */
+ array_pop($tmp);
+ }
+ for ($i = sizeof($tmp) - 1; $i > 0; $i--) {
+ if (strpos($tmp[$i], '---------') === false) {
+ /* no delimiter found, so add this to the last-log */
+ $lastLog[] = $tmp[$i];
+ } else {
+ /* delimiter found, so there is no more line left! */
+ break;
+ }
+ }
+
+ /*
+ * Now we have the last log in the array.
+ * Check if the outdated-string is found...
+ */
+ foreach ($lastLog as $line) {
+ if (strpos(strtolower($line), 'outdated') !== false) {
+ /*
+ * Outdatet is only info, because if we set this to warning, the server is
+ * as long in state warning, as there is a new version of ClamAv which takes
+ * sometimes weeks!
+ */
+ $state = $this->_tools->_setState($state, 'info');
+ }
+ }
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/100-monitor_cpu.inc.php b/server/lib/classes/cron.d/100-monitor_cpu.inc.php
new file mode 100644
index 0000000..b75239b
--- /dev/null
+++ b/server/lib/classes/cron.d/100-monitor_cpu.inc.php
@@ -0,0 +1,136 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_monitor_cpu extends cronjob {
+
+ // job schedule
+ protected $_schedule = '*/5 * * * *';
+ protected $_run_at_new = true;
+
+ private $_tools = null;
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ /* used for all monitor cronjobs */
+ $app->load('monitor_tools');
+ $this->_tools = new monitor_tools();
+ /* end global section for monitor cronjobs */
+
+ /* the id of the server as int */
+ $server_id = intval($conf['server_id']);
+
+ /** The type of the data */
+ $type = 'cpu_info';
+
+ /*
+ Fetch the data into a array
+ */
+ if (file_exists('/proc/cpuinfo')) {
+ $cpuData = shell_exec('cat /proc/cpuinfo');
+ $cpuInfo = explode("\n", $cpuData);
+ $processor = 0;
+
+ foreach ($cpuInfo as $line) {
+
+ $part = preg_split('/:/', $line);
+ $key = trim($part[0]);
+ $value = trim($part[1]);
+ if ($key == 'processor')
+ $processor = intval($value);
+ if ($key != '')
+ $data[$key . ' ' . $processor] = $value;
+ }
+
+ /* the cpu has no state. It is, what it is */
+ $state = 'no_state';
+ } else {
+ /*
+ * It is not Linux, so there is no data and no state
+ *
+ * no_state, NOT unknown, because "unknown" is shown as state
+ * inside the GUI. no_state is hidden.
+ *
+ * We have to write NO DATA inside the DB, because the GUI
+ * could not know, if there is any dat, or not...
+ */
+ $state = 'no_state';
+ $data['output'] = '';
+ }
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/100-monitor_disk_usage.inc.php b/server/lib/classes/cron.d/100-monitor_disk_usage.inc.php
new file mode 100644
index 0000000..706be3d
--- /dev/null
+++ b/server/lib/classes/cron.d/100-monitor_disk_usage.inc.php
@@ -0,0 +1,166 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_monitor_disk_usage extends cronjob {
+
+ // job schedule
+ protected $_schedule = '*/5 * * * *';
+ protected $_run_at_new = true;
+
+ private $_tools = null;
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ /* used for all monitor cronjobs */
+ $app->load('monitor_tools');
+ $this->_tools = new monitor_tools();
+ /* end global section for monitor cronjobs */
+
+ /* the id of the server as int */
+ $server_id = intval($conf['server_id']);
+
+ /** The type of the data */
+ $type = 'disk_usage';
+
+ /** The state of the disk-usage */
+ $state = 'ok';
+
+ /** Fetch the data of ALL devices into a array (needed for monitoring!) */
+ //$dfData = shell_exec('df -hT 2>/dev/null');
+ $app->uses('getconf');
+ $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
+ $dfData = shell_exec('df -hT|grep -v "'.$web_config['website_basedir'].'/" 2>/dev/null');
+
+ // split into array
+ $df = explode("\n", $dfData);
+
+ /*
+ * ignore the first line, process the rest
+ */
+ for ($i = 1; $i <= sizeof($df); $i++) {
+ if ($df[$i] != '') {
+ /*
+ * Make an array of the data
+ */
+ $s = preg_split('/[\s]+/', $df[$i]);
+ $data[$i]['fs'] = $s[0];
+ $data[$i]['type'] = $s[1];
+ $data[$i]['size'] = $s[2];
+ $data[$i]['used'] = $s[3];
+ $data[$i]['available'] = $s[4];
+ $data[$i]['percent'] = $s[5];
+ $data[$i]['mounted'] = $s[6];
+ /*
+ * calculate the state
+ */
+ $usePercent = floatval($data[$i]['percent']);
+
+ //* get the free memsize
+ if(substr($data[$i]['available'],-1) == 'G') {
+ $freesize = floatval($data[$i]['available'])*1024;
+ } elseif(substr($data[$i]['available'],-1) == 'T') {
+ $freesize = floatval($data[$i]['available'])*1024*1024;
+ } else {
+ $freesize = floatval($data[$i]['available']);
+ }
+
+ //* We don't want to check some filesystem which have no sensible filling levels
+ switch ($data[$i]['type']) {
+ case 'iso9660':
+ case 'cramfs':
+ case 'udf':
+ case 'tmpfs':
+ case 'devtmpfs':
+ case 'udev':
+ break;
+ default:
+ if ($usePercent > 75 && $freesize < 2000)
+ $state = $this->_tools->_setState($state, 'info');
+ if ($usePercent > 80 && $freesize < 1000)
+ $state = $this->_tools->_setState($state, 'warning');
+ if ($usePercent > 90 && $freesize < 500)
+ $state = $this->_tools->_setState($state, 'critical');
+ if ($usePercent > 95 && $freesize < 100)
+ $state = $this->_tools->_setState($state, 'error');
+ break;
+ }
+ }
+ }
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/100-monitor_email_quota.inc.php b/server/lib/classes/cron.d/100-monitor_email_quota.inc.php
new file mode 100644
index 0000000..12bd3fe
--- /dev/null
+++ b/server/lib/classes/cron.d/100-monitor_email_quota.inc.php
@@ -0,0 +1,149 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_monitor_email_quota extends cronjob {
+
+ // job schedule
+ protected $_schedule = '*/15 * * * *';
+ protected $_run_at_new = true;
+
+ private $_tools = null;
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ $app->uses('getconf');
+ $mail_config = $app->getconf->get_server_config($conf['server_id'], 'mail');
+ if($mail_config['mailbox_quota_stats'] == 'n') return;
+
+ /* used for all monitor cronjobs */
+ $app->load('monitor_tools');
+ $this->_tools = new monitor_tools();
+ /* end global section for monitor cronjobs */
+
+
+ //* Initialize data array
+ $data = array();
+
+ //* the id of the server as int
+ $server_id = intval($conf['server_id']);
+
+ //* The type of the data
+ $type = 'email_quota';
+
+ //* The state of the email_quota.
+ $state = 'ok';
+
+ $mailboxes = $app->db->queryAllRecords("SELECT email,maildir FROM mail_user WHERE server_id = $server_id");
+ if(is_array($mailboxes)) {
+ foreach($mailboxes as $mb) {
+ $email = $mb['email'];
+ $email_parts = explode('@',$mb['email']);
+ $filename = $mb['maildir'].'/.quotausage';
+ if(file_exists($filename) && !is_link($filename)) {
+ $quotafile = file($filename);
+ $data[$email]['used'] = trim($quotafile['1']);
+ unset($quotafile);
+ } else {
+ exec('du -s '.escapeshellcmd($mb['maildir']),$out);
+ $parts = explode(' ',$out[0]);
+ $data[$email]['used'] = intval($parts[0])*1024;
+ unset($out);
+ unset($parts);
+ }
+ }
+ }
+
+ unset($mailboxes);
+
+ //* Dovecot quota check Courier in progress lathama@gmail.com
+ /*
+ if($dir = opendir("/var/vmail")){
+ while (($quotafiles = readdir($dir)) !== false){
+ if(preg_match('/.\_quota$/', $quotafiles)){
+ $quotafile = (file("/var/vmail/" . $quotafiles));
+ $emailaddress = preg_replace('/_quota/',"", $quotafiles);
+ $emailaddress = preg_replace('/_/',"@", $emailaddress);
+ $data[$emailaddress]['used'] = trim($quotafile['1']);
+ }
+ }
+ closedir($dir);
+ }
+ */
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/100-monitor_fail2ban.inc.php b/server/lib/classes/cron.d/100-monitor_fail2ban.inc.php
new file mode 100644
index 0000000..6c77a07
--- /dev/null
+++ b/server/lib/classes/cron.d/100-monitor_fail2ban.inc.php
@@ -0,0 +1,127 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_monitor_fail2ban extends cronjob {
+
+ // job schedule
+ protected $_schedule = '*/5 * * * *';
+ protected $_run_at_new = true;
+
+ private $_tools = null;
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ /* used for all monitor cronjobs */
+ $app->load('monitor_tools');
+ $this->_tools = new monitor_tools();
+ /* end global section for monitor cronjobs */
+
+ /* the id of the server as int */
+ $server_id = intval($conf['server_id']);
+
+ /** The type of the data */
+ $type = 'log_fail2ban';
+
+ /* This monitoring is only available if fail2ban is installed */
+ system('which fail2ban-client', $retval); // Debian, Ubuntu, Fedora
+ if ($retval !== 0)
+ system('which fail2ban', $retval); // CentOS
+ if ($retval === 0) {
+ /* Get the data of the log */
+ $data = $this->_tools->_getLogData($type);
+
+ /*
+ * At this moment, there is no state (maybe later)
+ */
+ $state = 'no_state';
+ } else {
+ /*
+ * fail2ban is not installed, so there is no data and no state
+ *
+ * no_state, NOT unknown, because "unknown" is shown as state
+ * inside the GUI. no_state is hidden.
+ *
+ * We have to write NO DATA inside the DB, because the GUI
+ * could not know, if there is any dat, or not...
+ */
+ $state = 'no_state';
+ $data = '';
+ }
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/100-monitor_hd_quota.inc.php b/server/lib/classes/cron.d/100-monitor_hd_quota.inc.php
new file mode 100644
index 0000000..14f00d4
--- /dev/null
+++ b/server/lib/classes/cron.d/100-monitor_hd_quota.inc.php
@@ -0,0 +1,162 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_monitor_hd_quota extends cronjob {
+
+ // job schedule
+ protected $_schedule = '*/5 * * * *';
+ protected $_run_at_new = true;
+
+ private $_tools = null;
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ /* used for all monitor cronjobs */
+ $app->load('monitor_tools');
+ $this->_tools = new monitor_tools();
+ /* end global section for monitor cronjobs */
+
+ //* Initialize data array
+ $data = array();
+
+ //* the id of the server as int
+ $server_id = intval($conf['server_id']);
+
+ //* The type of the data
+ $type = 'harddisk_quota';
+
+ //* The state of the harddisk_quota.
+ $state = 'ok';
+
+ //* Fetch the data for all users
+ $dfData = shell_exec('repquota -au 2>/dev/null');
+
+ //* Split into array
+ $df = explode("\n", $dfData);
+
+ //* ignore the first 5 lines, process the rest
+ for ($i = 5; $i <= sizeof($df); $i++) {
+ if ($df[$i] != '') {
+ //* Make a array of the data
+ $s = preg_split('/[\s]+/', $df[$i]);
+ $username = $s[0];
+ if (substr($username, 0, 3) == 'web') {
+ if (isset($data['user'][$username])) {
+ $data['user'][$username]['used'] += $s[2];
+ $data['user'][$username]['soft'] += $s[3];
+ $data['user'][$username]['hard'] += $s[4];
+ $data['user'][$username]['files'] += $s[5];
+ } else {
+ $data['user'][$username]['used'] = $s[2];
+ $data['user'][$username]['soft'] = $s[3];
+ $data['user'][$username]['hard'] = $s[4];
+ $data['user'][$username]['files'] = $s[5];
+ }
+ }
+ }
+ }
+
+ //** Fetch the data for all users
+ $dfData = shell_exec('repquota -ag 2>/dev/null');
+
+ //* split into array
+ $df = explode("\n", $dfData);
+
+ //* ignore the first 5 lines, process the rest
+ for ($i = 5; $i <= sizeof($df); $i++) {
+ if ($df[$i] != '') {
+ //* Make a array of the data
+ $s = preg_split('/[\s]+/', $df[$i]);
+ $groupname = $s[0];
+ if (substr($groupname, 0, 6) == 'client') {
+ if (isset($data['group'][$groupname])) {
+ $data['group'][$groupname]['used'] += $s[1];
+ $data['group'][$groupname]['soft'] += $s[2];
+ $data['group'][$groupname]['hard'] += $s[3];
+ } else {
+ $data['group'][$groupname]['used'] = $s[1];
+ $data['group'][$groupname]['soft'] = $s[2];
+ $data['group'][$groupname]['hard'] = $s[3];
+ }
+ }
+ }
+ }
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/100-monitor_iptables.inc.php b/server/lib/classes/cron.d/100-monitor_iptables.inc.php
new file mode 100644
index 0000000..3b25e4c
--- /dev/null
+++ b/server/lib/classes/cron.d/100-monitor_iptables.inc.php
@@ -0,0 +1,132 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_monitor_iptables extends cronjob {
+
+ // job schedule
+ protected $_schedule = '*/5 * * * *';
+ protected $_run_at_new = true;
+
+ private $_tools = null;
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ /* used for all monitor cronjobs */
+ $app->load('monitor_tools');
+ $this->_tools = new monitor_tools();
+ /* end global section for monitor cronjobs */
+
+ /* the id of the server as int */
+ $server_id = intval($conf['server_id']);
+
+ /** The type of the data */
+ $type = 'iptables_rules';
+
+ /* This monitoring is only available if fail2ban is installed */
+ system('which iptables', $retval); // Debian, Ubuntu, Fedora
+ if ($retval === 0) {
+ /* Get the data of the log */
+ $data['output'] = '<h2>iptables -S (ipv4)</h2>'.shell_exec('iptables -S 2>/dev/null');
+
+ /*
+ * At this moment, there is no state (maybe later)
+ */
+ $state = 'no_state';
+ } else {
+ $state = 'no_state';
+ $data = '';
+ }
+
+
+ /* This monitoring is only available if fail2ban is installed */
+ system('which ip6tables', $retval); // Debian, Ubuntu, Fedora
+ if ($retval === 0) {
+ /* Get the data of the log */
+ $data['output'] .= '<br><h2>ip6tables -S (ipv6)</h2>'.shell_exec('ip6tables -S 2>/dev/null');
+
+ /*
+ * At this moment, there is no state (maybe later)
+ */
+ $state = 'no_state';
+ } else {
+ $state = 'no_state';
+ $data = '';
+ }
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/100-monitor_ispconfig_log.inc.php b/server/lib/classes/cron.d/100-monitor_ispconfig_log.inc.php
new file mode 100644
index 0000000..50674c4
--- /dev/null
+++ b/server/lib/classes/cron.d/100-monitor_ispconfig_log.inc.php
@@ -0,0 +1,146 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_monitor_ispconfig_log extends cronjob {
+
+ // job schedule
+ protected $_schedule = '*/5 * * * *';
+ protected $_run_at_new = true;
+
+ private $_tools = null;
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ /* used for all monitor cronjobs */
+ $app->load('monitor_tools');
+ $this->_tools = new monitor_tools();
+ /* end global section for monitor cronjobs */
+
+ /* the id of the server as int */
+ $server_id = intval($conf['server_id']);
+
+ /** The type of the data */
+ $type = 'log_ispconfig';
+
+ /* Get the data of the log */
+ $data = $this->_tools->_getLogData($type);
+
+ // Todo: the state should be calculated.
+ $state = 'ok';
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+
+ /** The type of the data */
+ $type = 'log_ispc_cron';
+
+ /* Get the data of the log */
+ $data = $this->_tools->_getLogData($type);
+
+ /*
+ * actually this info has no state.
+ * maybe someone knows better...???...
+ */
+ $state = 'no_state';
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ //* Ensure that output is encoded so that it does not break the serialize
+ if(is_array($res) && isset($res['data'])) $res['data'] = htmlentities($res['data']);
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/100-monitor_ispconfig_version.inc.php b/server/lib/classes/cron.d/100-monitor_ispconfig_version.inc.php
new file mode 100644
index 0000000..7f4688c
--- /dev/null
+++ b/server/lib/classes/cron.d/100-monitor_ispconfig_version.inc.php
@@ -0,0 +1,110 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_monitor_ispconfig_version extends cronjob {
+
+ // job schedule
+ protected $_schedule = '*/5 * * * *';
+ protected $_run_at_new = true;
+
+ private $_tools = null;
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ /* used for all monitor cronjobs */
+ $app->load('monitor_tools');
+ $this->_tools = new monitor_tools();
+ /* end global section for monitor cronjobs */
+
+ /* the id of the server as int */
+ $server_id = intval($conf['server_id']);
+
+ /** The type of the data */
+ $type = 'ispc_info';
+
+ /*
+ Fetch the data into a array
+ */
+ $data['name'] = ISPC_APP_TITLE;
+ $data['version'] = ISPC_APP_VERSION;
+
+ /* the ISPC-Version has no state. It is, what it is */
+ $state = 'no_state';
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/100-monitor_mail_log.inc.php b/server/lib/classes/cron.d/100-monitor_mail_log.inc.php
new file mode 100644
index 0000000..34194a7
--- /dev/null
+++ b/server/lib/classes/cron.d/100-monitor_mail_log.inc.php
@@ -0,0 +1,181 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_monitor_mail_log extends cronjob {
+
+ // job schedule
+ protected $_schedule = '*/5 * * * *';
+ protected $_run_at_new = true;
+
+ private $_tools = null;
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ /* used for all monitor cronjobs */
+ $app->load('monitor_tools');
+ $this->_tools = new monitor_tools();
+ /* end global section for monitor cronjobs */
+
+ /* the id of the server as int */
+ $server_id = intval($conf['server_id']);
+
+ /** The type of the data */
+ $type = 'log_mail';
+
+ /* Get the data of the log */
+ $data = $this->_tools->_getLogData($type);
+
+ /*
+ * actually this info has no state.
+ * maybe someone knows better...???...
+ */
+ $state = 'no_state';
+
+ /*
+ * Return the Result
+ */
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+ /** The type of the data */
+ $type = 'log_mail_warn';
+
+ /* Get the data of the log */
+ $data = $this->_tools->_getLogData($type);
+
+ /*
+ * actually this info has no state.
+ * maybe someone knows better...???...
+ */
+ $state = 'no_state';
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+ /** The type of the data */
+ $type = 'log_mail_err';
+
+ /* Get the data of the log */
+ $data = $this->_tools->_getLogData($type);
+
+ /*
+ * actually this info has no state.
+ * maybe someone knows better...???...
+ */
+ $state = 'no_state';
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/100-monitor_mail_queue.inc.php b/server/lib/classes/cron.d/100-monitor_mail_queue.inc.php
new file mode 100644
index 0000000..bda9031
--- /dev/null
+++ b/server/lib/classes/cron.d/100-monitor_mail_queue.inc.php
@@ -0,0 +1,138 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_monitor_mail_queue extends cronjob {
+
+ // job schedule
+ protected $_schedule = '*/5 * * * *';
+ protected $_run_at_new = true;
+
+ private $_tools = null;
+
+ private function _getIntArray($line) {
+ /** The array of float found */
+ $res = array();
+ /* First build a array from the line */
+ $data = explode(' ', $line);
+ /* then check if any item is a float */
+ foreach ($data as $item) {
+ if ($item . '' == (int) $item . '') {
+ $res[] = $item;
+ }
+ }
+ return $res;
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ /* used for all monitor cronjobs */
+ $app->load('monitor_tools');
+ $this->_tools = new monitor_tools();
+ /* end global section for monitor cronjobs */
+
+ /* the id of the server as int */
+ $server_id = intval($conf['server_id']);
+
+ /** The type of the data */
+ $type = 'mailq';
+
+ /* Get the data from the mailq */
+ $data['output'] = shell_exec('mailq');
+
+ /*
+ * The last line has more informations
+ */
+ $tmp = explode("\n", $data['output']);
+ $more = $tmp[sizeof($tmp) - 1];
+ $res = $this->_getIntArray($more);
+ $data['bytes'] = $res[0];
+ $data['requests'] = $res[1];
+
+ /** The state of the mailq. */
+ $state = 'ok';
+ if ($data['requests'] > 2000)
+ $state = 'info';
+ if ($data['requests'] > 5000)
+ $state = 'warning';
+ if ($data['requests'] > 8000)
+ $state = 'critical';
+ if ($data['requests'] > 10000)
+ $state = 'error';
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/100-monitor_mem_usage.inc.php b/server/lib/classes/cron.d/100-monitor_mem_usage.inc.php
new file mode 100644
index 0000000..91e3d41
--- /dev/null
+++ b/server/lib/classes/cron.d/100-monitor_mem_usage.inc.php
@@ -0,0 +1,124 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_monitor_mem_usage extends cronjob {
+
+ // job schedule
+ protected $_schedule = '*/5 * * * *';
+ protected $_run_at_new = true;
+
+ private $_tools = null;
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ /* used for all monitor cronjobs */
+ $app->load('monitor_tools');
+ $this->_tools = new monitor_tools();
+ /* end global section for monitor cronjobs */
+
+ /* the id of the server as int */
+ $server_id = intval($conf['server_id']);
+
+ /** The type of the data */
+ $type = 'mem_usage';
+
+ /*
+ Fetch the data into a array
+ */
+ $miData = shell_exec('cat /proc/meminfo');
+
+ $memInfo = explode("\n", $miData);
+
+ foreach ($memInfo as $line) {
+ $part = preg_split('/:/', $line);
+ $key = trim($part[0]);
+ $tmp = explode(' ', trim($part[1]));
+ $value = 0;
+ if ($tmp[1] == 'kB')
+ $value = $tmp[0] * 1024;
+ $data[$key] = $value;
+ }
+
+ /*
+ * actually this info has no state.
+ * maybe someone knows better...???...
+ */
+ $state = 'no_state';
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/100-monitor_mongodb.inc.php b/server/lib/classes/cron.d/100-monitor_mongodb.inc.php
new file mode 100644
index 0000000..a3d19c9
--- /dev/null
+++ b/server/lib/classes/cron.d/100-monitor_mongodb.inc.php
@@ -0,0 +1,127 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_monitor_mongodb extends cronjob {
+
+ // job schedule
+ protected $_schedule = '*/5 * * * *';
+ protected $_run_at_new = true;
+
+ private $_tools = null;
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ /* used for all monitor cronjobs */
+ $app->load('monitor_tools');
+ $this->_tools = new monitor_tools();
+ /* end global section for monitor cronjobs */
+
+ /* the id of the server as int */
+ $server_id = intval($conf['server_id']);
+
+ /** The type of the data */
+ $type = 'log_mongodb';
+
+ /* This monitoring is only available if MongoDB is installed */
+ system('which mongod', $retval); // Debian, Ubuntu, Fedora
+ if ($retval !== 0)
+ system('which mongod', $retval); // CentOS
+ if ($retval === 0) {
+ /* Get the data of the log */
+ $data = $this->_tools->_getLogData($type);
+
+ /*
+ * At this moment, there is no state (maybe later)
+ */
+ $state = 'no_state';
+ } else {
+ /*
+ * MongoDB is not installed, so there is no data and no state
+ *
+ * no_state, NOT unknown, because "unknown" is shown as state
+ * inside the GUI. no_state is hidden.
+ *
+ * We have to write NO DATA inside the DB, because the GUI
+ * could not know, if there is any dat, or not...
+ */
+ $state = 'no_state';
+ $data = '';
+ }
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/100-monitor_openvz.inc.php b/server/lib/classes/cron.d/100-monitor_openvz.inc.php
new file mode 100644
index 0000000..2abe6cc
--- /dev/null
+++ b/server/lib/classes/cron.d/100-monitor_openvz.inc.php
@@ -0,0 +1,183 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_monitor_openvz extends cronjob {
+
+ // job schedule
+ protected $_schedule = '*/5 * * * *';
+ protected $_run_at_new = true;
+
+ private $_tools = null;
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ /* used for all monitor cronjobs */
+ $app->load('monitor_tools');
+ $this->_tools = new monitor_tools();
+ /* end global section for monitor cronjobs */
+
+ /* the id of the server as int */
+ $server_id = intval($conf['server_id']);
+
+ /** The type of the data */
+ $type = 'openvz_veinfo';
+
+ /*
+ Fetch the data into a array
+ */
+ $app->load(openvz_tools);
+ $openVzTools = new openvz_tools();
+ $data = $openVzTools->getOpenVzVeInfo();
+
+ /* the VE-Info has no state. It is, what it is */
+ $state = 'no_state';
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+ /** The type of the data */
+ $type = 'openvz_beancounter';
+
+ /*
+ Fetch the data into a array
+ */
+ $app->load(openvz_tools);
+ $openVzTools = new openvz_tools();
+ $data = $openVzTools->getOpenVzVeBeanCounter();
+
+ /* calculate the state of the beancounter */
+ if ($data == '') {
+ $state = 'no_state';
+ } else {
+ $state = 'ok';
+
+ /* transfer this output-string into a array */
+ $test = explode("\n", $data);
+
+ /* the first list of the output is not needed */
+ array_shift($test);
+
+ /* now process all items of the rest */
+ foreach ($test as $item) {
+ /*
+ * eliminate all doubled spaces and spaces at the beginning and end
+ */
+ while (strpos($item, ' ') !== false) {
+ $item = str_replace(' ', ' ', $item);
+ }
+ $item = trim($item);
+
+ /*
+ * The failcounter is the LAST
+ */
+ if ($item != '') {
+ $tmp = explode(' ', $item);
+ $failCounter = $tmp[sizeof($tmp) - 1];
+ if ($failCounter > 0)
+ $state = 'info';
+ if ($failCounter > 50)
+ $state = 'warning';
+ if ($failCounter > 200)
+ $state = 'critical';
+ if ($failCounter > 10000)
+ $state = 'error';
+ }
+ }
+ }
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/100-monitor_os_version.inc.php b/server/lib/classes/cron.d/100-monitor_os_version.inc.php
new file mode 100644
index 0000000..a5f213e
--- /dev/null
+++ b/server/lib/classes/cron.d/100-monitor_os_version.inc.php
@@ -0,0 +1,112 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_monitor_os_version extends cronjob {
+
+ // job schedule
+ protected $_schedule = '*/5 * * * *';
+ protected $_run_at_new = true;
+
+ private $_tools = null;
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ /* used for all monitor cronjobs */
+ $app->load('monitor_tools');
+ $this->_tools = new monitor_tools();
+ /* end global section for monitor cronjobs */
+
+ /* the id of the server as int */
+ $server_id = $app->functions->intval($conf['server_id']);
+
+ /** The type of the data */
+ $type = 'os_info';
+
+ /*
+ Fetch the data into a array
+ */
+ $dist = $this->_tools->get_distname();
+
+ $data['name'] = $dist['name'];
+ $data['version'] = $dist['version'];
+
+ /* the OS has no state. It is, what it is */
+ $state = 'no_state';
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/100-monitor_raid.inc.php b/server/lib/classes/cron.d/100-monitor_raid.inc.php
new file mode 100644
index 0000000..969ff24
--- /dev/null
+++ b/server/lib/classes/cron.d/100-monitor_raid.inc.php
@@ -0,0 +1,263 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_monitor_raid extends cronjob {
+
+ // job schedule
+ protected $_schedule = '*/5 * * * *';
+ protected $_run_at_new = true;
+
+ private $_tools = null;
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ /* used for all monitor cronjobs */
+ $app->load('monitor_tools');
+ $this->_tools = new monitor_tools();
+ /* end global section for monitor cronjobs */
+
+ /* the id of the server as int */
+ $server_id = intval($conf['server_id']);
+
+ /** The type of the data */
+ $type = 'raid_state';
+
+ /*
+ * We support several RAID types, but if we can't find any of them, we have no data
+ */
+ $state = 'no_state';
+ $data['output'] = '';
+
+ /*
+ * Check, if Software-RAID is enabled
+ */
+ if (file_exists('/proc/mdstat')) {
+ /*
+ * Fetch the output
+ */
+ $data['output'] = shell_exec('cat /proc/mdstat');
+
+ /*
+ * Then calc the state.
+ */
+ $tmp = explode("\n", $data['output']);
+ $state = 'ok';
+ for ($i = 0; $i < sizeof($tmp); $i++) {
+ /* fetch the next line */
+ $line = $tmp[$i];
+
+ if ((strpos($line, '[U_]') !== false) || (strpos($line, '[_U]') !== false)) {
+ /* One Disk is not working.
+ * if the next line starts with "[>" or "[=" then
+ * recovery (resync) is in state and the state is
+ * information instead of critical
+ */
+ $nextLine = $tmp[$i + 1];
+ if ((strpos($nextLine, '[>') === false) && (strpos($nextLine, '[=') === false)) {
+ $state = $this->_tools->_setState($state, 'critical');
+ } else {
+ $state = $this->_tools->_setState($state, 'info');
+ }
+ }
+ if (strpos($line, '[__]') !== false) {
+ /* both Disk are not working */
+ $state = $this->_tools->_setState($state, 'error');
+ }
+ if (strpos($line, '[UU]') !== false) {
+ /* The disks are OK.
+ * if the next line starts with "[>" or "[=" then
+ * recovery (resync) is in state and the state is
+ * information instead of ok
+ */
+ $nextLine = $tmp[$i + 1];
+ if ((strpos($nextLine, '[>') === false) && (strpos($nextLine, '[=') === false)) {
+ $state = $this->_tools->_setState($state, 'ok');
+ } else {
+ $state = $this->_tools->_setState($state, 'info');
+ }
+ }
+ }
+ }
+ /*
+ * Check, if we have mpt-status installed (LSIsoftware-raid)
+ */
+ if (file_exists('/proc/mpt/summary')) {
+ system('which mpt-status', $retval);
+ if ($retval === 0) {
+ /*
+ * Fetch the output
+ */
+ $data['output'] = shell_exec('mpt-status --autoload');
+
+ /*
+ * Then calc the state.
+ */
+ $state = 'ok';
+ if(is_array($data['output'])) {
+ foreach ($data['output'] as $item) {
+ /*
+ * The output contains information for every RAID and every HDD.
+ * We only need the state of the RAID
+ */
+ if (strpos($item, 'state ') !== false) {
+ /*
+ * We found a raid, process the state of it
+ */
+ if (strpos($item, ' ONLINE ') !== false) {
+ $this->_tools->_setState($state, 'ok');
+ } elseif (strpos($item, ' OPTIMAL ') !== false) {
+ $this->_tools->_setState($state, 'ok');
+ } elseif (strpos($item, ' INITIAL ') !== false) {
+ $this->_tools->_setState($state, 'info');
+ } elseif (strpos($item, ' INACTIVE ') !== false) {
+ $this->_tools->_setState($state, 'critical');
+ } elseif (strpos($item, ' RESYNC ') !== false) {
+ $this->_tools->_setState($state, 'info');
+ } elseif (strpos($item, ' DEGRADED ') !== false) {
+ $this->_tools->_setState($state, 'critical');
+ } else {
+ /* we don't know the state. so we set the state to critical, that the
+ * admin is warned, that something is wrong
+ */
+ $this->_tools->_setState($state, 'critical');
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * 3ware Controller
+ */
+ system('which tw_cli', $retval);
+ if($retval === 0) {
+
+ $data['output'] = shell_exec('tw_cli info c0');
+
+ $state = 'ok';
+ if(is_array($data['output'])) {
+ foreach ($data['output'] as $item) {
+ if (strpos($item, 'RAID') !== false) {
+ if (strpos($item, ' VERIFYING ') !== false) {
+ $this->_tools->_setState($state, 'info');
+ }
+ else if (strpos($item, ' MIGRATE-PAUSED ') !== false) {
+ $this->_tools->_setState($state, 'info');
+ }
+ else if (strpos($item, ' MIGRATING ') !== false) {
+ $this->_tools->_setState($state, 'ok');
+ }
+ else if (strpos($item, ' INITIALIZING ') !== false) {
+ $this->_tools->_setState($state, 'info');
+ }
+ else if (strpos($item, ' INIT-PAUSED ') !== false) {
+ $this->_tools->_setState($state, 'info');
+ }
+ else if (strpos($item, ' REBUILDING ') !== false) {
+ $this->_tools->_setState($state, 'info');
+ }
+ else if (strpos($item, ' REBUILD-PAUSED ') !== false) {
+ $this->_tools->_setState($state, 'warning');
+ }
+ else if (strpos($item, ' RECOVERY ') !== false) {
+ $this->_tools->_setState($state, 'warning');
+ }
+ else if (strpos($item, ' DEGRADED ') !== false) {
+ $this->_tools->_setState($state, 'critical');
+ }
+ else if (strpos($item, ' UNKNOWN ') !== false) {
+ $this->_tools->_setState($state, 'critical');
+ }
+ else if (strpos($item, ' OK ') !== false) {
+ $this->_tools->_setState($state, 'ok');
+ }
+ else if (strpos($item, ' OPTIMAL ') !== false) {
+ $this->_tools->_setState($state, 'ok');
+ }
+ else {
+ $this->_tools->_setState($state, 'critical');
+ }
+ }
+ }
+ }
+ }
+
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/100-monitor_rkhunter.inc.php b/server/lib/classes/cron.d/100-monitor_rkhunter.inc.php
new file mode 100644
index 0000000..ba992da
--- /dev/null
+++ b/server/lib/classes/cron.d/100-monitor_rkhunter.inc.php
@@ -0,0 +1,127 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_monitor_rkhunter extends cronjob {
+
+ // job schedule
+ protected $_schedule = '0 0 * * *';
+ protected $_run_at_new = true;
+
+ private $_tools = null;
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ /* used for all monitor cronjobs */
+ $app->load('monitor_tools');
+ $this->_tools = new monitor_tools();
+ /* end global section for monitor cronjobs */
+
+ /* the id of the server as int */
+ $server_id = intval($conf['server_id']);
+
+ /** The type of the data */
+ $type = 'rkhunter';
+
+ /* This monitoring is only available if rkhunter is installed */
+ system('which rkhunter', $retval);
+ if ($retval === 0) {
+ /*
+ * Fetch the output
+ */
+ $data['output'] = shell_exec('rkhunter --update --checkall --nocolors --skip-keypress');
+
+ /*
+ * At this moment, there is no state (maybe later)
+ */
+ $state = 'no_state';
+ } else {
+ /*
+ * rkhunter is not installed, so there is no data and no state
+ *
+ * no_state, NOT unknown, because "unknown" is shown as state
+ * inside the GUI. no_state is hidden.
+ *
+ * We have to write NO DATA inside the DB, because the GUI
+ * could not know, if there is any dat, or not...
+ */
+ $state = 'no_state';
+ $data['output'] = '';
+ }
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/100-monitor_server.inc.php b/server/lib/classes/cron.d/100-monitor_server.inc.php
new file mode 100644
index 0000000..b732578
--- /dev/null
+++ b/server/lib/classes/cron.d/100-monitor_server.inc.php
@@ -0,0 +1,133 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_monitor_server extends cronjob {
+
+ // job schedule
+ protected $_schedule = '*/5 * * * *';
+ protected $_run_at_new = true;
+
+ private $_tools = null;
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ /* used for all monitor cronjobs */
+ $app->load('monitor_tools');
+ $this->_tools = new monitor_tools();
+ /* end global section for monitor cronjobs */
+
+ /* the id of the server as int */
+ $server_id = intval($conf['server_id']);
+
+ /** The type of the data */
+ $type = 'server_load';
+
+ /*
+ Fetch the data into a array
+ */
+ $procUptime = shell_exec("cat /proc/uptime | cut -f1 -d' '");
+ $data['up_days'] = floor($procUptime / 86400);
+ $data['up_hours'] = floor(($procUptime - $data['up_days'] * 86400) / 3600);
+ $data['up_minutes'] = floor(($procUptime - $data['up_days'] * 86400 - $data['up_hours'] * 3600) / 60);
+
+ $data['uptime'] = shell_exec('uptime');
+
+ $tmp = explode(',', $data['uptime'], 4);
+ $tmpUser = explode(' ', trim($tmp[2]));
+ $data['user_online'] = intval($tmpUser[0]);
+
+ //* New Load Average code to fix "always zero" bug in non-english distros. NEEDS TESTING
+ $loadTmp = shell_exec("cat /proc/loadavg | cut -f1-3 -d' '");
+ $load = explode(' ', $loadTmp);
+ $data['load_1'] = floatval(str_replace(',', '.', $load[0]));
+ $data['load_5'] = floatval(str_replace(',', '.', $load[1]));
+ $data['load_15'] = floatval(str_replace(',', '.', $load[2]));
+
+ /** The state of the server-load. */
+ $state = 'ok';
+ if ($data['load_1'] > 20)
+ $state = 'info';
+ if ($data['load_1'] > 50)
+ $state = 'warning';
+ if ($data['load_1'] > 100)
+ $state = 'critical';
+ if ($data['load_1'] > 150)
+ $state = 'error';
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/100-monitor_services.inc.php b/server/lib/classes/cron.d/100-monitor_services.inc.php
new file mode 100644
index 0000000..f3e9e72
--- /dev/null
+++ b/server/lib/classes/cron.d/100-monitor_services.inc.php
@@ -0,0 +1,94 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_monitor_services extends cronjob {
+
+ // job schedule
+ protected $_schedule = '*/5 * * * *';
+ protected $_run_at_new = true;
+
+ private $_tools = null;
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ /* used for all monitor cronjobs */
+ $app->load('monitor_tools');
+ $this->_tools = new monitor_tools();
+ /* end global section for monitor cronjobs */
+
+ /*
+ * First we get the Monitoring-data from the tools
+ */
+ $res = $this->_tools->monitorServices();
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/100-monitor_syslog.inc.php b/server/lib/classes/cron.d/100-monitor_syslog.inc.php
new file mode 100644
index 0000000..8aa8745
--- /dev/null
+++ b/server/lib/classes/cron.d/100-monitor_syslog.inc.php
@@ -0,0 +1,153 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_monitor_syslog extends cronjob {
+
+ // job schedule
+ protected $_schedule = '*/5 * * * *';
+ protected $_run_at_new = true;
+
+ private $_tools = null;
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ /* used for all monitor cronjobs */
+ $app->load('monitor_tools');
+ $this->_tools = new monitor_tools();
+ /* end global section for monitor cronjobs */
+
+ /* the id of the server as int */
+ $server_id = intval($conf['server_id']);
+
+ /** The type of the data */
+ $type = 'sys_log';
+
+ /*
+ * is there any warning or error for this server?
+ */
+ $state = 'ok';
+ $dbData = $app->dbmaster->queryAllRecords('SELECT loglevel FROM sys_log WHERE server_id = ' . $server_id . ' AND loglevel > 0');
+ if (is_array($dbData)) {
+ foreach ($dbData as $item) {
+ if ($item['loglevel'] == 1)
+ $state = $this->_tools->_setState($state, 'warning');
+ if ($item['loglevel'] == 2)
+ $state = $this->_tools->_setState($state, 'error');
+ }
+ }
+
+ /** There is no monitor-data because the data is in the sys_log table */
+ $data['output'] = '';
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+ /** The type of the data */
+ $type = 'log_messages';
+
+ /* Get the data of the log */
+ $data = $this->_tools->_getLogData($type);
+
+ /*
+ * actually this info has no state.
+ * maybe someone knows better...???...
+ */
+ $state = 'no_state';
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/100-monitor_system_update.inc.php b/server/lib/classes/cron.d/100-monitor_system_update.inc.php
new file mode 100644
index 0000000..022d667
--- /dev/null
+++ b/server/lib/classes/cron.d/100-monitor_system_update.inc.php
@@ -0,0 +1,208 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_monitor_system_update extends cronjob {
+
+ // job schedule
+ protected $_schedule = '0 * * * *';
+ protected $_run_at_new = true;
+
+ private $_tools = null;
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ /* used for all monitor cronjobs */
+ $app->load('monitor_tools');
+ $this->_tools = new monitor_tools();
+ /* end global section for monitor cronjobs */
+
+ /* the id of the server as int */
+ $server_id = intval($conf['server_id']);
+
+ /** The type of the data */
+ $type = 'system_update';
+
+ /* This monitoring is only available on Debian or Ubuntu */
+ if (file_exists('/etc/debian_version')) {
+
+ /*
+ * first update the "apt database"
+ */
+ shell_exec('apt-get update');
+
+ /*
+ * Then test the upgrade.
+ * if there is any output, then there is a needed update
+ */
+ $aptData = shell_exec('apt-get -s -qq dist-upgrade');
+ if ($aptData == '') {
+ /* There is nothing to update! */
+ $state = 'ok';
+ } else {
+ /*
+ * There is something to update! this is in most cases not critical, so we can
+ * do a system-update once a month or so...
+ */
+ $state = 'info';
+ }
+
+ /*
+ * Fetch the output
+ */
+ $data['output'] = $aptData;
+ } elseif (file_exists('/etc/gentoo-release')) {
+
+ /*
+ * first update the portage tree
+ */
+
+ // In keeping with gentoo's rsync policy, don't update to frequently (every four hours - taken from http://www.gentoo.org/doc/en/source_mirrors.xml)
+ $do_update = true;
+ if (file_exists('/usr/portage/metadata/timestamp.chk')) {
+ $datetime = file_get_contents('/usr/portage/metadata/timestamp.chk');
+ $datetime = trim($datetime);
+
+ $dstamp = strtotime($datetime);
+ if ($dstamp) {
+ $checkat = $dstamp + 14400; // + 4hours
+ if (mktime() < $checkat) {
+ $do_update = false;
+ }
+ }
+ }
+
+ if ($do_update) {
+ shell_exec('emerge --sync --quiet');
+ }
+
+ /*
+ * Then test the upgrade.
+ * if there is any output, then there is a needed update
+ */
+ $emergeData = shell_exec('glsa-check -t affected');
+ if ($emergeData == '') {
+ /* There is nothing to update! */
+ $state = 'ok';
+ $data['output'] = 'No unapplied GLSA\'s found on the system.';
+ } else {
+ /* There is something to update! */
+ $state = 'info';
+ $data['output'] = shell_exec('glsa-check -pv --nocolor affected 2>/dev/null');
+ }
+ } elseif (file_exists('/etc/SuSE-release')) {
+
+ /*
+ * update and find the upgrade.
+ * if there is any output, then there is a needed update
+ */
+ $aptData = shell_exec('zypper -q lu');
+ if ($aptData == '') {
+ /* There is nothing to update! */
+ $state = 'ok';
+ } else {
+ /*
+ * There is something to update! this is in most cases not critical, so we can
+ * do a system-update once a month or so...
+ */
+ $state = 'info';
+ }
+
+ /*
+ * Fetch the output
+ */
+ $data['output'] = shell_exec('zypper lu');
+ } else {
+ /*
+ * It is not Debian/Ubuntu, so there is no data and no state
+ *
+ * no_state, NOT unknown, because "unknown" is shown as state
+ * inside the GUI. no_state is hidden.
+ *
+ * We have to write NO DATA inside the DB, because the GUI
+ * could not know, if there is any dat, or not...
+ */
+ $state = 'no_state';
+ $data['output'] = '';
+ }
+
+ $res = array();
+ $res['server_id'] = $server_id;
+ $res['type'] = $type;
+ $res['data'] = $data;
+ $res['state'] = $state;
+
+ //* Ensure that output is encoded so that it does not break the serialize
+ //$res['data']['output'] = htmlentities($res['data']['output']);
+ $res['data']['output'] = htmlentities($res['data']['output'],ENT_QUOTES,'UTF-8');
+
+ /*
+ * Insert the data into the database
+ */
+ $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
+ 'VALUES (' .
+ $res['server_id'] . ', ' .
+ "'" . $app->dbmaster->quote($res['type']) . "', " .
+ 'UNIX_TIMESTAMP(), ' .
+ "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
+ "'" . $res['state'] . "'" .
+ ')';
+ $app->dbmaster->query($sql);
+
+ /* The new data is written, now we can delete the old one */
+ $this->_tools->delOldRecords($res['type'], $res['server_id']);
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/150-awstats.inc.php b/server/lib/classes/cron.d/150-awstats.inc.php
new file mode 100644
index 0000000..0638f09
--- /dev/null
+++ b/server/lib/classes/cron.d/150-awstats.inc.php
@@ -0,0 +1,183 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_awstats extends cronjob {
+
+ // job schedule
+ protected $_schedule = '0 0 * * *';
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ #######################################################################################################
+ // Create awstats statistics
+ #######################################################################################################
+
+ $sql = "SELECT domain_id, domain, document_root, web_folder, type, system_user, system_group, parent_domain_id FROM web_domain WHERE (type = 'vhost' or type = 'vhostsubdomain') and stats_type = 'awstats' AND server_id = ".$conf['server_id'];
+ $records = $app->db->queryAllRecords($sql);
+
+ $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
+
+ foreach($records as $rec) {
+ //$yesterday = date('Ymd',time() - 86400);
+ $yesterday = date('Ymd',strtotime("-1 day", time()));
+
+ $log_folder = 'log';
+ if($rec['type'] == 'vhostsubdomain') {
+ $tmp = $app->db->queryOneRecord('SELECT `domain` FROM web_domain WHERE domain_id = '.intval($rec['parent_domain_id']));
+ $subdomain_host = preg_replace('/^(.*)\.' . preg_quote($tmp['domain'], '/') . '$/', '$1', $rec['domain']);
+ if($subdomain_host == '') $subdomain_host = 'web'.$rec['domain_id'];
+ $log_folder .= '/' . $subdomain_host;
+ unset($tmp);
+ }
+ $logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/'.$yesterday.'-access.log');
+ if(!@is_file($logfile)) {
+ $logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/'.$yesterday.'-access.log.gz');
+ if(!@is_file($logfile)) {
+ continue;
+ }
+ }
+ $web_folder = ($rec['type'] == 'vhostsubdomain' ? $rec['web_folder'] : 'web');
+ $domain = escapeshellcmd($rec['domain']);
+ $statsdir = escapeshellcmd($rec['document_root'].'/'.$web_folder.'/stats');
+ $awstats_pl = $web_config['awstats_pl'];
+ $awstats_buildstaticpages_pl = $web_config['awstats_buildstaticpages_pl'];
+
+ $awstats_conf_dir = $web_config['awstats_conf_dir'];
+ $awstats_website_conf_file = $web_config['awstats_conf_dir'].'/awstats.'.$domain.'.conf';
+
+ if(is_file($awstats_website_conf_file)) unlink($awstats_website_conf_file);
+
+ $sql = "SELECT domain FROM web_domain WHERE (type = 'alias' OR type = 'subdomain') AND parent_domain_id = ".$rec['domain_id'];
+ $aliases = $app->db->queryAllRecords($sql);
+ $aliasdomain = '';
+
+ if(is_array($aliases)) {
+ foreach ($aliases as $alias) {
+ $aliasdomain.= ' '.$alias['domain']. ' www.'.$alias['domain'];
+ }
+ }
+
+ if(!is_file($awstats_website_conf_file)) {
+ $awstats_conf_file_content = 'Include "'.$awstats_conf_dir.'/awstats.conf"
+ LogFile="/var/log/ispconfig/httpd/'.$domain.'/yesterday-access.log"
+ SiteDomain="'.$domain.'"
+ HostAliases="www.'.$domain.' localhost 127.0.0.1'.$aliasdomain.'"';
+ file_put_contents($awstats_website_conf_file,$awstats_conf_file_content);
+ }
+
+ if(!@is_dir($statsdir)) mkdir($statsdir);
+ if(is_link('/var/log/ispconfig/httpd/'.$domain.'/yesterday-access.log')) unlink('/var/log/ispconfig/httpd/'.$domain.'/yesterday-access.log');
+ symlink($logfile,'/var/log/ispconfig/httpd/'.$domain.'/yesterday-access.log');
+
+ $awmonth = date("n");
+ $awyear = date("Y");
+
+ if (date("d") == 1) {
+ $awmonth = date("m")-1;
+ if (date("m") == 1) {
+ $awyear = date("Y")-1;
+ $awmonth = "12";
+ }
+ }
+
+ // awstats_buildstaticpages.pl -update -config=mydomain.com -lang=en -dir=/var/www/domain.com/'.$web_folder.'/stats -awstatsprog=/path/to/awstats.pl
+ // $command = "$awstats_buildstaticpages_pl -update -config='$domain' -lang=".$conf['language']." -dir='$statsdir' -awstatsprog='$awstats_pl'";
+
+ $command = "$awstats_buildstaticpages_pl -month='$awmonth' -year='$awyear' -update -config='$domain' -lang=".$conf['language']." -dir='$statsdir' -awstatsprog='$awstats_pl'";
+
+ if (date("d") == 2) {
+ $awmonth = date("m")-1;
+ if (date("m") == 1) {
+ $awyear = date("Y")-1;
+ $awmonth = "12";
+ }
+
+ $statsdirold = $statsdir."/".$awyear."-".$awmonth."/";
+ mkdir($statsdirold);
+ $files = scandir($statsdir);
+ foreach ($files as $file) {
+ if (substr($file,0,1) != "." && !is_dir("$statsdir"."/"."$file") && substr($file,0,1) != "w" && substr($file,0,1) != "i") copy("$statsdir"."/"."$file","$statsdirold"."$file");
+ }
+ }
+
+
+ if($awstats_pl != '' && $awstats_buildstaticpages_pl != '' && fileowner($awstats_pl) == 0 && fileowner($awstats_buildstaticpages_pl) == 0) {
+ exec($command);
+ if(is_file($rec['document_root'].'/'.$web_folder.'/stats/index.html')) unlink($rec['document_root'].'/'.$web_folder.'/stats/index.html');
+ rename($rec['document_root'].'/'.$web_folder.'/stats/awstats.'.$domain.'.html',$rec['document_root'].'/'.$web_folder.'/stats/awsindex.html');
+ if(!is_file($rec['document_root']."/".$web_folder."/stats/index.php")) {
+ if(file_exists("/usr/local/ispconfig/server/conf-custom/awstats_index.php.master")) {
+ copy("/usr/local/ispconfig/server/conf-custom/awstats_index.php.master",$rec['document_root']."/".$web_folder."/stats/index.php");
+ } else {
+ copy("/usr/local/ispconfig/server/conf/awstats_index.php.master",$rec['document_root']."/".$web_folder."/stats/index.php");
+ }
+ }
+
+ $app->log('Created awstats statistics with command: '.$command,LOGLEVEL_DEBUG);
+ } else {
+ $app->log("No awstats statistics created. Either $awstats_pl or $awstats_buildstaticpages_pl is not owned by root user.",LOGLEVEL_WARN);
+ }
+
+ if(is_file($rec['document_root']."/".$web_folder."/stats/index.php")) {
+ chown($rec['document_root']."/".$web_folder."/stats/index.php",$rec['system_user']);
+ chgrp($rec['document_root']."/".$web_folder."/stats/index.php",$rec['system_group']);
+ }
+
+ }
+
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/150-webalizer.inc.php b/server/lib/classes/cron.d/150-webalizer.inc.php
new file mode 100644
index 0000000..ba75b8b
--- /dev/null
+++ b/server/lib/classes/cron.d/150-webalizer.inc.php
@@ -0,0 +1,142 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_webalizer extends cronjob {
+
+ // job schedule
+ protected $_schedule = '0 0 * * *';
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ #######################################################################################################
+ // Create webalizer statistics
+ #######################################################################################################
+
+ function setConfigVar( $filename, $varName, $varValue, $append = 0 ) {
+ if($lines = @file($filename)) {
+ $out = '';
+ $found = 0;
+ foreach($lines as $line) {
+ @list($key, $value) = preg_split('/[\t= ]+/', $line, 2);
+ if($key == $varName) {
+ $out .= $varName.' '.$varValue."\n";
+ $found = 1;
+ } else {
+ $out .= $line;
+ }
+ }
+ if($found == 0) {
+ //* add \n if the last line does not end with \n or \r
+ if(substr($out,-1) != "\n" && substr($out,-1) != "\r") $out .= "\n";
+ //* add the new line at the end of the file
+ if($append == 1) $out .= $varName.' '.$varValue."\n";
+ }
+
+ file_put_contents($filename,$out);
+ }
+ }
+
+
+ $sql = "SELECT domain_id, domain, document_root, web_folder, type, parent_domain_id FROM web_domain WHERE (type = 'vhost' or type = 'vhostsubdomain') and stats_type = 'webalizer' AND server_id = ".$conf['server_id'];
+ $records = $app->db->queryAllRecords($sql);
+
+ foreach($records as $rec) {
+ //$yesterday = date('Ymd',time() - 86400);
+ $yesterday = date('Ymd',strtotime("-1 day", time()));
+
+ $log_folder = 'log';
+ if($rec['type'] == 'vhostsubdomain') {
+ $tmp = $app->db->queryOneRecord('SELECT `domain` FROM web_domain WHERE domain_id = '.intval($rec['parent_domain_id']));
+ $subdomain_host = preg_replace('/^(.*)\.' . preg_quote($tmp['domain'], '/') . '$/', '$1', $rec['domain']);
+ if($subdomain_host == '') $subdomain_host = 'web'.$rec['domain_id'];
+ $log_folder .= '/' . $subdomain_host;
+ unset($tmp);
+ }
+ $logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/'.$yesterday.'-access.log');
+ if(!@is_file($logfile)) {
+ $logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/'.$yesterday.'-access.log.gz');
+ if(!@is_file($logfile)) {
+ continue;
+ }
+ }
+
+ $domain = escapeshellcmd($rec['domain']);
+ $statsdir = escapeshellcmd($rec['document_root'].'/'.($rec['type'] == 'vhostsubdomain' ? $rec['web_folder'] : 'web').'/stats');
+ $webalizer = '/usr/bin/webalizer';
+ $webalizer_conf_main = '/etc/webalizer/webalizer.conf';
+ $webalizer_conf = escapeshellcmd($rec['document_root'].'/log/webalizer.conf');
+
+ if(is_file($statsdir.'/index.php')) unlink($statsdir.'/index.php');
+
+ if(!@is_file($webalizer_conf)) {
+ copy($webalizer_conf_main,$webalizer_conf);
+ }
+
+ if(@is_file($webalizer_conf)) {
+ setConfigVar($webalizer_conf, 'Incremental', 'yes');
+ setConfigVar($webalizer_conf, 'IncrementalName', $statsdir.'/webalizer.current');
+ setConfigVar($webalizer_conf, 'HistoryName', $statsdir.'/webalizer.hist');
+ }
+
+
+ if(!@is_dir($statsdir)) mkdir($statsdir);
+ exec("$webalizer -c $webalizer_conf -n $domain -s $domain -r $domain -q -T -p -o $statsdir $logfile");
+ }
+
+
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/200-logfiles.inc.php b/server/lib/classes/cron.d/200-logfiles.inc.php
new file mode 100644
index 0000000..862f0f4
--- /dev/null
+++ b/server/lib/classes/cron.d/200-logfiles.inc.php
@@ -0,0 +1,271 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_logfiles extends cronjob {
+
+ // job schedule
+ protected $_schedule = '0 0 * * *';
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ #######################################################################################################
+ // Make the web logfiles directories world readable to enable ftp access
+ #######################################################################################################
+
+ if(is_dir('/var/log/ispconfig/httpd')) exec('chmod +r /var/log/ispconfig/httpd/*');
+
+ #######################################################################################################
+ // Manage and compress web logfiles and create traffic statistics
+ #######################################################################################################
+
+ $sql = "SELECT domain_id, domain, type, document_root, web_folder, parent_domain_id FROM web_domain WHERE (type = 'vhost' or type = 'vhostsubdomain') AND server_id = ".$conf['server_id'];
+ $records = $app->db->queryAllRecords($sql);
+ foreach($records as $rec) {
+
+ //* create traffic statistics based on yesterdays access log file
+ $yesterday = date('Ymd',time() - 86400);
+
+ $log_folder = 'log';
+ if($rec['type'] == 'vhostsubdomain') {
+ $tmp = $app->db->queryOneRecord('SELECT `domain` FROM web_domain WHERE domain_id = '.intval($rec['parent_domain_id']));
+ $subdomain_host = preg_replace('/^(.*)\.' . preg_quote($tmp['domain'], '/') . '$/', '$1', $rec['domain']);
+ if($subdomain_host == '') $subdomain_host = 'web'.$rec['domain_id'];
+ $log_folder .= '/' . $subdomain_host;
+ unset($tmp);
+ }
+
+ $logfile = $rec['document_root'].'/' . $log_folder . '/'.$yesterday.'-access.log';
+ $total_bytes = 0;
+
+ $handle = @fopen($logfile, "r");
+ if ($handle) {
+ while (($line = fgets($handle, 4096)) !== false) {
+ if (preg_match('/^\S+ \S+ \S+ \[.*?\] "\S+.*?" \d+ (\d+) ".*?" ".*?"/', $line, $m)) {
+ $total_bytes += intval($m[1]);
+ }
+ }
+
+ //* Insert / update traffic in master database
+ $traffic_date = date('Y-m-d',time() - 86400);
+ $tmp = $app->dbmaster->queryOneRecord("select hostname from web_traffic where hostname='".$rec['domain']."' and traffic_date='".$traffic_date."'");
+ if(is_array($tmp) && count($tmp) > 0) {
+ $sql = "update web_traffic set traffic_bytes=traffic_bytes+"
+ . $total_bytes
+ . " where hostname='" . $rec['domain']
+ . "' and traffic_date='" . $traffic_date . "'";
+ } else {
+ $sql = "insert into web_traffic (hostname, traffic_date, traffic_bytes) values ('".$rec['domain']."', '".$traffic_date."', '".$total_bytes."')";
+ }
+ $app->dbmaster->query($sql);
+
+ fclose($handle);
+ }
+
+ $yesterday2 = date('Ymd',time() - 86400*2);
+ $logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/'.$yesterday2.'-access.log');
+
+ //* Compress logfile
+ if(@is_file($logfile)) {
+ // Compress yesterdays logfile
+ exec("gzip -c $logfile > $logfile.gz");
+ unlink($logfile);
+ }
+
+ // rotate and compress the error.log when it exceeds a size of 10 MB
+ $logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/error.log');
+ if(is_file($logfile) && filesize($logfile) > 10000000) {
+ exec("gzip -c $logfile > $logfile.1.gz");
+ exec("cat /dev/null > $logfile");
+ }
+
+ // delete logfiles after 30 days
+ $month_ago = date('Ymd',time() - 86400 * 30);
+ $logfile = escapeshellcmd($rec['document_root'].'/' . $log_folder . '/'.$month_ago.'-access.log.gz');
+ if(@is_file($logfile)) {
+ unlink($logfile);
+ }
+
+ //* Delete older Log files, in case that we missed them before due to serverdowntimes.
+ $datepart = date('Ym',time() - 86400 * 31 * 2);
+
+ $logfile = escapeshellcmd($rec['document_root']).'/' . $log_folder . '/'.$datepart.'*-access.log.gz';
+ exec('rm -f '.$logfile);
+
+ $logfile = escapeshellcmd($rec['document_root']).'/' . $log_folder . '/'.$datepart.'*-access.log';
+ exec('rm -f '.$logfile);
+ }
+
+ //* Delete old logfiles in /var/log/ispconfig/httpd/ that were created by vlogger for the hostname of the server
+ exec('hostname -f', $tmp_hostname);
+ if($tmp_hostname[0] != '' && is_dir('/var/log/ispconfig/httpd/'.$tmp_hostname[0])) {
+ exec('cd /var/log/ispconfig/httpd/'.$tmp_hostname[0]."; find . -mtime +30 -name '*.log' | xargs rm > /dev/null 2> /dev/null");
+ }
+ unset($tmp_hostname);
+
+ #######################################################################################################
+ // Rotate the ispconfig.log file
+ #######################################################################################################
+
+ // rotate the ispconfig.log when it exceeds a size of 10 MB
+ $logfile = $conf['ispconfig_log_dir'].'/ispconfig.log';
+ if(is_file($logfile) && filesize($logfile) > 10000000) {
+ exec("gzip -c $logfile > $logfile.1.gz");
+ exec("cat /dev/null > $logfile");
+ }
+
+ // rotate the cron.log when it exceeds a size of 10 MB
+ $logfile = $conf['ispconfig_log_dir'].'/cron.log';
+ if(is_file($logfile) && filesize($logfile) > 10000000) {
+ exec("gzip -c $logfile > $logfile.1.gz");
+ exec("cat /dev/null > $logfile");
+ }
+
+ // rotate the auth.log when it exceeds a size of 10 MB
+ $logfile = $conf['ispconfig_log_dir'].'/auth.log';
+ if(is_file($logfile) && filesize($logfile) > 10000000) {
+ exec("gzip -c $logfile > $logfile.1.gz");
+ exec("cat /dev/null > $logfile");
+ }
+
+ #######################################################################################################
+ // Cleanup website tmp directories
+ #######################################################################################################
+
+ $sql = "SELECT domain_id, domain, document_root, system_user FROM web_domain WHERE server_id = ".$conf['server_id'];
+ $records = $app->db->queryAllRecords($sql);
+ $app->uses('system');
+ if(is_array($records)) {
+ foreach($records as $rec){
+ $tmp_path = realpath(escapeshellcmd($rec['document_root'].'/tmp'));
+ if($tmp_path != '' && strlen($tmp_path) > 10 && is_dir($tmp_path) && $app->system->is_user($rec['system_user'])){
+ exec('cd '.$tmp_path."; find . -mtime +1 -name 'sess_*' | grep -v -w .no_delete | xargs rm > /dev/null 2> /dev/null");
+ }
+ }
+ }
+
+ #######################################################################################################
+ // Cleanup logs in master database (only the "master-server")
+ #######################################################################################################
+
+ if ($app->dbmaster == $app->db) {
+ /** 7 days */
+ $tstamp = time() - (60*60*24*7);
+
+ /*
+ * Keep 7 days in sys_log
+ * (we can delete the old items, because if they are OK, they don't interrest anymore
+ * if they are NOT ok, the server will try to process them in 1 minute and so the
+ * error appears again after 1 minute. So it is no problem to delete the old one!
+ */
+ $sql = "DELETE FROM sys_log WHERE tstamp < " . $tstamp . " AND server_id != 0";
+ $app->dbmaster->query($sql);
+
+ /*
+ * Delete all remote-actions "done" and older than 7 days
+ * ATTENTION: We have the same problem as described in cleaning the datalog. We must not
+ * delete the last entry
+ */
+ $sql = "SELECT max(action_id) FROM sys_remoteaction";
+ $res = $app->dbmaster->queryOneRecord($sql);
+ $maxId = $res['max(action_id)'];
+ $sql = "DELETE FROM sys_remoteaction " .
+ "WHERE tstamp < " . $tstamp . " " .
+ " AND action_state = 'ok' " .
+ " AND action_id <" . intval($maxId);
+ $app->dbmaster->query($sql);
+
+ /*
+ * The sys_datalog is more difficult.
+ * 1) We have to keet ALL entries with
+ * server_id=0, because they depend on ALL servers (even if they are not
+ * actually in the system (and will be insered in 3 days or so).
+ * 2) We have to keey ALL entries which are not actually precessed by the
+ * server never mind how old they are!
+ * 3) We have to keep the entry with the highest autoinc-id, because mysql calculates the
+ * autoinc-id as "new value = max(row) +1" and does not store this in a separate table.
+ * This means, if we delete to entry with the highest autoinc-value then this value is
+ * reused as autoinc and so there are more than one entries with the same value (over
+ * for example 4 Weeks). This is confusing for our system.
+ * ATTENTION 2) and 3) is in some case NOT the same! so we have to check both!
+ */
+
+ /* First we need all servers and the last sys_datalog-id they processed */
+ $sql = "SELECT server_id, updated FROM server ORDER BY server_id";
+ $records = $app->dbmaster->queryAllRecords($sql);
+
+ /* Then we need the highest value ever */
+ $sql = "SELECT max(datalog_id) FROM sys_datalog";
+ $res = $app->dbmaster->queryOneRecord($sql);
+ $maxId = $res['max(datalog_id)'];
+
+ /* Then delete server by server */
+ foreach($records as $server) {
+ $tmp_server_id = intval($server['server_id']);
+ if($tmp_server_id > 0) {
+ $sql = "DELETE FROM sys_datalog " .
+ "WHERE tstamp < " . $tstamp .
+ " AND server_id = " . intval($server['server_id']) .
+ " AND datalog_id < " . intval($server['updated']) .
+ " AND datalog_id < " . intval($maxId);
+ }
+ // echo $sql . "\n";
+ $app->dbmaster->query($sql);
+ }
+ }
+
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/300-quota_notify.inc.php b/server/lib/classes/cron.d/300-quota_notify.inc.php
new file mode 100644
index 0000000..c2ce895
--- /dev/null
+++ b/server/lib/classes/cron.d/300-quota_notify.inc.php
@@ -0,0 +1,479 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_quota_notify extends cronjob {
+
+ // job schedule
+ protected $_schedule = '0 0 * * *';
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ #########
+ // function for sending notification emails
+ #########
+ function send_notification_email($template, $placeholders, $recipients) {
+ global $conf;
+
+ if(!is_array($recipients) || count($recipients) < 1) return false;
+ if(!is_array($placeholders)) $placeholders = array();
+
+ if(file_exists($conf['rootpath'].'/conf-custom/mail/' . $template . '_'.$conf['language'].'.txt')) {
+ $lines = file($conf['rootpath'].'/conf-custom/mail/' . $template . '_'.$conf['language'].'.txt');
+ } elseif(file_exists($conf['rootpath'].'/conf-custom/mail/' . $template . '_en.txt')) {
+ $lines = file($conf['rootpath'].'/conf-custom/mail/' . $template . '_en.txt');
+ } elseif(file_exists($conf['rootpath'].'/conf/mail/' . $template . '_'.$conf['language'].'.txt')) {
+ $lines = file($conf['rootpath'].'/conf/mail/' . $template . '_'.$conf['language'].'.txt');
+ } else {
+ $lines = file($conf['rootpath'].'/conf/mail/' . $template . '_en.txt');
+ }
+
+ //* get mail headers, subject and body
+ $mailHeaders = '';
+ $mailBody = '';
+ $mailSubject = '';
+ $inHeader = true;
+ for($l = 0; $l < count($lines); $l++) {
+ if($lines[$l] == '') {
+ $inHeader = false;
+ continue;
+ }
+ if($inHeader == true) {
+ $parts = explode(':', $lines[$l], 2);
+ if(strtolower($parts[0]) == 'subject') $mailSubject = trim($parts[1]);
+ unset($parts);
+ $mailHeaders .= trim($lines[$l]) . "\n";
+ } else {
+ $mailBody .= trim($lines[$l]) . "\n";
+ }
+ }
+ $mailBody = trim($mailBody);
+
+ //* Replace placeholders
+ $mailHeaders = strtr($mailHeaders, $placeholders);
+ $mailSubject = strtr($mailSubject, $placeholders);
+ $mailBody = strtr($mailBody, $placeholders);
+
+ for($r = 0; $r < count($recipients); $r++) {
+ mail($recipients[$r], $mailSubject, $mailBody, $mailHeaders);
+ }
+
+ unset($mailSubject);
+ unset($mailHeaders);
+ unset($mailBody);
+ unset($lines);
+
+ return true;
+ }
+
+
+ #######################################################################################################
+ // enforce traffic quota (run only on the "master-server")
+ #######################################################################################################
+
+ if ($app->dbmaster == $app->db) {
+
+ $global_config = $app->getconf->get_global_config('mail');
+
+ $current_month = date('Y-m');
+
+ //* Check website traffic quota
+ $sql = "SELECT sys_groupid,domain_id,domain,traffic_quota,traffic_quota_lock FROM web_domain WHERE (traffic_quota > 0 or traffic_quota_lock = 'y') and (type = 'vhost' OR type = 'vhostsubdomain')";
+ $records = $app->db->queryAllRecords($sql);
+ if(is_array($records)) {
+ foreach($records as $rec) {
+
+ $web_traffic_quota = $rec['traffic_quota'];
+ $domain = $rec['domain'];
+
+ // get the client
+ /*
+ $client_group_id = $rec["sys_groupid"];
+ $client = $app->db->queryOneRecord("SELECT limit_traffic_quota,parent_client_id FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
+ $reseller = $app->db->queryOneRecord("SELECT limit_traffic_quota FROM client WHERE client_id = ".intval($client['parent_client_id']));
+
+ $client_traffic_quota = intval($client['limit_traffic_quota']);
+ $reseller_traffic_quota = intval($reseller['limit_traffic_quota']);
+ */
+
+ //* get the traffic
+ $tmp = $app->db->queryOneRecord("SELECT SUM(traffic_bytes) As total_traffic_bytes FROM web_traffic WHERE traffic_date like '$current_month%' AND hostname = '$domain'");
+ $web_traffic = round($tmp['total_traffic_bytes']/1024/1024);
+
+ //* Website is over quota, we will disable it
+ /*if( ($web_traffic_quota > 0 && $web_traffic > $web_traffic_quota) ||
+ ($client_traffic_quota > 0 && $web_traffic > $client_traffic_quota) ||
+ ($reseller_traffic_quota > 0 && $web_traffic > $reseller_traffic_quota)) {*/
+ if($web_traffic_quota > 0 && $web_traffic > $web_traffic_quota) {
+ $app->dbmaster->datalogUpdate('web_domain', "traffic_quota_lock = 'y',active = 'n'", 'domain_id', $rec['domain_id']);
+ $app->log('Traffic quota for '.$rec['domain'].' exceeded. Disabling website.',LOGLEVEL_DEBUG);
+
+ //* Send traffic notifications
+ if($rec['traffic_quota_lock'] != 'y' && ($web_config['overtraffic_notify_admin'] == 'y' || $web_config['overtraffic_notify_client'] == 'y')) {
+
+ $placeholders = array('{domain}' => $rec['domain'],
+ '{admin_mail}' => ($global_config['admin_mail'] != ''? $global_config['admin_mail'] : 'root'));
+
+ $recipients = array();
+ //* send email to admin
+ if($global_config['admin_mail'] != '' && $web_config['overtraffic_notify_admin'] == 'y') {
+ $recipients[] = $global_config['admin_mail'];
+ }
+
+ //* Send email to client
+ if($web_config['overtraffic_notify_client'] == 'y') {
+ $client_group_id = $rec["sys_groupid"];
+ $client = $app->db->queryOneRecord("SELECT client.email FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
+ if($client['email'] != '') {
+ $recipients[] = $client['email'];
+ }
+ }
+
+ send_notification_email('web_traffic_notification', $placeholders, $recipients);
+ }
+
+ } else {
+ //* unlock the website, if traffic is lower then quota
+ if($rec['traffic_quota_lock'] == 'y') {
+ $app->dbmaster->datalogUpdate('web_domain', "traffic_quota_lock = 'n',active = 'y'", 'domain_id', $rec['domain_id']);
+ $app->log('Traffic quota for '.$rec['domain'].' ok again. Re-enabling website.',LOGLEVEL_DEBUG);
+ }
+ }
+ }
+ }
+
+
+ }
+
+
+ #######################################################################################################
+ // send website quota warnings by email
+ #######################################################################################################
+
+ if ($app->dbmaster == $app->db) {
+
+ $global_config = $app->getconf->get_global_config('mail');
+
+ //* Check website disk quota
+ $sql = "SELECT domain_id,sys_groupid,domain,system_user,last_quota_notification,DATEDIFF(CURDATE(), last_quota_notification) as `notified_before` FROM web_domain WHERE (type = 'vhost' OR type = 'vhostsubdomain')";
+ $records = $app->db->queryAllRecords($sql);
+ if(is_array($records) && !empty($records)) {
+
+ $tmp_rec = $app->db->queryAllRecords("SELECT data from monitor_data WHERE type = 'harddisk_quota' ORDER BY created DESC");
+ $monitor_data = array();
+ if(is_array($tmp_rec)) {
+ foreach ($tmp_rec as $tmp_mon) {
+ $monitor_data = array_merge_recursive($monitor_data,unserialize($app->db->unquote($tmp_mon['data'])));
+ }
+ }
+
+ foreach($records as $rec) {
+
+ //$web_hd_quota = $rec['hd_quota'];
+ $domain = $rec['domain'];
+
+ $username = $rec['system_user'];
+ $rec['used'] = $monitor_data['user'][$username]['used'];
+ $rec['soft'] = $monitor_data['user'][$username]['soft'];
+ $rec['hard'] = $monitor_data['user'][$username]['hard'];
+ $rec['files'] = $monitor_data['user'][$username]['files'];
+
+ if (!is_numeric($rec['used'])){
+ if ($rec['used'][0] > $rec['used'][1]){
+ $rec['used'] = $rec['used'][0];
+ } else {
+ $rec['used'] = $rec['used'][1];
+ }
+ }
+ if (!is_numeric($rec['soft'])) $rec['soft']=$rec['soft'][1];
+ if (!is_numeric($rec['hard'])) $rec['hard']=$rec['hard'][1];
+ if (!is_numeric($rec['files'])) $rec['files']=$rec['files'][1];
+
+ // used space ratio
+ if($rec['soft'] > 0){
+ $used_ratio = $rec['used']/$rec['soft'];
+ } else {
+ $used_ratio = 0;
+ }
+
+ $rec['ratio'] = number_format($used_ratio * 100, 2, '.', '').'%';
+
+ if($rec['used'] > 1024) {
+ $rec['used'] = round($rec['used'] / 1024,2).' MB';
+ } else {
+ if ($rec['used'] != '') $rec['used'] .= ' KB';
+ }
+
+ if($rec['soft'] > 1024) {
+ $rec['soft'] = round($rec['soft'] / 1024,2).' MB';
+ } elseif($rec['soft'] == 0){
+ $rec['soft'] = '----';
+ } else {
+ $rec['soft'] .= ' KB';
+ }
+
+ if($rec['hard'] > 1024) {
+ $rec['hard'] = round($rec['hard'] / 1024,2).' MB';
+ } elseif($rec['hard'] == 0){
+ $rec['hard'] = '----';
+ } else {
+ $rec['hard'] .= ' KB';
+ }
+
+ // send notifications only if 90% or more of the quota are used
+ if($used_ratio < 0.9) {
+ // reset notification date
+ if($rec['last_quota_notification']) $app->dbmaster->datalogUpdate('web_domain', "last_quota_notification = NULL", 'domain_id', $rec['domain_id']);
+
+ // send notification - everything ok again
+ if($rec['last_quota_notification'] && $web_config['overquota_notify_onok'] == 'y' && ($web_config['overquota_notify_admin'] == 'y' || $web_config['overquota_notify_client'] == 'y')) {
+ $placeholders = array('{domain}' => $rec['domain'],
+ '{admin_mail}' => ($global_config['admin_mail'] != ''? $global_config['admin_mail'] : 'root'),
+ '{used}' => $rec['used'],
+ '{soft}' => $rec['soft'],
+ '{hard}' => $rec['hard'],
+ '{ratio}' => $rec['ratio']);
+
+ $recipients = array();
+
+ //* send email to admin
+ if($global_config['admin_mail'] != '' && $web_config['overquota_notify_admin'] == 'y') {
+ $recipients[] = $global_config['admin_mail'];
+ }
+
+ //* Send email to client
+ if($web_config['overquota_notify_client'] == 'y') {
+ $client_group_id = $rec["sys_groupid"];
+ $client = $app->db->queryOneRecord("SELECT client.email FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
+ if($client['email'] != '') {
+ $recipients[] = $client['email'];
+ }
+ }
+ send_notification_email('web_quota_ok_notification', $placeholders, $recipients);
+ }
+
+ continue;
+ }
+
+ // could a notification be sent?
+ $send_notification = false;
+ if(!$rec['last_quota_notification']) $send_notification = true; // not yet notified
+ elseif($web_config['overquota_notify_freq'] > 0 && $rec['notified_before'] >= $web_config['overquota_notify_freq']) $send_notification = true;
+
+ //* Send quota notifications
+ if(($web_config['overquota_notify_admin'] == 'y' || $web_config['overquota_notify_client'] == 'y') && $send_notification == true) {
+ $app->dbmaster->datalogUpdate('web_domain', "last_quota_notification = CURDATE()", 'domain_id', $rec['domain_id']);
+
+ $placeholders = array('{domain}' => $rec['domain'],
+ '{admin_mail}' => ($global_config['admin_mail'] != ''? $global_config['admin_mail'] : 'root'),
+ '{used}' => $rec['used'],
+ '{soft}' => $rec['soft'],
+ '{hard}' => $rec['hard'],
+ '{ratio}' => $rec['ratio']);
+
+ $recipients = array();
+
+ //* send email to admin
+ if($global_config['admin_mail'] != '' && $web_config['overquota_notify_admin'] == 'y') {
+ $recipients[] = $global_config['admin_mail'];
+ }
+
+ //* Send email to client
+ if($web_config['overquota_notify_client'] == 'y') {
+ $client_group_id = $rec["sys_groupid"];
+ $client = $app->db->queryOneRecord("SELECT client.email FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
+ if($client['email'] != '') {
+ $recipients[] = $client['email'];
+ }
+ }
+ send_notification_email('web_quota_notification', $placeholders, $recipients);
+ }
+ }
+ }
+ }
+
+
+ #######################################################################################################
+ // send mail quota warnings by email
+ #######################################################################################################
+
+ if ($app->dbmaster == $app->db) {
+
+ $global_config = $app->getconf->get_global_config('mail');
+ $mail_config = $app->getconf->get_server_config($conf['server_id'], 'mail');
+
+ //* Check email quota
+ $sql = "SELECT mailuser_id,sys_groupid,email,name,quota,last_quota_notification,DATEDIFF(CURDATE(), last_quota_notification) as `notified_before` FROM mail_user";
+ $records = $app->db->queryAllRecords($sql);
+ if(is_array($records) && !empty($records)) {
+
+ $tmp_rec = $app->db->queryAllRecords("SELECT data from monitor_data WHERE type = 'email_quota' ORDER BY created DESC");
+ $monitor_data = array();
+ if(is_array($tmp_rec)) {
+ foreach ($tmp_rec as $tmp_mon) {
+ //$monitor_data = array_merge_recursive($monitor_data,unserialize($app->db->unquote($tmp_mon['data'])));
+ $tmp_array = unserialize($app->db->unquote($tmp_mon['data']));
+ if(is_array($tmp_array)) {
+ foreach($tmp_array as $username => $data) {
+ if(@!$monitor_data[$username]['used']) $monitor_data[$username]['used'] = $data['used'];
+ }
+ }
+ }
+ }
+
+ foreach($records as $rec) {
+
+ $email = $rec['email'];
+
+ $rec['used'] = isset($monitor_data[$email]['used']) ? $monitor_data[$email]['used'] : array(1 => 0);
+
+ if (!is_numeric($rec['used'])) $rec['used']=$rec['used'][1];
+
+ // used space ratio
+ if($rec['quota'] > 0){
+ $used_ratio = $rec['used']/$rec['quota'];
+ } else {
+ $used_ratio = 0;
+ }
+
+ $rec['ratio'] = number_format($used_ratio * 100, 2, '.', '').'%';
+
+ if($rec['quota'] > 0){
+ $rec['quota'] = round($rec['quota'] / 1048576,4).' MB';
+ } else {
+ $rec['quota'] = '----';
+ }
+
+ if($rec['used'] < 1544000) {
+ $rec['used'] = round($rec['used'] / 1024,4).' KB';
+ } else {
+ $rec['used'] = round($rec['used'] / 1048576,4).' MB';
+ }
+
+ // send notifications only if 90% or more of the quota are used
+ if($used_ratio < 0.9) {
+ // reset notification date
+ if($rec['last_quota_notification']) $app->dbmaster->datalogUpdate('mail_user', "last_quota_notification = NULL", 'mailuser_id', $rec['mailuser_id']);
+
+ // send notification - everything ok again
+ if($rec['last_quota_notification'] && $mail_config['overquota_notify_onok'] == 'y' && ($mail_config['overquota_notify_admin'] == 'y' || $mail_config['overquota_notify_client'] == 'y')) {
+ $placeholders = array('{email}' => $rec['email'],
+ '{admin_mail}' => ($global_config['admin_mail'] != ''? $global_config['admin_mail'] : 'root'),
+ '{used}' => $rec['used'],
+ '{name}' => $rec['name'],
+ '{quota}' => $rec['quota'],
+ '{ratio}' => $rec['ratio']);
+
+ $recipients = array();
+ //* send email to admin
+ if($global_config['admin_mail'] != '' && $mail_config['overquota_notify_admin'] == 'y') {
+ $recipients[] = $global_config['admin_mail'];
+ }
+
+ //* Send email to client
+ if($mail_config['overquota_notify_client'] == 'y') {
+ $client_group_id = $rec["sys_groupid"];
+ $client = $app->db->queryOneRecord("SELECT client.email FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
+ if($client['email'] != '') {
+ $recipients[] = $client['email'];
+ }
+ }
+
+ send_notification_email('mail_quota_ok_notification', $placeholders, $recipients);
+ }
+
+ continue;
+ }
+
+ //* Send quota notifications
+ // could a notification be sent?
+ $send_notification = false;
+ if(!$rec['last_quota_notification']) $send_notification = true; // not yet notified
+ elseif($mail_config['overquota_notify_freq'] > 0 && $rec['notified_before'] >= $mail_config['overquota_notify_freq']) $send_notification = true;
+
+ if(($mail_config['overquota_notify_admin'] == 'y' || $mail_config['overquota_notify_client'] == 'y') && $send_notification == true) {
+ $app->dbmaster->datalogUpdate('mail_user', "last_quota_notification = CURDATE()", 'mailuser_id', $rec['mailuser_id']);
+
+ $placeholders = array('{email}' => $rec['email'],
+ '{admin_mail}' => ($global_config['admin_mail'] != ''? $global_config['admin_mail'] : 'root'),
+ '{used}' => $rec['used'],
+ '{name}' => $rec['name'],
+ '{quota}' => $rec['quota'],
+ '{ratio}' => $rec['ratio']);
+
+ $recipients = array();
+ //* send email to admin
+ if($global_config['admin_mail'] != '' && $mail_config['overquota_notify_admin'] == 'y') {
+ $recipients[] = $global_config['admin_mail'];
+ }
+
+ //* Send email to client
+ if($mail_config['overquota_notify_client'] == 'y') {
+ $client_group_id = $rec["sys_groupid"];
+ $client = $app->db->queryOneRecord("SELECT client.email FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = $client_group_id");
+ if($client['email'] != '') {
+ $recipients[] = $client['email'];
+ }
+ }
+
+ send_notification_email('mail_quota_notification', $placeholders, $recipients);
+ }
+ }
+ }
+ }
+
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/400-openvz.inc.php b/server/lib/classes/cron.d/400-openvz.inc.php
new file mode 100644
index 0000000..daee5c4
--- /dev/null
+++ b/server/lib/classes/cron.d/400-openvz.inc.php
@@ -0,0 +1,83 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_openvz extends cronjob {
+
+ // job schedule
+ protected $_schedule = '0 0 * * *';
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ #######################################################################################################
+ // deactivate virtual servers (run only on the "master-server")
+ #######################################################################################################
+
+ if ($app->dbmaster == $app->db) {
+ $current_date = date('Y-m-d');
+
+ //* Check which virtual machines have to be deactivated
+ $sql = "SELECT * FROM openvz_vm WHERE active = 'y' AND active_until_date != '0000-00-00' AND active_until_date < '$current_date'";
+ $records = $app->db->queryAllRecords($sql);
+ if(is_array($records)) {
+ foreach($records as $rec) {
+ $app->dbmaster->datalogUpdate('openvz_vm', "active = 'n'", 'vm_id', $rec['vm_id']);
+ $app->log('Virtual machine active date expired. Disabling VM '.$rec['veid'],LOGLEVEL_DEBUG);
+ }
+ }
+ }
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.d/500-backup.inc.php b/server/lib/classes/cron.d/500-backup.inc.php
new file mode 100644
index 0000000..39c721c
--- /dev/null
+++ b/server/lib/classes/cron.d/500-backup.inc.php
@@ -0,0 +1,330 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob_backup extends cronjob {
+
+ // job schedule
+ protected $_schedule = '0 0 * * *';
+
+ /* this function is optional if it contains no custom code */
+ public function onPrepare() {
+ global $app;
+
+ parent::onPrepare();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onBeforeRun() {
+ global $app;
+
+ return parent::onBeforeRun();
+ }
+
+ public function onRunJob() {
+ global $app, $conf;
+
+ #######################################################################################################
+ // Create website backups
+ #######################################################################################################
+ function formatBytes($size, $precision = 2) {
+ $base=log($size)/log(1024);
+ $suffixes=array('','k','M','G','T');
+ return round(pow(1024,$base-floor($base)),$precision).$suffixes[floor($base)];
+ }
+
+ $server_config = $app->getconf->get_server_config($conf['server_id'], 'server');
+ $backup_dir = $server_config['backup_dir'];
+ $backup_mode = $server_config['backup_mode'];
+ if($backup_mode == '') $backup_mode = 'userzip';
+
+ $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
+ $http_server_user = $web_config['user'];
+
+ if($backup_dir != '') {
+
+ if(isset($server_config['backup_dir_ftpread']) && $server_config['backup_dir_ftpread'] == 'y') {
+ $backup_dir_permissions = 0755;
+ } else {
+ $backup_dir_permissions = 0750;
+ }
+
+ if(!is_dir($backup_dir)) {
+ mkdir(escapeshellcmd($backup_dir), $backup_dir_permissions, true);
+ } else {
+ chmod(escapeshellcmd($backup_dir), $backup_dir_permissions);
+ }
+
+ $sql = "SELECT * FROM web_domain WHERE server_id = '".$conf['server_id']."' AND (type = 'vhost' OR type = 'vhostsubdomain') AND backup_interval != 'none'";
+ $records = $app->db->queryAllRecords($sql);
+ if(is_array($records)) {
+ foreach($records as $rec) {
+
+ //* Do the website backup
+ if($rec['backup_interval'] == 'daily' or ($rec['backup_interval'] == 'weekly' && date('w') == 0) or ($rec['backup_interval'] == 'monthly' && date('d') == '01')) {
+
+ $web_path = $rec['document_root'];
+ $web_user = $rec['system_user'];
+ $web_group = $rec['system_group'];
+ $web_id = $rec['domain_id'];
+ $web_backup_dir = $backup_dir.'/web'.$web_id;
+ if(!is_dir($web_backup_dir)) mkdir($web_backup_dir, 0750);
+ chmod($web_backup_dir, 0750);
+ //if(isset($server_config['backup_dir_ftpread']) && $server_config['backup_dir_ftpread'] == 'y') {
+ chown($web_backup_dir, $rec['system_user']);
+ chgrp($web_backup_dir, $rec['system_group']);
+ /*} else {
+ chown($web_backup_dir, 'root');
+ chgrp($web_backup_dir, 'root');
+ }*/
+ if($backup_mode == 'userzip') {
+ //* Create a .zip backup as web user and include also files owned by apache / nginx user
+ $web_backup_file = 'web'.$web_id.'_'.date('Y-m-d_H-i').'.zip';
+ exec('cd '.escapeshellarg($web_path).' && sudo -u '.escapeshellarg($web_user).' find . -group '.escapeshellarg($web_group).' -print 2> /dev/null | zip -b /tmp --exclude=backup\* --symlinks '.escapeshellarg($web_backup_dir.'/'.$web_backup_file).' -@', $tmp_output, $retval);
+ if($retval == 0) exec('cd '.escapeshellarg($web_path).' && sudo -u '.escapeshellarg($web_user).' find . -user '.escapeshellarg($http_server_user).' -print 2> /dev/null | zip -b /tmp --exclude=backup\* --update --symlinks '.escapeshellarg($web_backup_dir.'/'.$web_backup_file).' -@', $tmp_output, $retval);
+ } else {
+ //* Create a tar.gz backup as root user
+ $web_backup_file = 'web'.$web_id.'_'.date('Y-m-d_H-i').'.tar.gz';
+ exec('tar pczf '.escapeshellarg($web_backup_dir.'/'.$web_backup_file).' --exclude=backup\* --directory '.escapeshellarg($web_path).' .', $tmp_output, $retval);
+ }
+ if($retval == 0){
+ chown($web_backup_dir.'/'.$web_backup_file, 'root');
+ chgrp($web_backup_dir.'/'.$web_backup_file, 'root');
+ chmod($web_backup_dir.'/'.$web_backup_file, 0750);
+
+ //* Insert web backup record in database
+ //$insert_data = "(server_id,parent_domain_id,backup_type,backup_mode,tstamp,filename) VALUES (".$conf['server_id'].",".$web_id.",'web','".$backup_mode."',".time().",'".$app->db->quote($web_backup_file)."')";
+ //$app->dbmaster->datalogInsert('web_backup', $insert_data, 'backup_id');
+ $sql = "INSERT INTO web_backup (server_id,parent_domain_id,backup_type,backup_mode,tstamp,filename) VALUES (".$conf['server_id'].",".$web_id.",'web','".$backup_mode."',".time().",'".$app->db->quote($web_backup_file)."')";
+ $app->db->query($sql);
+ if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql);
+ } else {
+ if(is_file($web_backup_dir.'/'.$web_backup_file)) unlink($web_backup_dir.'/'.$web_backup_file);
+ }
+
+ //* Remove old backups
+ $backup_copies = intval($rec['backup_copies']);
+
+ $dir_handle = dir($web_backup_dir);
+ $files = array();
+ while (false !== ($entry = $dir_handle->read())) {
+ if($entry != '.' && $entry != '..' && substr($entry,0,3) == 'web' && is_file($web_backup_dir.'/'.$entry)) {
+ $files[] = $entry;
+ }
+ }
+ $dir_handle->close();
+
+ rsort($files);
+
+ for ($n = $backup_copies; $n <= 10; $n++) {
+ if(isset($files[$n]) && is_file($web_backup_dir.'/'.$files[$n])) {
+ unlink($web_backup_dir.'/'.$files[$n]);
+ //$sql = "SELECT backup_id FROM web_backup WHERE server_id = ".$conf['server_id']." AND parent_domain_id = $web_id AND filename = '".$app->db->quote($files[$n])."'";
+ //$tmp = $app->dbmaster->queryOneRecord($sql);
+ //$app->dbmaster->datalogDelete('web_backup', 'backup_id', $tmp['backup_id']);
+ //$sql = "DELETE FROM web_backup WHERE backup_id = ".intval($tmp['backup_id']);
+ $sql = "DELETE FROM web_backup WHERE server_id = ".$conf['server_id']." AND parent_domain_id = $web_id AND filename = '".$app->db->quote($files[$n])."'";
+ $app->db->query($sql);
+ if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql);
+ }
+ }
+
+ unset($files);
+ unset($dir_handle);
+
+ //* Remove backupdir symlink and create as directory instead
+ $app->uses('system');
+ $app->system->web_folder_protection($web_path,false);
+
+ if(is_link($web_path.'/backup')) {
+ unlink($web_path.'/backup');
+ }
+ if(!is_dir($web_path.'/backup')) {
+ mkdir($web_path.'/backup');
+ chown($web_path.'/backup', $rec['system_user']);
+ chgrp($web_path.'/backup', $rec['system_group']);
+ }
+
+ $app->system->web_folder_protection($web_path,true);
+
+ }
+
+ /* If backup_interval is set to none and we have a
+ backup directory for the website, then remove the backups */
+ if($rec['backup_interval'] == 'none') {
+ $web_id = $rec['domain_id'];
+ $web_user = $rec['system_user'];
+ $web_backup_dir = realpath($backup_dir.'/web'.$web_id);
+ if(is_dir($web_backup_dir)) {
+ exec('sudo -u '.escapeshellarg($web_user).' rm -f '.escapeshellarg($web_backup_dir.'/*'));
+ }
+ }
+ }
+ }
+
+ $sql = "SELECT * FROM web_database WHERE server_id = '".$conf['server_id']."' AND backup_interval != 'none'";
+ $records = $app->db->queryAllRecords($sql);
+ if(is_array($records)) {
+
+ include('lib/mysql_clientdb.conf');
+
+ foreach($records as $rec) {
+
+ //* Do the database backup
+ if($rec['backup_interval'] == 'daily' or ($rec['backup_interval'] == 'weekly' && date('w') == 0) or ($rec['backup_interval'] == 'monthly' && date('d') == '01')) {
+
+ $web_id = $rec['parent_domain_id'];
+ $db_backup_dir = $backup_dir.'/web'.$web_id;
+ if(!is_dir($db_backup_dir)) mkdir($db_backup_dir, 0750);
+ chmod($db_backup_dir, 0750);
+ chown($db_backup_dir, 'root');
+ chgrp($db_backup_dir, 'root');
+
+ //* Do the mysql database backup with mysqldump or mongodump
+ $db_id = $rec['database_id'];
+ $db_name = $rec['database_name'];
+
+ if ($rec['type'] == 'mysql') {
+ $db_backup_file = 'db_'.$db_name.'_'.date('Y-m-d_H-i').'.sql';
+ //$command = "mysqldump -h '".escapeshellcmd($clientdb_host)."' -u '".escapeshellcmd($clientdb_user)."' -p'".escapeshellcmd($clientdb_password)."' -c --add-drop-table --create-options --quick --result-file='".$db_backup_dir.'/'.$db_backup_file."' '".$db_name."'";
+ $command = "mysqldump -h ".escapeshellarg($clientdb_host)." -u ".escapeshellarg($clientdb_user)." -p".escapeshellarg($clientdb_password)." -c --add-drop-table --quote-names --routines --events --triggers --hex-blob --create-options --quick --result-file='".$db_backup_dir.'/'.$db_backup_file."' '".$db_name."'";
+ exec($command, $tmp_output, $retval);
+
+ //* Compress the backup with gzip
+ if($retval == 0) exec("gzip -c '".escapeshellcmd($db_backup_dir.'/'.$db_backup_file)."' > '".escapeshellcmd($db_backup_dir.'/'.$db_backup_file).".gz'", $tmp_output, $retval);
+
+ if($retval == 0){
+ chmod($db_backup_dir.'/'.$db_backup_file.'.gz', 0750);
+ chown($db_backup_dir.'/'.$db_backup_file.'.gz', fileowner($db_backup_dir));
+ chgrp($db_backup_dir.'/'.$db_backup_file.'.gz', filegroup($db_backup_dir));
+
+ //* Insert web backup record in database
+ //$insert_data = "(server_id,parent_domain_id,backup_type,backup_mode,tstamp,filename) VALUES (".$conf['server_id'].",$web_id,'mysql','sqlgz',".time().",'".$app->db->quote($db_backup_file).".gz')";
+ //$app->dbmaster->datalogInsert('web_backup', $insert_data, 'backup_id');
+ $sql = "INSERT INTO web_backup (server_id,parent_domain_id,backup_type,backup_mode,tstamp,filename) VALUES (".$conf['server_id'].",$web_id,'mysql','sqlgz',".time().",'".$app->db->quote($db_backup_file).".gz')";
+ $app->db->query($sql);
+ if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql);
+
+ } else {
+ if(is_file($db_backup_dir.'/'.$db_backup_file.'.gz')) unlink($db_backup_dir.'/'.$db_backup_file.'.gz');
+ }
+ //* Remove the uncompressed file
+ if(is_file($db_backup_dir.'/'.$db_backup_file)) unlink($db_backup_dir.'/'.$db_backup_file);
+ } else if ($rec['type'] == 'mongo') {
+ $db_backup_file = 'db_'.$db_name.'_'.date('Y-m-d_H-i');
+
+ try {
+ $connection = new MongoClient("mongodb://root:123456@127.0.0.1:27017/admin");
+ $db = $connection->selectDB($db_name);
+ // exclude not supported by mongodump, only get user collections
+ $collections = $db->getCollectionNames(false);
+
+ foreach ($collections as $collection) {
+ // mongodump -h 127.0.0.1 --port 27017 -u root -p 123456 --authenticationDatabase admin -d <db> -c <table> -o /tmp/test
+ $command = "mongodump -h 127.0.0.1 --port 27017 -u root -p 123456 --authenticationDatabase admin -d ".escapeshellcmd($db_name)." -c ".escapeshellcmd($collection)." -o ".escapeshellcmd($db_backup_dir.'/'.$db_backup_file);
+ exec($command);
+ }
+
+ if (is_dir(escapeshellcmd($db_backup_dir.'/'.$db_backup_file))) {
+ //* Compress the backup with gzip
+ exec("cd ".escapeshellcmd($db_backup_dir)." && tar -pczf ".escapeshellcmd($db_backup_dir.'/'.$db_backup_file).".tar.gz ".escapeshellcmd($db_backup_file));
+ chmod($db_backup_dir.'/'.$db_backup_file.'.tar.gz', 0750);
+ chown($db_backup_dir.'/'.$db_backup_file.'.tar.gz', fileowner($db_backup_dir));
+ chgrp($db_backup_dir.'/'.$db_backup_file.'.tar.gz', filegroup($db_backup_dir));
+
+ //* Insert web backup record in database
+ $sql = "INSERT INTO web_backup (server_id,parent_domain_id,backup_type,backup_mode,tstamp,filename) VALUES (".$conf['server_id'].",$web_id,'mongodb','rootgz',".time().",'".$app->db->quote($db_backup_file).".tar.gz')";
+ $app->db->query($sql);
+
+ if ($app->db->dbHost != $app->dbmaster->dbHost) {
+ $app->dbmaster->query($sql);
+ }
+
+ //* Remove the uncompressed file
+ exec("rm -rf ".escapeshellcmd($db_backup_dir.'/'.$db_backup_file));
+ }
+ } catch (MongoConnnectionException $e) {
+ // connecting to MongoDB failed - cannot create backup
+ }
+ }
+
+ //* Remove old backups
+ $backup_copies = intval($rec['backup_copies']);
+
+ $dir_handle = dir($db_backup_dir);
+ $files = array();
+ while (false !== ($entry = $dir_handle->read())) {
+ if($entry != '.' && $entry != '..' && (preg_match('/^db_(.*?)_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}\.sql.gz$/', $entry, $matches) || preg_match('/^db_(.*?)_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}\.tar.gz$/', $entry, $matches)) && is_file($db_backup_dir.'/'.$entry)) {
+ if(array_key_exists($matches[1], $files) == false) $files[$matches[1]] = array();
+ $files[$matches[1]][] = $entry;
+ }
+ }
+ $dir_handle->close();
+
+ reset($files);
+ foreach($files as $db_name => $filelist) {
+ rsort($filelist);
+ for ($n = $backup_copies; $n <= 10; $n++) {
+ if(isset($filelist[$n]) && is_file($db_backup_dir.'/'.$filelist[$n])) {
+ unlink($db_backup_dir.'/'.$filelist[$n]);
+ //$sql = "SELECT backup_id FROM web_backup WHERE server_id = ".$conf['server_id']." AND parent_domain_id = $web_id AND filename = '".$app->db->quote($filelist[$n])."'";
+ //$tmp = $app->dbmaster->queryOneRecord($sql);
+ //$sql = "DELETE FROM web_backup WHERE backup_id = ".intval($tmp['backup_id']);
+ $sql = "DELETE FROM web_backup WHERE server_id = ".$conf['server_id']." AND parent_domain_id = $web_id AND filename = '".$app->db->quote($filelist[$n])."'";
+ $app->db->query($sql);
+ if($app->db->dbHost != $app->dbmaster->dbHost) $app->dbmaster->query($sql);
+ }
+ }
+ }
+
+ unset($files);
+ unset($dir_handle);
+ }
+ }
+
+ unset($clientdb_host);
+ unset($clientdb_user);
+ unset($clientdb_password);
+
+ }
+ }
+
+ parent::onRunJob();
+ }
+
+ /* this function is optional if it contains no custom code */
+ public function onAfterRun() {
+ global $app;
+
+ parent::onAfterRun();
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/cron.inc.php b/server/lib/classes/cron.inc.php
new file mode 100644
index 0000000..c7bea32
--- /dev/null
+++ b/server/lib/classes/cron.inc.php
@@ -0,0 +1,271 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cron {
+
+ /**#@+
+ * @access private
+ */
+ private $_sMinute = '';
+ private $_sHour = '';
+ private $_sDay = '';
+ private $_sMonth = '';
+ private $_sWDay = '';
+ private $_bParsed = false;
+ private $_iNextRun = null;
+ private $_aValidValues;
+
+ public function __construct() {
+ // empty
+ $this->_sMinute = '';
+ $this->_sHour = '';
+ $this->_sDay = '';
+ $this->_sMonth = '';
+ $this->_sWDay = '';
+ $this->_bParsed = false;
+ $this->_aValidValues = array('minute' => array(),
+ 'hour' => array(),
+ 'day' => array(),
+ 'month' => array(),
+ 'weekday' => array());
+ }
+
+ private function _calcValidValues() {
+ // minute field
+ $this->_aValidValues['minute'] = $this->_calcFieldValues('minute', $this->_sMinute);
+ $this->_aValidValues['hour'] = $this->_calcFieldValues('hour', $this->_sHour);
+ $this->_aValidValues['day'] = $this->_calcFieldValues('day', $this->_sDay);
+ $this->_aValidValues['month'] = $this->_calcFieldValues('month', $this->_sMonth);
+ $this->_aValidValues['weekday'] = $this->_calcFieldValues('weekday', $this->_sWDay);
+ $this->_bParsed = true;
+ }
+
+ private function _calcFieldValues($sField, $sValue) {
+ global $app;
+
+ $aValidValues = array();
+
+ // global checks
+ $iFrom = 0;
+ $iTo = 0;
+ switch($sField) {
+ case 'minute':
+ $iTo = 59;
+ break;
+ case 'hour':
+ $iTo = 23;
+ break;
+ case 'day':
+ $iFrom = 1;
+ $iTo = 31;
+ break;
+ case 'month':
+ $sValue = strtr($sValue, array('JAN' => 1,
+ 'FEB' => 2,
+ 'MAR' => 3,
+ 'APR' => 4,
+ 'MAY' => 5,
+ 'JUN' => 6,
+ 'JUL' => 7,
+ 'AUG' => 8,
+ 'SEP' => 9,
+ 'OCT' => 10,
+ 'NOV' => 11,
+ 'DEC' => 12)
+ );
+ $iFrom = 1;
+ $iTo = 12;
+ break;
+ case 'weekday':
+ $sValue = strtr($sValue, array('SUN' => 0,
+ 'MON' => 1,
+ 'TUE' => 2,
+ 'WED' => 3,
+ 'THU' => 4,
+ 'FRI' => 5,
+ 'SAT' => 6,
+ '7' => 0)
+ );
+ $iTo = 6;
+ break;
+ }
+ $aParts = explode(',', $sValue);
+ for($a = 0; $a < count($aParts); $a++) {
+ $sValue = $aParts[$a];
+ $iValue = $app->functions->intval($sValue);
+
+ if($sValue === '*') {
+ // everything is valid
+ for($i = $iFrom; $i <= $iTo; $i++) {
+ $aValidValues[] = $i;
+ }
+ break; // no need to go any further
+ } elseif((string)$iValue == $sValue) {
+ if($iValue >= $iFrom && $iValue <= $iTo) $aValidValues[] = $iValue;
+ } elseif(preg_match('/^([0-9]+)-([0-9]+)(\/([1-9][0-9]*))?$/', $sValue, $aMatch)) {
+ if($aMatch[1] < $iFrom) $aMatch[1] = $iFrom;
+ if($aMatch[2] > $iTo) $aMatch[2] = $iTo;
+ if(isset($aMatch[3])) {
+ for($i = $aMatch[1]; $i <= $aMatch[2]; $i++) {
+ if(($i - $aMatch[1]) % $aMatch[4] == 0) $aValidValues[] = $i;
+ }
+ } else {
+ for($i = $aMatch[1]; $i <= $aMatch[2]; $i++) $aValidValues[] = $i;
+ }
+ } elseif(preg_match('/^\*\/([1-9][0-9]*)$/', $sValue, $aMatch)) {
+ for($i = $iFrom; $i <= $iTo; $i++) {
+ if($i % $aMatch[1] == 0) $aValidValues[] = $i;
+ }
+ }
+ }
+
+ $aValidValues = array_unique($aValidValues);
+ sort($aValidValues);
+
+ return $aValidValues;
+ }
+
+ /**#@-*/
+
+ /**
+ * Set the cron field values
+ *
+ * @param string $sMinute the minute field value
+ * @param string $sHour the hour field value
+ * @param string $sDay the day field value
+ * @param string $sWDay the weekday field value
+ * @param string $sMonth the month field value
+ */
+ public function setCronFields($sMinute = '*', $sHour = '*', $sDay = '*', $sMonth = '*', $sWDay = '*') {
+ $this->_sMinute = $sMinute;
+ $this->_sHour = $sHour;
+ $this->_sDay = $sDay;
+ $this->_sMonth = $sMonth;
+ $this->_sWDay = $sWDay;
+ $this->_bParsed = false;
+ }
+
+ /**
+ * Parse a line of a cron and set the internal field values
+ *
+ * @param string $sLine cron line
+ */
+ public function parseCronLine($sLine) {
+ $aFields = preg_split('/[ \t]+/', trim($sLine));
+ for($i = 0; $i < 5; $i++) {
+ if(!isset($aFields[$i])) $aFields[$i] = '*';
+ }
+ if($aFields[0] == '@yearly' || $aFields[0] == '@annually') $aFields = array(0, 0, 1, 1, '*');
+ elseif($aFields[0] == '@monthly') $aFields = array(0, 0, 1, '*', '*');
+ elseif($aFields[0] == '@weekly') $aFields = array(0, 0, '*', '*', 0);
+ elseif($aFields[0] == '@daily' || $aFields[0] == '@midnight') $aFields = array(0, 0, '*', '*', '*');
+ elseif($aFields[0] == '@hourly') $aFields = array(0, '*', '*', '*', '*');
+
+ $this->setCronFields($aFields[0], $aFields[1], $aFields[2], $aFields[3], $aFields[4]);
+ }
+
+ public function getNextRun($vDate) {
+ global $app;
+
+ $iTimestamp = ISPConfigDatetime::to_timestamp($vDate);
+ if($iTimestamp === false) return $iTimestamp;
+
+ if($this->_bParsed == false) $this->_calcValidValues();
+
+ // get the field values for the given Date.
+ list($iMinute, $iHour, $iDay, $iWDay, $iMonth, $iYear) = explode(':', ISPConfigDateTime::to_string($vDate, 'custom:%M:%H:%d:%w:%m:%Y'));
+
+ $bValid = false;
+ $iStartYear = $iYear;
+ while($bValid == false) {
+ $iCurMinute = $this->_getNextValue('minute', $iMinute, true);
+ $iCurHour = $this->_getNextValue('hour', $iHour, true);
+ $iCurDay = $this->_getNextValue('day', $iDay, true);
+ $iCurMonth = $this->_getNextValue('month', $iMonth, true);
+ $iCurWDay = $this->_getNextValue('weekday', $iWDay, true);
+
+ $iNextMinute = $this->_getNextValue('minute', $iMinute);
+ $iNextHour = $this->_getNextValue('hour', $iHour);
+ $iNextDay = $this->_getNextValue('day', $iDay);
+ $iNextMonth = $this->_getNextValue('month', $iMonth);
+ $iNextWDay = $this->_getNextValue('weekday', $iWDay);
+
+ if($iNextMinute > $iMinute && $iHour == $iCurHour && $iDay == $iCurDay && $iWDay == $iCurWDay && $iMonth == $iCurMonth) {
+ $iMinute = $iNextMinute;
+ } elseif($iNextHour > $iHour && $iDay == $iCurDay && $iWDay == $iCurWDay && $iMonth == $iCurMonth) {
+ $iMinute = reset($this->_aValidValues['minute']);
+ $iHour = $iNextHour;
+ } elseif($iNextDay > $iDay && ISPConfigDateTime::last_day($iMonth) >= $iNextDay && $iMonth == $iCurMonth) {
+ $iMinute = reset($this->_aValidValues['minute']);
+ $iHour = reset($this->_aValidValues['hour']);
+ $iDay = $iNextDay;
+ } elseif($iNextMonth > $iMonth) {
+ $iMinute = reset($this->_aValidValues['minute']);
+ $iHour = reset($this->_aValidValues['hour']);
+ $iDay = reset($this->_aValidValues['day']);
+ $iMonth = $iNextMonth;
+ } else {
+ $iMinute = reset($this->_aValidValues['minute']);
+ $iHour = reset($this->_aValidValues['hour']);
+ $iDay = reset($this->_aValidValues['day']);
+ $iMonth = reset($this->_aValidValues['month']);
+ $iYear++;
+ }
+
+ $ts = mktime($iHour, $iMinute, 0, $iMonth, $iDay, $iYear);
+ //print strftime('%d.%m.%Y (%A) %H:%M', $ts) . "\n";
+ //var_dump($iCurMinute, $iCurHour, $iCurDay, $iCurMonth, $iCurWDay, '--', $iNextMinute, $iNextHour, $iNextDay, $iNextMonth, $iNextWDay);
+ if(ISPConfigDateTime::last_day($iMonth, $iYear) >= $iDay && in_array($app->functions->intval(strftime('%w', $ts)), $this->_aValidValues['weekday'], true) === true) {
+ $bValid = true;
+ } else {
+ if($iYear - $iStartYear > 5) {
+ if(LOG_PRIORITY <= PRIO_ERROR) $portal->log('No valid run dates for schedule ' . $this->_sMinute . ' ' . $this->_sHour . ' ' . $this->_sDay . ' ' . $this->_sMonth . ' ' . $this->_sWDay . ' in the next 5 years!', PRIO_ERROR, __FILE__, __LINE__);
+ return false;
+ }
+ }
+ }
+
+ //var_dump($vDate, implode('-', array($iYear, $iMonth, $iDay, $iHour, $iNextMinute, 0)), $this->_sMinute, $this->_sHour, $this->_sDay, $this->_sWDay, $this->_sMonth, $this->_aValidValues);
+ return $iYear . '-' . $iMonth . '-' . $iDay . ' ' . $iHour . ':' . $iNextMinute . ':0';
+ }
+
+ private function _getNextValue($sField, $iValue, $bIncludeCurrent = false) {
+ if(!array_key_exists($sField, $this->_aValidValues)) return false;
+
+ reset($this->_aValidValues[$sField]);
+ while(($cur = each($this->_aValidValues[$sField])) !== false) {
+ if($bIncludeCurrent == true && $cur['value'] >= $iValue) return $cur['value'];
+ elseif($cur['value'] > $iValue) return $cur['value'];
+ }
+ return reset($this->_aValidValues[$sField]);
+ }
+}
+
+?>
diff --git a/server/lib/classes/cronjob.inc.php b/server/lib/classes/cronjob.inc.php
new file mode 100644
index 0000000..6513654
--- /dev/null
+++ b/server/lib/classes/cronjob.inc.php
@@ -0,0 +1,158 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+class cronjob {
+
+ // default is every 5 minutes
+ protected $_schedule = '*/5 * * * *';
+
+ // may a run be skipped?
+ protected $_no_skip = false;
+
+ // if true, this job is run when it is first recognized. If false, the next run is calculated from schedule on first run.
+ protected $_run_at_new = false;
+
+ protected $_last_run = null;
+ protected $_next_run = null;
+ private $_running = false;
+
+ /** return schedule */
+ public function getSchedule() {
+ return $this->_schedule;
+ }
+
+ /** run through cronjob sequence **/
+ public function run() {
+
+ print "Called run() for class " . get_class($this) . "\n";
+ print "Job has schedule: " . $this->_schedule . "\n";
+ $this->onPrepare();
+ $run_it = $this->onBeforeRun();
+ if($run_it == true) {
+ $this->onRunJob();
+ $this->onAfterRun();
+ }
+ $this->onCompleted();
+
+ return;
+ }
+
+ /* this function prepares some data for the job and sets next run time if first executed */
+ protected function onPrepare() {
+ global $app;
+
+ print "Called onPrepare() for class " . get_class($this) . "\n";
+ // check the run time and values for this job
+
+ // get previous run data
+ $data = $app->db->queryOneRecord("SELECT `last_run`, `next_run`, `running` FROM `sys_cron` WHERE `name` = '" . $app->db->quote(get_class($this)) . "'");
+ if($data) {
+ if($data['last_run']) $this->_last_run = $data['last_run'];
+ if($data['next_run']) $this->_next_run = $data['next_run'];
+ if($data['running'] == 1) $this->_running = true;
+ }
+ if(!$this->_next_run) {
+ if($this->_run_at_new == true) {
+ $this->_next_run = ISPConfigDateTime::dbtime(); // run now.
+ } else {
+ $app->cron->parseCronLine($this->_schedule);
+ $next_run = $app->cron->getNextRun(ISPConfigDateTime::dbtime());
+ $this->_next_run = $next_run;
+
+ $app->db->query("REPLACE INTO `sys_cron` (`name`, `last_run`, `next_run`, `running`) VALUES ('" . $app->db->quote(get_class($this)) . "', " . ($this->_last_run ? "'" . $app->db->quote($this->_last_run) . "'" : "NULL") . ", " . ($next_run === false ? "NULL" : "'" . $app->db->quote($next_run) . "'") . ", " . ($this->_running == true ? "1" : "0") . ")");
+ }
+ }
+ }
+
+ /* this function checks if a cron job's next runtime is reached and returns true or false */
+ protected function onBeforeRun() {
+ global $app;
+
+ print "Called onBeforeRun() for class " . get_class($this) . "\n";
+
+ if($this->_running == true) return false; // job is still marked as running!
+
+ print "Jobs next run is " . $this->_next_run . "\n";
+ $reached = ISPConfigDateTime::compare($this->_next_run, ISPConfigDateTime::dbtime());
+ print "Date compare of " . ISPConfigDateTime::to_timestamp($this->_next_run) . " and " . ISPConfigDateTime::dbtime() . " is " . $reached . "\n";
+ if($reached === false) return false; // error!
+
+ if($reached === -1) {
+ // next_run time not reached
+ return false;
+ }
+
+ // next_run time reached (reached === 0 or -1)
+
+ // calculare next run time based on last_run or current time
+ $app->cron->parseCronLine($this->_schedule);
+ if($this->_no_skip == true) {
+ // we need to calculare the next run based on the previous next_run, as we may not skip one.
+ $next_run = $app->cron->getNextRun($this->_next_run);
+ if($next_run === false) {
+ // we could not calculate next run, try it with current time
+ $next_run = $app->cron->getNextRun(ISPConfigDateTime::dbtime());
+ }
+ } else {
+ // calculate next run based on current time
+ $next_run = $app->cron->getNextRun(ISPConfigDateTime::dbtime());
+ }
+
+ print "Jobs next run is now " . $next_run . "\n";
+
+ $app->db->query("REPLACE INTO `sys_cron` (`name`, `last_run`, `next_run`, `running`) VALUES ('" . $app->db->quote(get_class($this)) . "', NOW(), " . ($next_run === false ? "NULL" : "'" . $app->db->quote($next_run) . "'") . ", 1)");
+ return true;
+ }
+
+ // child classes should override this!
+ protected function onRunJob() {
+ global $app;
+
+ print "Called onRun() for class " . get_class($this) . "\n";
+ }
+
+ // child classes may override this!
+ protected function onAfterRun() {
+ global $app;
+
+ print "Called onAfterRun() for class " . get_class($this) . "\n";
+ }
+
+ // child classes may NOT override this!
+ private function onCompleted() {
+ global $app;
+
+ print "Called onCompleted() for class " . get_class($this) . "\n";
+ $app->db->query("UPDATE `sys_cron` SET `running` = 0 WHERE `name` = '" . $app->db->quote(get_class($this)) . "'");
+ }
+
+}
+
+?>
diff --git a/server/lib/classes/functions.inc.php b/server/lib/classes/functions.inc.php
new file mode 100644
index 0000000..74f8400
--- /dev/null
+++ b/server/lib/classes/functions.inc.php
@@ -0,0 +1,398 @@
+<?php
+
+/*
+Copyright (c) 2010, Till Brehm, projektfarm Gmbh
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+//* The purpose of this library is to provide some general functions.
+//* This class is loaded automatically by the ispconfig framework.
+
+class functions {
+ var $idn_converter = null;
+ var $idn_converter_name = '';
+
+ public function mail($to, $subject, $text, $from, $filepath = '', $filetype = 'application/pdf', $filename = '', $cc = '', $bcc = '', $from_name = '') {
+ global $app,$conf;
+
+ if($conf['demo_mode'] == true) $app->error("Mail sending disabled in demo mode.");
+
+ $app->uses('getconf,ispcmail');
+ $mail_config = $app->getconf->get_global_config('mail');
+ if($mail_config['smtp_enabled'] == 'y') {
+ $mail_config['use_smtp'] = true;
+ $app->ispcmail->setOptions($mail_config);
+ }
+ $app->ispcmail->setSender($from, $from_name);
+ $app->ispcmail->setSubject($subject);
+ $app->ispcmail->setMailText($text);
+
+ if($filepath != '') {
+ if(!file_exists($filepath)) $app->error("Mail attachement does not exist ".$filepath);
+ $app->ispcmail->readAttachFile($filepath);
+ }
+
+ if($cc != '') $app->ispcmail->setHeader('Cc', $cc);
+ if($bcc != '') $app->ispcmail->setHeader('Bcc', $bcc);
+
+ $app->ispcmail->send($to);
+ $app->ispcmail->finish();
+
+ /* left in here just for the case...
+ if($filepath != '') {
+ if(!file_exists($filepath)) $app->error("Mail attachement does not exist ".$filepath);
+
+ $content = file_get_contents($filepath);
+ $content = chunk_split(base64_encode($content));
+ $uid = strtoupper(md5(uniqid(time())));
+ $subject = "=?utf-8?B?".base64_encode($subject)."?=";
+
+ if($filename == '') {
+ $path_parts = pathinfo($filepath);
+ $filename = $path_parts["basename"];
+ unset($path_parts);
+ }
+
+ $header = "Return-Path: $from\nFrom: $from\nReply-To: $from\n";
+ if($cc != '') $header .= "Cc: $cc\n";
+ if($bcc != '') $header .= "Bcc: $bcc\n";
+ $header .= "MIME-Version: 1.0\n";
+ $header .= "Content-Type: multipart/mixed; boundary=$uid\n";
+
+ $header .= "--$uid\n";
+ $header .= "Content-Type: text/plain;\n\tcharset=\"UTF-8\"\n";
+ $header .= "Content-Transfer-Encoding: 8bit\n\n";
+ $header .= "$text\n";
+
+ $header .= "--$uid\n";
+ $header .= "Content-Type: $filetype; name=\"$filename\"\n";
+
+ $header .= "Content-Transfer-Encoding: base64\n";
+ $header .= "Content-Disposition: attachment; filename=\"$filename\"\n\n";
+ $header .= "$content\n";
+
+ $header .= "--$uid--";
+
+ mail($to, $subject, "", $header);
+ } else {
+ $header = "From: $from\nReply-To: $from\n";
+ if($cc != '') $header .= "Cc: $cc\n";
+ if($bcc != '') $header .= "Bcc: $bcc\n";
+ $header .= "Content-Type: text/plain;\n\tcharset=\"UTF-8\"\n";
+ $header .= "Content-Transfer-Encoding: 8bit\n\n";
+ $subject = "=?utf-8?B?".base64_encode($subject)."?=";
+ mail($to, $subject, $text, $header);
+ }
+ */
+ return true;
+ }
+
+ public function array_merge($array1,$array2) {
+ $out = $array1;
+ foreach($array2 as $key => $val) {
+ $out[$key] = $val;
+ }
+ return $out;
+ }
+
+ public function currency_format($number, $view = '') {
+ global $app;
+ if($view != '') $number_format_decimals = (int)$app->lng('number_format_decimals_'.$view);
+ if(!$number_format_decimals) $number_format_decimals = (int)$app->lng('number_format_decimals');
+
+ $number_format_dec_point = $app->lng('number_format_dec_point');
+ $number_format_thousands_sep = $app->lng('number_format_thousands_sep');
+ if($number_format_thousands_sep == 'number_format_thousands_sep') $number_format_thousands_sep = '';
+ return number_format((double)$number, $number_format_decimals, $number_format_dec_point, $number_format_thousands_sep);
+ }
+
+ public function get_ispconfig_url() {
+ global $app;
+
+ $url = (stristr($_SERVER['SERVER_PROTOCOL'],'HTTPS') || stristr($_SERVER['HTTPS'],'on'))?'https':'http';
+ if($_SERVER['SERVER_NAME'] != '_') {
+ $url .= '://'.$_SERVER['SERVER_NAME'];
+ if($_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443) {
+ $url .= ':'.$_SERVER['SERVER_PORT'];
+ }
+ } else {
+ $app->uses("getconf");
+ $server_config = $app->getconf->get_server_config(1,'server');
+ $url .= '://'.$server_config['hostname'];
+ if($_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443) {
+ $url .= ':'.$_SERVER['SERVER_PORT'];
+ }
+ }
+ return $url;
+ }
+
+ public function json_encode($data) {
+ if(!function_exists('json_encode')){
+ if(is_array($data) || is_object($data)){
+ $islist = is_array($data) && (empty($data) || array_keys($data) === range(0,count($data)-1));
+
+ if($islist){
+ $json = '[' . implode(',', array_map(array($this, "json_encode"), $data) ) . ']';
+ } else {
+ $items = Array();
+ foreach( $data as $key => $value ) {
+ $items[] = $this->json_encode("$key") . ':' . $this->json_encode($value);
+ }
+ $json = '{' . implode(',', $items) . '}';
+ }
+ } elseif(is_string($data)){
+ # Escape non-printable or Non-ASCII characters.
+ # I also put the \\ character first, as suggested in comments on the 'addclashes' page.
+ $string = '"'.addcslashes($data, "\\\"\n\r\t/".chr(8).chr(12)).'"';
+ $json = '';
+ $len = strlen($string);
+ # Convert UTF-8 to Hexadecimal Codepoints.
+ for($i = 0; $i < $len; $i++){
+ $char = $string[$i];
+ $c1 = ord($char);
+
+ # Single byte;
+ if($c1 <128){
+ $json .= ($c1 > 31) ? $char : sprintf("\\u%04x", $c1);
+ continue;
+ }
+
+ # Double byte
+ $c2 = ord($string[++$i]);
+ if(($c1 & 32) === 0){
+ $json .= sprintf("\\u%04x", ($c1 - 192) * 64 + $c2 - 128);
+ continue;
+ }
+
+ # Triple
+ $c3 = ord($string[++$i]);
+ if(($c1 & 16) === 0){
+ $json .= sprintf("\\u%04x", (($c1 - 224) <<12) + (($c2 - 128) << 6) + ($c3 - 128));
+ continue;
+ }
+
+ # Quadruple
+ $c4 = ord($string[++$i]);
+ if(($c1 & 8) === 0){
+ $u = (($c1 & 15) << 2) + (($c2>>4) & 3) - 1;
+
+ $w1 = (54<<10) + ($u<<6) + (($c2 & 15) << 2) + (($c3>>4) & 3);
+ $w2 = (55<<10) + (($c3 & 15)<<6) + ($c4-128);
+ $json .= sprintf("\\u%04x\\u%04x", $w1, $w2);
+ }
+ }
+ } else {
+ # int, floats, bools, null
+ $json = strtolower(var_export($data, true));
+ }
+ return $json;
+ } else {
+ return json_encode($data);
+ }
+ }
+
+ public function suggest_ips($type = 'IPv4'){
+ global $app;
+
+ if($type == 'IPv4'){
+ $regex = "/^[0-9]{1,3}(\.)[0-9]{1,3}(\.)[0-9]{1,3}(\.)[0-9]{1,3}$/";
+ } else {
+ // IPv6
+ $regex = "/^(\:\:([a-f0-9]{1,4}\:){0,6}?[a-f0-9]{0,4}|[a-f0-9]{1,4}(\:[a-f0-9]{1,4}){0,6}?\:\:|[a-f0-9]{1,4}(\:[a-f0-9]{1,4}){1,6}?\:\:([a-f0-9]{1,4}\:){1,6}?[a-f0-9]{1,4})(\/\d{1,3})?$/i";
+ }
+
+ $ips = array();
+ $results = $app->db->queryAllRecords("SELECT ip_address AS ip FROM server_ip WHERE ip_type = '".$type."'");
+ if(!empty($results) && is_array($results)){
+ foreach($results as $result){
+ if(preg_match($regex, $result['ip'])) $ips[] = $result['ip'];
+ }
+ }
+ $results = $app->db->queryAllRecords("SELECT ip_address AS ip FROM openvz_ip");
+ if(!empty($results) && is_array($results)){
+ foreach($results as $result){
+ if(preg_match($regex, $result['ip'])) $ips[] = $result['ip'];
+ }
+ }
+ $results = $app->db->queryAllRecords("SELECT data AS ip FROM dns_rr WHERE type = 'A' OR type = 'AAAA'");
+ if(!empty($results) && is_array($results)){
+ foreach($results as $result){
+ if(preg_match($regex, $result['ip'])) $ips[] = $result['ip'];
+ }
+ }
+ $results = $app->db->queryAllRecords("SELECT ns AS ip FROM dns_slave");
+ if(!empty($results) && is_array($results)){
+ foreach($results as $result){
+ if(preg_match($regex, $result['ip'])) $ips[] = $result['ip'];
+ }
+ }
+
+ $results = $app->db->queryAllRecords("SELECT xfer FROM dns_slave WHERE xfer != ''");
+ if(!empty($results) && is_array($results)){
+ foreach($results as $result){
+ $tmp_ips = explode(',', $result['xfer']);
+ foreach($tmp_ips as $tmp_ip){
+ $tmp_ip = trim($tmp_ip);
+ if(preg_match($regex, $tmp_ip)) $ips[] = $tmp_ip;
+ }
+ }
+ }
+ $results = $app->db->queryAllRecords("SELECT xfer FROM dns_soa WHERE xfer != ''");
+ if(!empty($results) && is_array($results)){
+ foreach($results as $result){
+ $tmp_ips = explode(',', $result['xfer']);
+ foreach($tmp_ips as $tmp_ip){
+ $tmp_ip = trim($tmp_ip);
+ if(preg_match($regex, $tmp_ip)) $ips[] = $tmp_ip;
+ }
+ }
+ }
+ $results = $app->db->queryAllRecords("SELECT also_notify FROM dns_soa WHERE also_notify != ''");
+ if(!empty($results) && is_array($results)){
+ foreach($results as $result){
+ $tmp_ips = explode(',', $result['also_notify']);
+ foreach($tmp_ips as $tmp_ip){
+ $tmp_ip = trim($tmp_ip);
+ if(preg_match($regex, $tmp_ip)) $ips[] = $tmp_ip;
+ }
+ }
+ }
+ $results = $app->db->queryAllRecords("SELECT remote_ips FROM web_database WHERE remote_ips != ''");
+ if(!empty($results) && is_array($results)){
+ foreach($results as $result){
+ $tmp_ips = explode(',', $result['remote_ips']);
+ foreach($tmp_ips as $tmp_ip){
+ $tmp_ip = trim($tmp_ip);
+ if(preg_match($regex, $tmp_ip)) $ips[] = $tmp_ip;
+ }
+ }
+ }
+ $ips = array_unique($ips);
+ sort($ips, SORT_NUMERIC);
+
+ $result_array = array('cheader' => array(), 'cdata' => array());
+
+ if(!empty($ips)){
+ $result_array['cheader'] = array('title' => 'IPs',
+ 'total' => count($ips),
+ 'limit' => count($ips)
+ );
+
+ foreach($ips as $ip){
+ $result_array['cdata'][] = array( 'title' => $ip,
+ 'description' => $type,
+ 'onclick' => '',
+ 'fill_text' => $ip
+ );
+ }
+ }
+
+ return $result_array;
+ }
+
+ public function intval($string, $force_numeric = false) {
+ if(intval($string) == 2147483647 || ($string > 0 && intval($string) < 0)) {
+ if($force_numeric == true) return floatval($string);
+ elseif(preg_match('/^([-]?)[0]*([1-9][0-9]*)([^0-9].*)*$/', $string, $match)) return $match[1].$match[2];
+ else return 0;
+ } else {
+ return intval($string);
+ }
+ }
+
+ /** IDN converter wrapper.
+ * all converter classes should be placed in ISPC_CLASS_PATH.'/idn/'
+ */
+ private function _idn_encode_decode($domain, $encode = true) {
+ if($domain == '') return '';
+ if(preg_match('/^[0-9\.]+$/', $domain)) return $domain; // may be an ip address - anyway does not need to bee encoded
+
+ // get domain and user part if it is an email
+ $user_part = false;
+ if(strpos($domain, '@') !== false) {
+ $user_part = substr($domain, 0, strrpos($domain, '@'));
+ $domain = substr($domain, strrpos($domain, '@') + 1);
+ }
+
+ if($encode == true) {
+ if(function_exists('idn_to_ascii')) {
+ $domain = idn_to_ascii($domain);
+ } elseif(file_exists(ISPC_CLASS_PATH.'/idn/idna_convert.class.php')) {
+ /* use idna class:
+ * @author Matthias Sommerfeld <mso@phlylabs.de>
+ * @copyright 2004-2011 phlyLabs Berlin, http://phlylabs.de
+ * @version 0.8.0 2011-03-11
+ */
+
+ if(!is_object($this->idn_converter) || $this->idn_converter_name != 'idna_convert.class') {
+ include_once(ISPC_CLASS_PATH.'/idn/idna_convert.class.php');
+ $this->idn_converter = new idna_convert(array('idn_version' => 2008));
+ $this->idn_converter_name = 'idna_convert.class';
+ }
+ $domain = $this->idn_converter->encode($domain);
+ }
+ } else {
+ if(function_exists('idn_to_utf8')) {
+ $domain = idn_to_utf8($domain);
+ } elseif(file_exists(ISPC_CLASS_PATH.'/idn/idna_convert.class.php')) {
+ /* use idna class:
+ * @author Matthias Sommerfeld <mso@phlylabs.de>
+ * @copyright 2004-2011 phlyLabs Berlin, http://phlylabs.de
+ * @version 0.8.0 2011-03-11
+ */
+
+ if(!is_object($this->idn_converter) || $this->idn_converter_name != 'idna_convert.class') {
+ include_once(ISPC_CLASS_PATH.'/idn/idna_convert.class.php');
+ $this->idn_converter = new idna_convert(array('idn_version' => 2008));
+ $this->idn_converter_name = 'idna_convert.class';
+ }
+ $domain = $this->idn_converter->decode($domain);
+ }
+ }
+
+ if($user_part !== false) return $user_part . '@' . $domain;
+ else return $domain;
+ }
+
+ public function idn_encode($domain) {
+ $domains = explode("\n", $domain);
+ for($d = 0; $d < count($domains); $d++) {
+ $domains[$d] = $this->_idn_encode_decode($domains[$d], true);
+ }
+ return implode("\n", $domains);
+ }
+
+ public function idn_decode($domain) {
+ $domains = explode("\n", $domain);
+ for($d = 0; $d < count($domains); $d++) {
+ $domains[$d] = $this->_idn_encode_decode($domains[$d], false);
+ }
+ return implode("\n", $domains);
+ }
+
+}
+
+?>
\ No newline at end of file
diff --git a/server/lib/classes/libdatetime.inc.php b/server/lib/classes/libdatetime.inc.php
new file mode 100644
index 0000000..2735768
--- /dev/null
+++ b/server/lib/classes/libdatetime.inc.php
@@ -0,0 +1,479 @@
+<?php
+
+/*
+Copyright (c) 2013, Marius Cramer, pixcept KG
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of ISPConfig nor the names of its contributors
+ may be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
+*/
+
+/**
+ * Date and Time class
+ *
+ * provides functions related to date and time operations
+ */
+abstract class ISPConfigDateTime {
+
+ /**
+ * Get days, hours, minutes and seconds
+ *
+ * Returns an array with days, hours, minutes and seconds from a given amount of seconds
+ *
+ * @access public
+ * @param int $seconds amount of seconds
+ * @param bool $get_days if true get the days, too
+ * @return array data (0 => days, 1 => hours, 2 => minutes, 3 => seconds)
+ */
+ public static function get_parts($seconds, $get_days = false) {
+ $days = 0;
+ if($get_days == true) {
+ $days = floor($seconds / (3600 * 24));
+ $seconds = $seconds % (3600 * 24);
+ }
+ $hours = floor($seconds / 3600);
+ $seconds = $seconds % 3600;
+ $minutes = floor($seconds / 60);
+ $seconds = $seconds % 60;
+
+ return array($days, $hours, $minutes, $seconds);
+ }
+
+ public static function dbtime() {
+ global $app;
+
+ $time = $app->db->queryOneRecord('SELECT UNIX_TIMESTAMP() as `time`');
+ return $time['time'];
+ }
+
+ /**
+ * Get a unix timestamp for a date
+ *
+ * @access public
+ * @param mixed $date the date to convert. Can be
+ * - int (unix timestamp)
+ * - date string yyyy-mm-dd[ hh:mm:ss]
+ * - date string dd.mm.yyyy[ hh:mm:ss]
+ * @return int the unix timestamp
+ */
+ public static function to_timestamp($date) {
+ if(!is_string($date) && !is_numeric($date)) return false;
+ $date = trim($date);
+
+ if(is_numeric($date)) return $date;
+
+ if(strpos($date, '-') !== false) {
+ $regex = "(\d{2,4})-(\d{1,2})-(\d{1,2})(\s+(\d{1,2}):(\d{1,2})(:(\d{1,2}))?)?";
+ $ok = preg_match("'$regex'", $date, $matches);
+ if($ok) {
+ $year = $matches[1];
+ $month = $matches[2];
+ $day = $matches[3];
+ $hour = isset($matches[5]) ? $matches[5] : 0;
+ $minute = isset($matches[6]) ? $matches[6] : 0;
+ $second = isset($matches[8]) ? $matches[8] : 0;
+ }
+ } else {
+ $regex = "(\d{1,2})[/.](\d{1,2})[/.](\d{2,4})(\s+(\d{1,2}):(\d{1,2})(:(\d{1,2}))?)?";
+ $ok = preg_match("'$regex'", $date, $matches);
+ if($ok) {
+ $year = $matches[3];
+ $month = $matches[2];
+ $day = $matches[1];
+ $hour = isset($matches[5]) ? $matches[5] : 0;
+ $minute = isset($matches[6]) ? $matches[6] : 0;
+ $second = isset($matches[8]) ? $matches[8] : 0;
+ }
+ }
+
+ if(!$ok) return false;
+
+ if(!$day || !$month || !$year) return false;
+ if(!$hour) $hour = 0;
+ if(!$minute) $minute = 0;
+ if(!$second) $second = 0;
+ if($year < 1900) $year += 1900;
+
+ if(!checkdate($month, $day, $year)) return false;
+
+ $date = mktime($hour, $minute, $second, $month, $day, $year);
+
+ return $date;
+ }
+
+ /**
+ * Get a date string
+ *
+ * Returns a formatted date string
+ *
+ * @access public
+ * @param mixed $date the date to convert. Can be
+ * - int (unix timestamp)
+ * - date string yyyy-mm-dd[ hh:mm:ss]
+ * - date string dd.mm.yyyy[ hh:mm:ss]
+ * @param string $format the format to get the date string in.
+ * - short: dd.mm.yy
+ * - veryshort: dd.mm.
+ * - medium: dd.mm.yyyy
+ * - long: dd. Month yyyy
+ * - extra: Day, dd. Month yyyy
+ * - day: dd
+ * - monthnum: mm
+ * - shortmonth: Short month name like Mar for March
+ * - month: Month name
+ * - shortyear: yy
+ * - year: yyyy
+ * - onlydate: dd.mm
+ * - onlydatelong: dd. Month
+ * - onlytime: HH:MM
+ * - rss: Rss time format for XML
+ * - nice: if you prepend a nice: (like nice:long) you will get results like "today" or "yesterday" if applicable
+ * - custom: you can give a strftime format like %d.%m.%Y %H:%M if you prepend custom: to it
+ * @param bool $time if true apped the time to the date string
+ * @param bool $seconds if true append the seconds to the time
+ * @return string date string
+ */
+ public static function to_string($date, $format = 'short', $time = false, $seconds = false) {
+ global $portal;
+
+ if(!$date) return '';
+
+ setlocale(LC_TIME, array('de_DE.UTF-8', 'de_DE', 'de_DE.ISO-8859-1', 'de_DE.ISO-8859-15'));
+
+ if(!is_numeric($date)) {
+ $date = self::to_timestamp($date);
+ if($date === false) return $date;
+ }
+
+ if($format == 'timestamp') return $date;
+
+ $fmt = '';
+ $prepend = '';
+ if(substr($format, 0, 5) == 'nice:') {
+ if(strftime('%d.%m.%Y', $date) == strftime('%d.%m.%Y', $portal->getTime())) {
+ if($time == true) $format = 'onlytime';
+ else $format = '';
+ $prepend = 'Heute';
+ } elseif(strftime('%d.%m.%Y', $date) == strftime('%d.%m.%Y', $portal->getTime() - 86400)) {
+ if($time == true) $format = 'onlytime';
+ else $format = '';
+ $prepend = 'Gestern';
+ } elseif(strftime('%d.%m.%Y', $date) == strftime('%d.%m.%Y', $portal->getTime() + 86400)) {
+ if($time == true) $format = 'onlytime';
+ else $format = '';
+ $prepend = 'Morgen';
+ } else {
+ $format = substr($format, 5);
+ }
+ } elseif(substr($format, 0, 7) == 'custom:') {
+ $fmt = substr($format, 7);
+ $format = '';
+ $time = false;
+ }
+
+ if($format == 'short') $fmt = '%d.%m.%y';
+ elseif($format == 'veryshort') $fmt = '%d.%m.';
+ elseif($format == 'medium') $fmt = '%d.%m.%Y';
+ elseif($format == 'long') $fmt = '%d. %B %Y';
+ elseif($format == 'extra') $fmt = '%A, %d. %B %Y';
+ elseif($format == 'day') $fmt = '%d';
+ elseif($format == 'monthnum') $fmt = '%m';
+ elseif($format == 'shortmonth') $fmt = '%b';
+ elseif($format == 'month') $fmt = '%B';
+ elseif($format == 'shortyear') $fmt = '%y';
+ elseif($format == 'year') $fmt = '%Y';
+ elseif($format == 'onlydate') $fmt = '%d.%m.';
+ elseif($format == 'onlydatelong') $fmt = '%d. %B';
+ elseif($format == 'onlytime') {
+ $fmt = '%H:%M';
+ $time = false;
+ } elseif($format == 'rss') {
+ $ret = date(DATE_RSS, $date);
+ if($prepend != '') $ret = $prepend . ' ' . $ret;
+ return $ret;
+ } elseif($format == 'sitemap') {
+ $ret = date(DATE_ATOM, $date);
+ if($prepend != '') $ret = $prepend . ' ' . $ret;
+ return $ret;
+ }
+ if($time == true) $fmt .= ' %H:%M' . ($seconds == true ? ':%S' : '');
+
+ if($fmt != '') $ret = strftime($fmt, $date);
+ else $ret = '';
+
+ if($prepend != '') $ret = trim($prepend . ' ' . $ret);
+ return $ret;
+ }
+
+ /**
+ * Get the month difference of two dates
+ *
+ * Gets the difference in months of two given dates.
+ * The days are ignored, so the difference between 2010-01-21 and 2010-05-01 is 4!
+ *
+ * @access public
+ * @param mixed $date_from the beginning date, either
+ * - int (unix timestamp)
+ * - date string yyyy-mm-dd[ hh:mm:ss]
+ * - date string dd.mm.yyyy[ hh:mm:ss]
+ * @param mixed $date_to the ending date, either
+ * - int (unix timestamp)
+ * - date string yyyy-mm-dd[ hh:mm:ss]
+ * - date string dd.mm.yyyy[ hh:mm:ss]
+ * @param bool $return_years if set to true, the function returns an array of years and months instead of months
+ * @param bool $include_both if set to true, the starting AND ending month is included, so the month count is +1
+ * @return mixed either int (months) or array of int (0 => years, 1 => months) or FALSE on invalid dates
+ */
+ public static function months_between($date_from, $date_to, $return_years = false, $include_both = false) {
+ $date_from = self::to_string($date_from, 'custom:%Y%m');
+ if($date_from === false) return $date_from;
+
+ $date_to = self::to_string($date_to, 'custom:%Y%m');
+ if($date_to === false) return $date_to;
+
+ $date_from = intval($date_from);
+ $date_to = intval($date_to);
+
+ if($date_to < $date_from) return false;
+
+ $result = $date_to - $date_from;
+ if($include_both == true) $result++;
+
+ $years = floor($result / 100);
+ $months = $result % 100;
+ if($months > 12) $months -= 88;
+ elseif($months == 12) {
+ $months = 0;
+ $years++;
+ }
+ if($return_years == true) return array($years, $months);
+
+ $months += ($years * 12);
+ return $months;
+ }
+
+ /**
+ * Get the day difference of two dates
+ *
+ * Gets the difference in days of two given dates.
+ *
+ * @access public
+ * @param mixed $date_from the beginning date, either
+ * - int (unix timestamp)
+ * - date string yyyy-mm-dd[ hh:mm:ss]
+ * - date string dd.mm.yyyy[ hh:mm:ss]
+ * @param mixed $date_to the ending date, either
+ * - int (unix timestamp)
+ * - date string yyyy-mm-dd[ hh:mm:ss]
+ * - date string dd.mm.yyyy[ hh:mm:ss]
+ * @param bool $include_both if set to true, the starting AND ending day is included, so the day count is +1
+ * @return mixed either int (days) or FALSE on invalid dates
+ */
+ public static function days_between($date_from, $date_to, $include_both = false) {
+ $date_from = self::to_string($date_from, 'custom:%Y-%m-%d');
+ if($date_from === false) return $date_from;
+ list($y, $m, $d) = explode('-', $date_from);
+ $ts_from = mktime(0, 0, 0, $m, $d, $y);
+
+ $date_to = self::to_string($date_to, 'custom:%Y-%m-%d');
+ if($date_to === false) return $date_to;
+ list($y, $m, $d) = explode('-', $date_to);
+ $ts_to = mktime(0, 0, 0, $m, $d, $y);
+
+ $result = $ts_to - $ts_from;
+ if($include_both == true) $result++;
+
+ $days = floor($result / (3600 * 24));
+
+ return $days;
+ }
+
+ /**
+ * Check if one date is before another
+ *
+ * @access public
+ * @param mixed $date_1 the first date, either
+ * - int (unix timestamp)
+ * - date string yyyy-mm-dd[ hh:mm:ss]
+ * - date string dd.mm.yyyy[ hh:mm:ss]
+ * @param mixed $date_2 the second date, either
+ * - int (unix timestamp)
+ * - date string yyyy-mm-dd[ hh:mm:ss]
+ * - date string dd.mm.yyyy[ hh:mm:ss]
+ * @return mixed either int (1 if the first date is earlier, -1 if the second date is earlier, 0 if both are the same) or FALSE on invalid dates
+ */
+ public static function compare($date_1, $date_2) {
+ $ts_1 = self::to_timestamp($date_1);
+ if($ts_1 === false) return false;
+ $ts_2 = self::to_timestamp($date_2);
+ if($ts_2 === false) return false;
+
+ if($ts_1 < $ts_2) return 1;
+ elseif($ts_1 > $ts_2) return -1;
+ else return 0;
+ }
+
+ /**
+ * Convert date to sql format
+ *
+ * Converts a date from different formats to the sql format if possible
+ *
+ * @access public
+ * @param string $date date string in forms
+ * - dd.mm.yy
+ * - yyyy-mm-dd
+ * - yy-mm-dd
+ * - yyyy/mm/dd
+ * - dd.mm.yy
+ * - all formats can have time information HH:MM:SS appended
+ * @param bool $no_time if true, the resulting sql date is without time part even if time was part of the input
+ * @return mixed sql date string on success, error object otherwise
+ */
+ public static function sql_date($date = false, $no_time = false) {
+ global $portal;
+
+ $result = '';
+ $time = '';
+
+ if($date === false) $date = $portal->getTime(true);
+
+ if(is_numeric($date)) {
+ return ($no_time ? strftime('%Y-%m-%d', $date) : strftime('%Y-%m-%d %H:%M:%S', $date));
+ }
+
+ if(preg_match('/^(.*)(\d{1,2}:\d{1,2}(:\d{1,2})?)(\D|$)/', $date, $matches)) {
+ $date = $matches[1];
+ $time = ' ' . $matches[2];
+ }
+ if(preg_match('/(^|\D)(\d{4,4})-(\d{1,2})-(\d{1,2})(\D|$)/', $date, $result)) {
+ $day = $result[4];
+ $month = $result[3];
+ $year = $result[2];
+ } elseif(preg_match('/(^|\D)(\d{4,4})\/(\d{1,2})\/(\d{1,2})(\D|$)/', $date, $result)) {
+ $day = $result[4];
+ $month = $result[3];
+ $year = $result[2];
+ } elseif(preg_match('/(^|\D)(\d{2,2})-(\d{1,2})-(\d{1,2})(\D|$)/', $date, $result)) {
+ $day = $result[4];
+ $month = $result[3];
+ $year = $result[2];
+ } elseif(preg_match('/(^|\D)(\d{1,2})\.(\d{1,2})\.(\d{4,4})(\D|$)/', $date, $result)) {
+ $day = $result[2];
+ $month = $result[3];
+ $year = $result[4];
+ } elseif(preg_match('/(^|\D)(\d{1,2})\.(\d{1,2})\.(\d{2,2})(\D|$)/', $date, $result)) {
+ $day = $result[2];
+ $month = $result[3];
+ $year = $result[4];
+ } else {
+ return false;
+ }
+ if($no_time == true) $time = '';
+
+ $day = str_pad(intval($day), 2, '0', STR_PAD_LEFT);
+ $month = str_pad(intval($month), 2, '0', STR_PAD_LEFT);
+ $year = intval($year);
+
+ $valid = checkdate($month, $day, $year);
+ if(!$valid) return false;
+
+ return $year . '-' . $month . '-' . $day . $time;
+ }
+
+ /**
+ * Get information if given date is leap year
+ *
+ * @access public
+ * @param mixed $date Date to check
+ * @return bool true if leap year, false otherwise
+ */
+ public static function is_leap_year($date) {
+ // check if only year was given
+ if(is_numeric($date) && $date < 10000) $date .= '-01-01';
+
+ $ts = self::to_timestamp($date);
+ if($ts === false) return false;
+
+ if(date('L', $ts) == 1) return true;
+ else return false;
+ }
+
+ /**
+ * Get the last day of the month
+ *
+ * @access public
+ * @param int $month the month to get the last day for
+ * @param int $year the corresponding year (for february in leap years)
+ * @return bool true if leap year, false otherwise
+ */
+ public static function last_day($month, $year = false) {
+ switch($month) {
+ case 1:
+ case 3:
+ case 5:
+ case 7:
+ case 8:
+ case 10:
+ case 12:
+ return 31;
+ break;
+ case 2:
+ return ($year !== false && self::is_leap_year($year) ? 29 : 28);
+ break;
+ default:
+ return 30;
+ break;
+ }
+ }
+
+ /**
+ * Get age for given date
+ *
+ * Returns the age for a given date if possible
+ *
+ * @access public
+ * @param string $date see ISPConfigDateTime::sql_date() for possible values
+ * @return mixed int of age if successful, error object otherwise
+ * @see ISPConfigDateTime::sql_date
+ */
+ public static function calc_age($date) {
+ global $portal;
+
+ $date = self::sql_date($date);
+ if($date === false) return $date;
+
+ list($year, $month, $day) = explode('-', $date);
+ list($curyear, $curmonth, $curday) = explode('-', strftime('%Y-%m-%d', $portal->getTime()));
+
+ $year_diff = $curyear - $year;
+ $month_diff = $curmonth - $month;
+ $day_diff = $curday - $day;
+
+ if($day_diff < 0) $month_diff--;
+ if($month_diff < 0) $year_diff--;
+ if($year_diff < 0) $year_diff = 0;
+
+ return $year_diff;
+ }
+}
+
diff --git a/server/lib/classes/monitor_tools.inc.php b/server/lib/classes/monitor_tools.inc.php
index 6b93e1e..42ef73f 100644
--- a/server/lib/classes/monitor_tools.inc.php
+++ b/server/lib/classes/monitor_tools.inc.php
@@ -226,432 +226,7 @@
return array('name' => $distname, 'version' => $distver, 'id' => $distid, 'baseid' => $distbaseid);
}
- //** Email Quota
- public function monitorEmailQuota() {
- global $conf, $app;
-
- //* Initialize data array
- $data = array();
-
- //* the id of the server as int
- $server_id = intval($conf['server_id']);
-
- //* The type of the data
- $type = 'email_quota';
-
- //* The state of the email_quota.
- $state = 'ok';
-
- $mailboxes = $app->db->queryAllRecords("SELECT email,maildir FROM mail_user WHERE server_id = $server_id");
- if(is_array($mailboxes)) {
- foreach($mailboxes as $mb) {
- $email = $mb['email'];
- $email_parts = explode('@',$mb['email']);
- $filename = $mb['maildir'].'/.quotausage';
- if(file_exists($filename) && !is_link($filename)) {
- $quotafile = file($filename);
- $data[$email]['used'] = trim($quotafile['1']);
- unset($quotafile);
- } else {
- exec('du -s '.escapeshellcmd($mb['maildir']),$out);
- $parts = explode(' ',$out[0]);
- $data[$email]['used'] = intval($parts[0])*1024;
- unset($out);
- unset($parts);
- }
- }
- }
-
- unset($mailboxes);
-
- //* Dovecot quota check Courier in progress lathama@gmail.com
- /*
- if($dir = opendir("/var/vmail")){
- while (($quotafiles = readdir($dir)) !== false){
- if(preg_match('/.\_quota$/', $quotafiles)){
- $quotafile = (file("/var/vmail/" . $quotafiles));
- $emailaddress = preg_replace('/_quota/',"", $quotafiles);
- $emailaddress = preg_replace('/_/',"@", $emailaddress);
- $data[$emailaddress]['used'] = trim($quotafile['1']);
- }
- }
- closedir($dir);
- }
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- //** Filesystem Quota
- public function monitorHDQuota() {
- global $conf;
-
- //* Initialize data array
- $data = array();
-
- //* the id of the server as int
- $server_id = intval($conf['server_id']);
-
- //* The type of the data
- $type = 'harddisk_quota';
-
- //* The state of the harddisk_quota.
- $state = 'ok';
-
- //* Fetch the data for all users
- $dfData = shell_exec('repquota -au 2>/dev/null');
-
- //* Split into array
- $df = explode("\n", $dfData);
-
- //* ignore the first 5 lines, process the rest
- for ($i = 5; $i <= sizeof($df); $i++) {
- if ($df[$i] != '') {
- //* Make a array of the data
- $s = preg_split('/[\s]+/', $df[$i]);
- $username = $s[0];
- if (substr($username, 0, 3) == 'web') {
- if (isset($data['user'][$username])) {
- $data['user'][$username]['used'] += $s[2];
- $data['user'][$username]['soft'] += $s[3];
- $data['user'][$username]['hard'] += $s[4];
- $data['user'][$username]['files'] += $s[5];
- } else {
- $data['user'][$username]['used'] = $s[2];
- $data['user'][$username]['soft'] = $s[3];
- $data['user'][$username]['hard'] = $s[4];
- $data['user'][$username]['files'] = $s[5];
- }
- }
- }
- }
-
- //** Fetch the data for all users
- $dfData = shell_exec('repquota -ag 2>/dev/null');
-
- //* split into array
- $df = explode("\n", $dfData);
-
- //* ignore the first 5 lines, process the rest
- for ($i = 5; $i <= sizeof($df); $i++) {
- if ($df[$i] != '') {
- //* Make a array of the data
- $s = preg_split('/[\s]+/', $df[$i]);
- $groupname = $s[0];
- if (substr($groupname, 0, 6) == 'client') {
- if (isset($data['group'][$groupname])) {
- $data['group'][$groupname]['used'] += $s[1];
- $data['group'][$groupname]['soft'] += $s[2];
- $data['group'][$groupname]['hard'] += $s[3];
- } else {
- $data['group'][$groupname]['used'] = $s[1];
- $data['group'][$groupname]['soft'] = $s[2];
- $data['group'][$groupname]['hard'] = $s[3];
- }
- }
- }
- }
-
- //* Return the Result
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorServer() {
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'server_load';
-
- /*
- Fetch the data into a array
- */
- $procUptime = shell_exec("cat /proc/uptime | cut -f1 -d' '");
- $data['up_days'] = floor($procUptime / 86400);
- $data['up_hours'] = floor(($procUptime - $data['up_days'] * 86400) / 3600);
- $data['up_minutes'] = floor(($procUptime - $data['up_days'] * 86400 - $data['up_hours'] * 3600) / 60);
-
- $data['uptime'] = shell_exec('uptime');
-
- $tmp = explode(',', $data['uptime'], 4);
- $tmpUser = explode(' ', trim($tmp[2]));
- $data['user_online'] = intval($tmpUser[0]);
-
- //* New Load Average code to fix "always zero" bug in non-english distros. NEEDS TESTING
- $loadTmp = shell_exec("cat /proc/loadavg | cut -f1-3 -d' '");
- $load = explode(' ', $loadTmp);
- $data['load_1'] = floatval(str_replace(',', '.', $load[0]));
- $data['load_5'] = floatval(str_replace(',', '.', $load[1]));
- $data['load_15'] = floatval(str_replace(',', '.', $load[2]));
-
- /** The state of the server-load. */
- $state = 'ok';
- if ($data['load_1'] > 20)
- $state = 'info';
- if ($data['load_1'] > 50)
- $state = 'warning';
- if ($data['load_1'] > 100)
- $state = 'critical';
- if ($data['load_1'] > 150)
- $state = 'error';
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorOsVer() {
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'os_info';
-
- /*
- Fetch the data into a array
- */
- $dist = $this->get_distname();
-
- $data['name'] = $dist['name'];
- $data['version'] = $dist['version'];
-
- /* the OS has no state. It is, what it is */
- $state = 'no_state';
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorIspcVer() {
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'ispc_info';
-
- /*
- Fetch the data into a array
- */
- $data['name'] = ISPC_APP_TITLE;
- $data['version'] = ISPC_APP_VERSION;
-
- /* the ISPC-Version has no state. It is, what it is */
- $state = 'no_state';
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorDiskUsage() {
- global $app,$conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'disk_usage';
-
- /** The state of the disk-usage */
- $state = 'ok';
-
- /** Fetch the data of ALL devices into a array (needed for monitoring!) */
- //$dfData = shell_exec('df -hT 2>/dev/null');
- $app->uses('getconf');
- $web_config = $app->getconf->get_server_config($conf['server_id'], 'web');
- $dfData = shell_exec('df -hT|grep -v "'.$web_config['website_basedir'].'/" 2>/dev/null');
-
- // split into array
- $df = explode("\n", $dfData);
-
- /*
- * ignore the first line, process the rest
- */
- for ($i = 1; $i <= sizeof($df); $i++) {
- if ($df[$i] != '') {
- /*
- * Make an array of the data
- */
- $s = preg_split('/[\s]+/', $df[$i]);
- $data[$i]['fs'] = $s[0];
- $data[$i]['type'] = $s[1];
- $data[$i]['size'] = $s[2];
- $data[$i]['used'] = $s[3];
- $data[$i]['available'] = $s[4];
- $data[$i]['percent'] = $s[5];
- $data[$i]['mounted'] = $s[6];
- /*
- * calculate the state
- */
- $usePercent = floatval($data[$i]['percent']);
-
- //* get the free memsize
- if(substr($data[$i]['available'],-1) == 'G') {
- $freesize = floatval($data[$i]['available'])*1024;
- } elseif(substr($data[$i]['available'],-1) == 'T') {
- $freesize = floatval($data[$i]['available'])*1024*1024;
- } else {
- $freesize = floatval($data[$i]['available']);
- }
-
- //* We don't want to check some filesystem which have no sensible filling levels
- switch ($data[$i]['type']) {
- case 'iso9660':
- case 'cramfs':
- case 'udf':
- case 'tmpfs':
- case 'devtmpfs':
- case 'udev':
- break;
- default:
- if ($usePercent > 75 && $freesize < 2000)
- $state = $this->_setState($state, 'info');
- if ($usePercent > 80 && $freesize < 1000)
- $state = $this->_setState($state, 'warning');
- if ($usePercent > 90 && $freesize < 500)
- $state = $this->_setState($state, 'critical');
- if ($usePercent > 95 && $freesize < 100)
- $state = $this->_setState($state, 'error');
- break;
- }
- }
- }
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorMemUsage() {
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'mem_usage';
-
- /*
- Fetch the data into a array
- */
- $miData = shell_exec('cat /proc/meminfo');
-
- $memInfo = explode("\n", $miData);
-
- foreach ($memInfo as $line) {
- $part = preg_split('/:/', $line);
- $key = trim($part[0]);
- $tmp = explode(' ', trim($part[1]));
- $value = 0;
- if ($tmp[1] == 'kB')
- $value = $tmp[0] * 1024;
- $data[$key] = $value;
- }
-
- /*
- * actually this info has no state.
- * maybe someone knows better...???...
- */
- $state = 'no_state';
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorCpu() {
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'cpu_info';
-
- /*
- Fetch the data into a array
- */
- if (file_exists('/proc/cpuinfo')) {
- $cpuData = shell_exec('cat /proc/cpuinfo');
- $cpuInfo = explode("\n", $cpuData);
- $processor = 0;
-
- foreach ($cpuInfo as $line) {
-
- $part = preg_split('/:/', $line);
- $key = trim($part[0]);
- $value = trim($part[1]);
- if ($key == 'processor')
- $processor = intval($value);
- if ($key != '')
- $data[$key . ' ' . $processor] = $value;
- }
-
- /* the cpu has no state. It is, what it is */
- $state = 'no_state';
- } else {
- /*
- * It is not Linux, so there is no data and no state
- *
- * no_state, NOT unknown, because "unknown" is shown as state
- * inside the GUI. no_state is hidden.
- *
- * We have to write NO DATA inside the DB, because the GUI
- * could not know, if there is any dat, or not...
- */
- $state = 'no_state';
- $data['output'] = '';
- }
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
+ // this function remains in the tools class, because it is used by cron AND rescue
public function monitorServices() {
global $app;
global $conf;
@@ -755,14 +330,15 @@
$data['mysqlserver'] = 0;
$state = 'error'; // because service is down
}
-
- if ($this->_checkTcp('localhost', 27017)) {
- $data['mongodbserver'] = 1;
- } else {
- $data['mongodbserver'] = 0;
- $state = 'error'; // because service is down
- }
}
+ $data['mongodbserver'] = -1;
+ if ($this->_checkTcp('localhost', 27017)) {
+ $data['mongodbserver'] = 1;
+ } else {
+ $data['mongodbserver'] = 0;
+ //$state = 'error'; // because service is down
+ /* TODO!!! check if this is a mongodbserver at all, otherwise it will always throw an error state!!! */
+ }
/*
* Return the Result
@@ -773,925 +349,7 @@
$res['state'] = $state;
return $res;
}
-
- public function monitorOpenVzHost() {
- global $app;
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'openvz_veinfo';
-
- /*
- Fetch the data into a array
- */
- $app->load(openvz_tools);
- $openVzTools = new openvz_tools();
- $data = $openVzTools->getOpenVzVeInfo();
-
- /* the VE-Info has no state. It is, what it is */
- $state = 'no_state';
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorOpenVzUserBeancounter() {
- global $app;
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'openvz_beancounter';
-
- /*
- Fetch the data into a array
- */
- $app->load(openvz_tools);
- $openVzTools = new openvz_tools();
- $data = $openVzTools->getOpenVzVeBeanCounter();
-
- /* calculate the state of the beancounter */
- if ($data == '') {
- $state = 'no_state';
- } else {
- $state = 'ok';
-
- /* transfer this output-string into a array */
- $test = explode("\n", $data);
-
- /* the first list of the output is not needed */
- array_shift($test);
-
- /* now process all items of the rest */
- foreach ($test as $item) {
- /*
- * eliminate all doubled spaces and spaces at the beginning and end
- */
- while (strpos($item, ' ') !== false) {
- $item = str_replace(' ', ' ', $item);
- }
- $item = trim($item);
-
- /*
- * The failcounter is the LAST
- */
- if ($item != '') {
- $tmp = explode(' ', $item);
- $failCounter = $tmp[sizeof($tmp) - 1];
- if ($failCounter > 0)
- $state = 'info';
- if ($failCounter > 50)
- $state = 'warning';
- if ($failCounter > 200)
- $state = 'critical';
- if ($failCounter > 10000)
- $state = 'error';
- }
- }
- }
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorSystemUpdate() {
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'system_update';
-
- /* This monitoring is only available on Debian or Ubuntu */
- if (file_exists('/etc/debian_version')) {
-
- /*
- * first update the "apt database"
- */
- shell_exec('apt-get update');
-
- /*
- * Then test the upgrade.
- * if there is any output, then there is a needed update
- */
- $aptData = shell_exec('apt-get -s -qq dist-upgrade');
- if ($aptData == '') {
- /* There is nothing to update! */
- $state = 'ok';
- } else {
- /*
- * There is something to update! this is in most cases not critical, so we can
- * do a system-update once a month or so...
- */
- $state = 'info';
- }
-
- /*
- * Fetch the output
- */
- $data['output'] = $aptData;
- } elseif (file_exists('/etc/gentoo-release')) {
-
- /*
- * first update the portage tree
- */
-
- // In keeping with gentoo's rsync policy, don't update to frequently (every four hours - taken from http://www.gentoo.org/doc/en/source_mirrors.xml)
- $do_update = true;
- if (file_exists('/usr/portage/metadata/timestamp.chk')) {
- $datetime = file_get_contents('/usr/portage/metadata/timestamp.chk');
- $datetime = trim($datetime);
-
- $dstamp = strtotime($datetime);
- if ($dstamp) {
- $checkat = $dstamp + 14400; // + 4hours
- if (mktime() < $checkat) {
- $do_update = false;
- }
- }
- }
-
- if ($do_update) {
- shell_exec('emerge --sync --quiet');
- }
-
- /*
- * Then test the upgrade.
- * if there is any output, then there is a needed update
- */
- $emergeData = shell_exec('glsa-check -t affected');
- if ($emergeData == '') {
- /* There is nothing to update! */
- $state = 'ok';
- $data['output'] = 'No unapplied GLSA\'s found on the system.';
- } else {
- /* There is something to update! */
- $state = 'info';
- $data['output'] = shell_exec('glsa-check -pv --nocolor affected 2>/dev/null');
- }
- } elseif (file_exists('/etc/SuSE-release')) {
-
- /*
- * update and find the upgrade.
- * if there is any output, then there is a needed update
- */
- $aptData = shell_exec('zypper -q lu');
- if ($aptData == '') {
- /* There is nothing to update! */
- $state = 'ok';
- } else {
- /*
- * There is something to update! this is in most cases not critical, so we can
- * do a system-update once a month or so...
- */
- $state = 'info';
- }
-
- /*
- * Fetch the output
- */
- $data['output'] = shell_exec('zypper lu');
- } else {
- /*
- * It is not Debian/Ubuntu, so there is no data and no state
- *
- * no_state, NOT unknown, because "unknown" is shown as state
- * inside the GUI. no_state is hidden.
- *
- * We have to write NO DATA inside the DB, because the GUI
- * could not know, if there is any dat, or not...
- */
- $state = 'no_state';
- $data['output'] = '';
- }
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorMailQueue() {
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'mailq';
-
- /* Get the data from the mailq */
- $data['output'] = shell_exec('mailq');
-
- /*
- * The last line has more informations
- */
- $tmp = explode("\n", $data['output']);
- $more = $tmp[sizeof($tmp) - 1];
- $res = $this->_getIntArray($more);
- $data['bytes'] = $res[0];
- $data['requests'] = $res[1];
-
- /** The state of the mailq. */
- $state = 'ok';
- if ($data['requests'] > 2000)
- $state = 'info';
- if ($data['requests'] > 5000)
- $state = 'warning';
- if ($data['requests'] > 8000)
- $state = 'critical';
- if ($data['requests'] > 10000)
- $state = 'error';
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorRaid() {
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'raid_state';
-
- /*
- * We support several RAID types, but if we can't find any of them, we have no data
- */
- $state = 'no_state';
- $data['output'] = '';
-
- /*
- * Check, if Software-RAID is enabled
- */
- if (file_exists('/proc/mdstat')) {
- /*
- * Fetch the output
- */
- $data['output'] = shell_exec('cat /proc/mdstat');
-
- /*
- * Then calc the state.
- */
- $tmp = explode("\n", $data['output']);
- $state = 'ok';
- for ($i = 0; $i < sizeof($tmp); $i++) {
- /* fetch the next line */
- $line = $tmp[$i];
-
- if ((strpos($line, '[U_]') !== false) || (strpos($line, '[_U]') !== false)) {
- /* One Disk is not working.
- * if the next line starts with "[>" or "[=" then
- * recovery (resync) is in state and the state is
- * information instead of critical
- */
- $nextLine = $tmp[$i + 1];
- if ((strpos($nextLine, '[>') === false) && (strpos($nextLine, '[=') === false)) {
- $state = $this->_setState($state, 'critical');
- } else {
- $state = $this->_setState($state, 'info');
- }
- }
- if (strpos($line, '[__]') !== false) {
- /* both Disk are not working */
- $state = $this->_setState($state, 'error');
- }
- if (strpos($line, '[UU]') !== false) {
- /* The disks are OK.
- * if the next line starts with "[>" or "[=" then
- * recovery (resync) is in state and the state is
- * information instead of ok
- */
- $nextLine = $tmp[$i + 1];
- if ((strpos($nextLine, '[>') === false) && (strpos($nextLine, '[=') === false)) {
- $state = $this->_setState($state, 'ok');
- } else {
- $state = $this->_setState($state, 'info');
- }
- }
- }
- }
- /*
- * Check, if we have mpt-status installed (LSIsoftware-raid)
- */
- if (file_exists('/proc/mpt/summary')) {
- system('which mpt-status', $retval);
- if ($retval === 0) {
- /*
- * Fetch the output
- */
- $data['output'] = shell_exec('mpt-status --autoload');
-
- /*
- * Then calc the state.
- */
- $state = 'ok';
- if(is_array($data['output'])) {
- foreach ($data['output'] as $item) {
- /*
- * The output contains information for every RAID and every HDD.
- * We only need the state of the RAID
- */
- if (strpos($item, 'state ') !== false) {
- /*
- * We found a raid, process the state of it
- */
- if (strpos($item, ' ONLINE ') !== false) {
- $this->_setState($state, 'ok');
- } elseif (strpos($item, ' OPTIMAL ') !== false) {
- $this->_setState($state, 'ok');
- } elseif (strpos($item, ' INITIAL ') !== false) {
- $this->_setState($state, 'info');
- } elseif (strpos($item, ' INACTIVE ') !== false) {
- $this->_setState($state, 'critical');
- } elseif (strpos($item, ' RESYNC ') !== false) {
- $this->_setState($state, 'info');
- } elseif (strpos($item, ' DEGRADED ') !== false) {
- $this->_setState($state, 'critical');
- } else {
- /* we don't know the state. so we set the state to critical, that the
- * admin is warned, that something is wrong
- */
- $this->_setState($state, 'critical');
- }
- }
- }
- }
- }
- }
-
- /*
- * 3ware Controller
- */
- system('which tw_cli', $retval);
- if($retval === 0) {
-
- $data['output'] = shell_exec('tw_cli info c0');
-
- $state = 'ok';
- if(is_array($data['output'])) {
- foreach ($data['output'] as $item) {
- if (strpos($item, 'RAID') !== false) {
- if (strpos($item, ' VERIFYING ') !== false) {
- $this->_setState($state, 'info');
- }
- else if (strpos($item, ' MIGRATE-PAUSED ') !== false) {
- $this->_setState($state, 'info');
- }
- else if (strpos($item, ' MIGRATING ') !== false) {
- $this->_setState($state, 'ok');
- }
- else if (strpos($item, ' INITIALIZING ') !== false) {
- $this->_setState($state, 'info');
- }
- else if (strpos($item, ' INIT-PAUSED ') !== false) {
- $this->_setState($state, 'info');
- }
- else if (strpos($item, ' REBUILDING ') !== false) {
- $this->_setState($state, 'info');
- }
- else if (strpos($item, ' REBUILD-PAUSED ') !== false) {
- $this->_setState($state, 'warning');
- }
- else if (strpos($item, ' RECOVERY ') !== false) {
- $this->_setState($state, 'warning');
- }
- else if (strpos($item, ' DEGRADED ') !== false) {
- $this->_setState($state, 'critical');
- }
- else if (strpos($item, ' UNKNOWN ') !== false) {
- $this->_setState($state, 'critical');
- }
- else if (strpos($item, ' OK ') !== false) {
- $this->_setState($state, 'ok');
- }
- else if (strpos($item, ' OPTIMAL ') !== false) {
- $this->_setState($state, 'ok');
- }
- else {
- $this->_setState($state, 'critical');
- }
- }
- }
- }
- }
-
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorRkHunter() {
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'rkhunter';
-
- /* This monitoring is only available if rkhunter is installed */
- system('which rkhunter', $retval);
- if ($retval === 0) {
- /*
- * Fetch the output
- */
- $data['output'] = shell_exec('rkhunter --update --checkall --nocolors --skip-keypress');
-
- /*
- * At this moment, there is no state (maybe later)
- */
- $state = 'no_state';
- } else {
- /*
- * rkhunter is not installed, so there is no data and no state
- *
- * no_state, NOT unknown, because "unknown" is shown as state
- * inside the GUI. no_state is hidden.
- *
- * We have to write NO DATA inside the DB, because the GUI
- * could not know, if there is any dat, or not...
- */
- $state = 'no_state';
- $data['output'] = '';
- }
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorFail2ban() {
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'log_fail2ban';
-
- /* This monitoring is only available if fail2ban is installed */
- system('which fail2ban-client', $retval); // Debian, Ubuntu, Fedora
- if ($retval !== 0)
- system('which fail2ban', $retval); // CentOS
- if ($retval === 0) {
- /* Get the data of the log */
- $data = $this->_getLogData($type);
-
- /*
- * At this moment, there is no state (maybe later)
- */
- $state = 'no_state';
- } else {
- /*
- * fail2ban is not installed, so there is no data and no state
- *
- * no_state, NOT unknown, because "unknown" is shown as state
- * inside the GUI. no_state is hidden.
- *
- * We have to write NO DATA inside the DB, because the GUI
- * could not know, if there is any dat, or not...
- */
- $state = 'no_state';
- $data = '';
- }
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorMongoDB() {
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'log_mongodb';
-
- /* This monitoring is only available if MongoDB is installed */
- system('which mongod', $retval); // Debian, Ubuntu, Fedora
- if ($retval !== 0)
- system('which mongod', $retval); // CentOS
- if ($retval === 0) {
- /* Get the data of the log */
- $data = $this->_getLogData($type);
-
- /*
- * At this moment, there is no state (maybe later)
- */
- $state = 'no_state';
- } else {
- /*
- * MongoDB is not installed, so there is no data and no state
- *
- * no_state, NOT unknown, because "unknown" is shown as state
- * inside the GUI. no_state is hidden.
- *
- * We have to write NO DATA inside the DB, because the GUI
- * could not know, if there is any dat, or not...
- */
- $state = 'no_state';
- $data = '';
- }
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorIPTables() {
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'iptables_rules';
-
- /* This monitoring is only available if fail2ban is installed */
- system('which iptables', $retval); // Debian, Ubuntu, Fedora
- if ($retval === 0) {
- /* Get the data of the log */
- $data['output'] = '<h2>iptables -S (ipv4)</h2>'.shell_exec('iptables -S 2>/dev/null');
-
- /*
- * At this moment, there is no state (maybe later)
- */
- $state = 'no_state';
- } else {
- $state = 'no_state';
- $data = '';
- }
-
-
- /* This monitoring is only available if fail2ban is installed */
- system('which ip6tables', $retval); // Debian, Ubuntu, Fedora
- if ($retval === 0) {
- /* Get the data of the log */
- $data['output'] .= '<br><h2>ip6tables -S (ipv6)</h2>'.shell_exec('ip6tables -S 2>/dev/null');
-
- /*
- * At this moment, there is no state (maybe later)
- */
- $state = 'no_state';
- } else {
- $state = 'no_state';
- $data = '';
- }
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorSysLog() {
- global $app;
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'sys_log';
-
- /*
- * is there any warning or error for this server?
- */
- $state = 'ok';
- $dbData = $app->dbmaster->queryAllRecords('SELECT loglevel FROM sys_log WHERE server_id = ' . $server_id . ' AND loglevel > 0');
- if (is_array($dbData)) {
- foreach ($dbData as $item) {
- if ($item['loglevel'] == 1)
- $state = $this->_setState($state, 'warning');
- if ($item['loglevel'] == 2)
- $state = $this->_setState($state, 'error');
- }
- }
-
- /** There is no monitor-data because the data is in the sys_log table */
- $data['output'] = '';
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorMailLog() {
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'log_mail';
-
- /* Get the data of the log */
- $data = $this->_getLogData($type);
-
- /*
- * actually this info has no state.
- * maybe someone knows better...???...
- */
- $state = 'no_state';
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorMailWarnLog() {
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'log_mail_warn';
-
- /* Get the data of the log */
- $data = $this->_getLogData($type);
-
- /*
- * actually this info has no state.
- * maybe someone knows better...???...
- */
- $state = 'no_state';
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorMailErrLog() {
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'log_mail_err';
-
- /* Get the data of the log */
- $data = $this->_getLogData($type);
-
- /*
- * actually this info has no state.
- * maybe someone knows better...???...
- */
- $state = 'no_state';
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorMessagesLog() {
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'log_messages';
-
- /* Get the data of the log */
- $data = $this->_getLogData($type);
-
- /*
- * actually this info has no state.
- * maybe someone knows better...???...
- */
- $state = 'no_state';
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorISPCCronLog() {
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'log_ispc_cron';
-
- /* Get the data of the log */
- $data = $this->_getLogData($type);
-
- /*
- * actually this info has no state.
- * maybe someone knows better...???...
- */
- $state = 'no_state';
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorFreshClamLog() {
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'log_freshclam';
-
- /* Get the data of the log */
- $data = $this->_getLogData($type);
-
- /* Get the data from the LAST log-Entry.
- * if there can be found:
- * WARNING: Your ClamAV installation is OUTDATED!
- * then the clamav is outdated. This is a warning!
- */
- $state = 'ok';
-
- $tmp = explode("\n", $data);
- $lastLog = array();
- if ($tmp[sizeof($tmp) - 1] == '') {
- /* the log ends with an empty line remove this */
- array_pop($tmp);
- }
- if (strpos($tmp[sizeof($tmp) - 1], '-------------') !== false) {
- /* the log ends with "-----..." remove this */
- array_pop($tmp);
- }
- for ($i = sizeof($tmp) - 1; $i > 0; $i--) {
- if (strpos($tmp[$i], '---------') === false) {
- /* no delimiter found, so add this to the last-log */
- $lastLog[] = $tmp[$i];
- } else {
- /* delimiter found, so there is no more line left! */
- break;
- }
- }
-
- /*
- * Now we have the last log in the array.
- * Check if the outdated-string is found...
- */
- foreach ($lastLog as $line) {
- if (strpos(strtolower($line), 'outdated') !== false) {
- /*
- * Outdatet is only info, because if we set this to warning, the server is
- * as long in state warning, as there is a new version of ClamAv which takes
- * sometimes weeks!
- */
- $state = $this->_setState($state, 'info');
- }
- }
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorClamAvLog() {
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'log_clamav';
-
- /* Get the data of the log */
- $data = $this->_getLogData($type);
-
- // Todo: the state should be calculated.
- $state = 'ok';
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
- public function monitorIspConfigLog() {
- global $conf;
-
- /* the id of the server as int */
- $server_id = intval($conf['server_id']);
-
- /** The type of the data */
- $type = 'log_ispconfig';
-
- /* Get the data of the log */
- $data = $this->_getLogData($type);
-
- // Todo: the state should be calculated.
- $state = 'ok';
-
- /*
- * Return the Result
- */
- $res['server_id'] = $server_id;
- $res['type'] = $type;
- $res['data'] = $data;
- $res['state'] = $state;
- return $res;
- }
-
+
public function _getLogData($log) {
global $conf;
@@ -1915,7 +573,7 @@
* * If the actual state is critical and you call the method with error,
* then the state is error.
*/
- private function _setState($oldState, $newState) {
+ public function _setState($oldState, $newState) {
/*
* Calculate the weight of the old state
*/
@@ -1965,20 +623,38 @@
}
}
- private function _getIntArray($line) {
- /** The array of float found */
- $res = array();
- /* First build a array from the line */
- $data = explode(' ', $line);
- /* then check if any item is a float */
- foreach ($data as $item) {
- if ($item . '' == (int) $item . '') {
- $res[] = $item;
- }
- }
- return $res;
+ /**
+ * Deletes Records older than 4 minutes.
+ * The monitor writes new data every 5 minutes or longer (4 hour, 1 day).
+ * So if i delete all Date older than 4 minutes i can be sure, that all old data
+ * are deleted...
+ */
+ public function delOldRecords($type, $serverId) {
+ global $app;
+
+ // $now = time();
+ // $old = $now - (4 * 60); // 4 minutes
+ $old = 'UNIX_TIMESTAMP() - 240';
+
+ /*
+ * ATTENTION if i do NOT pay attention of the server id, i delete all data (of the type)
+ * of ALL servers. This means, if i have a multiserver-environment and a server has a
+ * time not synced with the others (for example, all server has 11:00 and ONE server has
+ * 10:45) then the actual data of this server (with the time-stamp 10:45) get lost
+ * even though it is the NEWEST data of this server. To avoid this i HAVE to include
+ * the server-id!
+ */
+ $sql = 'DELETE FROM monitor_data ' .
+ 'WHERE ' .
+ ' type =' . "'" . $app->dbmaster->quote($type) . "' " .
+ 'AND ' .
+ ' created < ' . $old . ' ' .
+ 'AND ' .
+ ' server_id = ' . $serverId;
+ $app->dbmaster->query($sql);
}
+
}
?>
diff --git a/server/mods-available/monitor_core_module.inc.php b/server/mods-available/monitor_core_module.inc.php
deleted file mode 100644
index 88e994d..0000000
--- a/server/mods-available/monitor_core_module.inc.php
+++ /dev/null
@@ -1,870 +0,0 @@
-<?php
-
-/*
- Copyright (c) 2007-2011, Till Brehm, projektfarm Gmbh and Oliver Vogel www.muv.com
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without modification,
- are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- * 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.
- * Neither the name of ISPConfig nor the names of its contributors
- may be used to endorse or promote products derived from this software without
- specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
- */
-
-class monitor_core_module {
-
- var $interval = 5; // do the monitoring every 5 minutes
- var $module_name = 'monitor_core_module';
- var $class_name = 'monitor_core_module';
- /* No actions at this time. maybe later... */
- var $actions_available = array();
- /** The Tools */
- private $_tools = null;
- //** time the script was called
- private $_run_time = null;
-
- /**
- * This function is called during ispconfig installation to determine
- * if a symlink shall be created for this plugin.
- */
- public function onInstall() {
- global $conf;
- return true;
- }
-
- /**
- * This function is called when the module is loaded
- */
- public function onLoad() {
- global $app;
-
- //* store the running time
- $this->_run_time = time();
-
- /*
- * Do the monitor every n minutes and write the result to the db
- */
- $min = @date('i', $this->_run_time);
- if (($min % $this->interval) == 0) {
- $this->_doMonitor();
- }
- }
-
- /**
- * This function is called when a change in one of the registered tables is detected.
- * The function then raises the events for the plugins.
- */
- public function process($tablename, $action, $data) {
- // not needed
- }
-
- /**
- * This method is called every n minutes, when the module ist loaded.
- * The method then does a system-monitoring
- */
- // TODO: what monitoring is done should be a config-var
- private function _doMonitor() {
- global $app;
- /*
- * We need the tools in almost every method, so initialize them once...
- */
- $app->load('monitor_tools');
- $this->_tools = new monitor_tools();
-
- /*
- * Calls the single Monitoring steps
- */
- $this->_monitorEmailQuota();
- $this->_monitorHDQuota();
- $this->_monitorServer();
- $this->_monitorOsVer();
- $this->_monitorIspcVer();
- $this->_monitorDiskUsage();
- $this->_monitorMemUsage();
- $this->_monitorCpu();
- $this->_monitorServices();
- if (@file_exists('/proc/user_beancounters')) {
- $this->_monitorOpenVzHost();
- $this->_monitorOpenVzUserBeancounter();
- }
- $this->_monitorMailLog();
- $this->_monitorMailWarnLog();
- $this->_monitorMailErrLog();
- $this->_monitorMessagesLog();
- $this->_monitorISPCCronLog();
- $this->_monitorFreshClamLog();
- $this->_monitorClamAvLog();
- $this->_monitorIspConfigLog();
- $this->_monitorSystemUpdate();
- $this->_monitorMailQueue();
- $this->_monitorRaid();
- $this->_monitorRkHunter();
- $this->_monitorFail2ban();
- $this->_monitorMongoDB();
- $this->_monitorIPTables();
- $this->_monitorSysLog();
- }
-
- private function _monitorEmailQuota() {
- global $app, $conf;
-
- /*
- * This monitoring is expensive, so do it only every 15 minutes
- */
- $min = @date('i', $this->_run_time);
- if ($min % 15 != 0) return;
-
- $app->uses('getconf');
- $mail_config = $app->getconf->get_server_config($conf['server_id'], 'mail');
- if($mail_config['mailbox_quota_stats'] == 'n') return;
-
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorEmailQuota();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorHDQuota() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorHDQuota();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorServer() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorServer();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorOsVer() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorOsVer();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorIspcVer() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorIspcVer();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorDiskUsage() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorDiskUsage();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorMemUsage() {
- global $app;
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorMemUsage();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorCpu() {
- global $app;
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorCpu();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorServices() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorServices();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorOpenVzHost() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorOpenVzHost();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorOpenVzUserBeancounter() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorOpenVzUserBeancounter();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorSystemUpdate() {
- /*
- * This monitoring is expensive, so do it only once an hour
- */
- $min = @date('i', $this->_run_time);
- if ($min != 0)
- return;
-
- /*
- * OK - here we go...
- */
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorSystemUpdate();
-
- //* Ensure that output is encoded so that it does not break the serialize
- //$res['data']['output'] = htmlentities($res['data']['output']);
- $res['data']['output'] = htmlentities($res['data']['output'],ENT_QUOTES,'UTF-8');
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorMailQueue() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorMailQueue();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorRaid() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorRaid();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorRkHunter() {
- /*
- * This monitoring is expensive, so do it only once a day
- */
- $min = @date('i', $this->_run_time);
- $hour = @date('H', $this->_run_time);
- if (!($min == 0 && $hour == 23))
- return;
- /*
- * OK . here we go...
- */
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorRkHunter();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorFail2ban() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorFail2ban();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorMongoDB() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorMongoDB();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
-
- private function _monitorIPTables() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorIPTables();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorSysLog() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorSysLog();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorMailLog() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorMailLog();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorMailWarnLog() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorMailWarnLog();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorMailErrLog() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorMailErrLog();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorMessagesLog() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorMessagesLog();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorISPCCronLog() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorISPCCronLog();
-
- //* Ensure that output is encoded so that it does not break the serialize
- if(is_array($res) && isset($res['data'])) $res['data'] = htmlentities($res['data']);
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorFreshClamLog() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorFreshClamLog();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorClamAvLog() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorClamAvLog();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- private function _monitorIspConfigLog() {
- global $app;
-
- /*
- * First we get the Monitoring-data from the tools
- */
- $res = $this->_tools->monitorIspConfigLog();
-
- /*
- * Insert the data into the database
- */
- $sql = 'REPLACE INTO monitor_data (server_id, type, created, data, state) ' .
- 'VALUES (' .
- $res['server_id'] . ', ' .
- "'" . $app->dbmaster->quote($res['type']) . "', " .
- 'UNIX_TIMESTAMP(), ' .
- "'" . $app->dbmaster->quote(serialize($res['data'])) . "', " .
- "'" . $res['state'] . "'" .
- ')';
- $app->dbmaster->query($sql);
-
- /* The new data is written, now we can delete the old one */
- $this->_delOldRecords($res['type'], $res['server_id']);
- }
-
- /**
- * Deletes Records older than 4 minutes.
- * The monitor writes new data every 5 minutes or longer (4 hour, 1 day).
- * So if i delete all Date older than 4 minutes i can be sure, that all old data
- * are deleted...
- */
- private function _delOldRecords($type, $serverId) {
- global $app;
-
- // $now = time();
- // $old = $now - (4 * 60); // 4 minutes
- $old = 'UNIX_TIMESTAMP() - 240';
-
- /*
- * ATTENTION if i do NOT pay attention of the server id, i delete all data (of the type)
- * of ALL servers. This means, if i have a multiserver-environment and a server has a
- * time not synced with the others (for example, all server has 11:00 and ONE server has
- * 10:45) then the actual data of this server (with the time-stamp 10:45) get lost
- * even though it is the NEWEST data of this server. To avoid this i HAVE to include
- * the server-id!
- */
- $sql = 'DELETE FROM monitor_data ' .
- 'WHERE ' .
- ' type =' . "'" . $app->dbmaster->quote($type) . "' " .
- 'AND ' .
- ' created < ' . $old . ' ' .
- 'AND ' .
- ' server_id = ' . $serverId;
- $app->dbmaster->query($sql);
- }
-
-}
-
-?>
--
Gitblit v1.9.1