Files
Froxlor/scripts/jobs/cron_tasks.php
Fabrício Zimmerer Murta 432e898318 Additional modifications to domain/user/Maildir email file structure
- Added email settings' option to specify Maildir directory (depending
  on postfix version this is ./Maildir/, .maildir/ or, optionally, one
  can choose to leave Maildir file structure directly on user's
  directory.
- Fixed database 'insert' command to describe the new structure using
  specified Maildir directory into new accounts.
- Fixed maildirExists function to the new file structure
- Fixed older bug that email exclusions that were scheduled (task 7)
  were not being displayed on overview.
- Added entries on 'english' language file for the new entries on panel
- Changed task id 6 (delete customer) behavior on scrips/jobs/cron_tasks.php
  to assure email account is owned to mail uid/gid and the target is an
  actual directory before zapping it.
- Fixed task id 7 (delete customer mail data) behavior on script above
  to correctly fill and find Maildir and also do additional paranoid
  checks before zapping the mail account directory. Notice this is not
  the same from above directory-wise: here we erase a single account's
  data, while in task id a entire customer set of accounts and domains
  are eliminated.
2012-07-09 23:46:51 -03:00

510 lines
18 KiB
PHP

<?php
/**
* 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
*
*/
/*
* necessary includes
*/
require_once(makeCorrectFile(dirname(__FILE__) . '/cron_tasks.inc.dns.10.bind.php'));
require_once(makeCorrectFile(dirname(__FILE__) . '/cron_tasks.inc.http.10.apache.php'));
require_once(makeCorrectFile(dirname(__FILE__) . '/cron_tasks.inc.http.15.apache_fcgid.php'));
require_once(makeCorrectFile(dirname(__FILE__) . '/cron_tasks.inc.http.20.lighttpd.php'));
require_once(makeCorrectFile(dirname(__FILE__) . '/cron_tasks.inc.http.25.lighttpd_fcgid.php'));
require_once(makeCorrectFile(dirname(__FILE__) . '/cron_tasks.inc.http.30.nginx.php'));
require_once(makeCorrectFile(dirname(__FILE__) . '/cron_tasks.inc.http.35.nginx_phpfpm.php'));
/**
* LOOK INTO TASKS TABLE TO SEE IF THERE ARE ANY UNDONE JOBS
*/
fwrite($debugHandler, ' cron_tasks: Searching for tasks to do' . "\n");
$cronlog->logAction(CRON_ACTION, LOG_INFO, "Searching for tasks to do");
$result_tasks = $db->query("SELECT `id`, `type`, `data` FROM `" . TABLE_PANEL_TASKS . "` ORDER BY `id` ASC");
$resultIDs = array();
while($row = $db->fetch_array($result_tasks))
{
$resultIDs[] = $row['id'];
if($row['data'] != '')
{
$row['data'] = unserialize($row['data']);
}
/**
* TYPE=1 MEANS TO REBUILD APACHE VHOSTS.CONF
*/
if($row['type'] == '1')
{
//dhr: cleanout froxlor-generated awstats configs prior to re-creation
if ($settings['system']['awstats_enabled'] == '1')
{
$awstatsclean['header'] = "## GENERATED BY FROXLOR\n";
$awstatsclean['headerold'] = "## GENERATED BY SYSCP\n";
$awstatsclean['path'] = $settings['system']['awstats_conf'];
/**
* dont do anyting if the directory not exists
* (e.g. awstats not installed yet or whatever)
* fixes #45
*/
if (is_dir($awstatsclean['path']))
{
$awstatsclean['dir'] = dir($awstatsclean['path']);
while($awstatsclean['entry'] = $awstatsclean['dir']->read()) {
$awstatsclean['fullentry'] = makeCorrectFile($awstatsclean['path'].'/'.$awstatsclean['entry']);
/**
* dont do anything if the file does not exist
*/
if (file_exists($awstatsclean['fullentry']))
{
$awstatsclean['fh'] = fopen($awstatsclean['fullentry'], 'r');
$awstatsclean['headerRead'] = fgets($awstatsclean['fh'], strlen($awstatsclean['header'])+1);
fclose($awstatsclean['fh']);
if($awstatsclean['headerRead'] == $awstatsclean['header'] || $awstatsclean['headerRead'] == $awstatsclean['headerold']) {
$awstats_conf_file = makeCorrectFile($awstatsclean['fullentry']);
$cronlog->logAction(CRON_ACTION, LOG_INFO, "Removing awstats configuration ".$awstats_conf_file." for re-creation");
@unlink($awstats_conf_file);
}
}
else
{
$cronlog->logAction(CRON_ACTION, LOG_WARNING, "File '".$awstatsclean['fullentry']."' could not be found, please check if you followed all the instructions on the configuration page");
}
}
}
unset($awstatsclean);
}
//end dhr
// clear fcgid - starter files prior to re-creation to keep it clean, #367
if ($settings['system']['mod_fcgid'] == '1')
{
$configdir = makeCorrectDir($settings['system']['mod_fcgid_configdir']);
if (is_dir($configdir))
{
$its = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($configdir)
);
// iterate through all subdirs,
// look for php-fcgi-starter files
// and take immutable-flag away from them
// so we can delete them :)
foreach ($its as $fullFileName => $it )
{
if ($it->isFile() && $it->getFilename() == 'php-fcgi-starter')
{
removeImmutable($its->getPathname());
}
}
// now get rid of old stuff
//(but append /* so we don't delete the directory)
$configdir.='/*';
safe_exec('rm -rf '. escapeshellarg(makeCorrectFile($configdir)));
}
}
// clear php-fpm-configurations prior to re-creation to keep it clean
if ($settings['phpfpm']['enabled'] == '1')
{
$configdir = makeCorrectDir($settings['phpfpm']['configdir']);
if (is_dir($configdir))
{
// now get rid of old stuff
//(but append /* so we don't delete the directory)
$configdir.='/*';
safe_exec('rm -rf '. escapeshellarg(makeCorrectFile($configdir)));
}
}
if(!isset($webserver))
{
if($settings['system']['webserver'] == "apache2")
{
if($settings['system']['mod_fcgid'] == 1 || $settings['phpfpm']['enabled'] == 1)
{
$webserver = new apache_fcgid($db, $cronlog, $debugHandler, $idna_convert, $settings);
}
else
{
$webserver = new apache($db, $cronlog, $debugHandler, $idna_convert, $settings);
}
}
elseif($settings['system']['webserver'] == "lighttpd")
{
if($settings['system']['mod_fcgid'] == 1 || $settings['phpfpm']['enabled'] == 1)
{
$webserver = new lighttpd_fcgid($db, $cronlog, $debugHandler, $idna_convert, $settings);
}
else
{
$webserver = new lighttpd($db, $cronlog, $debugHandler, $idna_convert, $settings);
}
}
elseif($settings['system']['webserver'] == "nginx")
{
if($settings['phpfpm']['enabled'] == 1)
{
$webserver = new nginx_phpfpm($db, $cronlog, $debugHandler, $idna_convert, $settings);
}
else
{
$webserver = new nginx($db, $cronlog, $debugHandler, $idna_convert, $settings);
}
}
}
if(isset($webserver))
{
$webserver->createIpPort();
$webserver->createVirtualHosts();
$webserver->createFileDirOptions();
$webserver->writeConfigs();
$webserver->createOwnVhostStarter();
$webserver->reload();
}
else
{
echo "Please check you Webserver settings\n";
}
}
/**
* TYPE=2 MEANS TO CREATE A NEW HOME AND CHOWN
*/
elseif ($row['type'] == '2')
{
fwrite($debugHandler, ' cron_tasks: Task2 started - create new home' . "\n");
$cronlog->logAction(CRON_ACTION, LOG_INFO, 'Task2 started - create new home');
if(is_array($row['data']))
{
// define paths
$userhomedir = makeCorrectDir($settings['system']['documentroot_prefix'] . '/' . $row['data']['loginname'] . '/');
$usermaildir = makeCorrectDir($settings['system']['vmail_homedir'] . '/' . $row['data']['loginname'] . '/');
// stats directory
if($settings['system']['awstats_enabled'] == '1')
{
$cronlog->logAction(CRON_ACTION, LOG_NOTICE, 'Running: mkdir -p ' . escapeshellarg($userhomedir . 'awstats'));
safe_exec('mkdir -p ' . escapeshellarg($userhomedir . 'awstats'));
} else {
$cronlog->logAction(CRON_ACTION, LOG_NOTICE, 'Running: mkdir -p ' . escapeshellarg($userhomedir . 'webalizer'));
safe_exec('mkdir -p ' . escapeshellarg($userhomedir . 'webalizer'));
}
// maildir
$cronlog->logAction(CRON_ACTION, LOG_NOTICE, 'Running: mkdir -p ' . escapeshellarg($usermaildir));
safe_exec('mkdir -p ' . escapeshellarg($usermaildir));
//check if admin of customer has added template for new customer directories
if((int)$row['data']['store_defaultindex'] == 1)
{
storeDefaultIndex($row['data']['loginname'], $userhomedir, $cronlog, true);
}
// strip of last slash of paths to have correct chown results
$userhomedir = (substr($userhomedir, 0, -1) == '/') ? substr($userhomedir, 0, -1) : $userhomedir;
$usermaildir = (substr($usermaildir, 0, -1) == '/') ? substr($usermaildir, 0, -1) : $usermaildir;
$cronlog->logAction(CRON_ACTION, LOG_NOTICE, 'Running: chown -R ' . (int)$row['data']['uid'] . ':' . (int)$row['data']['gid'] . ' ' . escapeshellarg($userhomedir));
safe_exec('chown -R ' . (int)$row['data']['uid'] . ':' . (int)$row['data']['gid'] . ' ' . escapeshellarg($userhomedir));
$cronlog->logAction(CRON_ACTION, LOG_NOTICE, 'Running: chown -R ' . (int)$settings['system']['vmail_uid'] . ':' . (int)$settings['system']['vmail_gid'] . ' ' . escapeshellarg($usermaildir));
safe_exec('chown -R ' . (int)$settings['system']['vmail_uid'] . ':' . (int)$settings['system']['vmail_gid'] . ' ' . escapeshellarg($usermaildir));
}
}
/**
* TYPE=3 MEANS TO DO NOTHING
*/
elseif ($row['type'] == '3')
{
}
/**
* TYPE=4 MEANS THAT SOMETHING IN THE BIND CONFIG HAS CHANGED. REBUILD froxlor_bind.conf IF BIND IS ENABLED
*/
elseif ($row['type'] == '4' && (int)$settings['system']['bind_enable'] != 0)
{
if(!isset($nameserver))
{
$nameserver = new bind($db, $cronlog, $debugHandler, $settings);
}
if($settings['dkim']['use_dkim'] == '1')
{
$nameserver->writeDKIMconfigs();
}
$nameserver->writeConfigs();
}
/**
* TYPE=5 MEANS THAT A NEW FTP-ACCOUNT HAS BEEN CREATED, CREATE THE DIRECTORY
*/
elseif ($row['type'] == '5')
{
$cronlog->logAction(CRON_ACTION, LOG_INFO, 'Creating new FTP-home');
$result_directories = $db->query('SELECT `f`.`homedir`, `f`.`uid`, `f`.`gid`, `c`.`documentroot` AS `customerroot` FROM `' . TABLE_FTP_USERS . '` `f` LEFT JOIN `' . TABLE_PANEL_CUSTOMERS . '` `c` USING (`customerid`) WHERE `f`.`username` NOT LIKE \'%_backup\'');
while($directory = $db->fetch_array($result_directories))
{
mkDirWithCorrectOwnership($directory['customerroot'], $directory['homedir'], $directory['uid'], $directory['gid']);
}
}
/**
* TYPE=6 MEANS THAT A CUSTOMER HAS BEEN DELETED AND THAT WE HAVE TO REMOVE ITS FILES
*/
elseif ($row['type'] == '6')
{
fwrite($debugHandler, ' cron_tasks: Task6 started - deleting customer data' . "\n");
$cronlog->logAction(CRON_ACTION, LOG_INFO, 'Task6 started - deleting customer data');
if(is_array($row['data']))
{
if(isset($row['data']['loginname']))
{
/*
* remove homedir
*/
$homedir = makeCorrectDir($settings['system']['documentroot_prefix'] . '/' . $row['data']['loginname']);
if($homedir != '/'
&& $homedir != $settings['system']['documentroot_prefix']
&& substr($homedir, 0, strlen($settings['system']['documentroot_prefix'])) == $settings['system']['documentroot_prefix'])
{
$cronlog->logAction(CRON_ACTION, LOG_NOTICE, 'Running: rm -rf ' . escapeshellarg($homedir));
safe_exec('rm -rf '.escapeshellarg($homedir));
}
/*
* remove backup dir
*/
$backupdir = makeCorrectDir($settings['system']['backup_dir'] . $row['data']['loginname']);
if($backupdir != '/'
&& $backupdir != $settings['system']['backup_dir']
&& substr($backupdir, 0, strlen($settings['system']['backup_dir'])) == $settings['system']['backup_dir'])
{
$cronlog->logAction(CRON_ACTION, LOG_NOTICE, 'Running: rm -rf ' . escapeshellarg($backupdir));
safe_exec('rm -rf '.escapeshellarg($backupdir));
}
/*
* remove maildir
*/
$maildir = makeCorrectDir($settings['system']['vmail_homedir'] . '/' . $row['data']['loginname']);
if($maildir != '/'
&& $maildir != $settings['system']['vmail_homedir']
&& substr($maildir, 0, strlen($settings['system']['vmail_homedir'])) == $settings['system']['vmail_homedir']
&& is_dir($maildir)
&& fileowner($maildir) == $settings['system']['vmail_uid']
&& filegroup($maildir) == $settings['system']['vmail_gid'])
{
$cronlog->logAction(CRON_ACTION, LOG_NOTICE, 'Running: rm -rf ' . escapeshellarg($maildir));
safe_exec('rm -rf '.escapeshellarg($maildir));
}
/*
* remove tmpdir if it exists
*/
$tmpdir = makeCorrectDir($settings['system']['mod_fcgid_tmpdir'] . '/' . $row['data']['loginname'] . '/');
if (is_dir($tmpdir)
&& $tmpdir != "/"
&& $tmpdir != $settings['system']['mod_fcgid_tmpdir']
&& substr($tmpdir, 0, strlen($settings['system']['mod_fcgid_tmpdir'])) == $settings['system']['mod_fcgid_tmpdir'])
{
$cronlog->logAction(CRON_ACTION, LOG_NOTICE, 'Running: rm -rf ' . escapeshellarg($tmpdir));
safe_exec('rm -rf '.escapeshellarg($tmpdir));
}
/*
* see if we have some php-fcgid leftovers if used
* and remove them, #200
*/
if($settings['system']['mod_fcgid'] == 1)
{
// e.g. /var/www/php-fcgi-starter/web1/
$configdir = makeCorrectDir($settings['system']['mod_fcgid_configdir'] . '/' . $row['data']['loginname'] . '/');
if (is_dir($configdir))
{
$its = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($configdir)
);
// iterate through all subdirs,
// look for php-fcgi-starter files
// and take immutable-flag away from them
// so we can delete them :)
foreach ($its as $fullFileName => $it )
{
if ($it->isFile() && $it->getFilename() == 'php-fcgi-starter')
{
removeImmutable($its->getPathname());
}
}
// now get rid of old stuff
safe_exec('rm -rf '. escapeshellarg($configdir));
}
}
}
}
}
/**
* TYPE=7 Customer deleted an email account and wants the data to be deleted on the filesystem
*/
elseif ($row['type'] == '7')
{
fwrite($debugHandler, ' cron_tasks: Task7 started - deleting customer e-mail data' . "\n");
$cronlog->logAction(CRON_ACTION, LOG_INFO, 'Task7 started - deleting customer e-mail data');
if(is_array($row['data']))
{
if(isset($row['data']['loginname'])
&& isset($row['data']['email'])
) {
/*
* remove specific maildir
*/
$email_full = $row['data']['email'];
if (empty($email_full)) {
$cronlog->logAction(CRON_ACTION, LOG_ERROR, 'FATAL: Task7 asks to delete a email account but email field is empty!');
}
$email_user=substr($email_full,0,strrpos($email_full,"@"));
$email_domain=substr($email_full,strrpos($email_full,"@")+1);
$maildirname=trim($settings['system']['vmail_maildirname']);
// Add trailing slash to Maildir if needed
$maildirpath=$maildirname;
if (!empty($maildirname) and substr($maildirname,-1) != "/") $maildirpath.="/";
$maildir = makeCorrectDir($settings['system']['vmail_homedir'] .'/'. $row['data']['loginname'] .'/'. $email_domain .'/'. $email_user .'/'. $maildirpath);
if($maildir != '/' && !empty($maildir) && !empty($email_full)
&& $maildir != $settings['system']['vmail_homedir']
&& substr($maildir, 0, strlen($settings['system']['vmail_homedir'])) == $settings['system']['vmail_homedir']
&& is_dir($maildir)
&& fileowner($maildir) == $settings['system']['vmail_uid']
&& filegroup($maildir) == $settings['system']['vmail_gid'])
{
$cronlog->logAction(CRON_ACTION, LOG_NOTICE, 'Running: rm -rf ' . escapeshellarg($maildir));
safe_exec('rm -rf '.escapeshellarg($maildir));
}
}
}
}
/**
* TYPE=8 Customer deleted a ftp account and wants the homedir to be deleted on the filesystem
* refs #293
*/
elseif ($row['type'] == '8')
{
fwrite($debugHandler, ' cron_tasks: Task8 started - deleting customer ftp homedir' . "\n");
$cronlog->logAction(CRON_ACTION, LOG_INFO, 'Task8 started - deleting customer ftp homedir');
if(is_array($row['data']))
{
if(isset($row['data']['loginname'])
&& isset($row['data']['homedir'])
) {
/*
* remove specific homedir
*/
$ftphomedir = makeCorrectDir($row['data']['homedir']);
$customerdocroot = makeCorrectDir($settings['system']['documentroot_prefix'].'/'.$row['data']['loginname'].'/');
if($ftphomedir != '/'
&& $ftphomedir != $settings['system']['documentroot_prefix']
&& $ftphomedir != $customerdocroot
) {
$cronlog->logAction(CRON_ACTION, LOG_NOTICE, 'Running: rm -rf ' . escapeshellarg($ftphomedir));
safe_exec('rm -rf '.escapeshellarg($ftphomedir));
}
}
}
}
/**
* TYPE=10 Set the filesystem - quota
*/
elseif ($row['type'] == '10')
{
if ($settings['system']['diskquota_enabled'])
{
fwrite($debugHandler, ' cron_tasks: Task10 started - setting filesystem quota' . "\n");
$cronlog->logAction(CRON_ACTION, LOG_INFO, 'Task10 started - setting filesystem quota');
$usedquota = getFilesystemQuota();
# Select all customers Froxlor knows about
$result = $db->query("SELECT `guid`, `loginname`, `diskspace` FROM `" . TABLE_PANEL_CUSTOMERS . "`;");
while($row = $db->fetch_array($result))
{
# We do not want to set a quota for root by accident
if ($row['guid'] != 0)
{
# The user has no quota in Froxlor, but on the filesystem
if (($row['diskspace'] == 0 || $row['diskspace'] == -1024) && $usedquota[$row['guid']]['block']['hard'] != 0)
{
$cronlog->logAction(CRON_ACTION, LOG_NOTICE, "Disabling quota for " . $row['loginname']);
safe_exec($settings['system']['diskquota_quotatool_path'] . " -u " . $row['guid'] . " -bl 0 -q 0 " . escapeshellarg($settings['system']['diskquota_customer_partition']));
}
# The user quota in Froxlor is different than on the filesystem
elseif($row['diskspace'] != $usedquota[$row['guid']]['block']['hard'] && $row['diskspace'] != -1024)
{
$cronlog->logAction(CRON_ACTION, LOG_NOTICE, "Setting quota for " . $row['loginname'] . " from " . $usedquota[$row['guid']]['block']['hard'] . " to " . $row['diskspace']);
safe_exec($settings['system']['diskquota_quotatool_path'] . " -u " . $row['guid'] . " -bl " . $row['diskspace'] . " -q " . $row['diskspace'] . " " . escapeshellarg($settings['system']['diskquota_customer_partition']));
}
}
}
}
else
{
fwrite($debugHandler, ' cron_tasks: Task10 skipped - filesystem quota not enabled' . "\n");
$cronlog->logAction(CRON_ACTION, LOG_INFO, 'Task10 skipped - filesystem quota not enabled');
}
}
}
if($db->num_rows($result_tasks) != 0)
{
$where = array();
foreach($resultIDs as $id)
{
$where[] = '`id`=\'' . (int)$id . '\'';
}
$where = implode($where, ' OR ');
$db->query('DELETE FROM `' . TABLE_PANEL_TASKS . '` WHERE ' . $where);
unset($resultIDs);
unset($where);
}
$db->query('UPDATE `' . TABLE_PANEL_SETTINGS . '` SET `value` = UNIX_TIMESTAMP() WHERE `settinggroup` = \'system\' AND `varname` = \'last_tasks_run\' ');
?>