Merge remote-tracking branch 'refs/remotes/origin/0.11-dev' into 0.11-dev
This commit is contained in:
@@ -105,7 +105,7 @@ abstract class ApiCommand extends ApiParameter
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct($header = null, $params = null, $userinfo = null, $internal = false)
|
||||
final public function __construct($header = null, $params = null, $userinfo = null, $internal = false)
|
||||
{
|
||||
parent::__construct($params);
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ class Admins extends ApiCommand implements ResourceEntity
|
||||
* returns the total number of admins for the given admin
|
||||
*
|
||||
* @access admin
|
||||
* @return string json-encoded array
|
||||
* @return string json-encoded response message
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listingCount()
|
||||
@@ -131,6 +131,7 @@ class Admins extends ApiCommand implements ResourceEntity
|
||||
if ($result) {
|
||||
return $this->response($result['num_admins']);
|
||||
}
|
||||
$this->response(0);
|
||||
}
|
||||
throw new Exception("Not allowed to execute given command.", 403);
|
||||
}
|
||||
|
||||
@@ -371,7 +371,7 @@ class Certificates extends ApiCommand implements ResourceEntity
|
||||
* returns the total number of certificates for the given user
|
||||
*
|
||||
* @access admin, customer
|
||||
* @return string json-encoded array
|
||||
* @return string json-encoded response message
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listingCount()
|
||||
@@ -399,6 +399,7 @@ class Certificates extends ApiCommand implements ResourceEntity
|
||||
if ($result) {
|
||||
return $this->response($result['num_certs']);
|
||||
}
|
||||
return $this->response(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -185,7 +185,7 @@ class Cronjobs extends ApiCommand implements ResourceEntity
|
||||
* returns the total number of cronjobs
|
||||
*
|
||||
* @access admin
|
||||
* @return string json-encoded array
|
||||
* @return string json-encoded response message
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listingCount()
|
||||
@@ -198,6 +198,7 @@ class Cronjobs extends ApiCommand implements ResourceEntity
|
||||
if ($result) {
|
||||
return $this->response($result['num_crons']);
|
||||
}
|
||||
return $this->response(0);
|
||||
}
|
||||
throw new Exception("Not allowed to execute given command.", 403);
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ class CustomerBackups extends ApiCommand implements ResourceEntity
|
||||
* optional, admin-only, select backup-jobs of a specific customer by loginname
|
||||
*
|
||||
* @access admin, customer
|
||||
* @return string json-encoded array
|
||||
* @return string json-encoded response message
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listingCount()
|
||||
|
||||
@@ -143,7 +143,7 @@ class Customers extends ApiCommand implements ResourceEntity
|
||||
* returns the total number of customers for the given admin
|
||||
*
|
||||
* @access admin
|
||||
* @return string json-encoded array
|
||||
* @return string json-encoded response message
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listingCount()
|
||||
@@ -163,6 +163,7 @@ class Customers extends ApiCommand implements ResourceEntity
|
||||
if ($result) {
|
||||
return $this->response($result['num_customers']);
|
||||
}
|
||||
return $this->response(0);
|
||||
}
|
||||
throw new Exception("Not allowed to execute given command.", 403);
|
||||
}
|
||||
|
||||
@@ -396,7 +396,7 @@ class DirOptions extends ApiCommand implements ResourceEntity
|
||||
* optional, admin-only, select directory-protections of a specific customer by loginname
|
||||
*
|
||||
* @access admin, customer
|
||||
* @return string json-encoded array count|list
|
||||
* @return string json-encoded response message
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listingCount()
|
||||
@@ -415,6 +415,7 @@ class DirOptions extends ApiCommand implements ResourceEntity
|
||||
if ($result) {
|
||||
return $this->response($result['num_htaccess']);
|
||||
}
|
||||
return $this->response(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -339,7 +339,7 @@ class DirProtections extends ApiCommand implements ResourceEntity
|
||||
* optional, admin-only, select directory-protections of a specific customer by loginname
|
||||
*
|
||||
* @access admin, customer
|
||||
* @return string json-encoded array count|list
|
||||
* @return string json-encoded response message
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listingCount()
|
||||
@@ -358,6 +358,7 @@ class DirProtections extends ApiCommand implements ResourceEntity
|
||||
if ($result) {
|
||||
return $this->response($result['num_htpasswd']);
|
||||
}
|
||||
return $this->response(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -491,7 +491,7 @@ class DomainZones extends ApiCommand implements ResourceEntity
|
||||
* optional, the domain name
|
||||
*
|
||||
* @access admin, customer
|
||||
* @return bool
|
||||
* @return string json-encoded response message
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listingCount()
|
||||
@@ -522,6 +522,7 @@ class DomainZones extends ApiCommand implements ResourceEntity
|
||||
if ($result) {
|
||||
return $this->response($result['num_dns']);
|
||||
}
|
||||
return $this->response(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1743,9 +1743,6 @@ class Domains extends ApiCommand implements ResourceEntity
|
||||
$upd_specialsettings = ", `specialsettings` = :specialsettings, `ssl_specialsettings` = :ssl_specialsettings, `include_specialsettings` = :include_specialsettings ";
|
||||
} else {
|
||||
$upd_specialsettings = '';
|
||||
unset($_update_data['specialsettings']);
|
||||
unset($_update_data['ssl_specialsettings']);
|
||||
unset($_update_data['include_specialsettings']);
|
||||
$upd_stmt = Database::prepare("
|
||||
UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `specialsettings`='', `ssl_specialsettings`='', `include_specialsettings`='0' WHERE `parentdomainid` = :id
|
||||
");
|
||||
|
||||
@@ -216,7 +216,6 @@ class EmailAccounts extends ApiCommand implements ResourceEntity
|
||||
// replacer array for mail to create account on server
|
||||
$replace_arr = [
|
||||
'EMAIL' => $email_full,
|
||||
'USERNAME' => $username,
|
||||
'PASSWORD' => htmlentities(htmlentities($password)),
|
||||
'SALUTATION' => User::getCorrectUserSalutation($customer),
|
||||
'NAME' => $customer['name'],
|
||||
|
||||
@@ -206,7 +206,7 @@ class EmailForwarders extends ApiCommand implements ResourceEntity
|
||||
* optional, admin-only, the loginname
|
||||
*
|
||||
* @access admin,customer
|
||||
* @return string json-encoded array
|
||||
* @return string json-encoded response message
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listingCount()
|
||||
|
||||
@@ -356,7 +356,7 @@ class Emails extends ApiCommand implements ResourceEntity
|
||||
* optional, admin-only, select email addresses of a specific customer by loginname
|
||||
*
|
||||
* @access admin, customer
|
||||
* @return string json-encoded array
|
||||
* @return string json-encoded response message
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listingCount()
|
||||
@@ -373,6 +373,7 @@ class Emails extends ApiCommand implements ResourceEntity
|
||||
if ($result) {
|
||||
return $this->response($result['num_emails']);
|
||||
}
|
||||
return $this->response(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -105,7 +105,7 @@ class FpmDaemons extends ApiCommand implements ResourceEntity
|
||||
* returns the total number of accessible fpm daemons
|
||||
*
|
||||
* @access admin
|
||||
* @return string json-encoded array
|
||||
* @return string json-encoded response message
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listingCount()
|
||||
@@ -118,6 +118,7 @@ class FpmDaemons extends ApiCommand implements ResourceEntity
|
||||
if ($result) {
|
||||
return $this->response($result['num_fpms']);
|
||||
}
|
||||
return $this->response(0);
|
||||
}
|
||||
throw new Exception("Not allowed to execute given command.", 403);
|
||||
}
|
||||
|
||||
@@ -549,7 +549,7 @@ class Ftps extends ApiCommand implements ResourceEntity
|
||||
* optional, admin-only, select ftp-users of a specific customer by loginname
|
||||
*
|
||||
* @access admin, customer
|
||||
* @return string json-encoded array
|
||||
* @return string json-encoded response message
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listingCount()
|
||||
@@ -564,6 +564,7 @@ class Ftps extends ApiCommand implements ResourceEntity
|
||||
if ($result) {
|
||||
return $this->response($result['num_ftps']);
|
||||
}
|
||||
return $this->response(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -89,7 +89,7 @@ class HostingPlans extends ApiCommand implements ResourceEntity
|
||||
* returns the total number of accessible hosting plans
|
||||
*
|
||||
* @access admin
|
||||
* @return string json-encoded array
|
||||
* @return string json-encoded response message
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listingCount()
|
||||
@@ -107,6 +107,7 @@ class HostingPlans extends ApiCommand implements ResourceEntity
|
||||
if ($result) {
|
||||
return $this->response($result['num_plans']);
|
||||
}
|
||||
return $this->response(0);
|
||||
}
|
||||
throw new Exception("Not allowed to execute given command.", 403);
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ class IpsAndPorts extends ApiCommand implements ResourceEntity
|
||||
* returns the total number of accessible ip/port entries
|
||||
*
|
||||
* @access admin
|
||||
* @return string json-encoded array
|
||||
* @return string json-encoded response message
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listingCount()
|
||||
@@ -108,6 +108,7 @@ class IpsAndPorts extends ApiCommand implements ResourceEntity
|
||||
if ($result) {
|
||||
return $this->response($result['num_ips']);
|
||||
}
|
||||
return $this->response(0);
|
||||
}
|
||||
throw new Exception("Not allowed to execute given command.", 403);
|
||||
}
|
||||
|
||||
@@ -124,11 +124,14 @@ class MysqlServer extends ApiCommand implements ResourceEntity
|
||||
}
|
||||
}
|
||||
|
||||
$sql = [];
|
||||
$sql_root = [];
|
||||
|
||||
// get all data from lib/userdata
|
||||
require Froxlor::getInstallDir() . "/lib/userdata.inc.php";
|
||||
|
||||
// le format
|
||||
if (isset($sql['root_user']) && isset($sql['root_password']) && (!isset($sql_root) || !is_array($sql_root))) {
|
||||
if (isset($sql['root_user']) && isset($sql['root_password']) &&!is_array($sql_root)) {
|
||||
$sql_root = array(
|
||||
0 => array(
|
||||
'caption' => 'Default',
|
||||
@@ -151,7 +154,7 @@ class MysqlServer extends ApiCommand implements ResourceEntity
|
||||
'password' => $privileged_password,
|
||||
'ssl' => [
|
||||
'caFile' => $mysql_ca ?? "",
|
||||
'verifyServerCertificate' => $mysql_verifycert ?? false
|
||||
'verifyServerCertificate' => $mysql_verifycert
|
||||
]
|
||||
];
|
||||
|
||||
@@ -192,6 +195,7 @@ class MysqlServer extends ApiCommand implements ResourceEntity
|
||||
throw new Exception('Cannot delete first/default mysql-server', 406);
|
||||
}
|
||||
|
||||
$sql_root = [];
|
||||
// get all data from lib/userdata
|
||||
require Froxlor::getInstallDir() . "/lib/userdata.inc.php";
|
||||
|
||||
@@ -222,6 +226,8 @@ class MysqlServer extends ApiCommand implements ResourceEntity
|
||||
*/
|
||||
public function listing()
|
||||
{
|
||||
$sql = [];
|
||||
$sql_root = [];
|
||||
// get all data from lib/userdata
|
||||
require Froxlor::getInstallDir() . "/lib/userdata.inc.php";
|
||||
|
||||
@@ -255,7 +261,7 @@ class MysqlServer extends ApiCommand implements ResourceEntity
|
||||
* returns the total number of mysql servers
|
||||
*
|
||||
* @access admin, customer
|
||||
* @return string json-encoded array
|
||||
* @return string json-encoded response message
|
||||
*/
|
||||
public function listingCount()
|
||||
{
|
||||
@@ -266,6 +272,7 @@ class MysqlServer extends ApiCommand implements ResourceEntity
|
||||
}
|
||||
return $this->response(0);
|
||||
}
|
||||
$sql_root = [];
|
||||
// get all data from lib/userdata
|
||||
require Froxlor::getInstallDir() . "/lib/userdata.inc.php";
|
||||
return $this->response(count($sql_root));
|
||||
@@ -290,9 +297,14 @@ class MysqlServer extends ApiCommand implements ResourceEntity
|
||||
$dbserver = (int) $this->getParam('dbserver', $dn_optional, -1);
|
||||
$dbserver = $id >= 0 ? $id : $dbserver;
|
||||
|
||||
$sql_root = [];
|
||||
// get all data from lib/userdata
|
||||
require Froxlor::getInstallDir() . "/lib/userdata.inc.php";
|
||||
|
||||
if (!isset($sql_root[$dbserver])) {
|
||||
throw new Exception('Mysql server not found', 404);
|
||||
}
|
||||
|
||||
// limit customer to its allowed servers
|
||||
if ($this->isAdmin() == false) {
|
||||
$allowed_mysqls = json_decode($this->getUserDetail('allowed_mysqlserver'), true);
|
||||
@@ -300,11 +312,7 @@ class MysqlServer extends ApiCommand implements ResourceEntity
|
||||
throw new Exception("You cannot access this resource", 405);
|
||||
}
|
||||
// no usernames required for non-admins
|
||||
unset($sqlrootdata['user']);
|
||||
}
|
||||
|
||||
if (!isset($sql_root[$dbserver])) {
|
||||
throw new Exception('Mysql server not found', 404);
|
||||
unset($sql_root[$dbserver]['user']);
|
||||
}
|
||||
|
||||
unset($sql_root[$dbserver]['password']);
|
||||
@@ -351,6 +359,7 @@ class MysqlServer extends ApiCommand implements ResourceEntity
|
||||
$dbserver = (int) $this->getParam('dbserver', $dn_optional, -1);
|
||||
$dbserver = $id >= 0 ? $id : $dbserver;
|
||||
|
||||
$sql_root = [];
|
||||
require Froxlor::getInstallDir() . "/lib/userdata.inc.php";
|
||||
|
||||
if (!isset($sql_root[$dbserver])) {
|
||||
|
||||
@@ -94,7 +94,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
|
||||
Database::needSqlData();
|
||||
$sql_root = Database::getSqlData();
|
||||
Database::needRoot(false);
|
||||
if (!isset($sql_root) || !is_array($sql_root)) {
|
||||
if (!is_array($sql_root)) {
|
||||
throw new Exception("Database server with index #" . $dbserver . " is unknown", 404);
|
||||
}
|
||||
|
||||
@@ -481,7 +481,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
|
||||
* optional, admin-only, select dbs of a specific customer by loginname
|
||||
*
|
||||
* @access admin, customer
|
||||
* @return string json-encoded array
|
||||
* @return string json-encoded response message
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listingCount()
|
||||
@@ -495,6 +495,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
|
||||
if ($result) {
|
||||
return $this->response($result['num_dbs']);
|
||||
}
|
||||
return $this->response(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -123,7 +123,7 @@ class PhpSettings extends ApiCommand implements ResourceEntity
|
||||
}
|
||||
|
||||
// check whether we use that config as froxor-vhost config
|
||||
if (Settings::Get('system.mod_fcgid_defaultini_ownvhost') == $row['id'] || Settings::Get('phpfpm.vhost_defaultini') == $row['id']) {
|
||||
if ((Settings::Get('system.mod_fcgid') == '1' && Settings::Get('system.mod_fcgid_defaultini_ownvhost') == $row['id']) || (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.vhost_defaultini') == $row['id'])) {
|
||||
$domains[] = Settings::Get('system.hostname');
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ class PhpSettings extends ApiCommand implements ResourceEntity
|
||||
* returns the total number of accessible php-setting entries
|
||||
*
|
||||
* @access admin
|
||||
* @return string json-encoded array
|
||||
* @return string json-encoded response message
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listingCount()
|
||||
@@ -192,6 +192,7 @@ class PhpSettings extends ApiCommand implements ResourceEntity
|
||||
if ($result) {
|
||||
return $this->response($result['num_phps']);
|
||||
}
|
||||
return $this->response(0);
|
||||
}
|
||||
throw new Exception("Not allowed to execute given command.", 403);
|
||||
}
|
||||
|
||||
@@ -1017,7 +1017,7 @@ class SubDomains extends ApiCommand implements ResourceEntity
|
||||
* optional, admin-only, select (sub)domains of a specific customer by loginname
|
||||
*
|
||||
* @access admin, customer
|
||||
* @return string json-encoded array
|
||||
* @return string json-encoded response message
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listingCount()
|
||||
@@ -1069,6 +1069,7 @@ class SubDomains extends ApiCommand implements ResourceEntity
|
||||
if ($result) {
|
||||
return $this->response($result['num_subdom']);
|
||||
}
|
||||
return $this->response(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -103,7 +103,7 @@ class SysLog extends ApiCommand implements ResourceEntity
|
||||
* returns the total number of log-entries
|
||||
*
|
||||
* @access admin
|
||||
* @return string json-encoded array
|
||||
* @return string json-encoded response message
|
||||
* @throws Exception
|
||||
*/
|
||||
public function listingCount()
|
||||
@@ -150,6 +150,7 @@ class SysLog extends ApiCommand implements ResourceEntity
|
||||
if ($result) {
|
||||
return $this->response($result['num_logs']);
|
||||
}
|
||||
return $this->response(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -76,7 +76,7 @@ abstract class BulkAction
|
||||
*
|
||||
* @return object BulkAction instance
|
||||
*/
|
||||
protected function __construct($import_file = null, $userinfo = [])
|
||||
protected function __construct(string $import_file = null, array $userinfo = [])
|
||||
{
|
||||
if (!empty($import_file)) {
|
||||
$this->impFile = FileDir::makeCorrectFile($import_file);
|
||||
@@ -93,7 +93,7 @@ abstract class BulkAction
|
||||
*
|
||||
* @return array 'all' => amount of records processed, 'imported' => number of imported records
|
||||
*/
|
||||
abstract public function doImport($separator = ";", $offset = 0);
|
||||
abstract public function doImport(string $separator = ";", int $offset = 0);
|
||||
|
||||
/**
|
||||
* setter for import-file
|
||||
|
||||
@@ -34,10 +34,12 @@ class DomainBulkAction extends BulkAction
|
||||
{
|
||||
|
||||
/**
|
||||
* @param string $import_file
|
||||
* @param array $userinfo
|
||||
*
|
||||
* @return object DomainBulkAction instance
|
||||
* @return DomainBulkAction
|
||||
*/
|
||||
public function __construct($import_file = null, $userinfo)
|
||||
public function __construct(string $import_file = null, array $userinfo = [])
|
||||
{
|
||||
parent::__construct($import_file, $userinfo);
|
||||
$this->setApiCall('Domains.add');
|
||||
@@ -52,7 +54,7 @@ class DomainBulkAction extends BulkAction
|
||||
*
|
||||
* @return array 'all' => amount of records processed, 'imported' => number of imported records
|
||||
*/
|
||||
public function doImport($separator = ";", $offset = 0)
|
||||
public function doImport(string $separator = ";", int $offset = 0)
|
||||
{
|
||||
if ($this->userinfo['domains'] == "-1") {
|
||||
$dom_unlimited = true;
|
||||
|
||||
@@ -25,7 +25,11 @@
|
||||
|
||||
namespace Froxlor\Cli;
|
||||
|
||||
use PDO;
|
||||
use Exception;
|
||||
use Froxlor\Froxlor;
|
||||
use Froxlor\Settings;
|
||||
use Froxlor\Database\Database;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
@@ -39,10 +43,96 @@ class CliCommand extends Command
|
||||
$output->writeln("<error>Could not find froxlor's userdata.inc.php file. You should use this script only with an installed froxlor system.</>");
|
||||
return self::INVALID;
|
||||
}
|
||||
if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) {
|
||||
$output->writeln("<error>It seems that the froxlor files have been updated. Please login and finish the update procedure.</>");
|
||||
// try database connection
|
||||
try {
|
||||
Database::query("SELECT 1");
|
||||
} catch (Exception $e) {
|
||||
// Do not proceed further if no database connection could be established
|
||||
$output->writeln("<error>" . $e->getMessage() . "</>");
|
||||
return self::INVALID;
|
||||
}
|
||||
if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) {
|
||||
if ((int)Settings::Get('system.cron_allowautoupdate') == 1) {
|
||||
return $this->runUpdate($output);
|
||||
} else {
|
||||
$output->writeln("<error>It seems that the froxlor files have been updated. Please login and finish the update procedure.</>");
|
||||
return self::INVALID;
|
||||
}
|
||||
}
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
protected function getUserByName(?string $loginname, bool $deactivated_check = true): array
|
||||
{
|
||||
if (empty($loginname)) {
|
||||
throw new Exception("Empty username");
|
||||
}
|
||||
|
||||
$stmt = Database::prepare("
|
||||
SELECT `loginname` AS `customer`
|
||||
FROM `" . TABLE_PANEL_CUSTOMERS . "`
|
||||
WHERE `loginname`= :loginname
|
||||
");
|
||||
Database::pexecute($stmt, [
|
||||
"loginname" => $loginname
|
||||
]);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($row && $row['customer'] == $loginname) {
|
||||
$table = "`" . TABLE_PANEL_CUSTOMERS . "`";
|
||||
$adminsession = '0';
|
||||
} else {
|
||||
$stmt = Database::prepare("
|
||||
SELECT `loginname` AS `admin` FROM `" . TABLE_PANEL_ADMINS . "`
|
||||
WHERE `loginname`= :loginname
|
||||
");
|
||||
Database::pexecute($stmt, [
|
||||
"loginname" => $loginname
|
||||
]);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($row && $row['admin'] == $loginname) {
|
||||
$table = "`" . TABLE_PANEL_ADMINS . "`";
|
||||
$adminsession = '1';
|
||||
} else {
|
||||
throw new Exception("Unknown user '" . $loginname . "'");
|
||||
}
|
||||
}
|
||||
|
||||
$userinfo_stmt = Database::prepare("
|
||||
SELECT * FROM $table
|
||||
WHERE `loginname`= :loginname
|
||||
");
|
||||
Database::pexecute($userinfo_stmt, [
|
||||
"loginname" => $loginname
|
||||
]);
|
||||
$userinfo = $userinfo_stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$userinfo['adminsession'] = $adminsession;
|
||||
|
||||
if ($deactivated_check && $userinfo['deactivated']) {
|
||||
throw new Exception("User '" . $loginname . "' is currently deactivated");
|
||||
}
|
||||
|
||||
return $userinfo;
|
||||
}
|
||||
|
||||
private function runUpdate(OutputInterface $output): int
|
||||
{
|
||||
$output->writeln('<comment>Automatic update is activated and we are going to proceed without any notices</>');
|
||||
include_once Froxlor::getInstallDir() . '/lib/tables.inc.php';
|
||||
define('_CRON_UPDATE', 1);
|
||||
ob_start([
|
||||
'this',
|
||||
'cleanUpdateOutput'
|
||||
]);
|
||||
include_once Froxlor::getInstallDir() . '/install/updatesql.php';
|
||||
ob_end_flush();
|
||||
$output->writeln('<info>Automatic update done - you should check your settings to be sure everything is fine</>');
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
private function cleanUpdateOutput($buffer)
|
||||
{
|
||||
return strip_tags(preg_replace("/<br\W*?\/>/", "\n", $buffer));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,7 +410,7 @@ final class ConfigServices extends CliCommand
|
||||
// set is_configured flag
|
||||
Settings::Set('panel.is_configured', '1', true);
|
||||
// run cronjob at the end to ensure configs are all up to date
|
||||
exec('php ' . Froxlor::getInstallDir() . 'scripts/froxlor_master_cronjob.php --force');
|
||||
exec('php ' . Froxlor::getInstallDir() . 'bin/froxlor-cli froxlor:cron --force');
|
||||
// and done
|
||||
$output->writeln('<info>All services have been configured</>');
|
||||
return self::SUCCESS;
|
||||
|
||||
@@ -49,13 +49,26 @@ final class InstallCommand extends Command
|
||||
$this->setName('froxlor:install');
|
||||
$this->setDescription('Installation process to use instead of web-ui');
|
||||
$this->addArgument('input-file', InputArgument::OPTIONAL, 'Optional JSON array file to use for unattended installations');
|
||||
$this->addOption('print-example-file', 'p', InputOption::VALUE_NONE, 'Outputs an example JSON content to be used with the input file parameter');
|
||||
$this->addOption('print-example-file', 'p', InputOption::VALUE_NONE, 'Outputs an example JSON content to be used with the input file parameter')
|
||||
->addOption('create-userdata-from-str', 'c', InputOption::VALUE_REQUIRED, 'Creates lib/userdata.inc.php file from string created by web-install process');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$result = self::SUCCESS;
|
||||
|
||||
if ($input->getOption('create-userdata-from-str') !== null) {
|
||||
$ud_str = $input->getOption('create-userdata-from-str');
|
||||
$ud_dec = @json_decode(@base64_decode($ud_str), true);
|
||||
if (is_array($ud_dec) && !empty($ud_dec) && count($ud_dec) == 8) {
|
||||
$core = new Core($ud_dec);
|
||||
$core->createUserdataConf();
|
||||
return $result;
|
||||
}
|
||||
$output->writeln("<error>Invalid parameter value.</>");
|
||||
return self::INVALID;
|
||||
}
|
||||
|
||||
session_start();
|
||||
|
||||
require __DIR__ . '/install.functions.php';
|
||||
@@ -121,6 +134,7 @@ final class InstallCommand extends Command
|
||||
$this->io->info('Running unattended installation');
|
||||
} else {
|
||||
$extended = $this->io->confirm('Use advanced installation mode?', false);
|
||||
$decoded_input = [];
|
||||
}
|
||||
|
||||
$result = $this->showStep(0, $extended, $decoded_input);
|
||||
@@ -237,7 +251,7 @@ final class InstallCommand extends Command
|
||||
if ($step == 3) {
|
||||
// do actual install with data from $this->formfielddata
|
||||
$core = new Core($this->formfielddata);
|
||||
$core->doInstall();
|
||||
$core->doInstall(false);
|
||||
$core->createUserdataConf();
|
||||
}
|
||||
return $this->showStep(++$step, $extended, $decoded_input);
|
||||
|
||||
260
lib/Froxlor/Cli/MasterCron.php
Normal file
260
lib/Froxlor/Cli/MasterCron.php
Normal file
@@ -0,0 +1,260 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2010 the Froxlor Team (see authors).
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you can also view it online at
|
||||
* https://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright the authors
|
||||
* @author Froxlor team <team@froxlor.org>
|
||||
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
||||
*/
|
||||
|
||||
namespace Froxlor\Cli;
|
||||
|
||||
use PDO;
|
||||
use Froxlor\Froxlor;
|
||||
use Froxlor\FileDir;
|
||||
use Froxlor\Settings;
|
||||
use Froxlor\FroxlorLogger;
|
||||
use Froxlor\Database\Database;
|
||||
use Froxlor\System\Cronjob;
|
||||
use Froxlor\Cron\TaskId;
|
||||
use Froxlor\Cron\CronConfig;
|
||||
use Froxlor\Cron\System\Extrausers;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
final class MasterCron extends CliCommand
|
||||
{
|
||||
private $lockFile = null;
|
||||
|
||||
private $cronLog = null;
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('froxlor:cron');
|
||||
$this->setDescription('Regulary perform tasks created by froxlor');
|
||||
$this->addArgument('job', InputArgument::IS_ARRAY, 'Job(s) to run');
|
||||
$this->addOption('run-task', 'r', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Run a specific task [1 = re-generate configs, 4 = re-generate dns zones, 10 = re-set quotas, 99 = re-create cron.d-file]')
|
||||
->addOption('force', 'f', InputOption::VALUE_NONE, 'Forces re-generating of config-files (webserver, nameserver, etc.)')
|
||||
->addOption('debug', 'd', InputOption::VALUE_NONE, 'Output debug information about what is going on to STDOUT.')
|
||||
->addOption('no-fork', 'N', InputOption::VALUE_NONE, 'Do not fork to background (traffic cron only).');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$result = self::SUCCESS;
|
||||
$result = $this->validateRequirements($input, $output);
|
||||
|
||||
$jobs = $input->getArgument('job');
|
||||
|
||||
// handle force option
|
||||
if ($input->getOption('force')) {
|
||||
// rebuild all config files
|
||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||
Cronjob::inserttask(TaskId::REBUILD_DNS);
|
||||
Cronjob::inserttask(TaskId::CREATE_QUOTA);
|
||||
Cronjob::inserttask(TaskId::REBUILD_CRON);
|
||||
array_push($jobs, 'tasks');
|
||||
define('CRON_IS_FORCED', 1);
|
||||
}
|
||||
// handle debug option
|
||||
if ($input->getOption('debug')) {
|
||||
define('CRON_DEBUG_FLAG', 1);
|
||||
}
|
||||
// handle no-fork option
|
||||
if ($input->getOption('no-fork')) {
|
||||
define('CRON_NOFORK_FLAG', 1);
|
||||
}
|
||||
// handle run-task option
|
||||
if ($input->getOption('run-task')) {
|
||||
$tasks_to_run = $input->getOption('run-task');
|
||||
foreach ($tasks_to_run as $ttr) {
|
||||
if (in_array($ttr, [1, 4, 10, 99])) {
|
||||
Cronjob::inserttask($ttr);
|
||||
array_push($jobs, 'tasks');
|
||||
} else {
|
||||
$output->writeln('<comment>Unknown task number "' . $ttr . '"</>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unique job-array
|
||||
$jobs = array_unique($jobs);
|
||||
|
||||
// check for given job(s) to execute and return if empty
|
||||
if (empty($jobs)) {
|
||||
$output->writeln('<error>No job given. Nothing to do.</>');
|
||||
return self::INVALID;
|
||||
}
|
||||
|
||||
$this->validateOwnership($output);
|
||||
|
||||
$this->cronLog = FroxlorLogger::getInstanceOf([
|
||||
'loginname' => 'cronjob'
|
||||
]);
|
||||
$this->cronLog->setCronDebugFlag(defined('CRON_DEBUG_FLAG'));
|
||||
|
||||
// check whether there are actual tasks to perform by 'tasks'-cron so
|
||||
// we dont regenerate files unnecessarily
|
||||
$tasks_cnt_stmt = Database::query("SELECT COUNT(*) as jobcnt FROM `panel_tasks`");
|
||||
$tasks_cnt = $tasks_cnt_stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
// iterate through all needed jobs
|
||||
foreach ($jobs as $job) {
|
||||
// lock the job
|
||||
if ($this->lockJob($job, $output)) {
|
||||
// get FQDN of cron-class
|
||||
$cronfile = $this->getCronModule($job, $output);
|
||||
// validate
|
||||
if ($cronfile && class_exists($cronfile)) {
|
||||
// info
|
||||
$output->writeln('<info>Running "' . $job . '" job' . (defined('CRON_IS_FORCED') ? ' (forced)' : '') . (defined('CRON_DEBUG_FLAG') ? ' (debug)' : '') . (defined('CRON_NOFORK_FLAG') ? ' (not forking)' : '') . '</>');
|
||||
// update time of last run
|
||||
Cronjob::updateLastRunOfCron($job);
|
||||
// set logger
|
||||
$cronfile::setCronlog($this->cronLog);
|
||||
// run the job
|
||||
$cronfile::run();
|
||||
}
|
||||
// free the lockfile
|
||||
$this->unlockJob($job);
|
||||
}
|
||||
}
|
||||
|
||||
// regenerate nss-extrausers files / invalidate nscd cache (if used)
|
||||
$this->refreshUsers((int) $tasks_cnt['jobcnt']);
|
||||
|
||||
// we have to check the system's last guid with every cron run
|
||||
// in case the admin installed new software which added a new user
|
||||
//so users in the database don't conflict with system users
|
||||
$this->cronLog->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Checking system\'s last guid');
|
||||
Cronjob::checkLastGuid();
|
||||
|
||||
// check for cron.d-generation task and create it if necessary
|
||||
CronConfig::checkCrondConfigurationFile();
|
||||
|
||||
// reset cronlog-flag if set to "once"
|
||||
if ((int) Settings::Get('logger.log_cron') == 1) {
|
||||
FroxlorLogger::getInstanceOf()->setCronLog(0);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function refreshUsers(int $jobcount = 0)
|
||||
{
|
||||
if ($jobcount > 0) {
|
||||
if (Settings::Get('system.nssextrausers') == 1) {
|
||||
Extrausers::generateFiles($this->cronLog);
|
||||
return;
|
||||
}
|
||||
|
||||
// clear NSCD cache if using fcgid or fpm, #1570 - not needed for nss-extrausers
|
||||
if ((Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) && Settings::Get('system.nssextrausers') == 0) {
|
||||
$false_val = false;
|
||||
FileDir::safe_exec('nscd -i passwd 1> /dev/null', $false_val, [
|
||||
'>'
|
||||
]);
|
||||
FileDir::safe_exec('nscd -i group 1> /dev/null', $false_val, [
|
||||
'>'
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function validateOwnership(OutputInterface $output)
|
||||
{
|
||||
// when using fcgid or fpm for froxlor-vhost itself, we have to check
|
||||
// whether the permission of the files are still correct
|
||||
$output->write('Checking froxlor file permissions...');
|
||||
$_mypath = FileDir::makeCorrectDir(Froxlor::getInstallDir());
|
||||
|
||||
if (((int)Settings::Get('system.mod_fcgid') == 1 && (int)Settings::Get('system.mod_fcgid_ownvhost') == 1) || ((int)Settings::Get('phpfpm.enabled') == 1 && (int)Settings::Get('phpfpm.enabled_ownvhost') == 1)) {
|
||||
$user = Settings::Get('system.mod_fcgid_httpuser');
|
||||
$group = Settings::Get('system.mod_fcgid_httpgroup');
|
||||
|
||||
if (Settings::Get('phpfpm.enabled') == 1) {
|
||||
$user = Settings::Get('phpfpm.vhost_httpuser');
|
||||
$group = Settings::Get('phpfpm.vhost_httpgroup');
|
||||
}
|
||||
// all the files and folders have to belong to the local user
|
||||
FileDir::safe_exec('chown -R ' . $user . ':' . $group . ' ' . escapeshellarg($_mypath));
|
||||
} else {
|
||||
// back to webserver permission
|
||||
$user = Settings::Get('system.httpuser');
|
||||
$group = Settings::Get('system.httpgroup');
|
||||
FileDir::safe_exec('chown -R ' . $user . ':' . $group . ' ' . escapeshellarg($_mypath));
|
||||
}
|
||||
$output->writeln('OK');
|
||||
}
|
||||
|
||||
private function getCronModule(string $cronname, OutputInterface $output)
|
||||
{
|
||||
$upd_stmt = Database::prepare("
|
||||
SELECT `cronclass` FROM `" . TABLE_PANEL_CRONRUNS . "` WHERE `cronfile` = :cron;
|
||||
");
|
||||
$cron = Database::pexecute_first($upd_stmt, [
|
||||
'cron' => $cronname
|
||||
]);
|
||||
if ($cron) {
|
||||
return $cron['cronclass'];
|
||||
}
|
||||
$output->writeln("<error>Requested cronjob '" . $cronname . "' could not be found.</>");
|
||||
return false;
|
||||
}
|
||||
|
||||
private function lockJob(string $job, OutputInterface $output): bool
|
||||
{
|
||||
|
||||
$this->lockFile = '/run/lock/froxlor_' . $job . '.lock';
|
||||
|
||||
if (file_exists($this->lockFile)) {
|
||||
$jobinfo = json_decode(file_get_contents($this->lockFile), true);
|
||||
$check_pid_return = null;
|
||||
// get status of process
|
||||
system("kill -CHLD " . (int)$jobinfo['pid'] . " 1> /dev/null 2> /dev/null", $check_pid_return);
|
||||
if ($check_pid_return == 1) {
|
||||
// Process does not seem to run, most likely it has died
|
||||
$this->unlockJob($job);
|
||||
} else {
|
||||
// cronjob still running, output info and stop
|
||||
$output->writeln([
|
||||
'<comment>Job "' . $jobinfo['job'] . '" is currently running.',
|
||||
'Started: ' . date('d.m.Y H:i', (int) $jobinfo['startts']),
|
||||
'PID: ' . $jobinfo['pid'] . '</>'
|
||||
]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$jobinfo = [
|
||||
'job' => $job,
|
||||
'startts' => time(),
|
||||
'pid' => getmypid()
|
||||
];
|
||||
file_put_contents($this->lockFile, json_encode($jobinfo));
|
||||
return true;
|
||||
}
|
||||
|
||||
private function unlockJob(string $job): bool
|
||||
{
|
||||
return @unlink($this->lockFile);
|
||||
}
|
||||
}
|
||||
@@ -126,57 +126,4 @@ final class RunApiCommand extends CliCommand
|
||||
return ['class' => $command[0], 'function' => $command[1]];
|
||||
}
|
||||
|
||||
private function getUserByName(?string $loginname): array
|
||||
{
|
||||
if (empty($loginname)) {
|
||||
throw new Exception("Empty username");
|
||||
}
|
||||
|
||||
$stmt = Database::prepare("
|
||||
SELECT `loginname` AS `customer`
|
||||
FROM `" . TABLE_PANEL_CUSTOMERS . "`
|
||||
WHERE `loginname`= :loginname
|
||||
");
|
||||
Database::pexecute($stmt, [
|
||||
"loginname" => $loginname
|
||||
]);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($row && $row['customer'] == $loginname) {
|
||||
$table = "`" . TABLE_PANEL_CUSTOMERS . "`";
|
||||
$adminsession = '0';
|
||||
} else {
|
||||
$stmt = Database::prepare("
|
||||
SELECT `loginname` AS `admin` FROM `" . TABLE_PANEL_ADMINS . "`
|
||||
WHERE `loginname`= :loginname
|
||||
");
|
||||
Database::pexecute($stmt, [
|
||||
"loginname" => $loginname
|
||||
]);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($row && $row['admin'] == $loginname) {
|
||||
$table = "`" . TABLE_PANEL_ADMINS . "`";
|
||||
$adminsession = '1';
|
||||
} else {
|
||||
throw new Exception("Unknown user '" . $loginname . "'");
|
||||
}
|
||||
}
|
||||
|
||||
$userinfo_stmt = Database::prepare("
|
||||
SELECT * FROM $table
|
||||
WHERE `loginname`= :loginname
|
||||
");
|
||||
Database::pexecute($userinfo_stmt, [
|
||||
"loginname" => $loginname
|
||||
]);
|
||||
$userinfo = $userinfo_stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$userinfo['adminsession'] = $adminsession;
|
||||
|
||||
if ($userinfo['deactivated']) {
|
||||
throw new Exception("User '" . $loginname . "' is currently deactivated");
|
||||
}
|
||||
|
||||
return $userinfo;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ final class UpdateCommand extends CliCommand
|
||||
$auex = AutoUpdate::extractZip($audl);
|
||||
if ($auex == 0) {
|
||||
$output->writeln("<info>Froxlor files updated successfully.</>");
|
||||
$result = self::SUCCCESS;
|
||||
$result = self::SUCCESS;
|
||||
$question = new ConfirmationQuestion('Update database? [no] ', false, '/^(y|j)/i');
|
||||
if ($yestoall || $helper->ask($input, $output, $question)) {
|
||||
$result = $this->updateDatabase();
|
||||
@@ -193,7 +193,7 @@ final class UpdateCommand extends CliCommand
|
||||
]);
|
||||
include_once Froxlor::getInstallDir() . '/install/updatesql.php';
|
||||
ob_end_flush();
|
||||
return self::SUCCCESS;
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
private function cleanUpdateOutput($buffer)
|
||||
|
||||
135
lib/Froxlor/Cli/UserCommand.php
Normal file
135
lib/Froxlor/Cli/UserCommand.php
Normal file
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2010 the Froxlor Team (see authors).
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you can also view it online at
|
||||
* https://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright the authors
|
||||
* @author Froxlor team <team@froxlor.org>
|
||||
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
||||
*/
|
||||
|
||||
namespace Froxlor\Cli;
|
||||
|
||||
use Exception;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Froxlor\Api\Commands\Admins;
|
||||
use Froxlor\Api\Commands\Customers;
|
||||
use Froxlor\System\Crypt;
|
||||
use Froxlor\Froxlor;
|
||||
|
||||
final class UserCommand extends CliCommand
|
||||
{
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('froxlor:user');
|
||||
$this->setDescription('Various user actions');
|
||||
$this->addArgument('user', InputArgument::REQUIRED, 'Loginname of the target user')
|
||||
->addArgument('admin', InputArgument::OPTIONAL, 'Loginname of the executing admin/reseller user', 'admin');
|
||||
$this->addOption('unlock', 'u', InputOption::VALUE_NONE, 'Unock user after too many failed login attempts')
|
||||
->addOption('change-passwd', 'p', InputOption::VALUE_NONE, 'Set new password for given user')
|
||||
->addOption('show-info', 's', InputOption::VALUE_NONE, 'Output information details of given user');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$result = self::SUCCESS;
|
||||
|
||||
$result = $this->validateRequirements($input, $output);
|
||||
|
||||
require Froxlor::getInstallDir() . '/lib/functions.php';
|
||||
|
||||
// set error-handler
|
||||
@set_error_handler([
|
||||
'\\Froxlor\\Api\\Api',
|
||||
'phpErrHandler'
|
||||
]);
|
||||
|
||||
if ($result == self::SUCCESS) {
|
||||
try {
|
||||
$adminname = $input->getArgument('admin');
|
||||
$admininfo = $this->getUserByName($adminname);
|
||||
$loginname = $input->getArgument('user');
|
||||
$userinfo = $this->getUserByName($loginname, false);
|
||||
|
||||
$do_unlock = $input->getOption('unlock');
|
||||
$do_passwd = $input->getOption('change-passwd');
|
||||
$do_show = $input->getOption('show-info');
|
||||
|
||||
if ($do_unlock === false && $do_passwd === false && $do_show === false) {
|
||||
$output->writeln('<error>No option given, nothing to do.</>');
|
||||
$result = self::INVALID;
|
||||
}
|
||||
|
||||
if ($do_unlock !== false) {
|
||||
// unlock given user
|
||||
if ((int)$userinfo['adminsession'] == 1) {
|
||||
Admins::getLocal($admininfo, ['loginname' => $loginname])->unlock();
|
||||
} else {
|
||||
Customers::getLocal($admininfo, ['loginname' => $loginname])->unlock();
|
||||
}
|
||||
$output->writeln('<info>User ' . $loginname . ' unlocked successfully</>');
|
||||
$result = self::SUCCESS;
|
||||
}
|
||||
if ($result == self::SUCCESS && $do_passwd !== false) {
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$passwd = $io->askHidden("Enter new password", function ($value) {
|
||||
if (empty($value)) {
|
||||
throw new \RuntimeException('You must enter a value.');
|
||||
}
|
||||
$value = Crypt::validatePassword($value, 'new password');
|
||||
return $value;
|
||||
});
|
||||
$passwd2 = $io->askHidden("Confirm new password", function ($value) use ($passwd) {
|
||||
if (empty($value)) {
|
||||
throw new \RuntimeException('You must enter a value.');
|
||||
} elseif ($value != $passwd) {
|
||||
throw new \RuntimeException('Passwords do not match');
|
||||
}
|
||||
return $value;
|
||||
});
|
||||
if ((int)$userinfo['adminsession'] == 1) {
|
||||
Admins::getLocal($admininfo, ['id' => $userinfo['adminid'], 'admin_password' => $passwd])->update();
|
||||
} else {
|
||||
Customers::getLocal($admininfo, ['id' => $userinfo['customerid'], 'new_customer_password' => $passwd])->update();
|
||||
}
|
||||
$output->writeln('<info>Changed password for ' . $loginname . '</>');
|
||||
$result = self::SUCCESS;
|
||||
}
|
||||
if ($result == self::SUCCESS && $do_show !== false) {
|
||||
$userinfo['password'] = '[hidden]';
|
||||
$userinfo['data_2fa'] = '[hidden]';
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$io->horizontalTable(
|
||||
array_keys($userinfo),
|
||||
[array_values($userinfo)]
|
||||
);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$output->writeln('<error>' . $e->getMessage() . '</>');
|
||||
$result = self::FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -127,6 +127,8 @@ class ConfigDaemon
|
||||
if (is_null($this->sqldata_cache)) {
|
||||
// read in sql-data (if exists)
|
||||
if (file_exists(Froxlor::getInstallDir() . "/lib/userdata.inc.php")) {
|
||||
$sql = [];
|
||||
$sql_root = [];
|
||||
require Froxlor::getInstallDir() . "/lib/userdata.inc.php";
|
||||
unset($sql_root);
|
||||
$this->sqldata_cache = $sql;
|
||||
|
||||
@@ -109,7 +109,7 @@ class ConfigDisplay
|
||||
}
|
||||
}
|
||||
|
||||
Database::needSqlData(true);
|
||||
Database::needSqlData();
|
||||
$sql = Database::getSqlData();
|
||||
|
||||
self::$replace_arr = [
|
||||
|
||||
@@ -110,7 +110,7 @@ class CronConfig
|
||||
}
|
||||
|
||||
// create entry-line
|
||||
$cronfile .= "root " . $binpath . " " . FileDir::makeCorrectFile(Froxlor::getInstallDir() . "/scripts/froxlor_master_cronjob.php") . " --" . $row_cronentry['cronfile'] . " 1> /dev/null\n";
|
||||
$cronfile .= "root " . $binpath . " " . FileDir::makeCorrectFile(Froxlor::getInstallDir() . "/bin/froxlor-cli") . " froxlor:cron " . escapeshellarg($row_cronentry['cronfile']) . " -q 1> /dev/null\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ class CronConfig
|
||||
$newcrontab = "";
|
||||
foreach ($crontablines as $ctl) {
|
||||
$ctl = trim($ctl);
|
||||
if (!empty($ctl) && !preg_match("/(.*)froxlor_master_cronjob\.php(.*)/", $ctl)) {
|
||||
if (!empty($ctl) && !preg_match("/(.*)froxlor\:cron(.*)/", $ctl)) {
|
||||
$newcrontab .= $ctl . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,4 +42,9 @@ abstract class FroxlorCron
|
||||
{
|
||||
static::$lockfile = $lockfile;
|
||||
}
|
||||
|
||||
public static function setCronlog($cronlog = null)
|
||||
{
|
||||
static::$cronlog = $cronlog;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
namespace Froxlor\Cron\Http;
|
||||
|
||||
use Froxlor\Froxlor;
|
||||
use Froxlor\Cron\Http\Php\PhpInterface;
|
||||
use Froxlor\Customer\Customer;
|
||||
use Froxlor\Database\Database;
|
||||
@@ -39,16 +40,10 @@ use Froxlor\Validate\Validate;
|
||||
use Froxlor\System\Crypt;
|
||||
use PDO;
|
||||
|
||||
/**
|
||||
* @author Florian Lippert <flo@syscp.org> (2003-2009)
|
||||
* @author Froxlor team <team@froxlor.org> (2010-)
|
||||
*/
|
||||
class Apache extends HttpConfigBase
|
||||
{
|
||||
|
||||
// protected
|
||||
protected $known_vhostfilenames = [];
|
||||
|
||||
protected $known_diroptionsfilenames = [];
|
||||
|
||||
protected $known_htpasswdsfilenames = [];
|
||||
@@ -161,6 +156,27 @@ class Apache extends HttpConfigBase
|
||||
}
|
||||
|
||||
if (!$is_redirect) {
|
||||
// protect lib/userdata.inc.php
|
||||
$this->virtualhosts_data[$vhosts_filename] .= ' <Directory "' . rtrim(Froxlor::getInstallDir(), "/") . '/lib/">' . "\n";
|
||||
$this->virtualhosts_data[$vhosts_filename] .= ' <Files "userdata.inc.php">' . "\n";
|
||||
if (Settings::Get('system.apache24') == '1') {
|
||||
$this->virtualhosts_data[$vhosts_filename] .= ' Require all denied' . "\n";
|
||||
} else {
|
||||
$this->virtualhosts_data[$vhosts_filename] .= ' Order deny,allow' . "\n";
|
||||
$this->virtualhosts_data[$vhosts_filename] .= ' deny from all' . "\n";
|
||||
}
|
||||
$this->virtualhosts_data[$vhosts_filename] .= ' </Files>' . "\n";
|
||||
$this->virtualhosts_data[$vhosts_filename] .= ' </Directory>' . "\n";
|
||||
// protect bin/
|
||||
$this->virtualhosts_data[$vhosts_filename] .= ' <Directory "' . rtrim(Froxlor::getInstallDir(), "/") . '/bin/">' . "\n";
|
||||
if (Settings::Get('system.apache24') == '1') {
|
||||
$this->virtualhosts_data[$vhosts_filename] .= ' Require all denied' . "\n";
|
||||
} else {
|
||||
$this->virtualhosts_data[$vhosts_filename] .= ' Order deny,allow' . "\n";
|
||||
$this->virtualhosts_data[$vhosts_filename] .= ' deny from all' . "\n";
|
||||
}
|
||||
$this->virtualhosts_data[$vhosts_filename] .= ' </Directory>' . "\n";
|
||||
|
||||
// create fcgid <Directory>-Part (starter is created in apache_fcgid)
|
||||
if (Settings::Get('system.mod_fcgid_ownvhost') == '1' && Settings::Get('system.mod_fcgid') == '1') {
|
||||
$configdir = FileDir::makeCorrectDir(Settings::Get('system.mod_fcgid_configdir') . '/froxlor.panel/' . Settings::Get('system.hostname'));
|
||||
@@ -1438,8 +1454,6 @@ class Apache extends HttpConfigBase
|
||||
|
||||
// Write a single file for every vhost
|
||||
foreach ($this->virtualhosts_data as $vhosts_filename => $vhosts_file) {
|
||||
$this->known_vhostfilenames[] = basename($vhosts_filename);
|
||||
|
||||
// Apply header
|
||||
$vhosts_file = '# ' . basename($vhosts_filename) . "\n" . '# Created ' . date('d.m.Y H:i') . "\n" . '# Do NOT manually edit this file, all changes will be deleted after the next domain change at the panel.' . "\n" . "\n" . $vhosts_file;
|
||||
$vhosts_file_handler = fopen($vhosts_filename, 'w');
|
||||
|
||||
@@ -65,10 +65,10 @@ class AcmeSh extends FroxlorCron
|
||||
/**
|
||||
* run the task
|
||||
*
|
||||
* @param boolean $internal
|
||||
* @param bool $internal
|
||||
* @return number
|
||||
*/
|
||||
public static function run($internal = false)
|
||||
public static function run(bool $internal = false)
|
||||
{
|
||||
// usually, this is action is called from within the tasks-jobs
|
||||
if (!defined('CRON_IS_FORCED') && !defined('CRON_DEBUG_FLAG') && $internal == false) {
|
||||
@@ -201,6 +201,7 @@ class AcmeSh extends FroxlorCron
|
||||
} else {
|
||||
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "No new certificates or certificate updates found");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,6 +29,7 @@ use Froxlor\Cron\Http\Php\PhpInterface;
|
||||
use Froxlor\Customer\Customer;
|
||||
use Froxlor\Database\Database;
|
||||
use Froxlor\Domain\Domain;
|
||||
use Froxlor\Froxlor;
|
||||
use Froxlor\FileDir;
|
||||
use Froxlor\FroxlorLogger;
|
||||
use Froxlor\Http\Directory;
|
||||
@@ -36,14 +37,9 @@ use Froxlor\Http\Statistics;
|
||||
use Froxlor\Settings;
|
||||
use Froxlor\Validate\Validate;
|
||||
use Froxlor\System\Crypt;
|
||||
use Froxlor\Idna\IdnaWrapper;
|
||||
use PDO;
|
||||
|
||||
/**
|
||||
* @author Florian Lippert <flo@syscp.org> (2003-2009)
|
||||
* @author Froxlor team <team@froxlor.org> (2010-)
|
||||
*
|
||||
* @todo ssl-redirect to non-standard port
|
||||
*/
|
||||
class Lighttpd extends HttpConfigBase
|
||||
{
|
||||
|
||||
@@ -81,7 +77,7 @@ class Lighttpd extends HttpConfigBase
|
||||
$ipv6 = '';
|
||||
}
|
||||
|
||||
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'lighttpd::createIpPort: creating ip/port settings for ' . $ip . ":" . $port);
|
||||
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'lighttpd::createIpPort: creating ip/port settings for ' . $ip . ":" . $port);
|
||||
$vhost_filename = FileDir::makeCorrectFile(Settings::Get('system.apacheconf_vhost') . '/10_froxlor_ipandport_' . trim(str_replace(':', '.', $row_ipsandports['ip']), '.') . '.' . $row_ipsandports['port'] . '.conf');
|
||||
|
||||
if (!isset($this->lighttpd_data[$vhost_filename])) {
|
||||
@@ -125,6 +121,15 @@ class Lighttpd extends HttpConfigBase
|
||||
}
|
||||
|
||||
if (!$is_redirect) {
|
||||
// protect lib/userdata.inc.php
|
||||
$this->lighttpd_data[$vhost_filename] .= ' $HTTP["host"] =~ "' . rtrim(Froxlor::getInstallDir(), "/") . '/lib" {' . "\n";
|
||||
$this->lighttpd_data[$vhost_filename] .= ' url.access-deny = ("userdata.inc.php")' . "\n";
|
||||
$this->lighttpd_data[$vhost_filename] .= ' }' . "\n";
|
||||
// protect bin/
|
||||
$this->lighttpd_data[$vhost_filename] .= ' $HTTP["host"] =~ "' . rtrim(Froxlor::getInstallDir(), "/") . '/bin" {' . "\n";
|
||||
$this->lighttpd_data[$vhost_filename] .= ' url.access-deny = ("")' . "\n";
|
||||
$this->lighttpd_data[$vhost_filename] .= ' }' . "\n";
|
||||
|
||||
/**
|
||||
* dirprotection, see #72
|
||||
*
|
||||
@@ -213,7 +218,7 @@ class Lighttpd extends HttpConfigBase
|
||||
if (($row_ipsandports['ssl_cert_file'] == '' || !file_exists($row_ipsandports['ssl_cert_file'])) && (Settings::Get('system.le_froxlor_enabled') == '0' || $this->froxlorVhostHasLetsEncryptCert() == false)) {
|
||||
$row_ipsandports['ssl_cert_file'] = Settings::Get('system.ssl_cert_file');
|
||||
if (!file_exists($row_ipsandports['ssl_cert_file'])) {
|
||||
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate file "' . Settings::Get('system.ssl_cert_file') . '" does not seem to exist. Creating self-signed certificate...');
|
||||
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate file "' . Settings::Get('system.ssl_cert_file') . '" does not seem to exist. Creating self-signed certificate...');
|
||||
Crypt::createSelfSignedCertificate();
|
||||
}
|
||||
}
|
||||
@@ -255,7 +260,7 @@ class Lighttpd extends HttpConfigBase
|
||||
if ($domain['ssl_cert_file'] != '') {
|
||||
// check for existence, #1485
|
||||
if (!file_exists($domain['ssl_cert_file'])) {
|
||||
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, $ip . ':' . $port . ' :: certificate file "' . $domain['ssl_cert_file'] . '" does not exist! Cannot create ssl-directives');
|
||||
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, $ip . ':' . $port . ' :: certificate file "' . $domain['ssl_cert_file'] . '" does not exist! Cannot create ssl-directives');
|
||||
echo $ip . ':' . $port . ' :: certificate file "' . $domain['ssl_cert_file'] . '" does not exist! Cannot create SSL-directives' . "\n";
|
||||
} else {
|
||||
$this->lighttpd_data[$vhost_filename] .= 'ssl.engine = "enable"' . "\n";
|
||||
@@ -277,7 +282,7 @@ class Lighttpd extends HttpConfigBase
|
||||
if ($domain['ssl_ca_file'] != '') {
|
||||
// check for existence, #1485
|
||||
if (!file_exists($domain['ssl_ca_file'])) {
|
||||
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, $ip . ':' . $port . ' :: certificate CA file "' . $domain['ssl_ca_file'] . '" does not exist! Cannot create ssl-directives');
|
||||
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, $ip . ':' . $port . ' :: certificate CA file "' . $domain['ssl_ca_file'] . '" does not exist! Cannot create ssl-directives');
|
||||
echo $ip . ':' . $port . ' :: certificate CA file "' . $domain['ssl_ca_file'] . '" does not exist! SSL-directives might not be working' . "\n";
|
||||
} else {
|
||||
$this->lighttpd_data[$vhost_filename] .= 'ssl.ca-file = "' . FileDir::makeCorrectFile($domain['ssl_ca_file']) . '"' . "\n";
|
||||
@@ -562,21 +567,19 @@ class Lighttpd extends HttpConfigBase
|
||||
$this->deactivated = true;
|
||||
} else {
|
||||
if ($ssl === false && $domain['ssl_redirect'] == '1') {
|
||||
$redirect_domain = $this->idnaConvert->encode('https://' . $domain['domain']);
|
||||
$webroot_text .= ' url.redirect = (' . "\n";
|
||||
$webroot_text .= "\t" . '"^/(.*)" => "' . $redirect_domain . '/$1",' . "\n";
|
||||
$webroot_text .= "\t" . '"" => "' . $redirect_domain . '",' . "\n";
|
||||
$webroot_text .= "\t" . '"/" => "' . $redirect_domain . '"' . "\n";
|
||||
$webroot_text .= ' )' . "\n";
|
||||
$redirect_domain = (new IdnaWrapper)->encode('https://' . $domain['domain']);
|
||||
} elseif (preg_match("#^https?://#i", $domain['documentroot'])) {
|
||||
$redirect_domain = $this->idnaConvert->encode($domain['documentroot']);
|
||||
$webroot_text .= ' url.redirect = (' . "\n";
|
||||
$webroot_text .= "\t" . '"^/(.*)" => "' . $redirect_domain . '/$1",' . "\n";
|
||||
$webroot_text .= "\t" . '"" => "' . $redirect_domain . '",' . "\n";
|
||||
$webroot_text .= "\t" . '"/" => "' . $redirect_domain . '"' . "\n";
|
||||
$webroot_text .= ' )' . "\n";
|
||||
$redirect_domain = (new IdnaWrapper)->encode($domain['documentroot']);
|
||||
} else {
|
||||
$webroot_text .= ' server.document-root = "' . FileDir::makeCorrectDir($domain['documentroot']) . "\"\n";
|
||||
$redirect_domain = '';
|
||||
}
|
||||
if (!empty($redirect_domain)) {
|
||||
$webroot_text .= ' url.redirect = (' . "\n";
|
||||
$webroot_text .= "\t" . '"^/(.*)" => "' . $redirect_domain . '/$1",' . "\n";
|
||||
$webroot_text .= "\t" . '"" => "' . $redirect_domain . '",' . "\n";
|
||||
$webroot_text .= "\t" . '"/" => "' . $redirect_domain . '"' . "\n";
|
||||
$webroot_text .= ' )' . "\n";
|
||||
}
|
||||
$this->deactivated = false;
|
||||
}
|
||||
@@ -756,7 +759,7 @@ class Lighttpd extends HttpConfigBase
|
||||
if (!file_exists($domain['ssl_cert_file'])) {
|
||||
// explicitly disable ssl for this vhost
|
||||
$domain['ssl_cert_file'] = "";
|
||||
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate file "' . Settings::Get('system.ssl_cert_file') . '" does not seem to exist. Disabling SSL-vhost for "' . $domain['domain'] . '"');
|
||||
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'System certificate file "' . Settings::Get('system.ssl_cert_file') . '" does not seem to exist. Disabling SSL-vhost for "' . $domain['domain'] . '"');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -914,7 +917,7 @@ class Lighttpd extends HttpConfigBase
|
||||
|
||||
public function writeConfigs()
|
||||
{
|
||||
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "lighttpd::writeConfigs: rebuilding " . Settings::Get('system.apacheconf_vhost'));
|
||||
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "lighttpd::writeConfigs: rebuilding " . Settings::Get('system.apacheconf_vhost'));
|
||||
|
||||
$vhostDir = new Directory(Settings::Get('system.apacheconf_vhost'));
|
||||
if (!$vhostDir->isConfigDir()) {
|
||||
@@ -941,14 +944,12 @@ class Lighttpd extends HttpConfigBase
|
||||
fclose($vhosts_file_handler);
|
||||
} else {
|
||||
if (!file_exists(Settings::Get('system.apacheconf_vhost'))) {
|
||||
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'lighttpd::writeConfigs: mkdir ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost'))));
|
||||
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'lighttpd::writeConfigs: mkdir ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost'))));
|
||||
FileDir::safe_exec('mkdir ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('system.apacheconf_vhost'))));
|
||||
}
|
||||
|
||||
// Write a single file for every vhost
|
||||
foreach ($this->lighttpd_data as $vhosts_filename => $vhosts_file) {
|
||||
$this->known_filenames[] = basename($vhosts_filename);
|
||||
|
||||
// Apply header
|
||||
$vhosts_file = '# ' . basename($vhosts_filename) . "\n" . '# Created ' . date('d.m.Y H:i') . "\n" . '# Do NOT manually edit this file, all changes will be deleted after the next domain change at the panel.' . "\n" . "\n" . $vhosts_file;
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ use Froxlor\Cron\Http\Php\PhpInterface;
|
||||
use Froxlor\Customer\Customer;
|
||||
use Froxlor\Database\Database;
|
||||
use Froxlor\Domain\Domain;
|
||||
use Froxlor\Froxlor;
|
||||
use Froxlor\FileDir;
|
||||
use Froxlor\FroxlorLogger;
|
||||
use Froxlor\Http\Directory;
|
||||
@@ -50,8 +51,7 @@ class Nginx extends HttpConfigBase
|
||||
protected $known_htpasswdsfilenames = [];
|
||||
protected $mod_accesslog_loaded = '0';
|
||||
protected $vhost_root_autoindex = false;
|
||||
protected $known_vhostfilenames = [];
|
||||
private $nginx_server = [];
|
||||
|
||||
/**
|
||||
* indicator whether a customer is deactivated or not
|
||||
* if yes, only the webroot will be generated
|
||||
@@ -60,11 +60,6 @@ class Nginx extends HttpConfigBase
|
||||
*/
|
||||
private $deactivated = false;
|
||||
|
||||
public function __construct($nginx_server = [])
|
||||
{
|
||||
$this->nginx_server = $nginx_server;
|
||||
}
|
||||
|
||||
public function createVirtualHosts()
|
||||
{
|
||||
return;
|
||||
@@ -218,15 +213,25 @@ class Nginx extends HttpConfigBase
|
||||
$this->nginx_data[$vhost_filename] .= "\t" . 'index index.php index.html index.htm;' . "\n\n";
|
||||
$this->nginx_data[$vhost_filename] .= "\t" . 'location / {' . "\n";
|
||||
$this->nginx_data[$vhost_filename] .= "\t" . '}' . "\n";
|
||||
|
||||
// protect lib/userdata.inc.php
|
||||
$this->nginx_data[$vhost_filename] .= "\t" . 'location = ' . rtrim(Froxlor::getInstallDir(), "/") . '/lib/userdata.inc.php {' . "\n";
|
||||
$this->nginx_data[$vhost_filename] .= "\t" . ' deny all;' . "\n";
|
||||
$this->nginx_data[$vhost_filename] .= "\t" . '}' . "\n";
|
||||
|
||||
// protect bin/
|
||||
$this->nginx_data[$vhost_filename] .= "\t" . 'location = ' . rtrim(Froxlor::getInstallDir(), "/") . '/bin {' . "\n";
|
||||
$this->nginx_data[$vhost_filename] .= "\t" . ' deny all;' . "\n";
|
||||
$this->nginx_data[$vhost_filename] .= "\t" . '}' . "\n";
|
||||
}
|
||||
|
||||
if ($row_ipsandports['specialsettings'] != '' && ($row_ipsandports['ssl'] == '0' || ($row_ipsandports['ssl'] == '1' && Settings::Get('system.use_ssl') == '1' && $row_ipsandports['include_specialsettings'] == '1'))) {
|
||||
$this->nginx_data[$vhost_filename] .= $this->processSpecialConfigTemplate($row_ipsandports['specialsettings'], [
|
||||
'domain' => Settings::Get('system.hostname'),
|
||||
'loginname' => Settings::Get('phpfpm.vhost_httpuser'),
|
||||
'documentroot' => $mypath,
|
||||
'customerroot' => $mypath
|
||||
], $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n";
|
||||
'domain' => Settings::Get('system.hostname'),
|
||||
'loginname' => Settings::Get('phpfpm.vhost_httpuser'),
|
||||
'documentroot' => $mypath,
|
||||
'customerroot' => $mypath
|
||||
], $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -239,11 +244,11 @@ class Nginx extends HttpConfigBase
|
||||
$this->nginx_data[$vhost_filename] .= $this->composeSslSettings($row_ipsandports);
|
||||
if ($row_ipsandports['ssl_specialsettings'] != '') {
|
||||
$this->nginx_data[$vhost_filename] .= $this->processSpecialConfigTemplate($row_ipsandports['ssl_specialsettings'], [
|
||||
'domain' => Settings::Get('system.hostname'),
|
||||
'loginname' => Settings::Get('phpfpm.vhost_httpuser'),
|
||||
'documentroot' => $mypath,
|
||||
'customerroot' => $mypath
|
||||
], $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n";
|
||||
'domain' => Settings::Get('system.hostname'),
|
||||
'loginname' => Settings::Get('phpfpm.vhost_httpuser'),
|
||||
'documentroot' => $mypath,
|
||||
'customerroot' => $mypath
|
||||
], $row_ipsandports['ip'], $row_ipsandports['port'], $row_ipsandports['ssl'] == '1') . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1242,8 +1247,6 @@ class Nginx extends HttpConfigBase
|
||||
|
||||
// Write a single file for every vhost
|
||||
foreach ($this->nginx_data as $vhosts_filename => $vhosts_file) {
|
||||
$this->known_filenames[] = basename($vhosts_filename);
|
||||
|
||||
// Apply header
|
||||
$vhosts_file = '# ' . basename($vhosts_filename) . "\n" . '# Created ' . date('d.m.Y H:i') . "\n" . '# Do NOT manually edit this file, all changes will be deleted after the next domain change at the panel.' . "\n" . "\n" . $vhosts_file;
|
||||
|
||||
|
||||
@@ -46,11 +46,11 @@ class PhpInterface
|
||||
private $interface = null;
|
||||
|
||||
/**
|
||||
* Admin-User data array
|
||||
* PHP-Config data array
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $admin_cache = [];
|
||||
private $php_configs_cache = [];
|
||||
|
||||
/**
|
||||
* main constructor
|
||||
@@ -93,10 +93,8 @@ class PhpInterface
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPhpConfig($php_config_id)
|
||||
public function getPhpConfig(int $php_config_id)
|
||||
{
|
||||
$php_config_id = intval($php_config_id);
|
||||
|
||||
// If domain has no config, we will use the default one.
|
||||
if ($php_config_id == 0) {
|
||||
$php_config_id = 1;
|
||||
@@ -104,24 +102,26 @@ class PhpInterface
|
||||
|
||||
if (!isset($this->php_configs_cache[$php_config_id])) {
|
||||
$stmt = Database::prepare("
|
||||
SELECT * FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `id` = :id");
|
||||
$this->_php_configs_cache[$php_config_id] = Database::pexecute_first($stmt, [
|
||||
SELECT * FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `id` = :id
|
||||
");
|
||||
$this->php_configs_cache[$php_config_id] = Database::pexecute_first($stmt, [
|
||||
'id' => $php_config_id
|
||||
]);
|
||||
if ((int)Settings::Get('phpfpm.enabled') == 1) {
|
||||
$stmt = Database::prepare("
|
||||
SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "` WHERE `id` = :id");
|
||||
$this->_php_configs_cache[$php_config_id]['fpm_settings'] = Database::pexecute_first($stmt, [
|
||||
'id' => $this->_php_configs_cache[$php_config_id]['fpmsettingid']
|
||||
SELECT * FROM `" . TABLE_PANEL_FPMDAEMONS . "` WHERE `id` = :id
|
||||
");
|
||||
$this->php_configs_cache[$php_config_id]['fpm_settings'] = Database::pexecute_first($stmt, [
|
||||
'id' => $this->php_configs_cache[$php_config_id]['fpmsettingid']
|
||||
]);
|
||||
// override fpm daemon settings if set in php-config
|
||||
if ($this->_php_configs_cache[$php_config_id]['override_fpmconfig'] == 1) {
|
||||
$this->_php_configs_cache[$php_config_id]['fpm_settings']['limit_extensions'] = $this->_php_configs_cache[$php_config_id]['limit_extensions'];
|
||||
$this->_php_configs_cache[$php_config_id]['fpm_settings']['idle_timeout'] = $this->_php_configs_cache[$php_config_id]['idle_timeout'];
|
||||
if ($this->php_configs_cache[$php_config_id]['override_fpmconfig'] == 1) {
|
||||
$this->php_configs_cache[$php_config_id]['fpm_settings']['limit_extensions'] = $this->php_configs_cache[$php_config_id]['limit_extensions'];
|
||||
$this->php_configs_cache[$php_config_id]['fpm_settings']['idle_timeout'] = $this->php_configs_cache[$php_config_id]['idle_timeout'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_php_configs_cache[$php_config_id];
|
||||
return $this->php_configs_cache[$php_config_id];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,392 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2010 the Froxlor Team (see authors).
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you can also view it online at
|
||||
* https://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright the authors
|
||||
* @author Froxlor team <team@froxlor.org>
|
||||
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
||||
*/
|
||||
|
||||
namespace Froxlor\Cron;
|
||||
|
||||
use Exception;
|
||||
use Froxlor\Cron\System\Extrausers;
|
||||
use Froxlor\Database\Database;
|
||||
use Froxlor\FileDir;
|
||||
use Froxlor\Froxlor;
|
||||
use Froxlor\FroxlorLogger;
|
||||
use Froxlor\Settings;
|
||||
use Froxlor\System\Cronjob;
|
||||
use PDO;
|
||||
|
||||
class MasterCron extends FroxlorCron
|
||||
{
|
||||
|
||||
private static $argv = null;
|
||||
|
||||
private static $debugHandler = null;
|
||||
|
||||
private static $noncron_params = [
|
||||
'force',
|
||||
'debug',
|
||||
'no-fork',
|
||||
'run-task'
|
||||
];
|
||||
|
||||
public static function setArguments($argv = null)
|
||||
{
|
||||
self::$argv = $argv;
|
||||
}
|
||||
|
||||
public static function run()
|
||||
{
|
||||
self::init();
|
||||
|
||||
$jobs_to_run = [];
|
||||
|
||||
$argv = self::$argv;
|
||||
/**
|
||||
* check for --help
|
||||
*/
|
||||
if (count($argv) < 2 || (isset($argv[1]) && strtolower($argv[1]) == '--help')) {
|
||||
echo "\n*** Froxlor Master Cronjob ***\n\n";
|
||||
echo "Below are possible parameters for this file\n\n";
|
||||
echo "--[cronname]\t\tincludes the given cron-file\n";
|
||||
echo "--force\t\t\tforces re-generating of config-files (webserver, nameserver, etc.)\n";
|
||||
echo "--run-task\t\trun a specific task [1 = re-generate configs, 4 = re-generate dns zones, 10 = re-set quotas, 99 = re-create cron.d-file]\n";
|
||||
echo "--debug\t\t\toutput debug information about what is going on to STDOUT.\n";
|
||||
echo "--no-fork\t\tdo not fork to backkground (traffic cron only).\n\n";
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* check for parameters
|
||||
*
|
||||
* --[cronname] include [cronname]
|
||||
* --force to include cron_tasks even if it's not its turn
|
||||
* --debug to output debug information
|
||||
*/
|
||||
for ($x = 1; $x < count($argv); $x++) {
|
||||
// check argument
|
||||
if (isset($argv[$x])) {
|
||||
// --force
|
||||
if (strtolower($argv[$x]) == '--force') {
|
||||
// really force re-generating of config-files by
|
||||
// inserting task 1
|
||||
Cronjob::inserttask(TaskId::REBUILD_VHOST);
|
||||
// bind (if enabled, \Froxlor\System\Cronjob::inserttask() checks this)
|
||||
Cronjob::inserttask(TaskId::REBUILD_DNS);
|
||||
// set quotas (if enabled)
|
||||
Cronjob::inserttask(TaskId::CREATE_QUOTA);
|
||||
// also regenerate cron.d-file
|
||||
Cronjob::inserttask(TaskId::REBUILD_CRON);
|
||||
array_push($jobs_to_run, 'tasks');
|
||||
define('CRON_IS_FORCED', 1);
|
||||
} elseif (strtolower($argv[$x]) == '--debug') {
|
||||
define('CRON_DEBUG_FLAG', 1);
|
||||
} elseif (strtolower($argv[$x]) == '--no-fork') {
|
||||
define('CRON_NOFORK_FLAG', 1);
|
||||
} elseif (strtolower($argv[$x]) == '--run-task') {
|
||||
if (isset($argv[$x + 1]) && in_array($argv[$x + 1], [1, 4, 10, 99])) {
|
||||
Cronjob::inserttask($argv[$x + 1]);
|
||||
array_push($jobs_to_run, 'tasks');
|
||||
} else {
|
||||
echo "Invalid argument for --run-task\n";
|
||||
exit;
|
||||
}
|
||||
} elseif (substr(strtolower($argv[$x]), 0, 2) == '--') {
|
||||
// --[cronname]
|
||||
if (strlen($argv[$x]) > 3) {
|
||||
$cronname = substr(strtolower($argv[$x]), 2);
|
||||
array_push($jobs_to_run, $cronname);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$jobs_to_run = array_unique($jobs_to_run);
|
||||
|
||||
self::$cronlog->setCronDebugFlag(defined('CRON_DEBUG_FLAG'));
|
||||
|
||||
$tasks_cnt_stmt = Database::query("SELECT COUNT(*) as jobcnt FROM `panel_tasks`");
|
||||
$tasks_cnt = $tasks_cnt_stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
// do we have anything to include?
|
||||
if (count($jobs_to_run) > 0) {
|
||||
// include all jobs we want to execute
|
||||
foreach ($jobs_to_run as $cron) {
|
||||
Cronjob::updateLastRunOfCron($cron);
|
||||
$cronfile = self::getCronModule($cron);
|
||||
if ($cronfile && class_exists($cronfile)) {
|
||||
$cronfile::run();
|
||||
}
|
||||
}
|
||||
self::refreshUsers($tasks_cnt['jobcnt']);
|
||||
}
|
||||
|
||||
/**
|
||||
* we have to check the system's last guid with every cron run
|
||||
* in case the admin installed new software which added a new user
|
||||
* so users in the database don't conflict with system users
|
||||
*/
|
||||
self::$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Checking system\'s last guid');
|
||||
Cronjob::checkLastGuid();
|
||||
|
||||
// shutdown cron
|
||||
self::shutdown();
|
||||
}
|
||||
|
||||
private static function init()
|
||||
{
|
||||
if (@php_sapi_name() != 'cli' && @php_sapi_name() != 'cgi' && @php_sapi_name() != 'cgi-fcgi') {
|
||||
die('This script will only work in the shell.');
|
||||
}
|
||||
|
||||
// ensure that default timezone is set
|
||||
if (function_exists("date_default_timezone_set") && function_exists("date_default_timezone_get")) {
|
||||
@date_default_timezone_set(@date_default_timezone_get());
|
||||
}
|
||||
|
||||
$basename = basename($_SERVER['PHP_SELF'], '.php');
|
||||
$crontype = "";
|
||||
if (isset(self::$argv) && is_array(self::$argv) && count(self::$argv) > 1) {
|
||||
for ($x = 1; $x < count(self::$argv); $x++) {
|
||||
if (substr(self::$argv[$x], 0, 2) == '--' && strlen(self::$argv[$x]) > 3 && !in_array(substr(strtolower(self::$argv[$x]), 2), self::$noncron_params)) {
|
||||
$crontype = substr(strtolower(self::$argv[$x]), 2);
|
||||
$basename .= "-" . $crontype;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$lockdir = '/var/run/';
|
||||
$lockFilename = 'froxlor_' . $basename . '.lock-';
|
||||
$lockfName = $lockFilename . getmypid();
|
||||
$lockfile = $lockdir . $lockfName;
|
||||
self::setLockfile($lockfile);
|
||||
|
||||
// create and open the lockfile!
|
||||
self::$debugHandler = fopen($lockfile, 'w');
|
||||
fwrite(self::$debugHandler, 'Setting Lockfile to ' . $lockfile . "\n");
|
||||
fwrite(self::$debugHandler, 'Setting Froxlor installation path to ' . Froxlor::getInstallDir() . "\n");
|
||||
|
||||
if (!file_exists(Froxlor::getInstallDir() . '/lib/userdata.inc.php')) {
|
||||
die("Froxlor does not seem to be installed yet - skipping cronjob");
|
||||
}
|
||||
|
||||
$sql = [];
|
||||
$sql_root = [];
|
||||
// Includes the Usersettings eg. MySQL-Username/Passwort etc.
|
||||
require Froxlor::getInstallDir() . '/lib/userdata.inc.php';
|
||||
fwrite(self::$debugHandler, 'Userdatas included' . "\n");
|
||||
|
||||
// Legacy sql-root-information
|
||||
if (isset($sql['root_user']) && isset($sql['root_password']) && (!isset($sql_root) || !is_array($sql_root))) {
|
||||
$sql_root = [
|
||||
0 => [
|
||||
'caption' => 'Default',
|
||||
'host' => $sql['host'],
|
||||
'user' => $sql['root_user'],
|
||||
'password' => $sql['root_password']
|
||||
]
|
||||
];
|
||||
unset($sql['root_user']);
|
||||
unset($sql['root_password']);
|
||||
}
|
||||
|
||||
require Froxlor::getInstallDir() . '/lib/functions.php';
|
||||
// Includes the MySQL-Tabledefinitions etc.
|
||||
require Froxlor::getInstallDir() . '/lib/tables.inc.php';
|
||||
fwrite(self::$debugHandler, 'Table definitions included' . "\n");
|
||||
|
||||
// try database connection, it will throw
|
||||
// and exception itself if failed
|
||||
try {
|
||||
Database::query("SELECT 1");
|
||||
} catch (Exception $e) {
|
||||
// Do not proceed further if no database connection could be established
|
||||
fclose(self::$debugHandler);
|
||||
unlink($lockfile);
|
||||
die($e->getMessage());
|
||||
}
|
||||
|
||||
fwrite(self::$debugHandler, 'Database-connection established' . "\n");
|
||||
|
||||
// open the lockfile directory and scan for existing lockfiles
|
||||
$lockDirHandle = opendir($lockdir);
|
||||
|
||||
while ($fName = readdir($lockDirHandle)) {
|
||||
if ($lockFilename == substr($fName, 0, strlen($lockFilename)) && $lockfName != $fName) {
|
||||
// Check if last run jailed out with an exception
|
||||
$croncontent = file($lockdir . $fName);
|
||||
$lastline = $croncontent[(count($croncontent) - 1)];
|
||||
|
||||
if ($lastline == '=== Keep lockfile because of exception ===') {
|
||||
fclose(self::$debugHandler);
|
||||
unlink($lockfile);
|
||||
Cronjob::dieWithMail('Last cron jailed out with an exception. Exiting...' . "\n" . 'Take a look into the contents of ' . $lockdir . $fName . '* for more information!' . "\n");
|
||||
}
|
||||
|
||||
// Check if cron is running or has died.
|
||||
$check_pid = substr(strrchr($fName, "-"), 1);
|
||||
$check_pid_return = null;
|
||||
system("kill -CHLD " . (int)$check_pid . " 1> /dev/null 2> /dev/null", $check_pid_return);
|
||||
|
||||
if ($check_pid_return == 1) {
|
||||
// Result: Existing lockfile/pid isn't running
|
||||
// Most likely it has died
|
||||
//
|
||||
// Action: Remove it and continue
|
||||
//
|
||||
fwrite(self::$debugHandler, 'Previous cronjob didn\'t exit clean. PID: ' . $check_pid . "\n");
|
||||
fwrite(self::$debugHandler, 'Removing lockfile: ' . $lockdir . $fName . "\n");
|
||||
@unlink($lockdir . $fName);
|
||||
} else {
|
||||
// Result: A Cronscript with this pid
|
||||
// is still running
|
||||
// Action: remove my own Lock and die
|
||||
//
|
||||
// close the current lockfile
|
||||
fclose(self::$debugHandler);
|
||||
|
||||
// ... and delete it
|
||||
unlink($lockfile);
|
||||
Cronjob::dieWithMail('There is already a Cronjob for ' . $crontype . ' in progress. Exiting...' . "\n" . 'Take a look into the contents of ' . $lockdir . $lockFilename . '* for more information!' . "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* if using fcgid or fpm for froxlor-vhost itself, we have to check
|
||||
* whether the permission of the files are still correct
|
||||
*/
|
||||
fwrite(self::$debugHandler, 'Checking froxlor file permissions' . "\n");
|
||||
$_mypath = FileDir::makeCorrectDir(Froxlor::getInstallDir());
|
||||
|
||||
if (((int)Settings::Get('system.mod_fcgid') == 1 && (int)Settings::Get('system.mod_fcgid_ownvhost') == 1) || ((int)Settings::Get('phpfpm.enabled') == 1 && (int)Settings::Get('phpfpm.enabled_ownvhost') == 1)) {
|
||||
$user = Settings::Get('system.mod_fcgid_httpuser');
|
||||
$group = Settings::Get('system.mod_fcgid_httpgroup');
|
||||
|
||||
if (Settings::Get('phpfpm.enabled') == 1) {
|
||||
$user = Settings::Get('phpfpm.vhost_httpuser');
|
||||
$group = Settings::Get('phpfpm.vhost_httpgroup');
|
||||
}
|
||||
// all the files and folders have to belong to the local user
|
||||
// now because we also use fcgid for our own vhost
|
||||
FileDir::safe_exec('chown -R ' . $user . ':' . $group . ' ' . escapeshellarg($_mypath));
|
||||
} else {
|
||||
// back to webserver permission
|
||||
$user = Settings::Get('system.httpuser');
|
||||
$group = Settings::Get('system.httpgroup');
|
||||
FileDir::safe_exec('chown -R ' . $user . ':' . $group . ' ' . escapeshellarg($_mypath));
|
||||
}
|
||||
|
||||
// Initialize logging
|
||||
self::$cronlog = FroxlorLogger::getInstanceOf([
|
||||
'loginname' => 'cronjob'
|
||||
]);
|
||||
fwrite(self::$debugHandler, 'Logger has been included' . "\n");
|
||||
|
||||
if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) {
|
||||
if (Settings::Get('system.cron_allowautoupdate') == null || Settings::Get('system.cron_allowautoupdate') == 0) {
|
||||
/**
|
||||
* Do not proceed further if the Database version is not the same as the script version
|
||||
*/
|
||||
fclose(self::$debugHandler);
|
||||
unlink($lockfile);
|
||||
$errormessage = "Version of file doesn't match version of database. Exiting...\n\n";
|
||||
$errormessage .= "Possible reason: Froxlor update\n";
|
||||
$errormessage .= "Information: Current version in database: " . Settings::Get('panel.version') . (!empty(Froxlor::BRANDING) ? "-" . Froxlor::BRANDING : "") . " (DB: " . Settings::Get('panel.db_version') . ") - version of Froxlor files: " . Froxlor::getVersionString() . ")\n";
|
||||
$errormessage .= "Solution: Please visit your Foxlor admin interface for further information.\n";
|
||||
Cronjob::dieWithMail($errormessage);
|
||||
}
|
||||
|
||||
if (Settings::Get('system.cron_allowautoupdate') == 1) {
|
||||
/**
|
||||
* let's walk the walk - do the dangerous shit
|
||||
*/
|
||||
self::$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, 'Automatic update is activated and we are going to proceed without any notices');
|
||||
self::$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, 'all new settings etc. will be stored with the default value, that might not always be right for your system!');
|
||||
self::$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "If you don't want this to happen in the future consider removing the --allow-autoupdate flag from the cronjob");
|
||||
fwrite(self::$debugHandler, '*** WARNING *** - Automatic update is activated and we are going to proceed without any notices' . "\n");
|
||||
fwrite(self::$debugHandler, '*** WARNING *** - all new settings etc. will be stored with the default value, that might not always be right for your system!' . "\n");
|
||||
fwrite(self::$debugHandler, "*** WARNING *** - If you don't want this to happen in the future consider removing the --allow-autoupdate flag from the cronjob\n");
|
||||
// including update procedures
|
||||
define('_CRON_UPDATE', 1);
|
||||
include_once Froxlor::getInstallDir() . '/install/updatesql.php';
|
||||
// pew - everything went better than expected
|
||||
self::$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, 'Automatic update done - you should check your settings to be sure everything is fine');
|
||||
fwrite(self::$debugHandler, '*** WARNING *** - Automatic update done - you should check your settings to be sure everything is fine' . "\n");
|
||||
}
|
||||
}
|
||||
|
||||
fwrite(self::$debugHandler, 'Froxlor version and database version are correct' . "\n");
|
||||
}
|
||||
|
||||
private static function getCronModule($cronname)
|
||||
{
|
||||
$upd_stmt = Database::prepare("
|
||||
SELECT `cronclass` FROM `" . TABLE_PANEL_CRONRUNS . "` WHERE `cronfile` = :cron;
|
||||
");
|
||||
$cron = Database::pexecute_first($upd_stmt, [
|
||||
'cron' => $cronname
|
||||
]);
|
||||
if ($cron) {
|
||||
return $cron['cronclass'];
|
||||
}
|
||||
self::$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Requested cronjob '" . $cronname . "' could not be found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
private static function refreshUsers($jobcount = 0)
|
||||
{
|
||||
if ($jobcount > 0) {
|
||||
if (Settings::Get('system.nssextrausers') == 1) {
|
||||
Extrausers::generateFiles(self::$cronlog);
|
||||
}
|
||||
|
||||
// clear NSCD cache if using fcgid or fpm, #1570 - not needed for nss-extrausers
|
||||
if ((Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) && Settings::Get('system.nssextrausers') == 0) {
|
||||
$false_val = false;
|
||||
FileDir::safe_exec('nscd -i passwd 1> /dev/null', $false_val, [
|
||||
'>'
|
||||
]);
|
||||
FileDir::safe_exec('nscd -i group 1> /dev/null', $false_val, [
|
||||
'>'
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function shutdown()
|
||||
{
|
||||
// check for cron.d-generation task and create it if necessary
|
||||
CronConfig::checkCrondConfigurationFile();
|
||||
|
||||
if (Settings::Get('logger.log_cron') == '1') {
|
||||
FroxlorLogger::getInstanceOf()->setCronLog(0);
|
||||
fwrite(self::$debugHandler, 'Logging for cron has been shutdown' . "\n");
|
||||
}
|
||||
|
||||
fclose(self::$debugHandler);
|
||||
|
||||
if (Settings::Get('system.debug_cron') != '1') {
|
||||
unlink(self::getLockfile());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ namespace Froxlor\Cron\System;
|
||||
|
||||
use Froxlor\Cron\FroxlorCron;
|
||||
use Froxlor\Cron\Http\ConfigIO;
|
||||
use Froxlor\Cron\Http\HttpConfigBase;
|
||||
use Froxlor\Cron\TaskId;
|
||||
use Froxlor\Database\Database;
|
||||
use Froxlor\Dns\PowerDNS;
|
||||
@@ -158,7 +159,7 @@ class TasksCron extends FroxlorCron
|
||||
// get webserver object
|
||||
$webserver = new $websrv();
|
||||
|
||||
if (isset($webserver)) {
|
||||
if ($webserver instanceof HttpConfigBase) {
|
||||
$webserver->init();
|
||||
// clean up old configs
|
||||
$configio->cleanUp();
|
||||
|
||||
@@ -45,6 +45,7 @@ use PDOStatement;
|
||||
* object
|
||||
* @method static string lastInsertId ($name = null) Returns the ID of the last inserted row or sequence value
|
||||
* @method static string quote ($string, $parameter_type = null) Quotes a string for use in a query.
|
||||
* @method static mixed getAttribute(int $attribute) Retrieve a database connection attribute
|
||||
*/
|
||||
class Database
|
||||
{
|
||||
@@ -127,11 +128,14 @@ class Database
|
||||
{
|
||||
global $userinfo, $theme, $linker;
|
||||
|
||||
$sql = [];
|
||||
$sql_root = [];
|
||||
|
||||
// include userdata.inc.php
|
||||
require Froxlor::getInstallDir() . "/lib/userdata.inc.php";
|
||||
|
||||
// le format
|
||||
if (isset($sql['root_user']) && isset($sql['root_password']) && (!isset($sql_root) || !is_array($sql_root))) {
|
||||
if (isset($sql['root_user']) && isset($sql['root_password']) && !is_array($sql_root)) {
|
||||
$sql_root = [
|
||||
0 => [
|
||||
'caption' => 'Default',
|
||||
@@ -291,13 +295,13 @@ class Database
|
||||
*/
|
||||
private static function genUniqueToken(int $length = 16)
|
||||
{
|
||||
if (!isset($length) || intval($length) <= 8) {
|
||||
if (intval($length) <= 8) {
|
||||
$length = 16;
|
||||
}
|
||||
if (function_exists('random_bytes')) {
|
||||
return bin2hex(random_bytes($length));
|
||||
}
|
||||
if (function_exists('mcrypt_create_iv')) {
|
||||
if (function_exists('mcrypt_create_iv') && defined('MCRYPT_DEV_URANDOM')) {
|
||||
return bin2hex(mcrypt_create_iv($length, MCRYPT_DEV_URANDOM));
|
||||
}
|
||||
if (function_exists('openssl_random_pseudo_bytes')) {
|
||||
|
||||
@@ -26,12 +26,10 @@
|
||||
namespace Froxlor;
|
||||
|
||||
use Exception;
|
||||
use Froxlor\Customer\Customer;
|
||||
use Froxlor\Database\Database;
|
||||
use PDO;
|
||||
use RecursiveCallbackFilterIterator;
|
||||
use RecursiveDirectoryIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use Froxlor\Customer\Customer;
|
||||
use Froxlor\Database\Database;
|
||||
|
||||
class FileDir
|
||||
{
|
||||
@@ -315,9 +313,9 @@ class FileDir
|
||||
*
|
||||
* @return string the corrected filename
|
||||
*/
|
||||
public static function makeCorrectFile($filename)
|
||||
public static function makeCorrectFile(string $filename)
|
||||
{
|
||||
if (!isset($filename) || trim($filename) == '') {
|
||||
if (trim($filename) == '') {
|
||||
$error = 'Given filename for function ' . __FUNCTION__ . ' is empty.' . "\n";
|
||||
$error .= 'This is very dangerous and should not happen.' . "\n";
|
||||
$error .= 'Please inform the Froxlor team about this issue so they can fix it.';
|
||||
@@ -527,7 +525,7 @@ class FileDir
|
||||
new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS),
|
||||
$filter
|
||||
),
|
||||
\RecursiveIteratorIterator::LEAVES_ONLY,
|
||||
\RecursiveIteratorIterator::SELF_FIRST,
|
||||
\RecursiveIteratorIterator::CATCH_GET_CHILD
|
||||
);
|
||||
// we can limit the recursion-depth, but will it be helpful or
|
||||
@@ -550,26 +548,24 @@ class FileDir
|
||||
/**
|
||||
* set the immutable flag for a file
|
||||
*
|
||||
* @param string $filename
|
||||
* the file to set the flag for
|
||||
* @param string $filename the file to set the flag for
|
||||
*
|
||||
* @return boolean
|
||||
* @return void
|
||||
*/
|
||||
public static function setImmutable($filename = null)
|
||||
public static function setImmutable(string $filename)
|
||||
{
|
||||
FileDir::safe_exec(self::getImmutableFunction(false) . escapeshellarg($filename));
|
||||
self::safe_exec(self::getImmutableFunction(false) . escapeshellarg($filename));
|
||||
}
|
||||
|
||||
/**
|
||||
* internal function to check whether
|
||||
* to use chattr (Linux) or chflags (FreeBSD)
|
||||
*
|
||||
* @param boolean $remove
|
||||
* whether to use +i|schg (false) or -i|noschg (true)
|
||||
* @param bool $remove whether to use +i|schg (false) or -i|noschg (true)
|
||||
*
|
||||
* @return string functionname + parameter (not the file)
|
||||
*/
|
||||
private static function getImmutableFunction($remove = false)
|
||||
private static function getImmutableFunction(bool $remove = false)
|
||||
{
|
||||
if (self::isFreeBSD()) {
|
||||
// FreeBSD style
|
||||
@@ -585,12 +581,11 @@ class FileDir
|
||||
* or BSD-based (NetBSD, OpenBSD, etc.
|
||||
* if exact = false [default])
|
||||
*
|
||||
* @param boolean $exact
|
||||
* whether to check explicitly for FreeBSD or *BSD
|
||||
* @param bool $exact whether to check explicitly for FreeBSD or *BSD
|
||||
*
|
||||
* @return boolean
|
||||
* @return bool
|
||||
*/
|
||||
public static function isFreeBSD($exact = false)
|
||||
public static function isFreeBSD(bool $exact = false)
|
||||
{
|
||||
if (($exact && PHP_OS == 'FreeBSD') || (!$exact && stristr(PHP_OS, 'BSD'))) {
|
||||
return true;
|
||||
@@ -601,16 +596,19 @@ class FileDir
|
||||
/**
|
||||
* removes the immutable flag for a file
|
||||
*
|
||||
* @param string $filename
|
||||
* the file to set the flag for
|
||||
* @param string $filename the file to set the flag for
|
||||
*
|
||||
* @return boolean
|
||||
* @return void
|
||||
*/
|
||||
public static function removeImmutable($filename = null)
|
||||
public static function removeImmutable(string $filename)
|
||||
{
|
||||
FileDir::safe_exec(self::getImmutableFunction(true) . escapeshellarg($filename));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return array|false
|
||||
*/
|
||||
public static function getFilesystemQuota()
|
||||
{
|
||||
// enabled at all?
|
||||
|
||||
@@ -234,13 +234,13 @@ final class Froxlor
|
||||
*/
|
||||
public static function genSessionId(int $length = 16)
|
||||
{
|
||||
if (!isset($length) || intval($length) <= 8) {
|
||||
if (intval($length) <= 8) {
|
||||
$length = 16;
|
||||
}
|
||||
if (function_exists('random_bytes')) {
|
||||
return bin2hex(random_bytes($length));
|
||||
}
|
||||
if (function_exists('mcrypt_create_iv')) {
|
||||
if (function_exists('mcrypt_create_iv') && defined('MCRYPT_DEV_URANDOM')) {
|
||||
return bin2hex(mcrypt_create_iv($length, MCRYPT_DEV_URANDOM));
|
||||
}
|
||||
if (function_exists('openssl_random_pseudo_bytes')) {
|
||||
|
||||
@@ -258,30 +258,28 @@ class FroxlorLogger
|
||||
/**
|
||||
* Set whether to log cron-runs
|
||||
*
|
||||
* @param bool $_cronlog
|
||||
* @param int $cronlog
|
||||
*
|
||||
* @return boolean
|
||||
* @return int
|
||||
*/
|
||||
public function setCronLog($_cronlog = 0)
|
||||
public function setCronLog(int $cronlog = 0)
|
||||
{
|
||||
$_cronlog = (int)$_cronlog;
|
||||
|
||||
if ($_cronlog < 0 || $_cronlog > 2) {
|
||||
$_cronlog = 0;
|
||||
if ($cronlog < 0 || $cronlog > 2) {
|
||||
$cronlog = 0;
|
||||
}
|
||||
Settings::Set('logger.log_cron', $_cronlog);
|
||||
return $_cronlog;
|
||||
Settings::Set('logger.log_cron', $cronlog);
|
||||
return $cronlog;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter for crondebug-flag
|
||||
*
|
||||
* @param bool $_flag
|
||||
* @param bool $flag
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setCronDebugFlag($_flag = false)
|
||||
public function setCronDebugFlag(bool $flag = false)
|
||||
{
|
||||
self::$crondebug_flag = (bool)$_flag;
|
||||
self::$crondebug_flag = $flag;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
namespace Froxlor\Install;
|
||||
|
||||
use Exception;
|
||||
use ZipArchive;
|
||||
use Froxlor\Froxlor;
|
||||
use Froxlor\Settings;
|
||||
use Froxlor\Http\HttpClient;
|
||||
|
||||
@@ -332,7 +332,7 @@ class Install
|
||||
throw new Exception(lng('error.emailiswrong', [$email]));
|
||||
} elseif (empty($password) || $password != $password_confirm) {
|
||||
throw new Exception(lng('error.newpasswordconfirmerror'));
|
||||
} elseif (!empty($password) && $password == $loginname) {
|
||||
} elseif ($password == $loginname) {
|
||||
throw new Exception(lng('error.passwordshouldnotbeusername'));
|
||||
}
|
||||
}
|
||||
@@ -404,8 +404,20 @@ class Install
|
||||
$default = 'bullseye';
|
||||
|
||||
// read os-release
|
||||
if (@file_exists('/etc/os-release')) {
|
||||
$os_dist = parse_ini_file('/etc/os-release', false);
|
||||
if (@file_exists('/etc/os-release') && is_readable('/etc/os-release')) {
|
||||
if (function_exists('parse_ini_file')) {
|
||||
$os_dist = parse_ini_file('/etc/os-release', false);
|
||||
} else {
|
||||
$osrf = explode("\n", file_get_contents('/etc/os-release'));
|
||||
foreach ($osrf as $line) {
|
||||
$osrfline = explode("\n", $line);
|
||||
if ($osrfline[0] == 'VERSION_CODENAME') {
|
||||
$os_dist['VERSION_CODENAME'] = $osrfline[1];
|
||||
} else if ($osrfline[0] == 'ID') {
|
||||
$os_dist['ID'] = $osrfline[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
return strtolower($os_dist['VERSION_CODENAME'] ?? ($os_dist['ID'] ?? $default));
|
||||
}
|
||||
return $default;
|
||||
|
||||
@@ -52,7 +52,7 @@ class Core
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function doInstall()
|
||||
public function doInstall(bool $create_ud_str = true)
|
||||
{
|
||||
$options = [
|
||||
'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8'
|
||||
@@ -116,6 +116,9 @@ class Core
|
||||
$this->doDataEntries($pdo);
|
||||
// create JSON array for config-services
|
||||
$this->createJsonArray();
|
||||
if ($create_ud_str) {
|
||||
$this->createUserdataParamStr();
|
||||
}
|
||||
}
|
||||
|
||||
public function getUnprivilegedPdo(): PDO
|
||||
@@ -675,4 +678,23 @@ class Core
|
||||
];
|
||||
$_SESSION['installation']['json_params'] = json_encode($json_params);
|
||||
}
|
||||
|
||||
private function createUserdataParamStr()
|
||||
{
|
||||
$req_fields = [
|
||||
'mysql_host',
|
||||
'mysql_unprivileged_user',
|
||||
'mysql_unprivileged_pass',
|
||||
'mysql_database',
|
||||
'mysql_root_user',
|
||||
'mysql_root_pass',
|
||||
'mysql_ssl_ca_file',
|
||||
'mysql_ssl_verify_server_certificate'
|
||||
];
|
||||
$json_params = [];
|
||||
foreach ($req_fields as $field) {
|
||||
$json_params[$field] = $this->validatedData[$field] ?? "";
|
||||
}
|
||||
$_SESSION['installation']['ud_str'] = base64_encode(json_encode($json_params));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,9 @@ use Froxlor\Settings;
|
||||
|
||||
class Update
|
||||
{
|
||||
private static $update_tasks = [];
|
||||
|
||||
private static $task_counter = 0;
|
||||
|
||||
/**
|
||||
* Function showUpdateStep
|
||||
@@ -42,20 +45,18 @@ class Update
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function showUpdateStep($task = null, $needs_status = true)
|
||||
public static function showUpdateStep(string $task, bool $needs_status = true)
|
||||
{
|
||||
global $update_tasks, $task_counter;
|
||||
|
||||
set_time_limit(30);
|
||||
|
||||
// output
|
||||
$update_tasks[$task_counter] = ['title' => $task, 'result' => 0];
|
||||
self::$update_tasks[self::$task_counter] = ['title' => $task, 'result' => 0];
|
||||
|
||||
if (!$needs_status) {
|
||||
$task_counter++;
|
||||
self::$task_counter++;
|
||||
}
|
||||
|
||||
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, $task);
|
||||
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::ADM_ACTION, \LOG_WARNING, $task);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,35 +68,33 @@ class Update
|
||||
* @param string $message
|
||||
* @param string $additional_info
|
||||
*
|
||||
* @return string formatted output and log-entry
|
||||
* @return void
|
||||
*/
|
||||
public static function lastStepStatus(int $status = -1, string $message = '', string $additional_info = '')
|
||||
public static function lastStepStatus(int $status = -1, string $message = 'OK', string $additional_info = '')
|
||||
{
|
||||
global $update_tasks, $task_counter;
|
||||
|
||||
$update_tasks[$task_counter]['result_txt'] = $message ?? 'OK';
|
||||
$update_tasks[$task_counter]['result_desc'] = $additional_info ?? '';
|
||||
self::$update_tasks[self::$task_counter]['result_txt'] = $message;
|
||||
self::$update_tasks[self::$task_counter]['result_desc'] = $additional_info;
|
||||
|
||||
switch ($status) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
$update_tasks[$task_counter]['result'] = 2;
|
||||
self::$update_tasks[self::$task_counter]['result'] = 2;
|
||||
break;
|
||||
case 2:
|
||||
$update_tasks[$task_counter]['result'] = 1;
|
||||
self::$update_tasks[self::$task_counter]['result'] = 1;
|
||||
break;
|
||||
default:
|
||||
$update_tasks[$task_counter]['result'] = -1;
|
||||
self::$update_tasks[self::$task_counter]['result'] = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
$task_counter++;
|
||||
self::$task_counter++;
|
||||
|
||||
if ($status == -1 || $status == 2) {
|
||||
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, 'Attention - last update task failed!!!');
|
||||
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::ADM_ACTION, \LOG_WARNING, 'Attention - last update task failed!!!');
|
||||
} elseif ($status == 0 || $status == 1) {
|
||||
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, 'Success');
|
||||
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::ADM_ACTION, \LOG_WARNING, 'Success');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,4 +126,14 @@ class Update
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function getUpdateTasks(): array
|
||||
{
|
||||
return self::$update_tasks;
|
||||
}
|
||||
|
||||
public static function getTaskCounter(): int
|
||||
{
|
||||
return self::$task_counter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,7 +458,7 @@ class PhpHelper
|
||||
'ssl_default_vhostconf_domain',
|
||||
'filecontent'
|
||||
];
|
||||
if (isset($global) && !empty($global)) {
|
||||
if (!empty($global)) {
|
||||
$tmp = $global;
|
||||
foreach ($tmp as $index => $value) {
|
||||
if (!in_array($index, $ignored_fields)) {
|
||||
@@ -516,7 +516,7 @@ class PhpHelper
|
||||
$str .= self::tabPrefix(($depth-1), "[\n");
|
||||
}
|
||||
foreach ($array as $key => $value) {
|
||||
if (isset($key) && !is_array($value)) {
|
||||
if (!is_array($value)) {
|
||||
if (is_bool($value)) {
|
||||
$str .= self::tabPrefix($depth, sprintf("'%s' => %s,\n", $key, $value ? 'true' : 'false'));
|
||||
} elseif (is_int($value)) {
|
||||
|
||||
@@ -34,11 +34,11 @@ class Mailer extends PHPMailer
|
||||
/**
|
||||
* class constructor
|
||||
*
|
||||
* @param string $exceptions
|
||||
* @param bool $exceptions
|
||||
* whether to throw exceptions or not
|
||||
*
|
||||
*/
|
||||
public function __construct($exceptions = false)
|
||||
public function __construct(bool $exceptions = false)
|
||||
{
|
||||
parent::__construct($exceptions);
|
||||
$this->CharSet = "UTF-8";
|
||||
|
||||
@@ -66,6 +66,21 @@ class Style
|
||||
return $attributes['fields']['deactivated'] ? 'bg-info' : $termination_css;
|
||||
}
|
||||
|
||||
public static function resultCustomerLockedOrDeactivated(array $attributes): string
|
||||
{
|
||||
$row_css = '';
|
||||
if ((int)$attributes['fields']['deactivated'] == 1) {
|
||||
$row_css = 'bg-info';
|
||||
} elseif (
|
||||
$attributes['fields']['loginfail_count'] >= Settings::Get('login.maxloginattempts')
|
||||
&& $attributes['fields']['lastlogin_fail'] > (time() - Settings::Get('login.deactivatetime'))
|
||||
) {
|
||||
$row_css = 'bg-warning';
|
||||
}
|
||||
|
||||
return $row_css;
|
||||
}
|
||||
|
||||
public static function diskspaceWarning(array $attributes): string
|
||||
{
|
||||
return self::getWarningStyle('diskspace', $attributes['fields'], (int)Settings::Get('system.report_webmax'));
|
||||
|
||||
@@ -153,7 +153,7 @@ class Linker
|
||||
}
|
||||
|
||||
// Encode parameters and add them to the link
|
||||
$link .= urlencode($key) . (!empty($value) ? '=' . urlencode($value) : '');
|
||||
$link .= urlencode($key) . ($value !== "" ? '=' . urlencode($value) : '');
|
||||
}
|
||||
|
||||
// Reset our class for further use
|
||||
|
||||
@@ -52,7 +52,7 @@ class Listing
|
||||
'is_search' => $collection->getPagination() instanceof Pagination && $collection->getPagination()->isSearchResult(),
|
||||
'self_overview' => $tabellisting['self_overview'] ?? [],
|
||||
'available_columns' => self::getAvailableColumnsForListing($tabellisting),
|
||||
'listing_search_additional_param' => $listing_search_additional_param ?? [],
|
||||
'listing_search_additional_param' => $listing_search_additional_param,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -60,7 +60,6 @@ class Listing
|
||||
{
|
||||
return [
|
||||
'title' => $tabellisting['title'],
|
||||
'icon' => $tabellisting['icon'],
|
||||
'description' => $tabellisting['description'] ?? null,
|
||||
'icon' => $tabellisting['icon'] ?? null,
|
||||
'table' => [
|
||||
|
||||
@@ -163,11 +163,14 @@ class UI
|
||||
self::$install_mode = $install_mode;
|
||||
// init twig template engine
|
||||
$loader = new FilesystemLoader(Froxlor::getInstallDir() . '/templates/');
|
||||
self::$twig = new Environment($loader, [
|
||||
'debug' => true,
|
||||
'cache' => Froxlor::getInstallDir() . '/cache',
|
||||
'auto_reload' => true
|
||||
]);
|
||||
$twig_params = [
|
||||
'auto_reload' => true,
|
||||
'debug' => false,
|
||||
];
|
||||
if (is_writable(Froxlor::getInstallDir() . '/cache')) {
|
||||
$twig_params['cache'] = Froxlor::getInstallDir() . '/cache';
|
||||
}
|
||||
self::$twig = new Environment($loader, $twig_params);
|
||||
self::$twig->addExtension(new DebugExtension());
|
||||
self::$twig->addExtension(new CustomReflection());
|
||||
self::$twig->addExtension(new FroxlorTwig());
|
||||
@@ -279,7 +282,7 @@ class UI
|
||||
}
|
||||
}
|
||||
if (!file_exists(Froxlor::getInstallDir() . '/templates/' . $theme)) {
|
||||
PhpHelper::phpErrHandler(E_USER_WARNING, "Theme '" . $theme . "' could not be found.", __FILE__, __LINE__, null);
|
||||
PhpHelper::phpErrHandler(E_USER_WARNING, "Theme '" . $theme . "' could not be found.", __FILE__, __LINE__);
|
||||
$theme = self::$default_theme;
|
||||
}
|
||||
return $theme;
|
||||
|
||||
@@ -46,23 +46,19 @@ class Validate
|
||||
const REGEX_YYYY_MM_DD = '/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/';
|
||||
|
||||
/**
|
||||
* Validates the given string by matching against the pattern, prints an error on failure and exits
|
||||
* Validates the given string by matching against the pattern, prints an error on failure and exits.
|
||||
* If the default pattern is used and the string does not match, we try to replace the 'bad' values and log the action.
|
||||
*
|
||||
* @param string $str
|
||||
* the string to be tested (user input)
|
||||
* @param
|
||||
* string the $fieldname to be used in error messages
|
||||
* @param string $pattern
|
||||
* the regular expression to be used for testing
|
||||
* @param
|
||||
* string language id for the error
|
||||
* @return string the clean string
|
||||
*
|
||||
* If the default pattern is used and the string does not match, we try to replace the
|
||||
* 'bad' values and log the action.
|
||||
* @param string $str the string to be tested (user input)
|
||||
* @param string $fieldname to be used in error messages
|
||||
* @param string $pattern the regular expression to be used for testing
|
||||
* @param string|array $lng id for the error
|
||||
* @param string|array $emptydefault fallback value
|
||||
* @param bool $throw_exception whether to display error or throw an exception, default false
|
||||
*
|
||||
* @return string|void the clean string or error
|
||||
*/
|
||||
public static function validate($str, $fieldname, $pattern = '', $lng = '', $emptydefault = [], $throw_exception = false)
|
||||
public static function validate($str, string $fieldname, string $pattern = '', $lng = '', $emptydefault = [], bool $throw_exception = false)
|
||||
{
|
||||
if (!is_array($emptydefault)) {
|
||||
$emptydefault_array = [
|
||||
@@ -122,9 +118,9 @@ class Validate
|
||||
* @param bool $throw_exception
|
||||
* whether to throw an exception on failure
|
||||
*
|
||||
* @return string|bool ip address on success, false on failure
|
||||
* @return string|bool|void ip address on success, false on failure (or nothing if error is displayed)
|
||||
*/
|
||||
public static function validate_ip2($ip, $return_bool = false, $lng = 'invalidip', $allow_localhost = false, $allow_priv = false, $allow_cidr = false, $cidr_as_netmask = false, $throw_exception = false)
|
||||
public static function validate_ip2($ip, bool $return_bool = false, string $lng = 'invalidip', bool $allow_localhost = false, bool $allow_priv = false, bool $allow_cidr = false, bool $cidr_as_netmask = false, bool $throw_exception = false)
|
||||
{
|
||||
$cidr = "";
|
||||
if ($allow_cidr) {
|
||||
@@ -136,15 +132,17 @@ class Validate
|
||||
$cidr_range_max = 128;
|
||||
}
|
||||
if (strlen($ip_cidr[1]) <= 3 && in_array((int)$ip_cidr[1], array_values(range(1, $cidr_range_max)), true) === false) {
|
||||
if ($return_bool) {
|
||||
return false;
|
||||
}
|
||||
Response::standardError($lng, $ip, $throw_exception);
|
||||
}
|
||||
if ($cidr_as_netmask && IPTools::is_ipv6($ip_cidr[0])) {
|
||||
// MySQL does not handle CIDR of IPv6 addresses, return error
|
||||
if ($return_bool) {
|
||||
return false;
|
||||
} else {
|
||||
Response::standardError($lng, $ip, $throw_exception);
|
||||
}
|
||||
Response::standardError($lng, $ip, $throw_exception);
|
||||
}
|
||||
$ip = $ip_cidr[0];
|
||||
if ($cidr_as_netmask && strlen($ip_cidr[1]) <= 3) {
|
||||
@@ -157,9 +155,8 @@ class Validate
|
||||
} elseif (strpos($ip, "/") !== false) {
|
||||
if ($return_bool) {
|
||||
return false;
|
||||
} else {
|
||||
Response::standardError($lng, $ip, $throw_exception);
|
||||
}
|
||||
Response::standardError($lng, $ip, $throw_exception);
|
||||
}
|
||||
|
||||
$filter_lan = $allow_priv ? FILTER_FLAG_NO_RES_RANGE : (FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE);
|
||||
@@ -175,9 +172,8 @@ class Validate
|
||||
|
||||
if ($return_bool) {
|
||||
return false;
|
||||
} else {
|
||||
Response::standardError($lng, $ip, $throw_exception);
|
||||
}
|
||||
Response::standardError($lng, $ip, $throw_exception);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user