Compare commits

...

20 Commits

Author SHA1 Message Date
Michael Kaufmann
35c4e3d1b9 set version to 0.10.22 for upcoming maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-11-06 14:47:20 +01:00
Michael Kaufmann
b3f82f0981 remove duplicate AXFR records as nameserver get added automatically in case they have also been added to the axfr list
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-11-01 21:00:27 +01:00
Michael Kaufmann
b1b68364be do not allow setting www as CNAME record if domain has automatic www-Alias enabled, fixes #895
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-31 16:16:05 +01:00
Michael Kaufmann
ea76ce8fcc secure requests; refs #893
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-31 15:57:59 +01:00
Michael Kaufmann
16eca628dd add Unittest for traffic-filtering by customer-name, refs #894
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-31 15:53:07 +01:00
Michael Kaufmann
6bf5eccc24 update dependencies and add voku\AntiXSS
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-31 15:50:16 +01:00
Michael Kaufmann
63d00cd453 forgot to add the language strings to the commit for avoid deletion of (super)admin
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-31 15:48:01 +01:00
Michael Kaufmann
c79cba26f3 avoid deletion of (super)admin with id 1 due to fallbacks in the code using it; fixes #886
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-31 10:02:11 +01:00
Michael Kaufmann
36eb3cc1aa [domainbulk] remove reqiurement for customer-select in webinterface as it is an API-parameter
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-31 09:45:50 +01:00
Michael Kaufmann
15a13a7783 append file-extension for dkim-private-keys as external tools may require it (rspamd e.g.); thx to rseffner for finding this
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-20 15:28:51 +02:00
Michael Kaufmann
816874872d make given documentroot of domain relative to customerroot of no absolute path if given; fixes #892
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-14 16:58:19 +02:00
Michael Kaufmann
0e8449f28d Merge pull request #891 from andlinger/patch-1
Fixed typo in contribution document
2020-10-14 14:26:48 +02:00
Michael Kaufmann
3dcbbb9e7b do not set description to empty value if not passed as parameter as it is optionally; fixes #890
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-14 14:25:23 +02:00
David Andlinger
5ab9e6865d fixed typo 2020-10-14 14:17:37 +02:00
Michael Kaufmann
3a47b2050e fix awstats/webalizer directory protection when using nginx; fixes #888
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-13 20:18:44 +02:00
Michael Kaufmann
907c475361 create quotatallies entry if it not exists, fixes #885; correction in api-doc for Ftps.update ftp_password parameter, fixes #889
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-13 19:52:29 +02:00
Michael Kaufmann
0dfb4bdcdb list dns entries after add/delete action handling so the table of entries always shows the current state withouth reloading the page; fixes #887
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-12 09:50:48 +02:00
Michael Kaufmann
a5dc7b93a2 unify customerid/loginname api-parameter-descriptions; fixes #883
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2020-10-05 19:59:02 +02:00
Michael Kaufmann
244d2823a6 Merge pull request #882 from heavygale/patch-3
Fix for notices "Trying to access array offset on value of type bool" in ReportsCron.php
2020-10-03 13:10:40 +02:00
heavygale
2f0251bb19 Fix for "Trying to access array offset on value of type bool"
Proper check for success of query before accessing the result array. This notices occures if there's no custom mail-template for trafficmaxpercent_subject or trafficmaxpercent_mailbody for the required language.
2020-10-03 12:55:14 +02:00
41 changed files with 1832 additions and 502 deletions

View File

@@ -48,7 +48,7 @@ strings in
### New settings and database-layout changnes
### New settings and database-layout changes
If you add new settings or layout changes, please make sure you add these to
* `install/froxlor.sql`

View File

@@ -616,7 +616,6 @@ if ($page == 'domains' || $page == 'overview') {
if (isset($_POST['send']) && $_POST['send'] == 'send') {
$customerid = intval($_POST['customerid']);
$separator = \Froxlor\Validate\Validate::validate($_POST['separator'], 'separator');
$offset = (int) \Froxlor\Validate\Validate::validate($_POST['offset'], 'offset', "/[0-9]/i");
@@ -625,7 +624,7 @@ if ($page == 'domains' || $page == 'overview') {
$result = array();
try {
$bulk = new \Froxlor\Bulk\DomainBulkAction($file_name, $customerid);
$bulk = new \Froxlor\Bulk\DomainBulkAction($file_name, $userinfo);
$result = $bulk->doImport($separator, $offset);
} catch (Exception $e) {
\Froxlor\UI\Response::standard_error('domain_import_error', $e->getMessage());
@@ -647,19 +646,6 @@ if ($page == 'domains' || $page == 'overview') {
'page' => 'domains'
));
} else {
$customers = \Froxlor\UI\HTML::makeoption($lng['panel']['please_choose'], 0, 0, true);
$result_customers_stmt = Database::prepare("
SELECT `customerid`, `loginname`, `name`, `firstname`, `company`
FROM `" . TABLE_PANEL_CUSTOMERS . "` " . ($userinfo['customers_see_all'] ? '' : " WHERE `adminid` = '" . (int) $userinfo['adminid'] . "' ") . " ORDER BY `name` ASC");
$params = array();
if ($userinfo['customers_see_all'] == '0') {
$params['adminid'] = $userinfo['adminid'];
}
Database::pexecute($result_customers_stmt, $params);
while ($row_customer = $result_customers_stmt->fetch(PDO::FETCH_ASSOC)) {
$customers .= \Froxlor\UI\HTML::makeoption(\Froxlor\User::getCorrectFullUserDetails($row_customer) . ' (' . $row_customer['loginname'] . ')', $row_customer['customerid']);
}
$domain_import_data = include_once dirname(__FILE__) . '/lib/formfields/admin/domains/formfield.domains_import.php';
$domain_import_form = \Froxlor\UI\HtmlForm::genHTMLForm($domain_import_data);

View File

@@ -1,4 +1,6 @@
<?php
use voku\helper\AntiXSS;
require __DIR__ . '/vendor/autoload.php';
require \Froxlor\Froxlor::getInstallDir() . '/lib/tables.inc.php';
@@ -30,6 +32,12 @@ if (is_null($decoded_request)) {
json_response(400, "Invalid JSON");
}
/**
* check for xss attempts and clean request
*/
$antiXss = new AntiXSS();
$request = $antiXss->xss_clean($request);
// validate content
try {
$decoded_request = stripcslashes_deep($decoded_request);

View File

@@ -46,7 +46,8 @@
"phpmailer/phpmailer": "~6.0",
"monolog/monolog": "^1.24",
"robthree/twofactorauth": "^1.6",
"froxlor/idna-convert-legacy": "^2.1"
"froxlor/idna-convert-legacy": "^2.1",
"voku/anti-xss": "^4.1"
},
"require-dev": {
"phpunit/phpunit": "8.4.1",

1676
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -19,7 +19,6 @@ if (! defined('AREA')) {
*
*/
use Froxlor\Database\Database;
use Froxlor\Api\Commands\DomainZones as DomainZones;
// This file is being included in admin_domains and customer_domains
@@ -36,18 +35,6 @@ $ttl = isset($_POST['record']['ttl']) ? (int) $_POST['record']['ttl'] : 18000;
// get domain-name
$domain = \Froxlor\Dns\Dns::getAllowedDomainEntry($domain_id, AREA, $userinfo);
// select all entries
try {
// get list
$json_result = DomainZones::getLocal($userinfo, [
'id' => $domain_id
])->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$dom_entries = $result['list'];
$errors = "";
$success_message = "";
@@ -63,8 +50,9 @@ if ($action == 'add_record' && ! empty($_POST)) {
'ttl' => $ttl
))->add();
$success_message = $lng['success']['dns_record_added'];
$record = $prio = $content = "";
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
$errors = str_replace("\n", "<br>", $e->getMessage());
}
} elseif ($action == 'delete') {
// remove entry
@@ -75,26 +63,26 @@ if ($action == 'add_record' && ! empty($_POST)) {
'entry_id' => $entry_id,
'id' => $domain_id
))->delete();
// success message (inline)
$success_message = $lng['success']['dns_record_deleted'];
} catch (Exception $e) {
$errors = str_replace("\n", "<br>", $e->getMessage());
}
if (empty($errors)) {
// remove deleted entry from internal data array (no reread of DB necessary)
$_t = $dom_entries;
foreach ($_t as $idx => $entry) {
if ($entry['id'] == $entry_id) {
unset($dom_entries[$idx]);
break;
}
}
unset($_t);
// success message (inline)
$success_message = $lng['success']['dns_record_deleted'];
}
}
}
// select all entries
try {
// get list
$json_result = DomainZones::getLocal($userinfo, [
'id' => $domain_id
])->listing();
} catch (Exception $e) {
\Froxlor\UI\Response::dynamic_error($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
$dom_entries = $result['list'];
// show editor
$record_list = "";
$existing_entries = "";

View File

@@ -554,6 +554,7 @@ opcache.interned_strings_buffer'),
('system', 'ssl_cert_file', '/etc/apache2/apache2.pem'),
('system', 'use_ssl', '0'),
('system', 'default_vhostconf', ''),
('system', 'default_sslvhostconf', ''),
('system', 'mail_quota_enabled', '0'),
('system', 'mail_quota', '100'),
('system', 'webalizer_enabled', '1'),
@@ -704,7 +705,7 @@ opcache.interned_strings_buffer'),
('panel', 'password_special_char', '!?<>§$%+#=@'),
('panel', 'customer_hide_options', ''),
('panel', 'is_configured', '0'),
('panel', 'version', '0.10.21'),
('panel', 'version', '0.10.22'),
('panel', 'db_version', '202009070');

View File

@@ -682,3 +682,13 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.20')) {
showUpdateStep("Updating from 0.10.20 to 0.10.21", false);
\Froxlor\Froxlor::updateToVersion('0.10.21');
}
if (\Froxlor\Froxlor::isFroxlorVersion('0.10.21')) {
showUpdateStep("Adding settings for ssl-vhost default content if not updated from db-version 201910110", true);
Settings::AddNew("system.default_sslvhostconf", '');
lastStepStatus(0);
showUpdateStep("Updating from 0.10.21 to 0.10.22", false);
\Froxlor\Froxlor::updateToVersion('0.10.22');
}

View File

@@ -231,7 +231,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
$email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true));
$def_language = \Froxlor\Validate\Validate::validate($def_language, 'default language', '', '', array(), true);
$custom_notes = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', '/^[^\0]*$/', '', array(), true);
$custom_notes = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
if (Settings::Get('system.mail_quota_enabled') != '1') {
$email_quota = - 1;
@@ -531,7 +531,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
$email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true));
$def_language = \Froxlor\Validate\Validate::validate($def_language, 'default language', '', '', array(), true);
$custom_notes = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', '/^[^\0]*$/', '', array(), true);
$custom_notes = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$theme = \Froxlor\Validate\Validate::validate($theme, 'theme', '', '', array(), true);
$password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true);
@@ -713,6 +713,10 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
if ($id == $this->getUserDetail('adminid')) {
\Froxlor\UI\Response::standard_error('youcantdeleteyourself', '', true);
}
// can't delete the first superadmin
if ($id == 1) {
\Froxlor\UI\Response::standard_error('cannotdeletesuperadmin', '', true);
}
// delete admin
$del_stmt = Database::prepare("

View File

@@ -52,7 +52,9 @@ class CustomerBackups extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
* @param bool $backup_web
* optional whether to backup web-data, default is 0 (false)
* @param int $customerid
* required when called as admin, not needed when called as customer
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
*
* @access admin, customer
* @throws \Exception

View File

@@ -336,7 +336,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true));
$customernumber = \Froxlor\Validate\Validate::validate($customernumber, 'customer number', '/^[A-Za-z0-9 \-]*$/Di', '', array(), true);
$def_language = \Froxlor\Validate\Validate::validate($def_language, 'default language', '', '', array(), true);
$custom_notes = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', '/^[^\0]*$/', '', array(), true);
$custom_notes = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
if (Settings::Get('system.mail_quota_enabled') != '1') {
$email_quota = - 1;
@@ -928,7 +928,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$fax = \Froxlor\Validate\Validate::validate($fax, 'fax', '/^[0-9\- \+\(\)\/]*$/', '', array(), true);
$email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true));
$customernumber = \Froxlor\Validate\Validate::validate($customernumber, 'customer number', '/^[A-Za-z0-9 \-]*$/Di', '', array(), true);
$custom_notes = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', '/^[^\0]*$/', '', array(), true);
$custom_notes = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $custom_notes), 'custom_notes', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
if (! empty($allowed_phpconfigs)) {
$allowed_phpconfigs = array_map('intval', $allowed_phpconfigs);
}

View File

@@ -26,9 +26,9 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
* add options for a given directory
*
* @param int $customerid
* optional, admin-only, the customer-id
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, admin-only, the loginname
* optional, required when called as admin (if $customerid is not specified)
* @param string $path
* path relative to the customer's home-Directory
* @param bool $options_indexes
@@ -69,7 +69,7 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
$error500path = $this->getParam('error500path', true, '');
// validation
$path = \Froxlor\FileDir::makeCorrectDir(\Froxlor\Validate\Validate::validate($path, 'path', '', '', array(), true));
$path = \Froxlor\FileDir::makeCorrectDir(\Froxlor\Validate\Validate::validate($path, 'path', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true));
$userpath = $path;
$path = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path);
@@ -198,9 +198,9 @@ class DirOptions extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
* @param int $id
* id of dir-protection entry
* @param int $customerid
* optional, admin-only, the customer-id
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, admin-only, the loginname
* optional, required when called as admin (if $customerid is not specified)
* @param bool $options_indexes
* optional, activate directory-listing for this path, default 0 (false)
* @param bool $options_cgi

View File

@@ -26,9 +26,9 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
* add htaccess protection to a given directory
*
* @param int $customerid
* optional, admin-only, the customer-id
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, admin-only, the loginname
* optional, required when called as admin (if $customerid is not specified)
* @param string $path
* @param string $username
* @param string $directory_password
@@ -60,7 +60,7 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
$authname = $this->getParam('directory_authname', true, '');
// validation
$path = \Froxlor\FileDir::makeCorrectDir(\Froxlor\Validate\Validate::validate($path, 'path', '', '', array(), true));
$path = \Froxlor\FileDir::makeCorrectDir(\Froxlor\Validate\Validate::validate($path, 'path', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true));
$path = \Froxlor\FileDir::makeCorrectDir($customer['documentroot'] . '/' . $path);
$username = \Froxlor\Validate\Validate::validate($username, 'username', '/^[a-zA-Z0-9][a-zA-Z0-9\-_]+\$?$/', '', array(), true);
$authname = \Froxlor\Validate\Validate::validate($authname, 'directory_authname', '/^[a-zA-Z0-9][a-zA-Z0-9\-_ ]+\$?$/', '', array(), true);
@@ -187,9 +187,9 @@ class DirProtections extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Res
* @param string $username
* optional, the username
* @param int $customerid
* optional, admin-only, the customer-id
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, admin-only, the loginname
* optional, required when called as admin (if $customerid is not specified)
* @param string $directory_password
* optional, leave empty for no change
* @param string $directory_authname

View File

@@ -170,6 +170,10 @@ class DomainZones extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
break;
}
}
// check www-alias setting
if ($result['wwwserveralias'] == '1' && $result['iswildcarddomain'] == '0' && $record == 'www') {
$errors[] = $this->lng['error']['no_wwwcnamae_ifwwwalias'];
}
}
// append trailing dot (again)
$content .= '.';

View File

@@ -199,6 +199,9 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* @param string $domain
* domain-name
* @param int $customerid
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
* @param int $adminid
* optional, default is the calling admin's ID
* @param array $ipandport
@@ -297,7 +300,6 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
// parameters
$p_domain = $this->getParam('domain');
$customerid = intval($this->getParam('customerid'));
// optional parameters
$p_ipandports = $this->getParam('ipandport', true, explode(',', Settings::Get('system.defaultip')));
@@ -377,9 +379,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
), '', true);
}
$customer = $this->apiCall('Customers.get', array(
'id' => $customerid
));
$customer = $this->getCustomerData();
$customerid = $customer['customerid'];
if ($this->getUserDetail('customers_see_all') == '1' && $adminid != $this->getUserDetail('adminid')) {
$admin_stmt = Database::prepare("
@@ -428,8 +429,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$zonefile = '';
}
$specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $specialsettings), 'specialsettings', '/^[^\0]*$/', '', array(), true);
\Froxlor\Validate\Validate::validate($documentroot, 'documentroot', '', '', array(), true);
$specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $specialsettings), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
\Froxlor\Validate\Validate::validate($documentroot, 'documentroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true);
// If path is empty and 'Use domain name as default value for DocumentRoot path' is enabled in settings,
// set default path to subdomain or domain name
@@ -844,7 +845,9 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
* @param string $domainname
* optional, the domainname
* @param int $customerid
* optional customer-id
* required (if $loginname is not specified)
* @param string $loginname
* required (if $customerid is not specified)
* @param int $adminid
* optional, default is the calling admin's ID
* @param array $ipandport
@@ -952,9 +955,18 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
// optional parameters
$p_ipandports = $this->getParam('ipandport', true, array());
$customerid = intval($this->getParam('customerid', true, $result['customerid']));
$adminid = intval($this->getParam('adminid', true, $result['adminid']));
if ($this->getParam('customerid', true, 0) == 0 && $this->getParam('loginname', true, '') == '') {
$customerid = $result['customerid'];
$customer = $this->apiCall('Customers.get', array(
'id' => $customerid
));
} else {
$customer = $this->getCustomerData();
$customerid = $customer['customerid'];
}
$subcanemaildomain = $this->getParam('subcanemaildomain', true, $result['subcanemaildomain']);
$isemaildomain = $this->getBoolParam('isemaildomain', true, $result['isemaildomain']);
$email_only = $this->getBoolParam('email_only', true, $result['email_only']);
@@ -1085,13 +1097,6 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
if (empty($customer) || $customer['customerid'] != $customerid) {
\Froxlor\UI\Response::standard_error('customerdoesntexist', '', true);
}
} else {
$customerid = $result['customerid'];
// get customer
$customer = $this->apiCall('Customers.get', array(
'id' => $customerid
));
}
// handle change of admin (move domain from admin to admin)
@@ -1157,8 +1162,8 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
$dkim = $result['dkim'];
}
$specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $specialsettings), 'specialsettings', '/^[^\0]*$/', '', array(), true);
$documentroot = \Froxlor\Validate\Validate::validate($documentroot, 'documentroot', '', '', array(), true);
$specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $specialsettings), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$documentroot = \Froxlor\Validate\Validate::validate($documentroot, 'documentroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true);
// when moving customer and no path is specified, update would normally reuse the current document-root
// which would point to the wrong customer, therefore we will re-create that directory
@@ -1324,7 +1329,12 @@ class Domains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEn
}
if (! preg_match('/^https?\:\/\//', $documentroot)) {
$documentroot = \Froxlor\FileDir::makeCorrectDir($documentroot);
if ($documentroot != $result['documentroot']) {
if (substr($documentroot, 0, 1) != "/") {
$documentroot = $customer['documentroot'] . '/' . $documentroot;
}
$documentroot = \Froxlor\FileDir::makeCorrectDir($documentroot);
}
}
if ($email_only == '1') {

View File

@@ -30,9 +30,9 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
* @param string $emailaddr
* optional email-address to add the account for
* @param int $customerid
* optional, admin-only, the customer-id
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, admin-only, the loginname
* optional, required when called as admin (if $customerid is not specified)
* @param string $email_password
* password for the account
* @param string $alternative_email
@@ -295,9 +295,9 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
* @param string $emailaddr
* optional, the email-address to update
* @param int $customerid
* optional, admin-only, the customer-id
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, admin-only, the loginname
* optional, required when called as admin (if $customerid is not specified)
* @param int $email_quota
* optional, update quota
* @param string $email_password
@@ -418,9 +418,9 @@ class EmailAccounts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Reso
* @param string $emailaddr
* optional, the email-address to delete the account for
* @param int $customerid
* optional, admin-only, the customer-id
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, admin-only, the loginname
* optional, required when called as admin (if $customerid is not specified)
* @param bool $delete_userfiles
* optional, default false
*

View File

@@ -30,9 +30,9 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
* @param string $emailaddr
* optional, the email-address to add the forwarder for
* @param int $customerid
* optional, admin-only, the customer-id
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, admin-only, the loginname
* optional, required when called as admin (if $customerid is not specified)
* @param string $destination
* email-address to add as forwarder
*
@@ -221,9 +221,9 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
* @param string $emailaddr
* optional, the email-address to delete the forwarder from
* @param int $customerid
* optional, admin-only, the customer-id
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, admin-only, the loginname
* optional, required when called as admin (if $customerid is not specified)
* @param int $forwarderid
* id of the forwarder to delete
*

View File

@@ -32,9 +32,9 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* @param boolean $iscatchall
* optional, make this address a catchall address, default: no
* @param int $customerid
* optional, admin-only, the customer-id
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, admin-only, the loginname
* optional, required when called as admin (if $customerid is not specified)
*
* @access admin, customer
* @throws \Exception
@@ -190,9 +190,9 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* @param string $emailaddr
* optional, the email-address
* @param int $customerid
* optional, admin-only, the customer-id
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, admin-only, the loginname
* optional, required when called as admin (if $customerid is not specified)
* @param boolean $iscatchall
* optional
*
@@ -352,9 +352,9 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* @param string $emailaddr
* optional, the email-address
* @param int $customerid
* optional, admin-only, the customer-id
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, admin-only, the loginname
* optional, required when called as admin (if $customerid is not specified)
* @param boolean $delete_userfiles
* optional, delete email data from filesystem, default: 0 (false)
*
@@ -405,10 +405,6 @@ class Emails extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
Customers::decreaseUsage($customer['customerid'], 'email_forwarders_used', '', $number_forwarders);
Admins::decreaseUsage($customer['customerid'], 'email_forwarders_used', '', $number_forwarders);
if ($delete_userfiles) {
\Froxlor\System\Cronjob::inserttask('7', $customer['loginname'], $result['email_full']);
}
// delete address
$stmt = Database::prepare("DELETE FROM `" . TABLE_MAIL_VIRTUAL . "` WHERE `customerid`= :customerid AND `id`= :id");
Database::pexecute($stmt, array(

View File

@@ -40,7 +40,9 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
* @param string $ftp_domain
* optional if customer.ftpatdomain is allowed, specify a domain (customer must be owner)
* @param int $customerid
* required when called as admin, not needed when called as customer
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
* @param array $additional_members
* optional whether to add additional usernames to the group
* @param bool $is_defaultuser
@@ -180,6 +182,17 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
), true, true);
}
// create quotatallies entry if it not exists, refs #885
if ($result_stmt->rowCount() == 0) {
$stmt = Database::prepare("INSERT INTO `" . TABLE_FTP_QUOTATALLIES . "`
(`name`, `quota_type`, `bytes_in_used`, `bytes_out_used`, `bytes_xfer_used`, `files_in_used`, `files_out_used`, `files_xfer_used`)
VALUES (:name, 'user', '0', '0', '0', '0', '0', '0')
");
Database::pexecute($stmt, array(
"name" => $username
), true, true);
}
$group_upd_stmt = Database::prepare("
UPDATE `" . TABLE_FTP_GROUPS . "`
SET `members` = CONCAT_WS(',',`members`, :username)
@@ -343,7 +356,7 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
* @param string $username
* optional, the username
* @param string $ftp_password
* password for the created database and database-user
* optional, update password if specified
* @param string $path
* destination path relative to the customers-homedir
* @param string $ftp_description
@@ -351,7 +364,9 @@ class Ftps extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEntit
* @param string $shell
* optional, default /bin/false (not changeable when deactivated)
* @param int $customerid
* required when called as admin, not needed when called as customer
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
*
* @access admin, customer
* @throws \Exception

View File

@@ -171,17 +171,17 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
if ($this->isAdmin() && $this->getUserDetail('change_serversettings')) {
$ip = \Froxlor\Validate\Validate::validate_ip2($this->getParam('ip'), false, 'invalidip', false, true, false, false, true);
$port = \Froxlor\Validate\Validate::validate($this->getParam('port', true, 80), 'port', '/^(([1-9])|([1-9][0-9])|([1-9][0-9][0-9])|([1-9][0-9][0-9][0-9])|([1-5][0-9][0-9][0-9][0-9])|(6[0-4][0-9][0-9][0-9])|(65[0-4][0-9][0-9])|(655[0-2][0-9])|(6553[0-5]))$/Di', array(
$port = \Froxlor\Validate\Validate::validate($this->getParam('port', true, 80), 'port', \Froxlor\Validate\Validate::REGEX_PORT, array(
'stringisempty',
'myport'
), array(), true);
$listen_statement = ! empty($this->getBoolParam('listen_statement', true, 0)) ? 1 : 0;
$namevirtualhost_statement = ! empty($this->getBoolParam('namevirtualhost_statement', true, 0)) ? 1 : 0;
$vhostcontainer = ! empty($this->getBoolParam('vhostcontainer', true, 0)) ? 1 : 0;
$specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('specialsettings', true, '')), 'specialsettings', '/^[^\0]*$/', '', array(), true);
$specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('specialsettings', true, '')), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$vhostcontainer_servername_statement = ! empty($this->getBoolParam('vhostcontainer_servername_statement', true, 1)) ? 1 : 0;
$default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('default_vhostconf_domain', true, '')), 'default_vhostconf_domain', '/^[^\0]*$/', '', array(), true);
$docroot = \Froxlor\Validate\Validate::validate($this->getParam('docroot', true, ''), 'docroot', '', '', array(), true);
$default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('default_vhostconf_domain', true, '')), 'default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$docroot = \Froxlor\Validate\Validate::validate($this->getParam('docroot', true, ''), 'docroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true);
if ((int) Settings::Get('system.use_ssl') == 1) {
$ssl = ! empty($this->getBoolParam('ssl', true, 0)) ? intval($this->getBoolParam('ssl', true, 0)) : 0;
@@ -189,9 +189,9 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$ssl_key_file = \Froxlor\Validate\Validate::validate($this->getParam('ssl_key_file', $ssl, ''), 'ssl_key_file', '', '', array(), true);
$ssl_ca_file = \Froxlor\Validate\Validate::validate($this->getParam('ssl_ca_file', true, ''), 'ssl_ca_file', '', '', array(), true);
$ssl_cert_chainfile = \Froxlor\Validate\Validate::validate($this->getParam('ssl_cert_chainfile', true, ''), 'ssl_cert_chainfile', '', '', array(), true);
$ssl_specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_specialsettings', true, '')), 'ssl_specialsettings', '/^[^\0]*$/', '', array(), true);
$ssl_specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_specialsettings', true, '')), 'ssl_specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$include_specialsettings = ! empty($this->getBoolParam('include_specialsettings', true, 0)) ? 1 : 0;
$ssl_default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_default_vhostconf_domain', true, '')), 'ssl_default_vhostconf_domain', '/^[^\0]*$/', '', array(), true);
$ssl_default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_default_vhostconf_domain', true, '')), 'ssl_default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$include_default_vhostconf_domain = ! empty($this->getBoolParam('include_default_vhostconf_domain', true, 0)) ? 1 : 0;
} else {
$ssl = 0;
@@ -368,17 +368,17 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
));
$ip = \Froxlor\Validate\Validate::validate_ip2($this->getParam('ip', true, $result['ip']), false, 'invalidip', false, true, false, false, true);
$port = \Froxlor\Validate\Validate::validate($this->getParam('port', true, $result['port']), 'port', '/^(([1-9])|([1-9][0-9])|([1-9][0-9][0-9])|([1-9][0-9][0-9][0-9])|([1-5][0-9][0-9][0-9][0-9])|(6[0-4][0-9][0-9][0-9])|(65[0-4][0-9][0-9])|(655[0-2][0-9])|(6553[0-5]))$/Di', array(
$port = \Froxlor\Validate\Validate::validate($this->getParam('port', true, $result['port']), 'port', \Froxlor\Validate\Validate::REGEX_PORT, array(
'stringisempty',
'myport'
), array(), true);
$listen_statement = $this->getBoolParam('listen_statement', true, $result['listen_statement']);
$namevirtualhost_statement = $this->getBoolParam('namevirtualhost_statement', true, $result['namevirtualhost_statement']);
$vhostcontainer = $this->getBoolParam('vhostcontainer', true, $result['vhostcontainer']);
$specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('specialsettings', true, $result['specialsettings'])), 'specialsettings', '/^[^\0]*$/', '', array(), true);
$specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('specialsettings', true, $result['specialsettings'])), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$vhostcontainer_servername_statement = $this->getParam('vhostcontainer_servername_statement', true, $result['vhostcontainer_servername_statement']);
$default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('default_vhostconf_domain', true, $result['default_vhostconf_domain'])), 'default_vhostconf_domain', '/^[^\0]*$/', '', array(), true);
$docroot = \Froxlor\Validate\Validate::validate($this->getParam('docroot', true, $result['docroot']), 'docroot', '', '', array(), true);
$default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('default_vhostconf_domain', true, $result['default_vhostconf_domain'])), 'default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$docroot = \Froxlor\Validate\Validate::validate($this->getParam('docroot', true, $result['docroot']), 'docroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true);
if ((int) Settings::Get('system.use_ssl') == 1) {
$ssl = $this->getBoolParam('ssl', true, $result['ssl']);
@@ -386,9 +386,9 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$ssl_key_file = \Froxlor\Validate\Validate::validate($this->getParam('ssl_key_file', $ssl, $result['ssl_key_file']), 'ssl_key_file', '', '', array(), true);
$ssl_ca_file = \Froxlor\Validate\Validate::validate($this->getParam('ssl_ca_file', true, $result['ssl_ca_file']), 'ssl_ca_file', '', '', array(), true);
$ssl_cert_chainfile = \Froxlor\Validate\Validate::validate($this->getParam('ssl_cert_chainfile', true, $result['ssl_cert_chainfile']), 'ssl_cert_chainfile', '', '', array(), true);
$ssl_specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_specialsettings', true, $result['ssl_specialsettings'])), 'ssl_specialsettings', '/^[^\0]*$/', '', array(), true);
$ssl_specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_specialsettings', true, $result['ssl_specialsettings'])), 'ssl_specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$include_specialsettings = $this->getBoolParam('include_specialsettings', true, $result['include_specialsettings']);
$ssl_default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_default_vhostconf_domain', true, $result['ssl_default_vhostconf_domain'])), 'ssl_default_vhostconf_domain', '/^[^\0]*$/', '', array(), true);
$ssl_default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_default_vhostconf_domain', true, $result['ssl_default_vhostconf_domain'])), 'ssl_default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$include_default_vhostconf_domain = $this->getBoolParam('include_default_vhostconf_domain', true, $result['include_default_vhostconf_domain']);
} else {
$ssl = 0;

View File

@@ -34,9 +34,9 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* @param bool $sendinfomail
* optional, send created resource-information to customer, default: false
* @param int $customerid
* optional, admin-only, the customer-id
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, admin-only, the loginname
* optional, required when called as admin (if $customerid is not specified)
*
* @access admin, customer
* @throws \Exception
@@ -278,9 +278,9 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* @param string $description
* optional, description for database
* @param int $customerid
* optional, admin-only, the customer-id
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, admin-only, the loginname
* optional, required when called as admin (if $customerid is not specified)
*
* @access admin, customer
* @throws \Exception
@@ -307,7 +307,7 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
// paramters
$password = $this->getParam('mysql_password', true, '');
$databasedescription = $this->getParam('description', true, '');
$databasedescription = $this->getParam('description', true, $result['description']);
// validation
$password = \Froxlor\Validate\Validate::validate($password, 'password', '', '', array(), true);
@@ -462,9 +462,9 @@ class Mysqls extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* @param int $mysql_server
* optional, specify database-server, default is none
* @param int $customerid
* optional, admin-only, the customer-id
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, admin-only, the loginname
* optional, required when called as admin (if $customerid is not specified)
*
* @access admin, customer
* @throws \Exception

View File

@@ -56,7 +56,9 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
* @param bool $hsts_preload
* optional whether or not to preload HSTS header value, default 0
* @param int $customerid
* required when called as admin, not needed when called as customer
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
*
* @access admin, customer
* @throws \Exception
@@ -470,7 +472,9 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
* @param bool $hsts_preload
* optional whether or not to preload HSTS header value
* @param int $customerid
* required when called as admin, not needed when called as customer
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
*
* @access admin, customer
* @throws \Exception
@@ -876,7 +880,9 @@ class SubDomains extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resourc
* @param string $domainname
* optional, the domainname
* @param int $customerid
* required when called as admin, not needed when called as customer
* optional, required when called as admin (if $loginname is not specified)
* @param string $loginname
* optional, required when called as admin (if $customerid is not specified)
*
* @access admin, customer
* @throws \Exception

View File

@@ -35,20 +35,6 @@ abstract class BulkAction
*/
private $impFile = null;
/**
* customer id of the user the entity is being added to
*
* @var int
*/
private $custId = null;
/**
* array of customer data read from the database
*
* @var array
*/
private $custData = null;
/**
* api-function to call for addingg entity
*
@@ -70,20 +56,27 @@ abstract class BulkAction
*/
private $errors = array();
/**
* logged in user
*
* @var array
*/
protected $userinfo = array();
/**
* class constructor, optionally sets file and customer-id
*
* @param string $import_file
* @param int $customer_id
* @param array $userinfo
*
* @return object BulkAction instance
*/
protected function __construct($import_file = null, $customer_id = 0)
protected function __construct($import_file = null, $userinfo = array())
{
if (! empty($import_file)) {
$this->impFile = \Froxlor\FileDir::makeCorrectFile($import_file);
}
$this->custId = $customer_id;
$this->userinfo = $userinfo;
}
/**
@@ -109,18 +102,6 @@ abstract class BulkAction
$this->impFile = \Froxlor\FileDir::makeCorrectFile($import_file);
}
/**
* setter for customer-id
*
* @param int $customer_id
*
* @return void
*/
public function setCustomer($customer_id = 0)
{
$this->custId = $customer_id;
}
/**
* return the list of errors
*
@@ -145,7 +126,7 @@ abstract class BulkAction
protected function importEntity($data_array = null)
{
global $userinfo;
if (empty($data_array)) return null;
$module = '\\Froxlor\\Api\\Commands\\' . substr($this->api_call, 0, strpos($this->api_call, "."));
$function = substr($this->api_call, strpos($this->api_call, ".") + 1);
@@ -159,7 +140,7 @@ abstract class BulkAction
$result = null;
try {
$json_result = $module::getLocal($userinfo, $new_data)->$function();
$json_result = $module::getLocal($this->userinfo, $new_data)->$function();
$result = json_decode($json_result, true)['data'];
} catch (\Exception $e) {
$this->errors[] = $e->getMessage();
@@ -189,6 +170,10 @@ abstract class BulkAction
throw new \Exception("Unable to read file '" . $this->impFile . "'");
}
if (empty($separator) || strlen($separator) != 1) {
throw new \Exception("Invalid separator specified: '" . $separator . "'");
}
$file_data = array();
$is_params_line = true;
$fh = @fopen($this->impFile, "r");
@@ -218,37 +203,4 @@ abstract class BulkAction
return $file_data;
}
/**
* to be called first in doImport() to read in customer and entity data
*/
protected function preImport()
{
$this->readCustomerData();
if ($this->custId <= 0) {
throw new \Exception("Invalid customer selected");
}
if (is_null($this->custData)) {
throw new \Exception("Failed to read customer data");
}
}
/**
* reads customer data from panel_customer by $_custId
*
* @return bool
*/
protected function readCustomerData()
{
$cust_stmt = \Froxlor\Database\Database::prepare("SELECT * FROM `" . TABLE_PANEL_CUSTOMERS . "` WHERE `customerid` = :cid");
$this->custData = \Froxlor\Database\Database::pexecute_first($cust_stmt, array(
'cid' => $this->custId
));
if (is_array($this->custData) && isset($this->custData['customerid']) && $this->custData['customerid'] == $this->custId) {
return true;
}
$this->custData = null;
return false;
}
}

View File

@@ -32,9 +32,9 @@ class DomainBulkAction extends BulkAction
*
* @return object DomainBulkAction instance
*/
public function __construct($import_file = null, $customer_id = 0)
public function __construct($import_file = null, $userinfo)
{
parent::__construct($import_file, $customer_id);
parent::__construct($import_file, $userinfo);
$this->setApiCall('Domains.add');
}
@@ -49,23 +49,14 @@ class DomainBulkAction extends BulkAction
*/
public function doImport($separator = ";", $offset = 0)
{
$this->preImport();
// get the admins userinfo to check for domains_used, etc.
global $userinfo;
if ($userinfo['domains'] == "-1") {
if ($this->userinfo['domains'] == "-1") {
$dom_unlimited = true;
} else {
$dom_unlimited = false;
}
$domains_used = (int) $userinfo['domains_used'];
$domains_avail = (int) $userinfo['domains'];
if (empty($separator) || strlen($separator) != 1) {
throw new \Exception("Invalid separator specified: '" . $separator . "'");
}
$domains_used = (int) $this->userinfo['domains_used'];
$domains_avail = (int) $this->userinfo['domains'];
if (! is_int($offset) || $offset < 0) {
throw new \Exception("Invalid offset specified");

View File

@@ -41,6 +41,7 @@ abstract class DnsBase
{
$this->logger = $logger;
$known_ns_ips = [];
if (Settings::Get('system.nameservers') != '') {
$nameservers = explode(',', Settings::Get('system.nameservers'));
foreach ($nameservers as $nameserver) {
@@ -58,6 +59,8 @@ abstract class DnsBase
$nameserver_ips = array(
$nameserver
);
} else {
$known_ns_ips = array_merge($known_ns_ips, $nameserver_ips);
}
$this->ns[] = array(
'hostname' => $nameserver,
@@ -80,7 +83,9 @@ abstract class DnsBase
if (Settings::Get('system.axfrservers') != '') {
$axfrservers = explode(',', Settings::Get('system.axfrservers'));
foreach ($axfrservers as $axfrserver) {
$this->axfr[] = trim($axfrserver);
if (!in_array(trim($axfrserver), $known_ns_ips)) {
$this->axfr[] = trim($axfrserver);
}
}
}
}
@@ -195,14 +200,14 @@ abstract class DnsBase
while ($domain = $result_domains_stmt->fetch(\PDO::FETCH_ASSOC)) {
$privkey_filename = \Froxlor\FileDir::makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim' . $domain['dkim_id']);
$privkey_filename = \Froxlor\FileDir::makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim' . $domain['dkim_id'] . '.priv');
$pubkey_filename = \Froxlor\FileDir::makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim' . $domain['dkim_id'] . '.public');
if ($domain['dkim_privkey'] == '' || $domain['dkim_pubkey'] == '') {
$max_dkim_id_stmt = Database::query("SELECT MAX(`dkim_id`) as `max_dkim_id` FROM `" . TABLE_PANEL_DOMAINS . "`");
$max_dkim_id = $max_dkim_id_stmt->fetch(\PDO::FETCH_ASSOC);
$domain['dkim_id'] = (int) $max_dkim_id['max_dkim_id'] + 1;
$privkey_filename = \Froxlor\FileDir::makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim' . $domain['dkim_id']);
$privkey_filename = \Froxlor\FileDir::makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim' . $domain['dkim_id'] . '.priv');
\Froxlor\FileDir::safe_exec('openssl genrsa -out ' . escapeshellarg($privkey_filename) . ' ' . Settings::Get('dkim.dkim_keylength'));
$domain['dkim_privkey'] = file_get_contents($privkey_filename);
\Froxlor\FileDir::safe_exec("chmod 0640 " . escapeshellarg($privkey_filename));

View File

@@ -902,7 +902,6 @@ class Nginx extends HttpConfigBase
FROM `" . TABLE_PANEL_HTPASSWDS . "` AS a
JOIN `" . TABLE_PANEL_DOMAINS . "` AS b USING (`customerid`)
WHERE b.customerid = :customerid AND b.domain = :domain
AND path LIKE CONCAT(b.documentroot, '%')
");
Database::pexecute($result_stmt, array(
'customerid' => $domain['customerid'],
@@ -1042,10 +1041,10 @@ class Nginx extends HttpConfigBase
if (Settings::Get('system.awstats_enabled') == '1') {
// awstats
$stats_text .= "\t" . 'location /awstats {' . "\n";
$stats_text .= "\t" . 'location ^~ /awstats {' . "\n";
} else {
// webalizer
$stats_text .= "\t" . 'location /webalizer {' . "\n";
$stats_text .= "\t" . 'location ^~ /webalizer {' . "\n";
}
$stats_text .= "\t\t" . 'alias ' . $alias_dir . ';' . "\n";

View File

@@ -15,7 +15,7 @@ namespace Froxlor\Cron\Traffic;
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
*
*/
use Froxlor\Database\Database;
use Froxlor\Settings;
@@ -111,11 +111,11 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
'varname' => 'trafficmaxpercent_subject'
);
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_subject = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['subject']), $replace_arr));
$mail_subject = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['subject']), $replace_arr));
$result2_data['varname'] = 'trafficmaxpercent_mailbody';
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_body = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['mailbody']), $replace_arr));
$mail_body = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['mailbody']), $replace_arr));
$_mailerror = false;
$mailerr_msg = "";
@@ -217,11 +217,11 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
'varname' => 'trafficmaxpercent_subject'
);
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_subject = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['subject']), $replace_arr));
$mail_subject = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['subject']), $replace_arr));
$result2_data['varname'] = 'trafficmaxpercent_mailbody';
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_body = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['mailbody']), $replace_arr));
$mail_body = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['trafficmaxpercent']['mailbody']), $replace_arr));
$_mailerror = false;
$mailerr_msg = "";
@@ -424,11 +424,11 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
'varname' => 'diskmaxpercent_subject'
);
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_subject = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['subject']), $replace_arr));
$mail_subject = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['subject']), $replace_arr));
$result2_data['varname'] = 'diskmaxpercent_mailbody';
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_body = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['mailbody']), $replace_arr));
$mail_body = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['mailbody']), $replace_arr));
$_mailerror = false;
$mailerr_msg = "";
@@ -521,11 +521,11 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
'varname' => 'diskmaxpercent_subject'
);
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_subject = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['subject']), $replace_arr));
$mail_subject = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['subject']), $replace_arr));
$result2_data['varname'] = 'diskmaxpercent_mailbody';
$result2 = Database::pexecute_first($result2_stmt, $result2_data);
$mail_body = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['mailbody']), $replace_arr));
$mail_body = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result2 !== false && $result2['value'] != '') ? $result2['value'] : $lng['mails']['diskmaxpercent']['mailbody']), $replace_arr));
$_mailerror = false;
$mailerr_msg = "";

View File

@@ -7,7 +7,7 @@ final class Froxlor
{
// Main version variable
const VERSION = '0.10.21';
const VERSION = '0.10.22';
// Database version (YYYYMMDDC where C is a daily counter)
const DBVERSION = '202009070';

View File

@@ -223,9 +223,17 @@ class PhpHelper
*/
public static function gethostbynamel6($host, $try_a = true)
{
$dns6 = dns_get_record($host, DNS_AAAA);
$dns6 = @dns_get_record($host, DNS_AAAA);
if (!is_array($dns6)) {
// no record or failed to check
$dns6 = [];
}
if ($try_a == true) {
$dns4 = dns_get_record($host, DNS_A);
$dns4 = @dns_get_record($host, DNS_A);
if (!is_array($dns4)) {
// no record or failed to check
$dns4 = [];
}
$dns = array_merge($dns4, $dns6);
} else {
$dns = $dns6;
@@ -382,4 +390,21 @@ class PhpHelper
}
return $returnval;
}
/**
* function to check a super-global passed by reference
* so it gets automatically updated
*
* @param array $global
* @param \voku\helper\AntiXSS $antiXss
*/
public static function cleanGlobal(&$global = [], &$antiXss)
{
if (isset($global) && ! empty($global)) {
$tmp = $global;
foreach ($tmp as $index => $value) {
$global[$index] = $antiXss->xss_clean($value);
}
}
}
}

View File

@@ -299,7 +299,6 @@ class HTML
$checkbox = self::makecheckbox('delete_userfiles', $chk_text, '1', false, '0', true, true);
} else {
$checkbox = '<input type="hidden" name="delete_userfiles" value="0" />' . "\n";
;
}
$text = strtr($text, array(

View File

@@ -4,6 +4,12 @@ namespace Froxlor\Validate;
class Validate
{
const REGEX_DIR = '/^|(\/[\w-]+)+$/';
const REGEX_PORT = '/^(([1-9])|([1-9][0-9])|([1-9][0-9][0-9])|([1-9][0-9][0-9][0-9])|([1-5][0-9][0-9][0-9][0-9])|(6[0-4][0-9][0-9][0-9])|(65[0-4][0-9][0-9])|(655[0-2][0-9])|(6553[0-5]))$/Di';
const REGEX_CONF_TEXT = '/^[^\0]*$/';
/**
* Validates the given string by matching against the pattern, prints an error on failure and exits
*

View File

@@ -23,12 +23,6 @@ return array(
'title' => $lng['domains']['domain_import'],
'image' => 'icons/domain_add.png',
'fields' => array(
'customerid' => array(
'label' => $lng['admin']['customer'],
'type' => 'select',
'select_var' => $customers,
'mandatory' => true
),
'separator' => array(
'label' => $lng['domains']['import_separator'],
'type' => 'text',

View File

@@ -44,6 +44,8 @@ require dirname(__DIR__) . '/vendor/autoload.php';
use Froxlor\Database\Database;
use Froxlor\Settings;
use voku\helper\AntiXSS;
use Froxlor\PhpHelper;
header("Content-Type: text/html; charset=UTF-8");
@@ -86,6 +88,17 @@ foreach ($_REQUEST as $key => $value) {
}
}
/**
* check for xss attempts and clean important globals
*/
$antiXss = new AntiXSS();
// check $_GET
PhpHelper::cleanGlobal($_GET, $antiXss);
// check $_POST
PhpHelper::cleanGlobal($_POST, $antiXss);
// check $_COOKIE
PhpHelper::cleanGlobal($_COOKIE, $antiXss);
unset($_);
unset($value);
unset($key);
@@ -473,9 +486,9 @@ unset($js);
unset($css);
if (isset($_POST['action'])) {
$action = $_POST['action'];
$action = trim(strip_tags($_POST['action']));
} elseif (isset($_GET['action'])) {
$action = $_GET['action'];
$action = trim(strip_tags($_GET['action']));
} else {
$action = '';
// clear request data
@@ -485,9 +498,9 @@ if (isset($_POST['action'])) {
}
if (isset($_POST['page'])) {
$page = $_POST['page'];
$page = trim(strip_tags($_POST['page']));
} elseif (isset($_GET['page'])) {
$page = $_GET['page'];
$page = trim(strip_tags($_GET['page']));
} else {
$page = '';
}

View File

@@ -2098,3 +2098,5 @@ $lng['serversettings']['phpfpm_settings']['custom_config']['description'] = 'Add
$lng['serversettings']['awstats']['logformat']['title'] = 'LogFormat setting';
$lng['serversettings']['awstats']['logformat']['description'] = 'If you use customized logformat for your webserver, you need change the awstats LogFormat too.<br/>Default is 1. For more information check documentation <a target="_blank" href="https://awstats.sourceforge.io/docs/awstats_config.html#LogFormat">here</a>.';
$lng['error']['cannotdeletesuperadmin'] = 'The first admin cannot be deleted.';
$lng['error']['no_wwwcnamae_ifwwwalias'] = 'Cannot set CNAME record for "www" as domain is set to generate a www-alias. Please change settings to either "No alias" or "Wildcard alias"';

View File

@@ -1745,3 +1745,5 @@ $lng['serversettings']['phpfpm_settings']['custom_config']['description'] = 'Fü
$lng['serversettings']['awstats']['logformat']['title'] = 'LogFormat Einstellung';
$lng['serversettings']['awstats']['logformat']['description'] = 'Wenn ein benutzerdefiniertes LogFormat beim Webserver verwendet wird, muss LogFormat von awstats ebenso angepasst werden.<br/>Standard ist 1. Für weitere Informationen siehe Dokumentation unter <a target="_blank" href="https://awstats.sourceforge.io/docs/awstats_config.html#LogFormat">hier</a>.';
$lng['error']['cannotdeletesuperadmin'] = 'Der erste Administrator kann nicht gelöscht werden.';
$lng['error']['no_wwwcnamae_ifwwwalias'] = 'Es kann kein CNAME Eintrag für "www" angelegt werden, da die Domain einen www-Alias aktiviert hat. Ändere diese Einstellung auf "Kein Alias" oder "Wildcard Alias"';

View File

@@ -355,4 +355,16 @@ class AdminsTest extends TestCase
'loginname' => 'admin'
))->update();
}
public function testAdminsAdminsCannotDeleteFirstAdmin()
{
global $admin_userdata;
$testadmin_userdata = $admin_userdata;
$testadmin_userdata['adminid'] = 10;
$this->expectExceptionMessage("The first admin cannot be deleted.");
Admins::getLocal($testadmin_userdata, array(
'loginname' => 'admin'
))->delete();
}
}

View File

@@ -0,0 +1,79 @@
<?php
use PHPUnit\Framework\TestCase;
use Froxlor\Api\Commands\Domains;
use Froxlor\Bulk\DomainBulkAction;
/**
*
* @covers \Froxlor\Bulk\BulkAction
* @covers \Froxlor\Bulk\DomainBulkAction
*/
class DomainBulkTest extends TestCase
{
public function testNoImportFile()
{
global $admin_userdata;
$this->expectExceptionMessage("No file was given for import");
$bulk = new DomainBulkAction(null, $admin_userdata);
$bulk->doImport(";", 0);
}
public function testImportFileDoesNotExist()
{
global $admin_userdata;
$this->expectExceptionMessage("The file '/tmp/nonexisting.csv' could not be found");
$bulk = new DomainBulkAction("/tmp/nonexisting.csv", $admin_userdata);
$bulk->doImport(";", 0);
}
public function testImportDomains()
{
global $admin_userdata;
$content = <<<EOC
domain;loginname;
imported-a.com;test1;
imported-b.com;test1;
imported-c.com;test2;
EOC;
file_put_contents('/tmp/import-test.csv', $content);
$bulk = new DomainBulkAction("/tmp/import-test.csv", $admin_userdata);
$result = $bulk->doImport(";", 0);
$this->assertEquals(3, $result['all']);
$this->assertEquals(2, $result['imported']);
$this->assertEquals("Customer with loginname 'test2' could not be found", $bulk->getErrors()[0]);
// now check whether the domain really exists for test1 user
$data = [
'domain' => 'imported-a.com'
];
$json_result = Domains::getLocal($admin_userdata, $data)->get();
$result = json_decode($json_result, true)['data'];
$this->assertEquals('imported-a.com', $result['domain']);
$this->assertEquals(1, $result['customerid']);
}
public function testImportDomainsMaxAlloc()
{
global $admin_userdata;
// fake allocation restriction
$admin_userdata['domains'] = 1;
$content = <<<EOC
domain;loginname;
imported-a.com;test1;
imported-b.com;test1;
imported-c.com;test2;
EOC;
file_put_contents('/tmp/import-test.csv', $content);
$bulk = new DomainBulkAction("/tmp/import-test.csv", $admin_userdata);
$result = $bulk->doImport(";", 0);
$this->assertEquals(3, $result['all']);
$this->assertEquals(0, $result['imported']);
$this->assertEquals("You have reached your maximum allocation of domains (" . $admin_userdata['domains'] . ")", $result['notes']);
}
}

View File

@@ -4,6 +4,7 @@ use PHPUnit\Framework\TestCase;
use Froxlor\Settings;
use Froxlor\Api\Commands\Customers;
use Froxlor\Api\Commands\DomainZones;
use Froxlor\Api\Commands\Domains;
/**
*
@@ -719,6 +720,31 @@ class DomainZonesTest extends TestCase
DomainZones::getLocal($admin_userdata, $data)->add();
}
/**
*
* @depends testAdminDomainZonesAddCname
*/
public function testAdminDomainZonesAddCnameInvalidWwwAlias()
{
global $admin_userdata;
// set domain to www-alias
$data = [
'domainname' => 'test2.local',
'selectserveralias' => '1'
];
Domains::getLocal($admin_userdata, $data)->update();
$data = [
'domainname' => 'test2.local',
'record' => 'www',
'type' => 'CNAME',
'content' => 'testing.local'
];
$this->expectExceptionMessage('Cannot set CNAME record for "www" as domain is set to generate a www-alias. Please change settings to either "No alias" or "Wildcard alias"');
DomainZones::getLocal($admin_userdata, $data)->add();
}
/**
*
* @depends testAdminDomainZonesAddCname

View File

@@ -198,16 +198,39 @@ class DomainsTest extends TestCase
public function testAdminDomainsUpdate()
{
global $admin_userdata;
// get customer
$json_result = Customers::getLocal($admin_userdata, array(
'loginname' => 'test1'
))->get();
$customer_userdata = json_decode($json_result, true)['data'];
$data = [
'domainname' => 'test.local',
'email_only' => 1,
'override_tls' => 0
'override_tls' => 0,
'documentroot' => 'web'
];
$json_result = Domains::getLocal($admin_userdata, $data)->update();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result['email_only']);
$this->assertFalse(in_array('TLSv1.3', explode(",", $result['ssl_protocols'])));
$this->assertEquals('test.local', $result['domain']);
$this->assertEquals($customer_userdata['documentroot'] . 'web/', $result['documentroot']);
}
/**
*
* @depends testAdminDomainsAdd
*/
public function testAdminDomainsUpdateAbsolutePath()
{
global $admin_userdata;
$data = [
'domainname' => 'test.local',
'documentroot' => '/web'
];
$json_result = Domains::getLocal($admin_userdata, $data)->update();
$result = json_decode($json_result, true)['data'];
$this->assertEquals('/web/', $result['documentroot']);
}
/**
@@ -282,7 +305,7 @@ class DomainsTest extends TestCase
'customerid' => $customer_userdata['customerid'] + 1
];
Settings::Set('panel.allow_domain_change_customer', 1);
$this->expectExceptionMessage("The customer you have chosen doesn't exist.");
$this->expectExceptionMessage("Customer with id #2 could not be found");
Domains::getLocal($admin_userdata, $data)->update();
}

View File

@@ -136,6 +136,26 @@ class MysqlsTest extends TestCase
}
}
/**
*
* @depends testCustomerMysqlsAdd
*/
public function testAdminMysqlsUpdatePwdOnly()
{
global $admin_userdata;
$newPwd = \Froxlor\System\Crypt::generatePassword();
$data = [
'dbname' => 'test1sql1',
'mysql_password' => $newPwd,
'loginname' => 'test1'
];
$json_result = Mysqls::getLocal($admin_userdata, $data)->update();
$result = json_decode($json_result, true)['data'];
$this->assertEquals('testdb-upd', $result['description']);
}
/**
*
* @depends testCustomerMysqlsAdd

View File

@@ -111,6 +111,19 @@ class TrafficTest extends TestCase
$this->assertEquals(3, $result['list'][1]['customerid']);
}
public function testAdminTrafficListCustomersFilterCustomer()
{
global $admin_userdata;
$json_result = Traffic::getLocal($admin_userdata, array(
'customer_traffic' => 1,
'loginname' => 'test1'
))->listing();
$result = json_decode($json_result, true)['data'];
$this->assertEquals(1, $result['count']);
$this->assertEquals(1, $result['list'][0]['customerid']);
}
public function testCustomerTrafficList()
{
global $admin_userdata;