began to 'clean up' for future releases (APS, Autoresponder and Backup)
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
This commit is contained in:
@@ -1,21 +0,0 @@
|
||||
<?php if (!defined('MASTER_CRONJOB')) die('You cannot access this file directly!');
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2003-2009 the SysCP Team (see authors).
|
||||
* Copyright (c) 2010 the Froxlor Team (see authors).
|
||||
*
|
||||
* For the full copyright and license information, please view the COPYING
|
||||
* file that was distributed with this source code. You can also view the
|
||||
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright (c) the authors
|
||||
* @author Florian Lippert <flo@syscp.org> (2003-2009)
|
||||
* @author Froxlor team <team@froxlor.org> (2010-)
|
||||
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
|
||||
* @package Cron
|
||||
*
|
||||
*/
|
||||
|
||||
$Aps = new ApsInstaller($settings);
|
||||
$Aps->InstallHandler();
|
||||
@@ -1,21 +0,0 @@
|
||||
<?php if (!defined('MASTER_CRONJOB')) die('You cannot access this file directly!');
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2003-2009 the SysCP Team (see authors).
|
||||
* Copyright (c) 2010 the Froxlor Team (see authors).
|
||||
*
|
||||
* For the full copyright and license information, please view the COPYING
|
||||
* file that was distributed with this source code. You can also view the
|
||||
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright (c) the authors
|
||||
* @author Florian Lippert <flo@syscp.org> (2003-2009)
|
||||
* @author Froxlor team <team@froxlor.org> (2010-)
|
||||
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
|
||||
* @package Cron
|
||||
*
|
||||
*/
|
||||
|
||||
$Aps = new ApsUpdater($cronlog);
|
||||
$Aps->UpdateHandler();
|
||||
@@ -1,258 +0,0 @@
|
||||
<?php if (!defined('MASTER_CRONJOB')) die('You cannot access this file directly!');
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2003-2009 the SysCP Team (see authors).
|
||||
* Copyright (c) 2010 the Froxlor Team (see authors).
|
||||
*
|
||||
* For the full copyright and license information, please view the COPYING
|
||||
* file that was distributed with this source code. You can also view the
|
||||
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright (c) the authors
|
||||
* @author Florian Lippert <flo@syscp.org> (2003-2009)
|
||||
* @author Remo Fritzsche
|
||||
* @author Manuel Aller
|
||||
* @author Michael Schlechtinger
|
||||
* @author Froxlor team <team@froxlor.org> (2010-)
|
||||
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
|
||||
* @package Cron
|
||||
*
|
||||
* @todo skip mail parsing after x bytes for large mails
|
||||
*/
|
||||
|
||||
$mail = new PHPMailer(true);
|
||||
|
||||
//dont do anything when module is disabled
|
||||
if ((int)$settings['autoresponder']['autoresponder_active'] == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
//only send autoresponder to mails which were delivered since last run
|
||||
if ((int)$settings['autoresponder']['last_autoresponder_run'] == 0) {
|
||||
//mails from last 5 minutes, otherwise all mails will be parsed -> mailbomb prevention
|
||||
$cycle = 300;
|
||||
} else {
|
||||
// calculate seconds since last check
|
||||
$cycle = time() - (int)$settings['autoresponder']['last_autoresponder_run'];
|
||||
//prevent mailbombs when cycle is bigger than two days
|
||||
if($cycle > (2 * 60 * 60 * 24))$cycle = (60 * 60 * 24);
|
||||
}
|
||||
|
||||
// set last_autoresponder_run
|
||||
$upd_stmt = Database::prepare("
|
||||
UPDATE `" . TABLE_PANEL_SETTINGS . "` SET `value` = :timeval
|
||||
WHERE `settinggroup` = 'autoresponder' AND `varname` = 'last_autoresponder_run'
|
||||
");
|
||||
Database::pexecute($upd_stmt, array('timeval' => time()));
|
||||
|
||||
// get all customer set ip autoresponders
|
||||
$result_stmt = Database::query("
|
||||
SELECT * FROM `" . TABLE_MAIL_AUTORESPONDER . "` INNER JOIN `" . TABLE_MAIL_USERS . "`
|
||||
ON `" . TABLE_MAIL_AUTORESPONDER . "`.`email` = `" . TABLE_MAIL_USERS . "`.`email`
|
||||
WHERE `enabled` = 1
|
||||
");
|
||||
|
||||
if (Database::num_rows() > 0) {
|
||||
|
||||
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
//check if specific autoresponder should be used
|
||||
$ts_now = time();
|
||||
$ts_start = (int)$row['date_from'];
|
||||
$ts_end = (int)$row['date_until'];
|
||||
|
||||
$row['email'] = strtolower($row['email']);
|
||||
|
||||
// not yet
|
||||
if($ts_start != -1 && $ts_start > $ts_now) continue;
|
||||
// already ended
|
||||
if($ts_end != -1 && $ts_end < $ts_now) continue;
|
||||
|
||||
// setup mail-path (e.g. /var/customers/mail/[loginname]/[user@domain.tld]/new
|
||||
$path = makeCorrectDir($row['homedir'] . $row['maildir'] . "new/");
|
||||
|
||||
// if the directory does not exist, inform syslog
|
||||
if (!is_dir($path)) {
|
||||
$cronlog->logAction(CRON_ACTION, LOG_WARNING, "Error accessing maildir: " . $path);
|
||||
continue;
|
||||
}
|
||||
|
||||
// get all files
|
||||
$its = new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator($path)
|
||||
);
|
||||
|
||||
$responded_counter = 0;
|
||||
foreach ($its as $fullFilename => $it ) {
|
||||
if ($it->getFilename() == '.' || $it->getFilename() == '..') {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* is the time passed between now and
|
||||
* the time we received the mail lower/equal
|
||||
* than our cycle-seconds?
|
||||
*/
|
||||
$filemtime = $it->getMTime();
|
||||
if (time() - $filemtime <= $cycle) {
|
||||
// why not read up to k lines?
|
||||
// I've been patching this forever, to avoid FATAL ERROR / memory exhausted
|
||||
// (fgets() is now binary safe, too)
|
||||
// $content = file($fullFilename);
|
||||
$lcount = 0; $content = array(); $handle = @fopen($fullFilename, "r");
|
||||
if ($handle) {
|
||||
// 1023 lines of an email should be enough to analyze it
|
||||
while (($lcount++<1023) && (($buffer = fgets($handle)) !== false)) {
|
||||
$content[]=$buffer;
|
||||
}
|
||||
fclose($handle);
|
||||
}
|
||||
|
||||
// error reading mail contents or just empty
|
||||
if (count($content) == 0) {
|
||||
$cronlog->logAction(CRON_ACTION, LOG_WARNING, "Unable to read mail from maildir: " . dirname($fullFilename));
|
||||
continue;
|
||||
}
|
||||
|
||||
$match = array();
|
||||
$from = '';
|
||||
$to = '';
|
||||
$sender = '';
|
||||
$spam = false;
|
||||
foreach ($content as $line) {
|
||||
// header ends on first empty line, skip rest of mail
|
||||
if (strlen(rtrim($line)) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
//fetching from field
|
||||
if (!strlen($from)
|
||||
&& preg_match("/^From:(.+)<(.*)>$/", $line, $match)
|
||||
) {
|
||||
$from = strtolower($match[2]);
|
||||
}
|
||||
elseif (!strlen($from)
|
||||
&& preg_match("/^From:\s+(.*@.*)$/", $line, $match)
|
||||
) {
|
||||
$from = strtolower($match[1]);
|
||||
}
|
||||
|
||||
//fetching to field
|
||||
if ((!strlen($to) || $to != $row['email'])
|
||||
&& preg_match("/^To:(.+)<(.*)>$/", $line, $match)
|
||||
) {
|
||||
$to = strtolower($match[2]);
|
||||
}
|
||||
elseif ((!strlen($to) || $to != $row['email'])
|
||||
&& preg_match("/^To:\s+(.*@.*)$/", $line, $match)
|
||||
) {
|
||||
$to = strtolower($match[1]);
|
||||
}
|
||||
/*
|
||||
* if we still don't have a To:-address
|
||||
* OR even worse, the $to is NOT the mail-address
|
||||
* of the customer which autoresponder this is
|
||||
* we have to check for CC too, #476
|
||||
*/
|
||||
elseif ((!strlen($to) || $to != $row['email'])
|
||||
&& preg_match("/^Cc:(.+)<(.*)>$/", $line, $match)
|
||||
) {
|
||||
$to = strtolower($match[2]);
|
||||
}
|
||||
elseif ((!strlen($to) || $to != $row['email'])
|
||||
&& preg_match("/^Cc:\s+(.*@.*)$/", $line, $match)
|
||||
) {
|
||||
$to = strtolower($match[1]);
|
||||
}
|
||||
|
||||
// fetching sender field
|
||||
if (!strlen($sender)
|
||||
&& preg_match("/^Sender:(.+)<(.*)>$/", $line, $match)
|
||||
) {
|
||||
$sender = strtolower($match[2]);
|
||||
}
|
||||
elseif (!strlen($sender)
|
||||
&& preg_match("/Sender:\s+(.*@.*)$/", $line, $match)
|
||||
) {
|
||||
$sender = strtolower($match[1]);
|
||||
}
|
||||
|
||||
//check for amavis/spamassassin spam headers
|
||||
if (preg_match("/^X-Spam-Status: (Yes|No)(.*)$/", $line, $match)) {
|
||||
if(strtolower($match[1]) == 'yes') {
|
||||
$spam = true;
|
||||
}
|
||||
}
|
||||
|
||||
//check for precedence header
|
||||
if (preg_match("/^Precedence: (bulk|list|junk)(.*)$/", $line, $match)) {
|
||||
// use the spam flag to skip reply
|
||||
$spam = true;
|
||||
}
|
||||
}
|
||||
|
||||
// check if the receiver is really the one
|
||||
// with the autoresponder
|
||||
if (!strlen($to) || $to != $row['email']) {
|
||||
$to = '';
|
||||
}
|
||||
|
||||
//skip mail when marked as spam
|
||||
if ($spam == true) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//error while parsing mail
|
||||
if ($to == '' || $from == '') {
|
||||
$cronlog->logAction(CRON_ACTION, LOG_WARNING, "No valid headers found in mail to parse");
|
||||
continue;
|
||||
}
|
||||
|
||||
//important! prevent mailbombs when mail comes from a maildaemon/mailrobot
|
||||
//robot/daemon mails must go to Sender: field in envelope header
|
||||
//refers to "Das Postfix-Buch" / RFC 2822
|
||||
if ($sender != '') {
|
||||
$from = $sender;
|
||||
}
|
||||
|
||||
//make message valid to email format
|
||||
$message = str_replace("\r\n", "\n", $row['message']);
|
||||
|
||||
//check if mail is already an answer
|
||||
$fullcontent = implode("", $content);
|
||||
|
||||
if (strstr($fullcontent, $message) || $from == $to) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$_mailerror = false;
|
||||
try {
|
||||
$mail->CharSet = "UTF-8";
|
||||
$mail->SetFrom($to, $to);
|
||||
$mail->AddReplyTo($to, $to);
|
||||
$mail->Subject = $row['subject'];
|
||||
$mail->AltBody = $message;
|
||||
$html_message = str_replace("\n", "<br />", $message);
|
||||
$mail->MsgHTML(html_entity_decode($html_message));
|
||||
$mail->AddAddress($from, $from);
|
||||
$mail->AddCustomHeader('Precedence: bulk');
|
||||
$mail->Send();
|
||||
} catch(phpmailerException $e) {
|
||||
$mailerr_msg = $e->errorMessage();
|
||||
$_mailerror = true;
|
||||
} catch (Exception $e) {
|
||||
$mailerr_msg = $e->getMessage();
|
||||
$_mailerror = true;
|
||||
}
|
||||
|
||||
if ($_mailerror) {
|
||||
$cronlog->logAction(CRON_ACTION, LOG_WARNING, "Error sending autoresponder mail: " . $mailerr_msg);
|
||||
}
|
||||
|
||||
$mail->ClearAddresses();
|
||||
$responded_counter++;
|
||||
}
|
||||
}
|
||||
$cronlog->logAction(CRON_ACTION, LOG_INFO, "Responded to '" . $responded_counter . "' mails from '".$path."'");
|
||||
}
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
<?php if (!defined('MASTER_CRONJOB')) die('You cannot access this file directly!');
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2010 the Froxlor Team (see authors).
|
||||
*
|
||||
* For the full copyright and license information, please view the COPYING
|
||||
* file that was distributed with this source code. You can also view the
|
||||
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright (c) the authors
|
||||
* @author Froxlor team <team@froxlor.org> (2010-)
|
||||
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
|
||||
* @package Cron
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Backup
|
||||
*/
|
||||
if ($settings['system']['backup_enabled'] == '1') {
|
||||
|
||||
fwrite($debugHandler, 'backup customers started...' . "\n");
|
||||
|
||||
// get sql-root access data for mysqldump
|
||||
Database::needRoot(true);
|
||||
Database::needSqlData();
|
||||
$sql_root = Database::getSqlData();
|
||||
Database::needRoot(false);
|
||||
|
||||
$result_stmt = Database::query("
|
||||
SELECT customerid, loginname, guid, documentroot, backup_allowed, backup_enabled
|
||||
FROM `" . TABLE_PANEL_CUSTOMERS . "` ORDER BY `customerid` ASC;
|
||||
");
|
||||
|
||||
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
|
||||
fwrite($debugHandler, 'backup for ' . $row['loginname'] . ' started...' . "\n");
|
||||
|
||||
// backup
|
||||
if ($row['backup_allowed'] == '1'
|
||||
&& $row['backup_enabled'] == '1'
|
||||
) {
|
||||
// get uid & gid from ftp table
|
||||
$ftp_result_stmt = Database::prepare("
|
||||
SELECT uid, gid FROM `" . TABLE_FTP_USERS . "`
|
||||
WHERE `username` = :loginname
|
||||
");
|
||||
$ftp_row = Database::pexecute_first($ftp_result_stmt, array('loginname' => $row['loginname']));
|
||||
|
||||
// create backup dir an set rights
|
||||
$_backupdir = makeCorrectDir($settings['system']['backup_dir'] . $row['loginname']);
|
||||
if (!file_exists($_backupdir)) {
|
||||
safe_exec('install -d ' . escapeshellarg($_backupdir) . ' -o ' . escapeshellarg($ftp_row['uid']) . ' -g ' . escapeshellarg($ftp_row['gid']) . ' -m ' . '0500');
|
||||
}
|
||||
|
||||
// create customers html backup
|
||||
safe_exec('tar -C ' . escapeshellarg($row['documentroot']) . ' -c -z -f ' . escapeshellarg($_backupdir) . '/' . escapeshellarg($row['loginname']) . 'html.tar.gz .');
|
||||
|
||||
// get customer dbs
|
||||
$dbs_result_stmt = Database::prepare("
|
||||
SELECT `databasename` FROM `" . TABLE_PANEL_DATABASES . "`
|
||||
WHERE `customerid` = :customerid
|
||||
");
|
||||
Database::pexecute($dbs_result_stmt, array('customerid' => $row['customerid']));
|
||||
|
||||
while ($dbs_row = $dbs_result_stmt->fetch(PDO::FETCH_ASSOC)){
|
||||
// create customers sql backup
|
||||
safe_exec(escapeshellcmd($settings['system']['backup_mysqldump_path']) . ' --opt --force --allow-keywords -u ' . escapeshellarg($sql_root['user']) . ' -p' . escapeshellarg($sql_root['passwd']) . ' -h ' . $sql_root['host'] . ' -B ' . escapeshellarg($dbs_row['databasename']) . ' -r ' . escapeshellarg($_backupdir) . '/' . escapeshellarg($dbs_row['databasename']) . '.sql' );
|
||||
// compress sql backup
|
||||
safe_exec('tar -C ' . escapeshellarg($_backupdir) . ' -c -z -f ' . escapeshellarg($settings['system']['backup_dir']) . $row['loginname'] . '/' . escapeshellarg($dbs_row['databasename']) . '.tar.gz ' . escapeshellarg($dbs_row['databasename']) . '.sql');
|
||||
// remove uncompresed sql files
|
||||
safe_exec('rm ' . escapeshellarg($_backupdir) . '/' . escapeshellarg($dbs_row['databasename']) . '.sql');
|
||||
}
|
||||
|
||||
// create 1 big file with html & db
|
||||
if ($settings['system']['backup_bigfile'] == 1) {
|
||||
safe_exec('tar -C ' . escapeshellarg($_backupdir) . '/' . ' --exclude=' . escapeshellarg($row['loginname']) . '.tar.gz -c -z -f ' . escapeshellarg($_backupdir) . '/' . escapeshellarg($row['loginname']) . '.tar.gz .');
|
||||
// remove separated files
|
||||
$tmp_files = scandir($_backupdir);
|
||||
foreach ($tmp_files as $tmp_file) {
|
||||
if (preg_match('/.*(html|sql|aps).*\.tar\.gz$/', $tmp_file) && !preg_match('/^' . $row['loginname'] . '\.tar\.gz$/', $tmp_file)) {
|
||||
safe_exec('rm ' . escapeshellarg($_backupdir) . '/' . escapeshellarg($tmp_file));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//remove big file if separated backups are used
|
||||
if (file_exists(makeCorrectFile($_backupdir . '/' . $row['loginname'] . '.tar.gz'))) {
|
||||
safe_exec('rm ' . escapeshellarg($_backupdir) . '/' . escapeshellarg($row['loginname']) . '.tar.gz');
|
||||
}
|
||||
}
|
||||
|
||||
// chown & chmod files to prevent manipulation
|
||||
safe_exec('chown ' . escapeshellarg($row['guid']) . ':' . escapeshellarg($row['guid']) . ' ' . escapeshellarg($_backupdir) . '/*');
|
||||
safe_exec('chmod 0400 ' . escapeshellarg($_backupdir) . '/*');
|
||||
|
||||
// create ftp backup user
|
||||
$user_result_stmt = Database::prepare("
|
||||
SELECT username, password FROM `" . TABLE_FTP_USERS . "`
|
||||
WHERE `customerid` = :customerid AND `username` = :username;
|
||||
");
|
||||
$user_row = Database::pexecute_first($user_result_stmt, array('customerid' => $row['customerid'], 'username' => $row['loginname']));
|
||||
|
||||
$ins_stmt = Database::prepare("
|
||||
REPLACE INTO `" . TABLE_FTP_USERS . "`
|
||||
(`customerid`, `username`, `password`, `homedir`, `login_enabled`, `uid`, `gid`)
|
||||
VALUES
|
||||
(:customerid, :username, :password, :homedir, 'y', :guid, :guid)
|
||||
");
|
||||
$ins_data = array(
|
||||
'customerid' => $row['customerid'],
|
||||
'username' => $row['loginname']."_backup",
|
||||
'password' => $user_row['password'],
|
||||
'homedir' => makeCorrectDir($settings['system']['backup_dir'].'/'.$row['loginname'].'/'),
|
||||
'guid' => $row['guid']
|
||||
);
|
||||
Database::pexecute($ins_stmt, $ins_data);
|
||||
|
||||
if ($settings['system']['backup_ftp_enabled'] == '1') {
|
||||
// upload backup to customers ftp server
|
||||
$_ftpdir = makeCorrectDir($settings['system']['backup_dir'].'/'.$row['loginname'].'/');
|
||||
$ftp_files = scandir($_ftpdir);
|
||||
|
||||
foreach ($ftp_files as $ftp_file) {
|
||||
if (preg_match('/.*\.tar\.gz$/', $ftp_file)) {
|
||||
|
||||
$ftp_con = ftp_connect($settings['system']['backup_ftp_server']);
|
||||
$ftp_login = ftp_login($ftp_con, $settings['system']['backup_ftp_user'], $settings['system']['backup_ftp_pass']);
|
||||
|
||||
// Check whether to use passive mode or not
|
||||
if ($settings['system']['backup_ftp_passive'] == 1) {
|
||||
ftp_pasv($ftp_con, true);
|
||||
} else {
|
||||
ftp_pasv($ftp_con, false);
|
||||
}
|
||||
$_file = makeCorrectFile($_ftpdir.'/'.$ftp_file);
|
||||
$ftp_upload = ftp_put($ftp_con, $ftp_file, $_file, FTP_BINARY);
|
||||
}
|
||||
}
|
||||
}
|
||||
fwrite($debugHandler, 'backup for ' . $row['loginname'] . ' finished...' . "\n");
|
||||
}
|
||||
// delete old backup data (deletes backup if customer or admin disables backup)
|
||||
elseif ($row['backup_allowed'] == '0' || $row['backup_enabled'] == '0') {
|
||||
$_ftpdir = makeCorrectDir($settings['system']['backup_dir'].'/'.$row['loginname'].'/');
|
||||
if (file_exists($_ftpdir)){
|
||||
$files = scandir($_ftpdir);
|
||||
foreach ($files as $file) {
|
||||
if (preg_match('/.*\.tar\.gz$/', $file)){
|
||||
$_file = makeCorrectFile($_ftpdir.'/'.$file);
|
||||
safe_exec('rm -f ' . escapeshellarg($_file));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fwrite($debugHandler, 'backup customers finished...' . "\n");
|
||||
}
|
||||
Reference in New Issue
Block a user