Compare commits

..

45 Commits

Author SHA1 Message Date
Michael Kaufmann (d00p)
9d16790f5b Update phpMailer to 5.2.15
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-18 10:43:16 +02:00
Michael Kaufmann (d00p)
6ea4655fd8 set version to 0.9.36 for upcoming release
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-18 10:32:52 +02:00
Michael Kaufmann (d00p)
eb70e619c9 also check for punycode when customer adds a subdomain
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-18 10:28:13 +02:00
Michael Kaufmann (d00p)
41e4135f71 do not allow punycode input in domain-names
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-18 09:03:14 +02:00
Michael Kaufmann (d00p)
b03eab897a show a2enmod commands only when using apache, thx to d4n13L
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-16 18:41:01 +02:00
Michael Kaufmann
25ff78e295 Merge pull request #353 from nachtgeist/le
LE improvements, fixes #1597
2016-05-16 17:42:38 +02:00
Daniel Reichelt
6e2b1773a3 LE: support alias domains
LE CSRs are triggered for the aliasdomain target domain on

* domain deletion

* domain creation

* domain editing when
  * the aliasdomain target changes (CSR triggered both for old and new
    target)
  * wwwalias is disabled or enabled
  * letsencrypt is disabled or enabled (domain-local)

fixes #1597
2016-05-16 17:35:51 +02:00
Daniel Reichelt
f3e05742b5 LE: change semantics of setting.letsencryptreuseold
Previously setting.letsencryptreuseold determined wheter both a domain's
private key and a CSR should be re-generated.

Preparing support of alias domains in LE certificates, this is changed to
only determine the re-generation of the private key. CSRs now are always
re-generated.
2016-05-16 17:35:51 +02:00
Daniel Reichelt
001f10f74e LE: catch error due to rate-limited account registration
and fix bad english in log message
2016-05-16 17:35:51 +02:00
Daniel Reichelt
712aebb864 LE: improve SQL readability 2016-05-16 17:35:51 +02:00
Daniel Reichelt
0ae0178b4c LE: PSR-2 formatting 2016-05-16 17:35:51 +02:00
Michael Kaufmann (d00p)
1d4211a5ce remove wrong a2* commands for rhel/centos
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-16 17:20:49 +02:00
Michael Kaufmann (d00p)
da785500cc remove invalid self-closing <file /> tag as it produces php-notices and was just added for design reasons
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-14 18:39:18 +02:00
Michael Kaufmann (d00p)
bb9331904e (really) fix PHP notice #2048 Only variables should be passed by reference, thx to baudetail
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-10 11:55:03 +02:00
Michael Kaufmann (d00p)
6369e160b8 fix nscd group cache clearing call; refs #1570
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-09 21:33:07 +02:00
Michael Kaufmann (d00p)
5e09d56871 clear nscd group cache after adding a new customer to avoid permission issues of webserver; fixes #1570
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-09 08:27:01 +02:00
Michael Kaufmann (d00p)
0e79e8d670 fix default_server parameter for listen-statement in nginx since this changed since ngninx-0.8.21; fixes #1621
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-09 08:08:59 +02:00
Michael Kaufmann (d00p)
941a25ec9d avoid possible weird behaviour when resultset changes while running (if possible at all)
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-05 08:43:28 +02:00
Michael Kaufmann (d00p)
2210d3de12 fix mail-account backup; fix missing job description for admin-dashboard (outstanding tasks); avoid double backup-task insertion when customer presses refresh after scheduling the backup-job
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-05-05 08:23:46 +02:00
Michael Kaufmann
ae01f2cdb9 Merge pull request #351 from Froxlor/backup
Add Customer Backup Feature, fixes #786, fixes #975, fixes #1544, fixes #1576
2016-04-29 10:32:58 +02:00
Michael Kaufmann (d00p)
e8e980509f fix missing backup-enabled setting entry
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-04-29 10:27:19 +02:00
Michael Kaufmann (d00p)
b2cd992f92 add important information that the customer should protect the backup directory using htaccess
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-04-29 10:27:19 +02:00
Michael Kaufmann (d00p)
7c44c5ea75 handle exit of forked backup-cronjob correctly
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-04-29 10:27:19 +02:00
Michael Kaufmann (d00p)
b1446d366e add possibility to enable/disable backup function
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-04-29 10:27:19 +02:00
Michael Kaufmann (d00p)
9bfd5eb17e --exclude is relativ to path given via -C parameter
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-04-29 10:27:19 +02:00
Michael Kaufmann (d00p)
fb555027fd fix -C parameter and --exclude parameter for good now
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-04-29 10:27:19 +02:00
Michael Kaufmann (d00p)
05974de4d5 fix tar -C parameter again...
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-04-29 10:27:19 +02:00
Michael Kaufmann (d00p)
9c9bbb81de fix tar -C parameter and create_backup_tar_data list
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-04-29 10:27:18 +02:00
Michael Kaufmann (d00p)
ef7da53806 change directory before creating tarball to avoid having complete paths in it
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-04-29 10:27:18 +02:00
Michael Kaufmann (d00p)
a26ebb375b set db version for changes
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-04-29 10:27:18 +02:00
Michael Kaufmann (d00p)
c8bbefb2bb add simple backup-function for customers (testing state)
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-04-29 10:27:18 +02:00
Michael Kaufmann (d00p)
a485d9f4f9 TLSECCertificateFile and TLSECCertificateKeyFile for proftpds mod_tls require 1.3.5rc4 and later but Ubuntu 14.04 only provides 1.3.5rc3
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-04-19 13:31:09 +02:00
Michael Kaufmann (d00p)
f8be36d229 fix PHP notice #2048 Only variables should be passed by reference
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-04-17 13:44:42 +02:00
Michael Kaufmann (d00p)
28f0c3eac4 only include acme.conf to vhosts if system has ssl and LE enabled (might not exist if not)
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-04-15 15:09:11 +02:00
Michael Kaufmann
e8f5fc1a8a Merge pull request #347 from floreno/patch-3
min-height against height fix for ajax-changing-content
2016-04-12 07:36:37 +02:00
Michael Kaufmann (d00p)
a014b5cc2b minor preparations for system-hostname as 'normal' domain (to use ssl/LE/etc.)
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-04-11 09:19:43 +02:00
Michael Kaufmann (d00p)
84f1d94ad6 check for php-curl installed when cron_letsencrypt runs; format source
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-04-11 08:02:18 +02:00
Michael Kaufmann (d00p)
8565dbce8b insert task 99 (regeneration of /etc/cron.d/froxlor file) to the list of task when clicking on 'Regenerate configfiles'
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-04-11 08:01:38 +02:00
Michael Kaufmann (d00p)
72d1282651 require php-curl
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-04-11 08:00:38 +02:00
floreno
d474f2ec8f min-height against height fix for ajax-changing-content 2016-04-11 06:55:48 +02:00
Michael Kaufmann
252b42ee57 Merge pull request #346 from nachtgeist/master
fixes #1615
2016-04-10 19:08:33 +02:00
Daniel Reichelt
0dfaf376c0 remove obsolete language strings 2016-04-10 02:59:23 +02:00
Daniel Reichelt
2a05b89cc8 add explicit warning about sub-zones on usage of zonefiles 2016-04-10 02:59:23 +02:00
Daniel Reichelt
576c94f83c fix #1615 2016-04-10 02:59:22 +02:00
Michael Kaufmann (d00p)
5331127204 set version to 0.9.35.1; fix updater :x
Signed-off-by: Michael Kaufmann (d00p) <d00p@froxlor.org>
2016-04-08 13:52:06 +02:00
48 changed files with 2237 additions and 1411 deletions

View File

@@ -185,9 +185,17 @@ return array(
'onlyif' => 1 'onlyif' => 1
) )
), ),
'system_backupenabled' => array(
'label' => $lng['serversettings']['backupenabled'],
'settinggroup' => 'system',
'varname' => 'backupenabled',
'type' => 'bool',
'default' => false,
'cronmodule' => 'froxlor/backup',
'save_method' => 'storeSettingField'
), ),
), ),
), ),
); )
);
?>

View File

@@ -939,7 +939,9 @@ if ($page == 'customers'
SELECT ip, port FROM `".TABLE_PANEL_IPSANDPORTS."` SELECT ip, port FROM `".TABLE_PANEL_IPSANDPORTS."`
WHERE `id` = :defaultip WHERE `id` = :defaultip
"); ");
$srv_ip = Database::pexecute_first($srv_ip_stmt, array('defaultip' => reset(explode(',', Settings::Get('system.defaultip'))))); $default_ips = Settings::Get('system.defaultip');
$default_ips = explode(',', $default_ips);
$srv_ip = Database::pexecute_first($srv_ip_stmt, array('defaultip' => reset($default_ips)));
$replace_arr = array( $replace_arr = array(
'FIRSTNAME' => $firstname, 'FIRSTNAME' => $firstname,

File diff suppressed because it is too large Load Diff

View File

@@ -160,6 +160,8 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
inserttask('10'); inserttask('10');
// Using nameserver, insert a task which rebuilds the server config // Using nameserver, insert a task which rebuilds the server config
inserttask('4'); inserttask('4');
// cron.d file
inserttask('99');
standard_success('rebuildingconfigs', '', array('filename' => 'admin_index.php')); standard_success('rebuildingconfigs', '', array('filename' => 'admin_index.php'));

View File

@@ -54,7 +54,7 @@ if ($page == 'overview') {
} }
} }
if (hasDbUpdates($dbversion)) { if (hasDbUpdates($dbversion) || hasUpdates($version)) {
$successful_update = false; $successful_update = false;
$message = ''; $message = '';

View File

@@ -171,7 +171,7 @@ if ($page == 'overview') {
eval("echo \"" . getTemplate("domains/domainlist") . "\";"); eval("echo \"" . getTemplate("domains/domainlist") . "\";");
} elseif ($action == 'delete' && $id != 0) { } elseif ($action == 'delete' && $id != 0) {
$stmt = Database::prepare("SELECT `id`, `customerid`, `domain`, `documentroot`, `isemaildomain`, `parentdomainid` FROM `" . TABLE_PANEL_DOMAINS . "` $stmt = Database::prepare("SELECT `id`, `customerid`, `domain`, `documentroot`, `isemaildomain`, `parentdomainid`, `aliasdomain` FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `customerid` = :customerid WHERE `customerid` = :customerid
AND `id` = :id" AND `id` = :id"
); );
@@ -197,6 +197,8 @@ if ($page == 'overview') {
} }
} }
triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $log);
$log->logAction(USR_ACTION, LOG_INFO, "deleted subdomain '" . $idna_convert->decode($result['domain']) . "'"); $log->logAction(USR_ACTION, LOG_INFO, "deleted subdomain '" . $idna_convert->decode($result['domain']) . "'");
$stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_DOMAINS . "` WHERE $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_DOMAINS . "` WHERE
`customerid` = :customerid `customerid` = :customerid
@@ -245,6 +247,11 @@ if ($page == 'overview') {
} elseif ($action == 'add') { } elseif ($action == 'add') {
if ($userinfo['subdomains_used'] < $userinfo['subdomains'] || $userinfo['subdomains'] == '-1') { if ($userinfo['subdomains_used'] < $userinfo['subdomains'] || $userinfo['subdomains'] == '-1') {
if (isset($_POST['send']) && $_POST['send'] == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
if (strpos($_POST['subdomain'], '--') !== false) {
standard_error('domain_nopunycode');
}
$subdomain = $idna_convert->encode(preg_replace(array('/\:(\d)+$/', '/^https?\:\/\//'), '', validate($_POST['subdomain'], 'subdomain', '', 'subdomainiswrong'))); $subdomain = $idna_convert->encode(preg_replace(array('/\:(\d)+$/', '/^https?\:\/\//'), '', validate($_POST['subdomain'], 'subdomain', '', 'subdomainiswrong')));
$domain = $idna_convert->encode($_POST['domain']); $domain = $idna_convert->encode($_POST['domain']);
$domain_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DOMAINS . "` $domain_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DOMAINS . "`
@@ -290,6 +297,7 @@ if ($page == 'overview') {
ORDER BY `d`.`domain` ASC;" ORDER BY `d`.`domain` ASC;"
); );
$aliasdomain_check = Database::pexecute_first($aliasdomain_stmt, array("id" => $aliasdomain, "customerid" => $userinfo['customerid'])); $aliasdomain_check = Database::pexecute_first($aliasdomain_stmt, array("id" => $aliasdomain, "customerid" => $userinfo['customerid']));
triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $log);
} }
if (isset($_POST['url']) && $_POST['url'] != '' && validateUrl($idna_convert->encode($_POST['url']))) { if (isset($_POST['url']) && $_POST['url'] != '' && validateUrl($idna_convert->encode($_POST['url']))) {
@@ -342,11 +350,6 @@ if ($page == 'overview') {
} }
} }
if ($aliasdomain != 0 && $letsencrypt != 0)
{
standard_error('letsencryptdoesnotworkwithaliasdomains');
}
// Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated // Temporarily deactivate ssl_redirect until Let's Encrypt certificate was generated
if ($ssl_redirect > 0 && $letsencrypt == 1) { if ($ssl_redirect > 0 && $letsencrypt == 1) {
$ssl_redirect = 2; $ssl_redirect = 2;
@@ -610,11 +613,6 @@ if ($page == 'overview') {
$letsencrypt = '0'; $letsencrypt = '0';
} }
if ($aliasdomain != 0 && $letsencrypt != 0)
{
standard_error('letsencryptdoesnotworkwithaliasdomains');
}
// We can't enable let's encrypt for wildcard - domains // We can't enable let's encrypt for wildcard - domains
if ($iswildcarddomain == '1' && $letsencrypt == '1') { if ($iswildcarddomain == '1' && $letsencrypt == '1') {
standard_error('nowildcardwithletsencrypt'); standard_error('nowildcardwithletsencrypt');
@@ -677,6 +675,17 @@ if ($page == 'overview') {
"id" => $id "id" => $id
); );
Database::pexecute($stmt, $params); Database::pexecute($stmt, $params);
if ($result['aliasdomain'] != $aliasdomain) {
// trigger when domain id for alias destination has changed: both for old and new destination
triggerLetsEncryptCSRForAliasDestinationDomain($result['aliasdomain'], $log);
triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $log);
} else
if ($result['wwwserveralias'] != $wwwserveralias || $result['letsencrypt'] != $letsencrypt) {
// or when wwwserveralias or letsencrypt was changed
triggerLetsEncryptCSRForAliasDestinationDomain($aliasdomain, $log);
}
inserttask('1'); inserttask('1');
// Using nameserver, insert a task which rebuilds the server config // Using nameserver, insert a task which rebuilds the server config

View File

@@ -16,7 +16,6 @@
* @package Panel * @package Panel
* *
*/ */
define('AREA', 'customer'); define('AREA', 'customer');
require './lib/init.php'; require './lib/init.php';
@@ -38,9 +37,10 @@ if ($page == 'overview') {
); );
$paging = new paging($userinfo, TABLE_PANEL_HTPASSWDS, $fields); $paging = new paging($userinfo, TABLE_PANEL_HTPASSWDS, $fields);
$result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_HTPASSWDS . "` $result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_HTPASSWDS . "`
WHERE `customerid`= :customerid " . $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit() WHERE `customerid`= :customerid " . $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit());
); Database::pexecute($result_stmt, array(
Database::pexecute($result_stmt, array("customerid" => $userinfo['customerid'])); "customerid" => $userinfo['customerid']
));
$paging->setEntries(Database::num_rows()); $paging->setEntries(Database::num_rows());
$sortcode = $paging->getHtmlSortCode($lng); $sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s); $arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
@@ -58,38 +58,49 @@ if ($page == 'overview') {
$row['path'] = makeCorrectDir($row['path']); $row['path'] = makeCorrectDir($row['path']);
$row = htmlentities_array($row); $row = htmlentities_array($row);
eval("\$htpasswds.=\"" . getTemplate("extras/htpasswds_htpasswd") . "\";"); eval("\$htpasswds.=\"" . getTemplate("extras/htpasswds_htpasswd") . "\";");
$count++; $count ++;
} }
$i++; $i ++;
} }
eval("echo \"" . getTemplate("extras/htpasswds") . "\";"); eval("echo \"" . getTemplate("extras/htpasswds") . "\";");
} elseif ($action == 'delete' && $id != 0) { } elseif ($action == 'delete' && $id != 0) {
$result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_HTPASSWDS . "` $result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_HTPASSWDS . "`
WHERE `customerid`= :customerid WHERE `customerid`= :customerid
AND `id`= :id" AND `id`= :id");
); Database::pexecute($result_stmt, array(
Database::pexecute($result_stmt, array("customerid" => $userinfo['customerid'], "id" => $id)); "customerid" => $userinfo['customerid'],
"id" => $id
));
$result = $result_stmt->fetch(PDO::FETCH_ASSOC); $result = $result_stmt->fetch(PDO::FETCH_ASSOC);
if (isset($result['username']) && $result['username'] != '') { if (isset($result['username']) && $result['username'] != '') {
if (isset($_POST['send']) && $_POST['send'] == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
$stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_HTPASSWDS . "` $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_HTPASSWDS . "`
WHERE `customerid`= :customerid WHERE `customerid`= :customerid
AND `id`= :id" AND `id`= :id");
); Database::pexecute($stmt, array(
Database::pexecute($stmt, array("customerid" => $userinfo['customerid'], "id" => $id)); "customerid" => $userinfo['customerid'],
"id" => $id
));
$log->logAction(USR_ACTION, LOG_INFO, "deleted htpasswd for '" . $result['username'] . " (" . $result['path'] . ")'"); $log->logAction(USR_ACTION, LOG_INFO, "deleted htpasswd for '" . $result['username'] . " (" . $result['path'] . ")'");
inserttask('1'); inserttask('1');
redirectTo($filename, array('page' => $page, 's' => $s)); redirectTo($filename, array(
'page' => $page,
's' => $s
));
} else { } else {
if (strpos($result['path'], $userinfo['documentroot']) === 0) { if (strpos($result['path'], $userinfo['documentroot']) === 0) {
$result['path'] = str_replace($userinfo['documentroot'], "/", $result['path']); $result['path'] = str_replace($userinfo['documentroot'], "/", $result['path']);
} }
ask_yesno('extras_reallydelete', $filename, array('id' => $id, 'page' => $page, 'action' => $action), $result['username'] . ' (' . $result['path'] . ')'); ask_yesno('extras_reallydelete', $filename, array(
'id' => $id,
'page' => $page,
'action' => $action
), $result['username'] . ' (' . $result['path'] . ')');
} }
} }
} elseif ($action == 'add') { } elseif ($action == 'add') {
@@ -104,8 +115,7 @@ if ($page == 'overview') {
$username_path_check_stmt = Database::prepare("SELECT `id`, `username`, `path` FROM `" . TABLE_PANEL_HTPASSWDS . "` $username_path_check_stmt = Database::prepare("SELECT `id`, `username`, `path` FROM `" . TABLE_PANEL_HTPASSWDS . "`
WHERE `username`= :username WHERE `username`= :username
AND `path`= :path AND `path`= :path
AND `customerid`= :customerid" AND `customerid`= :customerid");
);
$params = array( $params = array(
"username" => $username, "username" => $username,
"path" => $path, "path" => $path,
@@ -121,16 +131,22 @@ if ($page == 'overview') {
$password = crypt($_POST['directory_password']); $password = crypt($_POST['directory_password']);
} }
if (!$_POST['path']) { if (! $_POST['path']) {
standard_error('invalidpath'); standard_error('invalidpath');
} }
if ($username == '') { if ($username == '') {
standard_error(array('stringisempty', 'myloginname')); standard_error(array(
'stringisempty',
'myloginname'
));
} elseif ($username_path_check['username'] == $username && $username_path_check['path'] == $path) { } elseif ($username_path_check['username'] == $username && $username_path_check['path'] == $path) {
standard_error('userpathcombinationdupe'); standard_error('userpathcombinationdupe');
} elseif ($_POST['directory_password'] == '') { } elseif ($_POST['directory_password'] == '') {
standard_error(array('stringisempty', 'mypassword')); standard_error(array(
'stringisempty',
'mypassword'
));
} elseif ($path == '') { } elseif ($path == '') {
standard_error('patherror'); standard_error('patherror');
} elseif ($_POST['directory_password'] == $username) { } elseif ($_POST['directory_password'] == $username) {
@@ -141,8 +157,7 @@ if ($page == 'overview') {
`username` = :username, `username` = :username,
`password` = :password, `password` = :password,
`path` = :path, `path` = :path,
`authname` = :authname" `authname` = :authname");
);
$params = array( $params = array(
"customerid" => $userinfo['customerid'], "customerid" => $userinfo['customerid'],
"username" => $username, "username" => $username,
@@ -153,12 +168,15 @@ if ($page == 'overview') {
Database::pexecute($stmt, $params); Database::pexecute($stmt, $params);
$log->logAction(USR_ACTION, LOG_INFO, "added htpasswd for '" . $username . " (" . $path . ")'"); $log->logAction(USR_ACTION, LOG_INFO, "added htpasswd for '" . $username . " (" . $path . ")'");
inserttask('1'); inserttask('1');
redirectTo($filename, array('page' => $page, 's' => $s)); redirectTo($filename, array(
'page' => $page,
's' => $s
));
} }
} else { } else {
$pathSelect = makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']); $pathSelect = makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']);
$htpasswd_add_data = include_once dirname(__FILE__).'/lib/formfields/customer/extras/formfield.htpasswd_add.php'; $htpasswd_add_data = include_once dirname(__FILE__) . '/lib/formfields/customer/extras/formfield.htpasswd_add.php';
$htpasswd_add_form = htmlform::genHTMLForm($htpasswd_add_data); $htpasswd_add_form = htmlform::genHTMLForm($htpasswd_add_data);
$title = $htpasswd_add_data['htpasswd_add']['title']; $title = $htpasswd_add_data['htpasswd_add']['title'];
@@ -169,9 +187,11 @@ if ($page == 'overview') {
} elseif ($action == 'edit' && $id != 0) { } elseif ($action == 'edit' && $id != 0) {
$result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_HTPASSWDS . "` $result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_HTPASSWDS . "`
WHERE `customerid`= :customerid WHERE `customerid`= :customerid
AND `id`= :id" AND `id`= :id");
); Database::pexecute($result_stmt, array(
Database::pexecute($result_stmt, array("customerid" => $userinfo['customerid'], "id" => $id)); "customerid" => $userinfo['customerid'],
"id" => $id
));
$result = $result_stmt->fetch(PDO::FETCH_ASSOC); $result = $result_stmt->fetch(PDO::FETCH_ASSOC);
if (isset($result['username']) && $result['username'] != '') { if (isset($result['username']) && $result['username'] != '') {
@@ -208,19 +228,21 @@ if ($page == 'overview') {
} }
if ($pwd_sql != '' || $auth_sql != '') { if ($pwd_sql != '' || $auth_sql != '') {
if ($pwd_sql !='' && $auth_sql != '') { if ($pwd_sql != '' && $auth_sql != '') {
$pwd_sql.= ', '; $pwd_sql .= ', ';
} }
$stmt = Database::prepare("UPDATE `" . TABLE_PANEL_HTPASSWDS . "` $stmt = Database::prepare("UPDATE `" . TABLE_PANEL_HTPASSWDS . "`
SET ".$pwd_sql.$auth_sql." SET " . $pwd_sql . $auth_sql . "
WHERE `customerid`= :customerid WHERE `customerid`= :customerid
AND `id`= :id" AND `id`= :id");
);
Database::pexecute($stmt, $params); Database::pexecute($stmt, $params);
$log->logAction(USR_ACTION, LOG_INFO, "edited htpasswd for '" . $result['username'] . " (" . $result['path'] . ")'"); $log->logAction(USR_ACTION, LOG_INFO, "edited htpasswd for '" . $result['username'] . " (" . $result['path'] . ")'");
inserttask('1'); inserttask('1');
redirectTo($filename, array('page' => $page, 's' => $s)); redirectTo($filename, array(
'page' => $page,
's' => $s
));
} }
} else { } else {
if (strpos($result['path'], $userinfo['documentroot']) === 0) { if (strpos($result['path'], $userinfo['documentroot']) === 0) {
@@ -229,7 +251,7 @@ if ($page == 'overview') {
$result = htmlentities_array($result); $result = htmlentities_array($result);
$htpasswd_edit_data = include_once dirname(__FILE__).'/lib/formfields/customer/extras/formfield.htpasswd_edit.php'; $htpasswd_edit_data = include_once dirname(__FILE__) . '/lib/formfields/customer/extras/formfield.htpasswd_edit.php';
$htpasswd_edit_form = htmlform::genHTMLForm($htpasswd_edit_data); $htpasswd_edit_form = htmlform::genHTMLForm($htpasswd_edit_data);
$title = $htpasswd_edit_data['htpasswd_edit']['title']; $title = $htpasswd_edit_data['htpasswd_edit']['title'];
@@ -252,9 +274,10 @@ if ($page == 'overview') {
); );
$paging = new paging($userinfo, TABLE_PANEL_HTACCESS, $fields); $paging = new paging($userinfo, TABLE_PANEL_HTACCESS, $fields);
$result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_HTACCESS . "` $result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_HTACCESS . "`
WHERE `customerid`= :customerid " . $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit() WHERE `customerid`= :customerid " . $paging->getSqlWhere(true) . " " . $paging->getSqlOrderBy() . " " . $paging->getSqlLimit());
); Database::pexecute($result_stmt, array(
Database::pexecute($result_stmt, array("customerid" => $userinfo['customerid'])); "customerid" => $userinfo['customerid']
));
$paging->setEntries(Database::num_rows()); $paging->setEntries(Database::num_rows());
$sortcode = $paging->getHtmlSortCode($lng); $sortcode = $paging->getHtmlSortCode($lng);
$arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s); $arrowcode = $paging->getHtmlArrowCode($filename . '?page=' . $page . '&s=' . $s);
@@ -278,49 +301,60 @@ if ($page == 'overview') {
$row['options_cgi'] = str_replace('0', $lng['panel']['no'], $row['options_cgi']); $row['options_cgi'] = str_replace('0', $lng['panel']['no'], $row['options_cgi']);
$row = htmlentities_array($row); $row = htmlentities_array($row);
eval("\$htaccess.=\"" . getTemplate("extras/htaccess_htaccess") . "\";"); eval("\$htaccess.=\"" . getTemplate("extras/htaccess_htaccess") . "\";");
$count++; $count ++;
} }
$i++; $i ++;
} }
eval("echo \"" . getTemplate("extras/htaccess") . "\";"); eval("echo \"" . getTemplate("extras/htaccess") . "\";");
} elseif ($action == 'delete' && $id != 0) { } elseif ($action == 'delete' && $id != 0) {
$result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_HTACCESS . "` $result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_HTACCESS . "`
WHERE `customerid` = :customerid WHERE `customerid` = :customerid
AND `id` = :id" AND `id` = :id");
); Database::pexecute($result_stmt, array(
Database::pexecute($result_stmt, array("customerid" => $userinfo['customerid'], "id" => $id)); "customerid" => $userinfo['customerid'],
"id" => $id
));
$result = $result_stmt->fetch(PDO::FETCH_ASSOC); $result = $result_stmt->fetch(PDO::FETCH_ASSOC);
if (isset($result['customerid']) && $result['customerid'] != '' && $result['customerid'] == $userinfo['customerid']) { if (isset($result['customerid']) && $result['customerid'] != '' && $result['customerid'] == $userinfo['customerid']) {
if (isset($_POST['send']) && $_POST['send'] == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
// do we have to remove the symlink and folder in suexecpath? // do we have to remove the symlink and folder in suexecpath?
if ((int)Settings::Get('perl.suexecworkaround') == 1) { if ((int) Settings::Get('perl.suexecworkaround') == 1) {
$loginname = getCustomerDetail($result['customerid'], 'loginname'); $loginname = getCustomerDetail($result['customerid'], 'loginname');
$suexecpath = makeCorrectDir(Settings::Get('perl.suexecpath').'/'.$loginname.'/'.md5($result['path']).'/'); $suexecpath = makeCorrectDir(Settings::Get('perl.suexecpath') . '/' . $loginname . '/' . md5($result['path']) . '/');
$perlsymlink = makeCorrectFile($result['path'].'/cgi-bin'); $perlsymlink = makeCorrectFile($result['path'] . '/cgi-bin');
// remove symlink // remove symlink
if (file_exists($perlsymlink)) { if (file_exists($perlsymlink)) {
safe_exec('rm -f '.escapeshellarg($perlsymlink)); safe_exec('rm -f ' . escapeshellarg($perlsymlink));
$log->logAction(USR_ACTION, LOG_DEBUG, "deleted suexecworkaround symlink '" . $perlsymlink . "'"); $log->logAction(USR_ACTION, LOG_DEBUG, "deleted suexecworkaround symlink '" . $perlsymlink . "'");
} }
// remove folder in suexec-path // remove folder in suexec-path
if (file_exists($suexecpath)) { if (file_exists($suexecpath)) {
safe_exec('rm -rf '.escapeshellarg($suexecpath)); safe_exec('rm -rf ' . escapeshellarg($suexecpath));
$log->logAction(USR_ACTION, LOG_DEBUG, "deleted suexecworkaround path '" . $suexecpath . "'"); $log->logAction(USR_ACTION, LOG_DEBUG, "deleted suexecworkaround path '" . $suexecpath . "'");
} }
} }
$stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_HTACCESS . "` $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_HTACCESS . "`
WHERE `customerid`= :customerid WHERE `customerid`= :customerid
AND `id`= :id" AND `id`= :id");
); Database::pexecute($stmt, array(
Database::pexecute($stmt, array("customerid" => $userinfo['customerid'], "id" => $id)); "customerid" => $userinfo['customerid'],
"id" => $id
));
$log->logAction(USR_ACTION, LOG_INFO, "deleted htaccess for '" . str_replace($userinfo['documentroot'], '/', $result['path']) . "'"); $log->logAction(USR_ACTION, LOG_INFO, "deleted htaccess for '" . str_replace($userinfo['documentroot'], '/', $result['path']) . "'");
inserttask('1'); inserttask('1');
redirectTo($filename, array('page' => $page, 's' => $s)); redirectTo($filename, array(
'page' => $page,
's' => $s
));
} else { } else {
ask_yesno('extras_reallydelete_pathoptions', $filename, array('id' => $id, 'page' => $page, 'action' => $action), str_replace($userinfo['documentroot'], '/', $result['path'])); ask_yesno('extras_reallydelete_pathoptions', $filename, array(
'id' => $id,
'page' => $page,
'action' => $action
), str_replace($userinfo['documentroot'], '/', $result['path']));
} }
} }
} elseif ($action == 'add') { } elseif ($action == 'add') {
@@ -330,16 +364,18 @@ if ($page == 'overview') {
$path = makeCorrectDir($userinfo['documentroot'] . '/' . $path); $path = makeCorrectDir($userinfo['documentroot'] . '/' . $path);
$path_dupe_check_stmt = Database::prepare("SELECT `id`, `path` FROM `" . TABLE_PANEL_HTACCESS . "` $path_dupe_check_stmt = Database::prepare("SELECT `id`, `path` FROM `" . TABLE_PANEL_HTACCESS . "`
WHERE `path`= :path WHERE `path`= :path
AND `customerid`= :customerid" AND `customerid`= :customerid");
); Database::pexecute($path_dupe_check_stmt, array(
Database::pexecute($path_dupe_check_stmt, array("path" => $path, "customerid" => $userinfo['customerid'])); "path" => $path,
"customerid" => $userinfo['customerid']
));
$path_dupe_check = $path_dupe_check_stmt->fetch(PDO::FETCH_ASSOC); $path_dupe_check = $path_dupe_check_stmt->fetch(PDO::FETCH_ASSOC);
if (!$_POST['path']) { if (! $_POST['path']) {
standard_error('invalidpath'); standard_error('invalidpath');
} }
if (isset($_POST['options_cgi']) && (int)$_POST['options_cgi'] != 0) { if (isset($_POST['options_cgi']) && (int) $_POST['options_cgi'] != 0) {
$options_cgi = '1'; $options_cgi = '1';
} else { } else {
$options_cgi = '0'; $options_cgi = '0';
@@ -372,8 +408,7 @@ if ($page == 'overview') {
`error404path` = :error404path, `error404path` = :error404path,
`error403path` = :error403path, `error403path` = :error403path,
`error500path` = :error500path, `error500path` = :error500path,
`options_cgi` = :options_cgi' `options_cgi` = :options_cgi');
);
$params = array( $params = array(
"customerid" => $userinfo['customerid'], "customerid" => $userinfo['customerid'],
"path" => $path, "path" => $path,
@@ -387,13 +422,16 @@ if ($page == 'overview') {
$log->logAction(USR_ACTION, LOG_INFO, "added htaccess for '" . $path . "'"); $log->logAction(USR_ACTION, LOG_INFO, "added htaccess for '" . $path . "'");
inserttask('1'); inserttask('1');
redirectTo($filename, array('page' => $page, 's' => $s)); redirectTo($filename, array(
'page' => $page,
's' => $s
));
} }
} else { } else {
$pathSelect = makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']); $pathSelect = makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']);
$cperlenabled = customerHasPerlEnabled($userinfo['customerid']); $cperlenabled = customerHasPerlEnabled($userinfo['customerid']);
$htaccess_add_data = include_once dirname(__FILE__).'/lib/formfields/customer/extras/formfield.htaccess_add.php'; $htaccess_add_data = include_once dirname(__FILE__) . '/lib/formfields/customer/extras/formfield.htaccess_add.php';
$htaccess_add_form = htmlform::genHTMLForm($htaccess_add_data); $htaccess_add_form = htmlform::genHTMLForm($htaccess_add_data);
$title = $htaccess_add_data['htaccess_add']['title']; $title = $htaccess_add_data['htaccess_add']['title'];
@@ -404,9 +442,11 @@ if ($page == 'overview') {
} elseif (($action == 'edit') && ($id != 0)) { } elseif (($action == 'edit') && ($id != 0)) {
$result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_HTACCESS . "` $result_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_HTACCESS . "`
WHERE `customerid` = :customerid WHERE `customerid` = :customerid
AND `id` = :id" AND `id` = :id");
); Database::pexecute($result_stmt, array(
Database::pexecute($result_stmt, array("customerid" => $userinfo['customerid'], "id" => $id)); "customerid" => $userinfo['customerid'],
"id" => $id
));
$result = $result_stmt->fetch(PDO::FETCH_ASSOC); $result = $result_stmt->fetch(PDO::FETCH_ASSOC);
if ((isset($result['customerid'])) && ($result['customerid'] != '') && ($result['customerid'] == $userinfo['customerid'])) { if ((isset($result['customerid'])) && ($result['customerid'] != '') && ($result['customerid'] == $userinfo['customerid'])) {
@@ -426,12 +466,7 @@ if ($page == 'overview') {
$error403path = correctErrorDocument($_POST['error403path']); $error403path = correctErrorDocument($_POST['error403path']);
$error500path = correctErrorDocument($_POST['error500path']); $error500path = correctErrorDocument($_POST['error500path']);
if (($option_indexes != $result['options_indexes']) if (($option_indexes != $result['options_indexes']) || ($error404path != $result['error404path']) || ($error403path != $result['error403path']) || ($error500path != $result['error500path']) || ($options_cgi != $result['options_cgi'])) {
|| ($error404path != $result['error404path'])
|| ($error403path != $result['error403path'])
|| ($error500path != $result['error500path'])
|| ($options_cgi != $result['options_cgi'])
) {
inserttask('1'); inserttask('1');
$stmt = Database::prepare("UPDATE `" . TABLE_PANEL_HTACCESS . "` $stmt = Database::prepare("UPDATE `" . TABLE_PANEL_HTACCESS . "`
SET `options_indexes` = :options_indexes, SET `options_indexes` = :options_indexes,
@@ -440,8 +475,7 @@ if ($page == 'overview') {
`error500path` = :error500path, `error500path` = :error500path,
`options_cgi` = :options_cgi `options_cgi` = :options_cgi
WHERE `customerid` = :customerid WHERE `customerid` = :customerid
AND `id` = :id" AND `id` = :id");
);
$params = array( $params = array(
"customerid" => $userinfo['customerid'], "customerid" => $userinfo['customerid'],
"options_indexes" => $_POST['options_indexes'] == '1' ? '1' : '0', "options_indexes" => $_POST['options_indexes'] == '1' ? '1' : '0',
@@ -455,7 +489,10 @@ if ($page == 'overview') {
$log->logAction(USR_ACTION, LOG_INFO, "edited htaccess for '" . str_replace($userinfo['documentroot'], '/', $result['path']) . "'"); $log->logAction(USR_ACTION, LOG_INFO, "edited htaccess for '" . str_replace($userinfo['documentroot'], '/', $result['path']) . "'");
} }
redirectTo($filename, array('page' => $page, 's' => $s)); redirectTo($filename, array(
'page' => $page,
's' => $s
));
} else { } else {
if (strpos($result['path'], $userinfo['documentroot']) === 0) { if (strpos($result['path'], $userinfo['documentroot']) === 0) {
$result['path'] = str_replace($userinfo['documentroot'], "/", $result['path']); $result['path'] = str_replace($userinfo['documentroot'], "/", $result['path']);
@@ -466,12 +503,12 @@ if ($page == 'overview') {
$result['error500path'] = $result['error500path']; $result['error500path'] = $result['error500path'];
$cperlenabled = customerHasPerlEnabled($userinfo['customerid']); $cperlenabled = customerHasPerlEnabled($userinfo['customerid']);
/* /*
$options_indexes = makeyesno('options_indexes', '1', '0', $result['options_indexes']); * $options_indexes = makeyesno('options_indexes', '1', '0', $result['options_indexes']);
$options_cgi = makeyesno('options_cgi', '1', '0', $result['options_cgi']); * $options_cgi = makeyesno('options_cgi', '1', '0', $result['options_cgi']);
*/ */
$result = htmlentities_array($result); $result = htmlentities_array($result);
$htaccess_edit_data = include_once dirname(__FILE__).'/lib/formfields/customer/extras/formfield.htaccess_edit.php'; $htaccess_edit_data = include_once dirname(__FILE__) . '/lib/formfields/customer/extras/formfield.htaccess_edit.php';
$htaccess_edit_form = htmlform::genHTMLForm($htaccess_edit_data); $htaccess_edit_form = htmlform::genHTMLForm($htaccess_edit_data);
$title = $htaccess_edit_data['htaccess_edit']['title']; $title = $htaccess_edit_data['htaccess_edit']['title'];
@@ -481,4 +518,76 @@ if ($page == 'overview') {
} }
} }
} }
} elseif ($page == 'backup') {
if (Settings::Get('system.backupenabled') == 1)
{
if ($action == '') {
$log->logAction(USR_ACTION, LOG_NOTICE, "viewed customer_extras::backup");
// check whether there is a backup-job for this customer
$sel_stmt = Database::prepare("SELECT * FROM `".TABLE_PANEL_TASKS."` WHERE `type` = '20'");
Database::pexecute($sel_stmt);
while ($entry = $sel_stmt->fetch())
{
$data = unserialize($entry['data']);
if ($data['customerid'] == $userinfo['customerid']) {
standard_error('customerhasongoingbackupjob');
}
}
if (isset($_POST['send']) && $_POST['send'] == 'send') {
if (! $_POST['path']) {
standard_error('invalidpath');
}
$path = makeCorrectDir(validate($_POST['path'], 'path'));
$path = makeCorrectDir($userinfo['documentroot'] . '/' . $path);
$backup_dbs = isset($_POST['backup_dbs']) ? intval($_POST['backup_dbs']) : 0;
$backup_mail = isset($_POST['backup_mail']) ? intval($_POST['backup_mail']) : 0;
$backup_web = isset($_POST['backup_web']) ? intval($_POST['backup_web']) : 0;
if ($backup_dbs != '1') {
$backup_dbs = '0';
}
if ($backup_mail != '1') {
$backup_mail = '0';
}
if ($backup_web != '1') {
$backup_web = '0';
}
$task_data = array(
'customerid' => $userinfo['customerid'],
'uid' => $userinfo['guid'],
'gid' => $userinfo['guid'],
'loginname' => $userinfo['loginname'],
'destdir' => $path,
'backup_dbs' => $backup_dbs,
'backup_mail' => $backup_mail,
'backup_web' => $backup_web
);
// schedule backup job
inserttask('20', $task_data);
standard_success('backupscheduled');
} else {
$pathSelect = makePathfield($userinfo['documentroot'], $userinfo['guid'], $userinfo['guid']);
$backup_data = include_once dirname(__FILE__) . '/lib/formfields/customer/extras/formfield.backup.php';
$backup_form = htmlform::genHTMLForm($backup_data);
$title = $backup_data['backup']['title'];
$image = $backup_data['backup']['image'];
eval("echo \"" . getTemplate("extras/backup") . "\";");
}
}
}
else
{
standard_error('backupfunctionnotenabled');
}
} }

View File

@@ -525,6 +525,7 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES
('system', 'letsencryptkeysize', '4096'), ('system', 'letsencryptkeysize', '4096'),
('system', 'letsencryptreuseold', 0), ('system', 'letsencryptreuseold', 0),
('system', 'leenabled', '0'), ('system', 'leenabled', '0'),
('system', 'backupenabled', '0'),
('panel', 'decimal_places', '4'), ('panel', 'decimal_places', '4'),
('panel', 'adminmail', 'admin@SERVERNAME'), ('panel', 'adminmail', 'admin@SERVERNAME'),
('panel', 'phpmyadmin_url', ''), ('panel', 'phpmyadmin_url', ''),
@@ -555,8 +556,8 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES
('panel', 'password_numeric', '0'), ('panel', 'password_numeric', '0'),
('panel', 'password_special_char_required', '0'), ('panel', 'password_special_char_required', '0'),
('panel', 'password_special_char', '!?<>§$%+#=@'), ('panel', 'password_special_char', '!?<>§$%+#=@'),
('panel', 'version', '0.9.35'), ('panel', 'version', '0.9.36'),
('panel', 'db_version', '201603150'); ('panel', 'db_version', '201604270');
DROP TABLE IF EXISTS `panel_tasks`; DROP TABLE IF EXISTS `panel_tasks`;
@@ -765,7 +766,8 @@ INSERT INTO `cronjobs_run` (`id`, `module`, `cronfile`, `interval`, `isactive`,
(4, 'froxlor/ticket', 'ticketarchive', '1 MONTH', '1', 'cron_ticketarchive'), (4, 'froxlor/ticket', 'ticketarchive', '1 MONTH', '1', 'cron_ticketarchive'),
(5, 'froxlor/reports', 'usage_report', '1 DAY', '1', 'cron_usage_report'), (5, 'froxlor/reports', 'usage_report', '1 DAY', '1', 'cron_usage_report'),
(6, 'froxlor/core', 'mailboxsize', '6 HOUR', '1', 'cron_mailboxsize'), (6, 'froxlor/core', 'mailboxsize', '6 HOUR', '1', 'cron_mailboxsize'),
(7, 'froxlor/letsencrypt', 'letsencrypt', '5 MINUTE', '0', 'cron_letsencrypt'); (7, 'froxlor/letsencrypt', 'letsencrypt', '5 MINUTE', '0', 'cron_letsencrypt'),
(8, 'froxlor/backup', 'backup', '1 DAY', '1', 'cron_backup');

File diff suppressed because it is too large Load Diff

View File

@@ -34,7 +34,6 @@ $lng['requirements']['phpbcmath'] = 'PHP bcmath-extension...';
$lng['requirements']['phpcurl'] = 'PHP curl-extension...'; $lng['requirements']['phpcurl'] = 'PHP curl-extension...';
$lng['requirements']['phpmbstring'] = 'PHP mbstring-extension...'; $lng['requirements']['phpmbstring'] = 'PHP mbstring-extension...';
$lng['requirements']['bcmathdescription'] = 'Traffic-calculation related functions will not work correctly!'; $lng['requirements']['bcmathdescription'] = 'Traffic-calculation related functions will not work correctly!';
$lng['requirements']['curldescription'] = 'Version-check and news-feed may not work correctly!';
$lng['requirements']['openbasedir'] = 'open_basedir...'; $lng['requirements']['openbasedir'] = 'open_basedir...';
$lng['requirements']['openbasedirenabled'] = 'Froxlor will not work properly with open_basedir enabled. Please disable open_basedir for Froxlor in the coresponding php.ini'; $lng['requirements']['openbasedirenabled'] = 'Froxlor will not work properly with open_basedir enabled. Please disable open_basedir for Froxlor in the coresponding php.ini';
$lng['requirements']['diedbecauseofrequirements'] = 'Cannot install Froxlor without these requirements! Try to fix them and retry.'; $lng['requirements']['diedbecauseofrequirements'] = 'Cannot install Froxlor without these requirements! Try to fix them and retry.';

View File

@@ -34,7 +34,6 @@ $lng['requirements']['phpbcmath'] = 'extension PHP bcmath ...';
$lng['requirements']['phpcurl'] = 'extension PHP curl...'; $lng['requirements']['phpcurl'] = 'extension PHP curl...';
$lng['requirements']['phpmbstring'] = 'extension PHP mbstring...'; $lng['requirements']['phpmbstring'] = 'extension PHP mbstring...';
$lng['requirements']['bcmathdescription'] = 'Les fonctions de calcul de traffic ne fonctionneront pas correctement!'; $lng['requirements']['bcmathdescription'] = 'Les fonctions de calcul de traffic ne fonctionneront pas correctement!';
$lng['requirements']['curldescription'] = 'Les vérifications de version et les flux d\'information peuvent ne pas fonctionner correctement!';
$lng['requirements']['openbasedir'] = 'open_basedir...'; $lng['requirements']['openbasedir'] = 'open_basedir...';
$lng['requirements']['openbasedirenabled'] = 'Froxlor ne fonctionnera pas correctement avec open_basedir activé. Merci de désactiver open_basedir pour Froxlor dans le php.ini correspondant'; $lng['requirements']['openbasedirenabled'] = 'Froxlor ne fonctionnera pas correctement avec open_basedir activé. Merci de désactiver open_basedir pour Froxlor dans le php.ini correspondant';
$lng['requirements']['diedbecauseofrequirements'] = 'Impossible d\'installer Froxlor sans ces prérequis! Essayez de les corriger et essayez à nouveau.'; $lng['requirements']['diedbecauseofrequirements'] = 'Impossible d\'installer Froxlor sans ces prérequis! Essayez de les corriger et essayez à nouveau.';

View File

@@ -34,7 +34,6 @@ $lng['requirements']['phpbcmath'] = 'PHP bcmath-Erweiterung...';
$lng['requirements']['phpcurl'] = 'PHP curl-Erweiterung...'; $lng['requirements']['phpcurl'] = 'PHP curl-Erweiterung...';
$lng['requirements']['phpmbstring'] = 'PHP mbstring-Erweiterung...'; $lng['requirements']['phpmbstring'] = 'PHP mbstring-Erweiterung...';
$lng['requirements']['bcmathdescription'] = 'Traffic-Berechnungs bezogene Funktionen stehen nicht vollständig zur Verfügung!'; $lng['requirements']['bcmathdescription'] = 'Traffic-Berechnungs bezogene Funktionen stehen nicht vollständig zur Verfügung!';
$lng['requirements']['curldescription'] = 'Versions-Prüfung und News-Feed stehen nicht vollständig zur Verfügung!';
$lng['requirements']['openbasedir'] = 'open_basedir genutzt wird...'; $lng['requirements']['openbasedir'] = 'open_basedir genutzt wird...';
$lng['requirements']['openbasedirenabled'] = 'Froxlor wird mit aktiviertem open_basedir nicht vollständig funktionieren. Bitte deaktivieren Sie open_basedir für Froxlor in der entsprechenden php.ini'; $lng['requirements']['openbasedirenabled'] = 'Froxlor wird mit aktiviertem open_basedir nicht vollständig funktionieren. Bitte deaktivieren Sie open_basedir für Froxlor in der entsprechenden php.ini';
$lng['requirements']['diedbecauseofrequirements'] = 'Kann Froxlor ohne diese Voraussetzungen nicht installieren! Beheben Sie die angezeigten Probleme und versuchen Sie es erneut.'; $lng['requirements']['diedbecauseofrequirements'] = 'Kann Froxlor ohne diese Voraussetzungen nicht installieren! Beheben Sie die angezeigten Probleme und versuchen Sie es erneut.';

View File

@@ -3284,3 +3284,39 @@ if (isFroxlorVersion('0.9.35-rc1')) {
updateToVersion('0.9.35'); updateToVersion('0.9.35');
} }
if (isFroxlorVersion('0.9.35')) {
showUpdateStep("Updating from 0.9.35 to 0.9.35.1");
lastStepStatus(0);
updateToVersion('0.9.35.1');
}
if (isFroxlorVersion('0.9.35.1') && isDatabaseVersion('201603150')) {
showUpdateStep("Adding new backup settings and cron");
$enable_backup = isset($_POST['enable_backup']) ? (int) $_POST['enable_backup'] : "0";
Settings::AddNew("system.backupenabled", $enable_backup);
$stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_CRONRUNS . "` SET
`module` = 'froxlor/backup',
`cronfile` = 'backup',
`interval` = '1 DAY',
`desc_lng_key` = 'cron_backup',
`lastrun` = 0,
`isactive` = :isactive"
);
Database::pexecute($stmt, array('isactive' => $enable_backup));
lastStepStatus(0);
updateToDbVersion('201604270');
}
if (isFroxlorVersion('0.9.35.1')) {
showUpdateStep("Updating from 0.9.35.1 to 0.9.36 final");
lastStepStatus(0);
updateToVersion('0.9.36');
}

View File

@@ -708,4 +708,12 @@ function parseAndOutputPreconfig(&$has_preconfig, &$return, $current_version, $c
$question.= makeyesno('enable_letsencrypt', '1', '0', '1').'<br />'; $question.= makeyesno('enable_letsencrypt', '1', '0', '1').'<br />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";"); eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
} }
if (versionInUpdate($current_db_version, '201604270')) {
$has_preconfig = true;
$description = 'You can chose whether you want to enable or disable our backup function.<br /><br />';
$question = '<strong>Do you want to enable Backup? (default: no):</strong>&nbsp;';
$question.= makeyesno('enable_backup', '1', '0', '0').'<br />';
eval("\$return.=\"" . getTemplate("update/preconfigitem") . "\";");
}
} }

View File

@@ -31,7 +31,7 @@ class PHPMailer
* The PHPMailer Version number. * The PHPMailer Version number.
* @var string * @var string
*/ */
public $Version = '5.2.14'; public $Version = '5.2.15';
/** /**
* Email priority. * Email priority.
@@ -352,6 +352,7 @@ class PHPMailer
/** /**
* Whether to split multiple to addresses into multiple messages * Whether to split multiple to addresses into multiple messages
* or send them all in one message. * or send them all in one message.
* Only supported in `mail` and `sendmail` transports, not in SMTP.
* @var boolean * @var boolean
*/ */
public $SingleTo = false; public $SingleTo = false;
@@ -446,6 +447,15 @@ class PHPMailer
*/ */
public $XMailer = ''; public $XMailer = '';
/**
* Which validator to use by default when validating email addresses.
* May be a callable to inject your own validator, but there are several built-in validators.
* @see PHPMailer::validateAddress()
* @var string|callable
* @static
*/
public static $validator = 'auto';
/** /**
* An instance of the SMTP sender class. * An instance of the SMTP sender class.
* @var SMTP * @var SMTP
@@ -634,10 +644,12 @@ class PHPMailer
* Constructor. * Constructor.
* @param boolean $exceptions Should we throw external exceptions? * @param boolean $exceptions Should we throw external exceptions?
*/ */
public function __construct($exceptions = false) public function __construct($exceptions = null)
{ {
if ($exceptions !== null) {
$this->exceptions = (boolean)$exceptions; $this->exceptions = (boolean)$exceptions;
} }
}
/** /**
* Destructor. * Destructor.
@@ -645,10 +657,8 @@ class PHPMailer
public function __destruct() public function __destruct()
{ {
//Close any open SMTP connection nicely //Close any open SMTP connection nicely
if ($this->Mailer == 'smtp') {
$this->smtpClose(); $this->smtpClose();
} }
}
/** /**
* Call mail() in a safe_mode-aware fashion. * Call mail() in a safe_mode-aware fashion.
@@ -713,7 +723,7 @@ class PHPMailer
case 'echo': case 'echo':
default: default:
//Normalize line breaks //Normalize line breaks
$str = preg_replace('/(\r\n|\r|\n)/ms', "\n", $str); $str = preg_replace('/\r\n?/ms', "\n", $str);
echo gmdate('Y-m-d H:i:s') . "\t" . str_replace( echo gmdate('Y-m-d H:i:s') . "\t" . str_replace(
"\n", "\n",
"\n \t ", "\n \t ",
@@ -850,7 +860,7 @@ class PHPMailer
$name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
if (($pos = strrpos($address, '@')) === false) { if (($pos = strrpos($address, '@')) === false) {
// At-sign is misssing. // At-sign is misssing.
$error_message = $this->lang('invalid_address') . $address; $error_message = $this->lang('invalid_address') . " (addAnAddress $kind): $address";
$this->setError($error_message); $this->setError($error_message);
$this->edebug($error_message); $this->edebug($error_message);
if ($this->exceptions) { if ($this->exceptions) {
@@ -900,7 +910,7 @@ class PHPMailer
return false; return false;
} }
if (!$this->validateAddress($address)) { if (!$this->validateAddress($address)) {
$error_message = $this->lang('invalid_address') . $address; $error_message = $this->lang('invalid_address') . " (addAnAddress $kind): $address";
$this->setError($error_message); $this->setError($error_message);
$this->edebug($error_message); $this->edebug($error_message);
if ($this->exceptions) { if ($this->exceptions) {
@@ -994,7 +1004,7 @@ class PHPMailer
if (($pos = strrpos($address, '@')) === false or if (($pos = strrpos($address, '@')) === false or
(!$this->has8bitChars(substr($address, ++$pos)) or !$this->idnSupported()) and (!$this->has8bitChars(substr($address, ++$pos)) or !$this->idnSupported()) and
!$this->validateAddress($address)) { !$this->validateAddress($address)) {
$error_message = $this->lang('invalid_address') . $address; $error_message = $this->lang('invalid_address') . " (setFrom) $address";
$this->setError($error_message); $this->setError($error_message);
$this->edebug($error_message); $this->edebug($error_message);
if ($this->exceptions) { if ($this->exceptions) {
@@ -1027,19 +1037,30 @@ class PHPMailer
/** /**
* Check that a string looks like an email address. * Check that a string looks like an email address.
* @param string $address The email address to check * @param string $address The email address to check
* @param string $patternselect A selector for the validation pattern to use : * @param string|callable $patternselect A selector for the validation pattern to use :
* * `auto` Pick best pattern automatically; * * `auto` Pick best pattern automatically;
* * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14; * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14;
* * `pcre` Use old PCRE implementation; * * `pcre` Use old PCRE implementation;
* * `php` Use PHP built-in FILTER_VALIDATE_EMAIL; * * `php` Use PHP built-in FILTER_VALIDATE_EMAIL;
* * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements. * * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements.
* * `noregex` Don't use a regex: super fast, really dumb. * * `noregex` Don't use a regex: super fast, really dumb.
* Alternatively you may pass in a callable to inject your own validator, for example:
* PHPMailer::validateAddress('user@example.com', function($address) {
* return (strpos($address, '@') !== false);
* });
* You can also set the PHPMailer::$validator static to a callable, allowing built-in methods to use your validator.
* @return boolean * @return boolean
* @static * @static
* @access public * @access public
*/ */
public static function validateAddress($address, $patternselect = 'auto') public static function validateAddress($address, $patternselect = null)
{ {
if (is_null($patternselect)) {
$patternselect = self::$validator;
}
if (is_callable($patternselect)) {
return call_user_func($patternselect, $address);
}
//Reject line breaks in addresses; it's valid RFC5322, but not RFC5321 //Reject line breaks in addresses; it's valid RFC5322, but not RFC5321
if (strpos($address, "\n") !== false or strpos($address, "\r") !== false) { if (strpos($address, "\n") !== false or strpos($address, "\r") !== false) {
return false; return false;
@@ -1216,7 +1237,7 @@ class PHPMailer
} }
$this->$address_kind = $this->punyencodeAddress($this->$address_kind); $this->$address_kind = $this->punyencodeAddress($this->$address_kind);
if (!$this->validateAddress($this->$address_kind)) { if (!$this->validateAddress($this->$address_kind)) {
$error_message = $this->lang('invalid_address') . $this->$address_kind; $error_message = $this->lang('invalid_address') . ' (punyEncode) ' . $this->$address_kind;
$this->setError($error_message); $this->setError($error_message);
$this->edebug($error_message); $this->edebug($error_message);
if ($this->exceptions) { if ($this->exceptions) {
@@ -1227,7 +1248,7 @@ class PHPMailer
} }
// Set whether the message is multipart/alternative // Set whether the message is multipart/alternative
if (!empty($this->AltBody)) { if ($this->alternativeExists()) {
$this->ContentType = 'multipart/alternative'; $this->ContentType = 'multipart/alternative';
} }
@@ -1634,7 +1655,7 @@ class PHPMailer
*/ */
public function smtpClose() public function smtpClose()
{ {
if ($this->smtp !== null) { if (is_a($this->smtp, 'SMTP')) {
if ($this->smtp->connected()) { if ($this->smtp->connected()) {
$this->smtp->quit(); $this->smtp->quit();
$this->smtp->close(); $this->smtp->close();
@@ -1972,7 +1993,7 @@ class PHPMailer
$result .= $this->headerLine('Subject', $this->encodeHeader($this->secureHeader($this->Subject))); $result .= $this->headerLine('Subject', $this->encodeHeader($this->secureHeader($this->Subject)));
} }
if ($this->MessageID != '') { if ('' != $this->MessageID and preg_match('/^<.*@.*>$/', $this->MessageID)) {
$this->lastMessageID = $this->MessageID; $this->lastMessageID = $this->MessageID;
} else { } else {
$this->lastMessageID = sprintf('<%s@%s>', $this->uniqueid, $this->serverHostname()); $this->lastMessageID = sprintf('<%s@%s>', $this->uniqueid, $this->serverHostname());
@@ -2074,7 +2095,7 @@ class PHPMailer
*/ */
public function getSentMIMEMessage() public function getSentMIMEMessage()
{ {
return $this->MIMEHeader . $this->mailHeader . self::CRLF . $this->MIMEBody; return rtrim($this->MIMEHeader . $this->mailHeader, "\n\r") . self::CRLF . self::CRLF . $this->MIMEBody;
} }
/** /**
@@ -2120,8 +2141,9 @@ class PHPMailer
$altBodyEncoding = '7bit'; $altBodyEncoding = '7bit';
$altBodyCharSet = 'us-ascii'; $altBodyCharSet = 'us-ascii';
} }
//If lines are too long, change to quoted-printable transfer encoding //If lines are too long, and we're not already using an encoding that will shorten them,
if (self::hasLineLongerThanMax($this->AltBody)) { //change to quoted-printable transfer encoding
if ('base64' != $altBodyEncoding and self::hasLineLongerThanMax($this->AltBody)) {
$altBodyEncoding = 'quoted-printable'; $altBodyEncoding = 'quoted-printable';
} }
//Use this as a preamble in all multipart message types //Use this as a preamble in all multipart message types
@@ -3296,7 +3318,7 @@ class PHPMailer
$message $message
); );
} }
} elseif (substr($url, 0, 4) !== 'cid:' && !preg_match('#^[A-z]+://#', $url)) { } elseif (substr($url, 0, 4) !== 'cid:' && !preg_match('#^[a-z][a-z0-9+.-]*://#i', $url)) {
// Do not change urls for absolute images (thanks to corvuscorax) // Do not change urls for absolute images (thanks to corvuscorax)
// Do not change urls that are already inline images // Do not change urls that are already inline images
$filename = basename($url); $filename = basename($url);
@@ -3332,7 +3354,7 @@ class PHPMailer
// Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better // Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better
$this->Body = $this->normalizeBreaks($message); $this->Body = $this->normalizeBreaks($message);
$this->AltBody = $this->normalizeBreaks($this->html2text($message, $advanced)); $this->AltBody = $this->normalizeBreaks($this->html2text($message, $advanced));
if (empty($this->AltBody)) { if (!$this->alternativeExists()) {
$this->AltBody = 'To view this email message, open it in a program that understands HTML!' . $this->AltBody = 'To view this email message, open it in a program that understands HTML!' .
self::CRLF . self::CRLF; self::CRLF . self::CRLF;
} }
@@ -3657,11 +3679,13 @@ class PHPMailer
if ($this->DKIM_passphrase != '') { if ($this->DKIM_passphrase != '') {
$privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase); $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase);
} else { } else {
$privKey = $privKeyStr; $privKey = openssl_pkey_get_private($privKeyStr);
} }
if (openssl_sign($signHeader, $signature, $privKey)) { if (openssl_sign($signHeader, $signature, $privKey, 'sha256WithRSAEncryption')) { //sha1WithRSAEncryption
openssl_pkey_free($privKey);
return base64_encode($signature); return base64_encode($signature);
} }
openssl_pkey_free($privKey);
return ''; return '';
} }
@@ -3678,7 +3702,7 @@ class PHPMailer
foreach ($lines as $key => $line) { foreach ($lines as $key => $line) {
list($heading, $value) = explode(':', $line, 2); list($heading, $value) = explode(':', $line, 2);
$heading = strtolower($heading); $heading = strtolower($heading);
$value = preg_replace('/\s+/', ' ', $value); // Compress useless spaces $value = preg_replace('/\s{2,}/', ' ', $value); // Compress useless spaces
$lines[$key] = $heading . ':' . trim($value); // Don't forget to remove WSP around the value $lines[$key] = $heading . ':' . trim($value); // Don't forget to remove WSP around the value
} }
$signHeader = implode("\r\n", $lines); $signHeader = implode("\r\n", $lines);
@@ -3716,7 +3740,7 @@ class PHPMailer
*/ */
public function DKIM_Add($headers_line, $subject, $body) public function DKIM_Add($headers_line, $subject, $body)
{ {
$DKIMsignatureType = 'rsa-sha1'; // Signature & hash algorithms $DKIMsignatureType = 'rsa-sha256'; // Signature & hash algorithms
$DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body
$DKIMquery = 'dns/txt'; // Query method $DKIMquery = 'dns/txt'; // Query method
$DKIMtime = time(); // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone) $DKIMtime = time(); // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)
@@ -3724,6 +3748,7 @@ class PHPMailer
$headers = explode($this->LE, $headers_line); $headers = explode($this->LE, $headers_line);
$from_header = ''; $from_header = '';
$to_header = ''; $to_header = '';
$date_header = '';
$current = ''; $current = '';
foreach ($headers as $header) { foreach ($headers as $header) {
if (strpos($header, 'From:') === 0) { if (strpos($header, 'From:') === 0) {
@@ -3732,6 +3757,9 @@ class PHPMailer
} elseif (strpos($header, 'To:') === 0) { } elseif (strpos($header, 'To:') === 0) {
$to_header = $header; $to_header = $header;
$current = 'to_header'; $current = 'to_header';
} elseif (strpos($header, 'Date:') === 0) {
$date_header = $header;
$current = 'date_header';
} else { } else {
if (!empty($$current) && strpos($header, ' =?') === 0) { if (!empty($$current) && strpos($header, ' =?') === 0) {
$$current .= $header; $$current .= $header;
@@ -3742,6 +3770,7 @@ class PHPMailer
} }
$from = str_replace('|', '=7C', $this->DKIM_QP($from_header)); $from = str_replace('|', '=7C', $this->DKIM_QP($from_header));
$to = str_replace('|', '=7C', $this->DKIM_QP($to_header)); $to = str_replace('|', '=7C', $this->DKIM_QP($to_header));
$date = str_replace('|', '=7C', $this->DKIM_QP($date_header));
$subject = str_replace( $subject = str_replace(
'|', '|',
'=7C', '=7C',
@@ -3749,7 +3778,7 @@ class PHPMailer
); // Copied header fields (dkim-quoted-printable) ); // Copied header fields (dkim-quoted-printable)
$body = $this->DKIM_BodyC($body); $body = $this->DKIM_BodyC($body);
$DKIMlen = strlen($body); // Length of body $DKIMlen = strlen($body); // Length of body
$DKIMb64 = base64_encode(pack('H*', sha1($body))); // Base64 of packed binary SHA-1 hash of body $DKIMb64 = base64_encode(pack('H*', hash('sha256', $body))); // Base64 of packed binary SHA-256 hash of body
if ('' == $this->DKIM_identity) { if ('' == $this->DKIM_identity) {
$ident = ''; $ident = '';
} else { } else {
@@ -3762,16 +3791,18 @@ class PHPMailer
$this->DKIM_selector . $this->DKIM_selector .
";\r\n" . ";\r\n" .
"\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" . "\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" .
"\th=From:To:Subject;\r\n" . "\th=From:To:Date:Subject;\r\n" .
"\td=" . $this->DKIM_domain . ';' . $ident . "\r\n" . "\td=" . $this->DKIM_domain . ';' . $ident . "\r\n" .
"\tz=$from\r\n" . "\tz=$from\r\n" .
"\t|$to\r\n" . "\t|$to\r\n" .
"\t|$date\r\n" .
"\t|$subject;\r\n" . "\t|$subject;\r\n" .
"\tbh=" . $DKIMb64 . ";\r\n" . "\tbh=" . $DKIMb64 . ";\r\n" .
"\tb="; "\tb=";
$toSign = $this->DKIM_HeaderC( $toSign = $this->DKIM_HeaderC(
$from_header . "\r\n" . $from_header . "\r\n" .
$to_header . "\r\n" . $to_header . "\r\n" .
$date_header . "\r\n" .
$subject_header . "\r\n" . $subject_header . "\r\n" .
$dkimhdrs $dkimhdrs
); );

View File

@@ -30,7 +30,7 @@ class SMTP
* The PHPMailer SMTP version number. * The PHPMailer SMTP version number.
* @var string * @var string
*/ */
const VERSION = '5.2.14'; const VERSION = '5.2.15';
/** /**
* SMTP line break constant. * SMTP line break constant.
@@ -81,7 +81,7 @@ class SMTP
* @deprecated Use the `VERSION` constant instead * @deprecated Use the `VERSION` constant instead
* @see SMTP::VERSION * @see SMTP::VERSION
*/ */
public $Version = '5.2.14'; public $Version = '5.2.15';
/** /**
* SMTP server port number. * SMTP server port number.
@@ -336,11 +336,22 @@ class SMTP
if (!$this->sendCommand('STARTTLS', 'STARTTLS', 220)) { if (!$this->sendCommand('STARTTLS', 'STARTTLS', 220)) {
return false; return false;
} }
//Allow the best TLS version(s) we can
$crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT;
//PHP 5.6.7 dropped inclusion of TLS 1.1 and 1.2 in STREAM_CRYPTO_METHOD_TLS_CLIENT
//so add them back in manually if we can
if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
$crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
$crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
}
// Begin encrypted connection // Begin encrypted connection
if (!stream_socket_enable_crypto( if (!stream_socket_enable_crypto(
$this->smtp_conn, $this->smtp_conn,
true, true,
STREAM_CRYPTO_METHOD_TLS_CLIENT $crypto_method
)) { )) {
return false; return false;
} }
@@ -736,7 +747,7 @@ class SMTP
protected function parseHelloFields($type) protected function parseHelloFields($type)
{ {
$this->server_caps = array(); $this->server_caps = array();
$lines = explode("\n", $this->last_reply); $lines = explode("\n", $this->helo_rply);
foreach ($lines as $n => $s) { foreach ($lines as $n => $s) {
//First 4 chars contain response code followed by - or space //First 4 chars contain response code followed by - or space

View File

@@ -28,10 +28,13 @@
// and modified to work without files and integrate in Froxlor // and modified to work without files and integrate in Froxlor
class lescript class lescript
{ {
public $license = 'https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf'; public $license = 'https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf';
private $logger; private $logger;
private $client; private $client;
private $accountKey; private $accountKey;
public function __construct($logger) public function __construct($logger)
@@ -50,7 +53,7 @@ class lescript
{ {
// Let's see if we have the private accountkey // Let's see if we have the private accountkey
$this->accountKey = $certrow['leprivatekey']; $this->accountKey = $certrow['leprivatekey'];
if (!$this->accountKey || $this->accountKey == 'unset' || Settings::Get('system.letsencryptca') != 'production') { if (! $this->accountKey || $this->accountKey == 'unset' || Settings::Get('system.letsencryptca') != 'production') {
// generate and save new private key for account // generate and save new private key for account
// --------------------------------------------- // ---------------------------------------------
@@ -59,27 +62,35 @@ class lescript
$keys = $this->generateKey(); $keys = $this->generateKey();
// Only store the accountkey in production, in staging always generate a new key // Only store the accountkey in production, in staging always generate a new key
if (Settings::Get('system.letsencryptca') == 'production') { if (Settings::Get('system.letsencryptca') == 'production') {
$upd_stmt = Database::prepare(" $upd_stmt = Database::prepare(
UPDATE `".TABLE_PANEL_CUSTOMERS."` SET `lepublickey` = :public, `leprivatekey` = :private WHERE `customerid` = :customerid; "UPDATE `" . TABLE_PANEL_CUSTOMERS . "` SET `lepublickey` = :public, `leprivatekey` = :private " .
"); "WHERE `customerid` = :customerid;");
Database::pexecute($upd_stmt, array('public' => $keys['public'], 'private' => $keys['private'], 'customerid' => $certrow['customerid'])); Database::pexecute($upd_stmt,
array(
'public' => $keys['public'],
'private' => $keys['private'],
'customerid' => $certrow['customerid']
));
} }
$this->accountKey = $keys['private']; $this->accountKey = $keys['private'];
$response = $this->postNewReg();
if ($this->client->getLastCode() != 201) {
throw new \RuntimeException("Account not initialized, probably due to rate limiting. Whole response: " . $response);
}
$this->postNewReg(); $this->postNewReg();
$this->log('New account certificate registered'); $this->log('New account certificate registered');
} else { } else {
$this->log('Account already registered. Continuing.'); $this->log('Account already registered. Continuing.');
} }
} }
public function signDomains(array $domains, $domainkey = null, $csr = null) public function signDomains(array $domains, $domainkey = null, $csr = null)
{ {
if (! $this->accountKey) {
if (!$this->accountKey) { throw new \RuntimeException("Account not initialized");
throw new \RuntimeException("Account not initiated");
} }
$this->log('Starting certificate generation process for domains'); $this->log('Starting certificate generation process for domains');
@@ -90,44 +101,51 @@ class lescript
// start domains authentication // start domains authentication
// ---------------------------- // ----------------------------
foreach($domains as $domain) { foreach ($domains as $domain) {
// 1. getting available authentication options // 1. getting available authentication options
// ------------------------------------------- // -------------------------------------------
$this->log("Requesting challenge for $domain"); $this->log("Requesting challenge for $domain");
$response = $this->signedRequest( $response = $this->signedRequest("/acme/new-authz",
"/acme/new-authz", array(
array("resource" => "new-authz", "identifier" => array("type" => "dns", "value" => $domain)) "resource" => "new-authz",
); "identifier" => array(
"type" => "dns",
"value" => $domain
)
));
// if response is not an array but a string, it's most likely a server-error, e.g. // if response is not an array but a string, it's most likely a server-error, e.g.
// <HTML><HEAD><TITLE>Error</TITLE></HEAD><BODY>An error occurred while processing your request. // <HTML><HEAD><TITLE>Error</TITLE></HEAD><BODY>An error occurred while processing your request.
// <p>Reference&#32;&#35;179&#46;d8be1402&#46;1458059103&#46;3613c4db</BODY></HTML> // <p>Reference&#32;&#35;179&#46;d8be1402&#46;1458059103&#46;3613c4db</BODY></HTML>
if (!is_array($response)) { if (! is_array($response)) {
throw new RuntimeException("Invalid response from LE for domain $domain. Whole response: ".$response); throw new RuntimeException("Invalid response from LE for domain $domain. Whole response: " . $response);
} }
if (!array_key_exists('challenges', $response)) { if (! array_key_exists('challenges', $response)) {
throw new RuntimeException("No challenges received for $domain. Whole response: ".json_encode($response)); throw new RuntimeException("No challenges received for $domain. Whole response: " . json_encode($response));
} }
// choose http-01 challenge only // choose http-01 challenge only
$challenge = array_reduce($response['challenges'], function($v, $w) { return $v ? $v : ($w['type'] == 'http-01' ? $w : false); }); $challenge = array_reduce($response['challenges'],
if(!$challenge) throw new RuntimeException("HTTP Challenge for $domain is not available. Whole response: ".json_encode($response)); function ($v, $w) {
return $v ? $v : ($w['type'] == 'http-01' ? $w : false);
});
if (! $challenge)
throw new RuntimeException("HTTP Challenge for $domain is not available. Whole response: " . json_encode($response));
$this->log("Got challenge token for $domain"); $this->log("Got challenge token for $domain");
$location = $this->client->getLastLocation(); $location = $this->client->getLastLocation();
// 2. saving authentication token for web verification // 2. saving authentication token for web verification
// --------------------------------------------------- // ---------------------------------------------------
$directory = Settings::Get('system.letsencryptchallengepath').'/.well-known/acme-challenge'; $directory = Settings::Get('system.letsencryptchallengepath') . '/.well-known/acme-challenge';
$tokenPath = $directory.'/'.$challenge['token']; $tokenPath = $directory . '/' . $challenge['token'];
if(!file_exists($directory) && !@mkdir($directory, 0755, true)) { if (! file_exists($directory) && ! @mkdir($directory, 0755, true)) {
throw new \RuntimeException("Couldn't create directory to expose challenge: ${tokenPath}"); throw new \RuntimeException("Couldn't create directory to expose challenge: ${tokenPath}");
} }
@@ -136,7 +154,6 @@ class lescript
"e" => Base64UrlSafeEncoder::encode($accountKeyDetails["rsa"]["e"]), "e" => Base64UrlSafeEncoder::encode($accountKeyDetails["rsa"]["e"]),
"kty" => "RSA", "kty" => "RSA",
"n" => Base64UrlSafeEncoder::encode($accountKeyDetails["rsa"]["n"]) "n" => Base64UrlSafeEncoder::encode($accountKeyDetails["rsa"]["n"])
); );
$payload = $challenge['token'] . '.' . Base64UrlSafeEncoder::encode(hash('sha256', json_encode($header), true)); $payload = $challenge['token'] . '.' . Base64UrlSafeEncoder::encode(hash('sha256', json_encode($header), true));
@@ -151,7 +168,7 @@ class lescript
$this->log("Token for $domain saved at $tokenPath and should be available at $uri"); $this->log("Token for $domain saved at $tokenPath and should be available at $uri");
// simple self check // simple self check
if($payload !== trim(@file_get_contents($uri))) { if ($payload !== trim(@file_get_contents($uri))) {
$errmsg = json_encode(error_get_last()); $errmsg = json_encode(error_get_last());
if ($errmsg != "null") { if ($errmsg != "null") {
$errmsg = "; PHP error: " . $errmsg; $errmsg = "; PHP error: " . $errmsg;
@@ -165,35 +182,32 @@ class lescript
$this->log("Sending request to challenge"); $this->log("Sending request to challenge");
// send request to challenge // send request to challenge
$result = $this->signedRequest( $result = $this->signedRequest($challenge['uri'],
$challenge['uri'],
array( array(
"resource" => "challenge", "resource" => "challenge",
"type" => "http-01", "type" => "http-01",
"keyAuthorization" => $payload, "keyAuthorization" => $payload,
"token" => $challenge['token'] "token" => $challenge['token']
) ));
);
// waiting loop // waiting loop
// we wait for a maximum of 30 seconds to avoid endless loops // we wait for a maximum of 30 seconds to avoid endless loops
$count = 0; $count = 0;
do { do {
if(empty($result['status']) || $result['status'] == "invalid") { if (empty($result['status']) || $result['status'] == "invalid") {
@unlink($tokenPath); @unlink($tokenPath);
throw new \RuntimeException("Verification ended with error: ".json_encode($result)); throw new \RuntimeException("Verification ended with error: " . json_encode($result));
} }
$ended = !($result['status'] === "pending"); $ended = ! ($result['status'] === "pending");
if(!$ended) { if (! $ended) {
$this->log("Verification pending, sleeping 1s"); $this->log("Verification pending, sleeping 1s");
sleep(1); sleep(1);
$count++; $count ++;
} }
$result = $this->client->get($location); $result = $this->client->get($location);
} while (! $ended && $count < 30);
} while (!$ended && $count < 30);
$this->log("Verification ended with status: ${result['status']}"); $this->log("Verification ended with status: ${result['status']}");
@unlink($tokenPath); @unlink($tokenPath);
@@ -203,7 +217,7 @@ class lescript
// ---------------------- // ----------------------
// generate private key for domain if not exist // generate private key for domain if not exist
if(empty($domainkey) || Settings::Get('system.letsencryptreuseold') == 0) { if (empty($domainkey) || Settings::Get('system.letsencryptreuseold') == 0) {
$keys = $this->generateKey(); $keys = $this->generateKey();
$domainkey = $keys['private']; $domainkey = $keys['private'];
} }
@@ -213,39 +227,36 @@ class lescript
$this->client->getLastLinks(); $this->client->getLastLinks();
if (empty($csrfile) || Settings::Get('system.letsencryptreuseold') == 0) {
$csr = $this->generateCSR($privateDomainKey, $domains); $csr = $this->generateCSR($privateDomainKey, $domains);
}
// request certificates creation // request certificates creation
$result = $this->signedRequest( $result = $this->signedRequest("/acme/new-cert", array(
"/acme/new-cert", 'resource' => 'new-cert',
array('resource' => 'new-cert', 'csr' => $csr) 'csr' => $csr
); ));
if ($this->client->getLastCode() !== 201) { if ($this->client->getLastCode() !== 201) {
throw new \RuntimeException("Invalid response code: ".$this->client->getLastCode().", ".json_encode($result)); throw new \RuntimeException("Invalid response code: " . $this->client->getLastCode() . ", " . json_encode($result));
} }
$location = $this->client->getLastLocation(); $location = $this->client->getLastLocation();
// waiting loop // waiting loop
$certificates = array(); $certificates = array();
while(1) { while (1) {
$this->client->getLastLinks(); $this->client->getLastLinks();
$result = $this->client->get($location); $result = $this->client->get($location);
if($this->client->getLastCode() == 202) { if ($this->client->getLastCode() == 202) {
$this->log("Certificate generation pending, sleeping 1s"); $this->log("Certificate generation pending, sleeping 1s");
sleep(1); sleep(1);
} else
} else if ($this->client->getLastCode() == 200) { if ($this->client->getLastCode() == 200) {
$this->log("Got certificate! YAY!"); $this->log("Got certificate! YAY!");
$certificates[] = $this->parsePemFromBody($result); $certificates[] = $this->parsePemFromBody($result);
foreach ($this->client->getLastLinks() as $link) {
foreach($this->client->getLastLinks() as $link) {
$this->log("Requesting chained cert at $link"); $this->log("Requesting chained cert at $link");
$result = $this->client->get($link); $result = $this->client->get($link);
$certificates[] = $this->parsePemFromBody($result); $certificates[] = $this->parsePemFromBody($result);
@@ -254,19 +265,25 @@ class lescript
break; break;
} else { } else {
throw new \RuntimeException("Can't get certificate: HTTP code ".$this->client->getLastCode()); throw new \RuntimeException("Can't get certificate: HTTP code " . $this->client->getLastCode());
} }
} }
if(empty($certificates)) throw new \RuntimeException('No certificates generated'); if (empty($certificates))
throw new \RuntimeException('No certificates generated');
$fullchain = implode("\n", $certificates); $fullchain = implode("\n", $certificates);
$crt = array_shift($certificates); $crt = array_shift($certificates);
$chain = implode("\n", $certificates); $chain = implode("\n", $certificates);
$this->log("Done, returning new certificates and key"); $this->log("Done, returning new certificates and key");
return array('fullchain' => $fullchain, 'crt' => $crt, 'chain' => $chain, 'key' => $domainkey, 'csr' => $csr); return array(
'fullchain' => $fullchain,
'crt' => $crt,
'chain' => $chain,
'key' => $domainkey,
'csr' => $csr
);
} }
private function parsePemFromBody($body) private function parsePemFromBody($body)
@@ -279,23 +296,25 @@ class lescript
{ {
$this->log('Sending registration to letsencrypt server'); $this->log('Sending registration to letsencrypt server');
return $this->signedRequest( return $this->signedRequest('/acme/new-reg', array(
'/acme/new-reg', 'resource' => 'new-reg',
array('resource' => 'new-reg', 'agreement' => $this->license) 'agreement' => $this->license
); ));
} }
private function generateCSR($privateKey, array $domains) private function generateCSR($privateKey, array $domains)
{ {
$domain = reset($domains); $domain = reset($domains);
$san = implode(",", array_map(function ($dns) { return "DNS:" . $dns; }, $domains)); $san = implode(",", array_map(function ($dns) {
return "DNS:" . $dns;
}, $domains));
$tmpConf = tmpfile(); $tmpConf = tmpfile();
$tmpConfMeta = stream_get_meta_data($tmpConf); $tmpConfMeta = stream_get_meta_data($tmpConf);
$tmpConfPath = $tmpConfMeta["uri"]; $tmpConfPath = $tmpConfMeta["uri"];
// workaround to get SAN working // workaround to get SAN working
fwrite($tmpConf, fwrite($tmpConf,
'HOME = . 'HOME = .
RANDFILE = $ENV::HOME/.rnd RANDFILE = $ENV::HOME/.rnd
[ req ] [ req ]
default_bits = ' . Settings::Get('system.letsencryptkeysize') . ' default_bits = ' . Settings::Get('system.letsencryptkeysize') . '
@@ -306,7 +325,7 @@ req_extensions = v3_req
countryName = Country Name (2 letter code) countryName = Country Name (2 letter code)
[ v3_req ] [ v3_req ]
basicConstraints = CA:FALSE basicConstraints = CA:FALSE
subjectAltName = '.$san.' subjectAltName = ' . $san . '
keyUsage = nonRepudiation, digitalSignature, keyEncipherment'); keyUsage = nonRepudiation, digitalSignature, keyEncipherment');
$csr = openssl_csr_new( $csr = openssl_csr_new(
@@ -314,16 +333,14 @@ keyUsage = nonRepudiation, digitalSignature, keyEncipherment');
"CN" => $domain, "CN" => $domain,
"ST" => Settings::Get('system.letsencryptstate'), "ST" => Settings::Get('system.letsencryptstate'),
"C" => Settings::Get('system.letsencryptcountrycode'), "C" => Settings::Get('system.letsencryptcountrycode'),
"O" => "Unknown", "O" => "Unknown"
), ), $privateKey, array(
$privateKey,
array(
"config" => $tmpConfPath, "config" => $tmpConfPath,
"digest_alg" => "sha256" "digest_alg" => "sha256"
) ));
);
if (!$csr) throw new \RuntimeException("CSR couldn't be generated! ".openssl_error_string()); if (! $csr)
throw new \RuntimeException("CSR couldn't be generated! " . openssl_error_string());
openssl_csr_export($csr, $csr); openssl_csr_export($csr, $csr);
fclose($tmpConf); fclose($tmpConf);
@@ -335,18 +352,22 @@ keyUsage = nonRepudiation, digitalSignature, keyEncipherment');
private function generateKey() private function generateKey()
{ {
$res = openssl_pkey_new(array( $res = openssl_pkey_new(
array(
"private_key_type" => OPENSSL_KEYTYPE_RSA, "private_key_type" => OPENSSL_KEYTYPE_RSA,
"private_key_bits" => (int)Settings::Get('system.letsencryptkeysize'), "private_key_bits" => (int) Settings::Get('system.letsencryptkeysize')
)); ));
if(!openssl_pkey_export($res, $privateKey)) { if (! openssl_pkey_export($res, $privateKey)) {
throw new \RuntimeException("Key export failed!"); throw new \RuntimeException("Key export failed!");
} }
$details = openssl_pkey_get_details($res); $details = openssl_pkey_get_details($res);
return array('private' => $privateKey, 'public' => $details['key']); return array(
'private' => $privateKey,
'public' => $details['key']
);
} }
private function signedRequest($uri, array $payload) private function signedRequest($uri, array $payload)
@@ -359,18 +380,17 @@ keyUsage = nonRepudiation, digitalSignature, keyEncipherment');
"jwk" => array( "jwk" => array(
"kty" => "RSA", "kty" => "RSA",
"n" => Base64UrlSafeEncoder::encode($details["rsa"]["n"]), "n" => Base64UrlSafeEncoder::encode($details["rsa"]["n"]),
"e" => Base64UrlSafeEncoder::encode($details["rsa"]["e"]), "e" => Base64UrlSafeEncoder::encode($details["rsa"]["e"])
) )
); );
$protected = $header; $protected = $header;
$protected["nonce"] = $this->client->getLastNonce(); $protected["nonce"] = $this->client->getLastNonce();
$payload64 = Base64UrlSafeEncoder::encode(str_replace('\\/', '/', json_encode($payload))); $payload64 = Base64UrlSafeEncoder::encode(str_replace('\\/', '/', json_encode($payload)));
$protected64 = Base64UrlSafeEncoder::encode(json_encode($protected)); $protected64 = Base64UrlSafeEncoder::encode(json_encode($protected));
openssl_sign($protected64.'.'.$payload64, $signed, $privateKey, "SHA256"); openssl_sign($protected64 . '.' . $payload64, $signed, $privateKey, "SHA256");
$signed64 = Base64UrlSafeEncoder::encode($signed); $signed64 = Base64UrlSafeEncoder::encode($signed);
@@ -394,7 +414,9 @@ keyUsage = nonRepudiation, digitalSignature, keyEncipherment');
class Client class Client
{ {
private $lastCode; private $lastCode;
private $lastHeader; private $lastHeader;
private $base; private $base;
@@ -406,9 +428,12 @@ class Client
private function curl($method, $url, $data = null) private function curl($method, $url, $data = null)
{ {
$headers = array('Accept: application/json', 'Content-Type: application/json'); $headers = array(
'Accept: application/json',
'Content-Type: application/json'
);
$handle = curl_init(); $handle = curl_init();
curl_setopt($handle, CURLOPT_URL, preg_match('~^http~', $url) ? $url : $this->base.$url); curl_setopt($handle, CURLOPT_URL, preg_match('~^http~', $url) ? $url : $this->base . $url);
curl_setopt($handle, CURLOPT_HTTPHEADER, $headers); curl_setopt($handle, CURLOPT_HTTPHEADER, $headers);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true); curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_HEADER, true); curl_setopt($handle, CURLOPT_HEADER, true);
@@ -427,8 +452,8 @@ class Client
} }
$response = curl_exec($handle); $response = curl_exec($handle);
if(curl_errno($handle)) { if (curl_errno($handle)) {
throw new \RuntimeException('Curl: '.curl_error($handle)); throw new \RuntimeException('Curl: ' . curl_error($handle));
} }
$header_size = curl_getinfo($handle, CURLINFO_HEADER_SIZE); $header_size = curl_getinfo($handle, CURLINFO_HEADER_SIZE);
@@ -455,7 +480,7 @@ class Client
public function getLastNonce() public function getLastNonce()
{ {
if(preg_match('~Replay\-Nonce: (.+)~i', $this->lastHeader, $matches)) { if (preg_match('~Replay\-Nonce: (.+)~i', $this->lastHeader, $matches)) {
return trim($matches[1]); return trim($matches[1]);
} }
@@ -465,7 +490,7 @@ class Client
public function getLastLocation() public function getLastLocation()
{ {
if(preg_match('~Location: (.+)~i', $this->lastHeader, $matches)) { if (preg_match('~Location: (.+)~i', $this->lastHeader, $matches)) {
return trim($matches[1]); return trim($matches[1]);
} }
return null; return null;
@@ -485,6 +510,7 @@ class Client
class Base64UrlSafeEncoder class Base64UrlSafeEncoder
{ {
public static function encode($input) public static function encode($input)
{ {
return str_replace('=', '', strtr(base64_encode($input), '+/', '-_')); return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));

View File

@@ -40,14 +40,14 @@
</visibility> </visibility>
<content><![CDATA[mkdir -p {{settings.system.deactivateddocroot}}]]></content> <content><![CDATA[mkdir -p {{settings.system.deactivateddocroot}}]]></content>
</command> </command>
<command><![CDATA[a2dismod userdir]]></command>
<command><![CDATA[a2enmod headers]]></command>
</commands> </commands>
</general> </general>
<!-- HTTP Apache --> <!-- HTTP Apache -->
<daemon name="apache" version="2.4" title="Apache 2.4" default="true"> <daemon name="apache" version="2.4" title="Apache 2.4" default="true">
<install><![CDATA[apt-get install apache2]]></install> <install><![CDATA[apt-get install apache2]]></install>
<include>//service[@type='http']/general/commands</include> <include>//service[@type='http']/general/commands</include>
<command><![CDATA[a2dismod userdir]]></command>
<command><![CDATA[a2enmod headers]]></command>
<command> <command>
<visibility mode="true">{{settings.phpfpm.enabled}} <visibility mode="true">{{settings.phpfpm.enabled}}
</visibility> </visibility>
@@ -4022,7 +4022,7 @@ aliases: files
<command><![CDATA[/etc/init.d/nscd restart]]></command> <command><![CDATA[/etc/init.d/nscd restart]]></command>
<!-- clear group chache --> <!-- clear group chache -->
<command><![CDATA[nscd --invalidate=group]]></command> <command><![CDATA[nscd --invalidate=group]]></command>
<file /><!-- separate the following mkdir command from the previous nscd --> <!-- @TODO separate the following mkdir command from the previous nscd -->
<command> <command>
<visibility mode="notisdir">/etc/insserv/overrides</visibility> <visibility mode="notisdir">/etc/insserv/overrides</visibility>
<content><![CDATA[mkdir -p /etc/insserv/overrides]]></content> <content><![CDATA[mkdir -p /etc/insserv/overrides]]></content>

View File

@@ -40,8 +40,6 @@
</visibility> </visibility>
<content><![CDATA[mkdir -p {{settings.system.deactivateddocroot}}]]></content> <content><![CDATA[mkdir -p {{settings.system.deactivateddocroot}}]]></content>
</command> </command>
<command><![CDATA[a2dismod userdir]]></command>
<command><![CDATA[a2enmod headers]]></command>
</commands> </commands>
</general> </general>
<!-- HTTP Apache --> <!-- HTTP Apache -->
@@ -49,6 +47,8 @@
default="true"> default="true">
<install><![CDATA[apt-get install apache2]]></install> <install><![CDATA[apt-get install apache2]]></install>
<include>//service[@type='http']/general/commands</include> <include>//service[@type='http']/general/commands</include>
<command><![CDATA[a2dismod userdir]]></command>
<command><![CDATA[a2enmod headers]]></command>
<file name="/etc/apache2/mods-enabled/fastcgi.conf"> <file name="/etc/apache2/mods-enabled/fastcgi.conf">
<visibility mode="true">{{settings.phpfpm.enabled}} <visibility mode="true">{{settings.phpfpm.enabled}}
</visibility> </visibility>

View File

@@ -40,8 +40,6 @@
</visibility> </visibility>
<content><![CDATA[mkdir -p {{settings.system.deactivateddocroot}}]]></content> <content><![CDATA[mkdir -p {{settings.system.deactivateddocroot}}]]></content>
</command> </command>
<command><![CDATA[a2dismod userdir]]></command>
<command><![CDATA[a2enmod headers]]></command>
</commands> </commands>
</general> </general>
<!-- HTTP Apache --> <!-- HTTP Apache -->

View File

@@ -40,8 +40,6 @@
</visibility> </visibility>
<content><![CDATA[mkdir -p {{settings.system.deactivateddocroot}}]]></content> <content><![CDATA[mkdir -p {{settings.system.deactivateddocroot}}]]></content>
</command> </command>
<command><![CDATA[a2dismod userdir]]></command>
<command><![CDATA[a2enmod headers]]></command>
</commands> </commands>
</general> </general>
<!-- HTTP Apache --> <!-- HTTP Apache -->
@@ -49,6 +47,8 @@
default="true"> default="true">
<install><![CDATA[apt-get install apache2]]></install> <install><![CDATA[apt-get install apache2]]></install>
<include>//service[@type='http']/general/commands</include> <include>//service[@type='http']/general/commands</include>
<command><![CDATA[a2dismod userdir]]></command>
<command><![CDATA[a2enmod headers]]></command>
<file name="/etc/apache2/mods-enabled/fastcgi.conf"> <file name="/etc/apache2/mods-enabled/fastcgi.conf">
<visibility mode="true">{{settings.phpfpm.enabled}} <visibility mode="true">{{settings.phpfpm.enabled}}
</visibility> </visibility>
@@ -83,6 +83,8 @@ Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath}
<daemon name="apache" version="2.4" title="Apache 2.4"> <daemon name="apache" version="2.4" title="Apache 2.4">
<install><![CDATA[apt-get install apache2]]></install> <install><![CDATA[apt-get install apache2]]></install>
<include>//service[@type='http']/general/commands</include> <include>//service[@type='http']/general/commands</include>
<command><![CDATA[a2dismod userdir]]></command>
<command><![CDATA[a2enmod headers]]></command>
<file name="/etc/apache2/mods-enabled/fastcgi.conf"> <file name="/etc/apache2/mods-enabled/fastcgi.conf">
<visibility mode="true">{{settings.phpfpm.enabled}} <visibility mode="true">{{settings.phpfpm.enabled}}
</visibility> </visibility>
@@ -1363,8 +1365,8 @@ TLSLog /var/log/proftpd/tls.log
TLSProtocol TLSv1 TLSv1.1 TLSv1.2 TLSProtocol TLSv1 TLSv1.1 TLSv1.2
TLSRSACertificateFile /etc/ssl/certs/proftpd.crt TLSRSACertificateFile /etc/ssl/certs/proftpd.crt
TLSRSACertificateKeyFile /etc/ssl/private/proftpd.key TLSRSACertificateKeyFile /etc/ssl/private/proftpd.key
TLSECCertificateFile /etc/ssl/certs/proftpd_ec.crt #TLSECCertificateFile /etc/ssl/certs/proftpd_ec.crt
TLSECCertificateKeyFile /etc/ssl/private/proftpd_ec.key #TLSECCertificateKeyFile /etc/ssl/private/proftpd_ec.key
TLSOptions NoCertRequest NoSessionReuseRequired TLSOptions NoCertRequest NoSessionReuseRequired
TLSVerifyClient off TLSVerifyClient off

View File

@@ -40,8 +40,6 @@
</visibility> </visibility>
<content><![CDATA[mkdir -p {{settings.system.deactivateddocroot}}]]></content> <content><![CDATA[mkdir -p {{settings.system.deactivateddocroot}}]]></content>
</command> </command>
<command><![CDATA[a2dismod userdir]]></command>
<command><![CDATA[a2enmod headers]]></command>
</commands> </commands>
</general> </general>
<!-- HTTP Apache --> <!-- HTTP Apache -->
@@ -49,6 +47,8 @@
default="true"> default="true">
<install><![CDATA[apt-get install apache2]]></install> <install><![CDATA[apt-get install apache2]]></install>
<include>//service[@type='http']/general/commands</include> <include>//service[@type='http']/general/commands</include>
<command><![CDATA[a2dismod userdir]]></command>
<command><![CDATA[a2enmod headers]]></command>
<file name="/etc/apache2/mods-enabled/fastcgi.conf"> <file name="/etc/apache2/mods-enabled/fastcgi.conf">
<visibility mode="true">{{settings.phpfpm.enabled}} <visibility mode="true">{{settings.phpfpm.enabled}}
</visibility> </visibility>
@@ -83,6 +83,8 @@ Alias "/.well-known/acme-challenge" "{{settings.system.letsencryptchallengepath}
<daemon name="apache" version="2.4" title="Apache 2.4"> <daemon name="apache" version="2.4" title="Apache 2.4">
<install><![CDATA[apt-get install apache2]]></install> <install><![CDATA[apt-get install apache2]]></install>
<include>//service[@type='http']/general/commands</include> <include>//service[@type='http']/general/commands</include>
<command><![CDATA[a2dismod userdir]]></command>
<command><![CDATA[a2enmod headers]]></command>
<file name="/etc/apache2/mods-enabled/fastcgi.conf"> <file name="/etc/apache2/mods-enabled/fastcgi.conf">
<visibility mode="true">{{settings.phpfpm.enabled}} <visibility mode="true">{{settings.phpfpm.enabled}}
</visibility> </visibility>

View File

@@ -129,7 +129,7 @@ while ($fName = readdir($lockDirHandle)) {
// //
fwrite($debugHandler, 'Previous cronjob didn\'t exit clean. PID: ' . $check_pid . "\n"); fwrite($debugHandler, 'Previous cronjob didn\'t exit clean. PID: ' . $check_pid . "\n");
fwrite($debugHandler, 'Removing lockfile: ' . $lockdir . $fName . "\n"); fwrite($debugHandler, 'Removing lockfile: ' . $lockdir . $fName . "\n");
unlink($lockdir . $fName); @unlink($lockdir . $fName);
} else { } else {
// Result: A Cronscript with this pid // Result: A Cronscript with this pid

View File

@@ -207,7 +207,7 @@ return array(
), ),
'zonefile' => array( 'zonefile' => array(
'label' => 'Zonefile', 'label' => 'Zonefile',
'desc' => $lng['panel']['emptyfordefault'], 'desc' => $lng['admin']['bindzonewarning'],
'type' => 'text' 'type' => 'text'
) )
) )

View File

@@ -232,7 +232,7 @@ return array(
), ),
'zonefile' => array( 'zonefile' => array(
'label' => 'Zonefile', 'label' => 'Zonefile',
'desc' => $lng['panel']['emptyfordefault'], 'desc' => $lng['admin']['bindzonewarning'],
'type' => 'text', 'type' => 'text',
'value' => $result['zonefile'] 'value' => $result['zonefile']
) )

View File

@@ -0,0 +1,75 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2016 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Formfields
*
*/
return array(
'backup' => array(
'title' => $lng['extras']['backup'],
'image' => 'icons/backup_big.png',
'sections' => array(
'section_a' => array(
'title' => $lng['extras']['backup'],
'image' => 'icons/backup_big.png',
'fields' => array(
'path' => array(
'label' => $lng['panel']['path'],
'desc' => (Settings::Get('panel.pathedit') != 'Dropdown' ? $lng['panel']['pathDescription'] : null).(isset($pathSelect['note']) ? '<br />'.$pathSelect['value'] : ''),
'type' => $pathSelect['type'],
'select_var' => $pathSelect['value'],
'value' => $pathSelect['value']
),
'path_protection_info' => array(
'label' => $lng['extras']['path_protection_label'],
'type' => 'label',
'value' => $lng['extras']['path_protection_info']
),
'backup_web' => array(
'label' => $lng['extras']['backup_web'],
'type' => 'checkbox',
'values' => array(
array(
'label' => $lng['panel']['yes'],
'value' => '1'
)
),
'value' => array('1')
),
'backup_mail' => array(
'label' => $lng['extras']['backup_mail'],
'type' => 'checkbox',
'values' => array(
array(
'label' => $lng['panel']['yes'],
'value' => '1'
)
),
'value' => array('1')
),
'backup_dbs' => array(
'label' => $lng['extras']['backup_dbs'],
'type' => 'checkbox',
'values' => array(
array(
'label' => $lng['panel']['yes'],
'value' => '1'
)
),
'value' => array('1')
)
)
)
)
)
);

View File

@@ -0,0 +1,123 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2016 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Functions
*
*/
/**
* depending on the give choice, the customers web-data, email-data and databases are being backup'ed
*
* @param array $data
*
* @return void
*
*/
function createCustomerBackup($data = null, $customerdocroot = null, &$cronlog)
{
$cronlog->logAction(CRON_ACTION, LOG_INFO, 'Creating Backup for user "'.$data['loginname'].'"');
// create tmp folder
$tmpdir = makeCorrectDir($data['destdir'] . '/.tmp/');
$cronlog->logAction(CRON_ACTION, LOG_DEBUG, 'Creating tmp-folder "'.$tmpdir.'"');
$cronlog->logAction(CRON_ACTION, LOG_DEBUG, 'shell> mkdir -p ' . escapeshellarg($tmpdir));
safe_exec('mkdir -p ' . escapeshellarg($tmpdir));
$create_backup_tar_data = "";
// MySQL databases
if ($data['backup_dbs'] == 1) {
$cronlog->logAction(CRON_ACTION, LOG_DEBUG, 'Creating mysql-folder "'.makeCorrectDir($tmpdir . '/mysql').'"');
$cronlog->logAction(CRON_ACTION, LOG_DEBUG, 'shell> mkdir -p ' . escapeshellarg(makeCorrectDir($tmpdir . '/mysql')));
safe_exec('mkdir -p ' . escapeshellarg(makeCorrectDir($tmpdir . '/mysql')));
// get all customer database-names
$sel_stmt = Database::prepare("SELECT `databasename` FROM `" . TABLE_PANEL_DATABASES . "` WHERE `customerid` = :cid");
Database::pexecute($sel_stmt, array(
'cid' => $data['customerid']
));
Database::needRoot(true);
Database::needSqlData();
$sql_root = Database::getSqlData();
Database::needRoot(false);
$has_dbs = false;
while ($row = $sel_stmt->fetch()) {
$cronlog->logAction(CRON_ACTION, LOG_DEBUG, 'shell> mysqldump -u ' . escapeshellarg($sql_root['user']) . ' -pXXXXX ' . $row['databasename'] . ' > ' . makeCorrectFile($tmpdir . '/mysql/' . $row['databasename'] . '_' . date('YmdHi', time()) . '.sql'));
$bool_false = false;
safe_exec('mysqldump -u ' . escapeshellarg($sql_root['user']) . ' -p' . $sql_root['passwd'] . ' ' . $row['databasename'] . ' > ' . makeCorrectFile($tmpdir . '/mysql/' . $row['databasename'] . '_' . date('YmdHi', time()) . '.sql'), $bool_false, array('>'));
$has_dbs = true;
}
if ($has_dbs) {
$create_backup_tar_data .= './mysql ';
}
unset($sql_root);
}
// E-mail data
if ($data['backup_mail'] == 1) {
$cronlog->logAction(CRON_ACTION, LOG_DEBUG, 'Creating mail-folder "'.makeCorrectDir($tmpdir . '/mail').'"');
safe_exec('mkdir -p ' . escapeshellarg(makeCorrectDir($tmpdir . '/mail')));
// get all customer mail-accounts
$sel_stmt = Database::prepare("SELECT `homedir`, `maildir` FROM `" . TABLE_MAIL_USERS . "` WHERE `customerid` = :cid");
Database::pexecute($sel_stmt, array(
'cid' => $data['customerid']
));
$tar_file_list = "";
$mail_homedir = "";
while ($row = $sel_stmt->fetch()) {
$tar_file_list .= escapeshellarg("./".$row['maildir']) . " ";
$mail_homedir = $row['homedir'];
}
if (! empty($tar_file_list)) {
$cronlog->logAction(CRON_ACTION, LOG_DEBUG, 'shell> tar cfvz ' . escapeshellarg(makeCorrectFile($tmpdir . '/mail/' . $data['loginname'] . '-mail.tar.gz')) . ' -C '.escapeshellarg($mail_homedir) . ' ' . trim($tar_file_list));
safe_exec('tar cfz ' . escapeshellarg(makeCorrectFile($tmpdir . '/mail/' . $data['loginname'] . '-mail.tar.gz')) . ' -C '.escapeshellarg($mail_homedir) . ' ' . trim($tar_file_list));
$create_backup_tar_data .= './mail ';
}
}
// Web data
if ($data['backup_web'] == 1) {
$cronlog->logAction(CRON_ACTION, LOG_DEBUG, 'Creating web-folder "'.makeCorrectDir($tmpdir . '/web').'"');
safe_exec('mkdir -p ' . escapeshellarg(makeCorrectDir($tmpdir . '/web')));
$cronlog->logAction(CRON_ACTION, LOG_DEBUG, 'shell> tar cfz ' . escapeshellarg(makeCorrectFile($tmpdir . '/web/' . $data['loginname'] . '-web.tar.gz')) . ' --exclude=' . escapeshellarg(str_replace($customerdocroot, "./", makeCorrectFile($tmpdir.'/*'))) .' --exclude=' . escapeshellarg(str_replace($customerdocroot, "./", substr(makeCorrectDir($tmpdir), 0, -1))) .' -C '.escapeshellarg($customerdocroot). ' .');
safe_exec('tar cfz ' . escapeshellarg(makeCorrectFile($tmpdir . '/web/' . $data['loginname'] . '-web.tar.gz')) . ' --exclude=' . escapeshellarg(str_replace($customerdocroot, "./", makeCorrectFile($tmpdir.'/*'))) .' --exclude=' . escapeshellarg(str_replace($customerdocroot, "./", substr(makeCorrectFile($tmpdir), 0, -1))) .' -C '.escapeshellarg($customerdocroot).' .');
$create_backup_tar_data .= './web ';
}
if (!empty($create_backup_tar_data))
{
$backup_file = makeCorrectFile($tmpdir . '/' . $data['loginname'] . '-backup_' . date('YmdHi', time()) . '.tar.gz');
$cronlog->logAction(CRON_ACTION, LOG_INFO, 'Creating backup-file "'.$backup_file.'"');
// pack all archives in tmp-dir to one
$cronlog->logAction(CRON_ACTION, LOG_DEBUG, 'shell> tar cfz ' . escapeshellarg($backup_file) . ' -C '.escapeshellarg($tmpdir).' '.trim($create_backup_tar_data));
safe_exec('tar cfz ' . escapeshellarg($backup_file) . ' -C '.escapeshellarg($tmpdir).' '.trim($create_backup_tar_data));
// move to destination directory
$cronlog->logAction(CRON_ACTION, LOG_DEBUG, 'shell> mv ' . escapeshellarg($backup_file) . ' ' . escapeshellarg($data['destdir']));
safe_exec('mv ' . escapeshellarg($backup_file) . ' ' . escapeshellarg($data['destdir']));
// remove tmp-files
$cronlog->logAction(CRON_ACTION, LOG_DEBUG, 'shell> rm -rf '.escapeshellarg($tmpdir));
safe_exec('rm -rf '.escapeshellarg($tmpdir));
// set owner to customer
$cronlog->logAction(CRON_ACTION, LOG_DEBUG, 'shell> chown -R ' . (int)$data['uid'] . ':' . (int)$data['gid'] . ' ' . escapeshellarg($data['destdir']));
safe_exec('chown -R ' . (int)$data['uid'] . ':' . (int)$data['gid'] . ' ' . escapeshellarg($data['destdir']));
}
}

View File

@@ -108,6 +108,15 @@ function getOutstandingTasks() {
elseif ($row['type'] == '10') { elseif ($row['type'] == '10') {
$task_desc = $lng['tasks']['diskspace_set_quota']; $task_desc = $lng['tasks']['diskspace_set_quota'];
} }
// deleting user-files
elseif ($row['type'] == '20') {
$loginname = '';
if (is_array($row['data'])) {
$loginname = $row['data']['loginname'];
}
$task_desc = $lng['tasks']['backup_customerfiles'];
$task_desc = str_replace('%loginname%', $loginname, $task_desc);
}
// re-generating of cron.d-file // re-generating of cron.d-file
elseif ($row['type'] == '99') { elseif ($row['type'] == '99') {
$task_desc = $lng['tasks']['regenerating_crond']; $task_desc = $lng['tasks']['regenerating_crond'];

View File

@@ -101,5 +101,10 @@ function inserttask($type, $param1 = '', $param2 = '', $param3 = '', $param4 = '
$data = serialize($data); $data = serialize($data);
Database::pexecute($ins_stmt, array('type' => '8', 'data' => $data)); Database::pexecute($ins_stmt, array('type' => '8', 'data' => $data));
} elseif ($type == '20'
&& is_array($param1)
) {
$data = serialize($param1);
Database::pexecute($ins_stmt, array('type' => '20', 'data' => $data));
} }
} }

View File

@@ -0,0 +1,34 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Daniel Reichelt <hacking@nachtgeist.net> (2016-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Functions
*
*/
function triggerLetsEncryptCSRForAliasDestinationDomain($aliasDestinationDomainID, $log)
{
if (isset($aliasDestinationDomainID) && $aliasDestinationDomainID > 0) {
$log->logAction(ADM_ACTION, LOG_INFO, "LetsEncrypt CSR triggered for domain ID " . $aliasDestinationDomainID);
$upd_stmt = Database::prepare(
"UPDATE
`" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "`
SET
`expirationdate` = null
WHERE
domainid = :domainid
");
Database::pexecute($upd_stmt, array(
'domainid' => $aliasDestinationDomainID
));
}
}

View File

@@ -129,6 +129,11 @@ return array (
'label' => $lng['menue']['logger']['logger'], 'label' => $lng['menue']['logger']['logger'],
'show_element' => ( Settings::Get('logger.enabled') == true ) 'show_element' => ( Settings::Get('logger.enabled') == true )
), ),
array (
'url' => 'customer_extras.php?page=backup',
'label' => $lng['menue']['extras']['backup'],
'show_element' => ( Settings::Get('system.backupenabled') == true ),
),
), ),
), ),
'traffic' => array ( 'traffic' => array (

View File

@@ -16,10 +16,10 @@
*/ */
// Main version variable // Main version variable
$version = '0.9.35'; $version = '0.9.36';
// Database version (YYYYMMDDC where C is a daily counter) // Database version (YYYYMMDDC where C is a daily counter)
$dbversion = '201603150'; $dbversion = '201604270';
// Distribution branding-tag (used for Debian etc.) // Distribution branding-tag (used for Debian etc.)
$branding = ''; $branding = '';

View File

@@ -310,8 +310,6 @@ $lng['serversettings']['bindconf_directory']['title'] = 'Bind configuratie map';
$lng['serversettings']['bindconf_directory']['description'] = 'Waar staan de bind configuratie bestanden?'; $lng['serversettings']['bindconf_directory']['description'] = 'Waar staan de bind configuratie bestanden?';
$lng['serversettings']['bindreload_command']['title'] = 'Bind reload commando'; $lng['serversettings']['bindreload_command']['title'] = 'Bind reload commando';
$lng['serversettings']['bindreload_command']['description'] = 'Wat is het command om bind te herladen?'; $lng['serversettings']['bindreload_command']['description'] = 'Wat is het command om bind te herladen?';
$lng['serversettings']['binddefaultzone']['title'] = 'Bind default zone';
$lng['serversettings']['binddefaultzone']['description'] = 'Wat is de naam van de default zone?';
$lng['serversettings']['vmail_uid']['title'] = 'Mails-Uid'; $lng['serversettings']['vmail_uid']['title'] = 'Mails-Uid';
$lng['serversettings']['vmail_uid']['description'] = 'Welk UserID moeten de e-mails hebben?'; $lng['serversettings']['vmail_uid']['description'] = 'Welk UserID moeten de e-mails hebben?';
$lng['serversettings']['vmail_gid']['title'] = 'Mails-Gid'; $lng['serversettings']['vmail_gid']['title'] = 'Mails-Gid';

View File

@@ -318,6 +318,7 @@ $lng['admin']['templates']['USERNAME'] = 'Replaced with the customers account us
$lng['admin']['templates']['PASSWORD'] = 'Replaced with the customers account password.'; $lng['admin']['templates']['PASSWORD'] = 'Replaced with the customers account password.';
$lng['admin']['templates']['EMAIL'] = 'Replaced with the address of the POP3/IMAP account.'; $lng['admin']['templates']['EMAIL'] = 'Replaced with the address of the POP3/IMAP account.';
$lng['admin']['webserver'] = 'Webserver'; $lng['admin']['webserver'] = 'Webserver';
$lng['admin']['bindzonewarning'] = $lng['panel']['emptyfordefault'] . '<br /><strong class="red">ATTENTION:</strong> If you use a zonefile you will have to manage all required records for all sub-zones manually as well.';
/** /**
* Serversettings * Serversettings
@@ -347,8 +348,6 @@ $lng['serversettings']['bindconf_directory']['title'] = 'Bind config directory';
$lng['serversettings']['bindconf_directory']['description'] = 'Where should bind configfiles be saved?'; $lng['serversettings']['bindconf_directory']['description'] = 'Where should bind configfiles be saved?';
$lng['serversettings']['bindreload_command']['title'] = 'Bind reload command'; $lng['serversettings']['bindreload_command']['title'] = 'Bind reload command';
$lng['serversettings']['bindreload_command']['description'] = 'What\'s the bind command to reload bind configfiles?'; $lng['serversettings']['bindreload_command']['description'] = 'What\'s the bind command to reload bind configfiles?';
$lng['serversettings']['binddefaultzone']['title'] = 'Bind default zone';
$lng['serversettings']['binddefaultzone']['description'] = 'What\'s the name of the default zone?';
$lng['serversettings']['vmail_uid']['title'] = 'Mails-UID'; $lng['serversettings']['vmail_uid']['title'] = 'Mails-UID';
$lng['serversettings']['vmail_uid']['description'] = 'Which UserID should mails have?'; $lng['serversettings']['vmail_uid']['description'] = 'Which UserID should mails have?';
$lng['serversettings']['vmail_gid']['title'] = 'Mails-GID'; $lng['serversettings']['vmail_gid']['title'] = 'Mails-GID';
@@ -1937,7 +1936,6 @@ $lng['customer']['letsencrypt']['title'] = 'Use Let\'s Encrypt';
$lng['customer']['letsencrypt']['description'] = 'Get a free certificate from <a href="https://letsencrypt.org">Let\'s Encrypt</a>. The certificate will be created and renewed automatically.<br><strong class="red">ATTENTION:</strong> This feature is still in beta.'; $lng['customer']['letsencrypt']['description'] = 'Get a free certificate from <a href="https://letsencrypt.org">Let\'s Encrypt</a>. The certificate will be created and renewed automatically.<br><strong class="red">ATTENTION:</strong> This feature is still in beta.';
$lng['error']['sslredirectonlypossiblewithsslipport'] = 'Using Let\'s Encrypt is only possible when the domain has at least one ssl-enabled IP/port combination assigned.'; $lng['error']['sslredirectonlypossiblewithsslipport'] = 'Using Let\'s Encrypt is only possible when the domain has at least one ssl-enabled IP/port combination assigned.';
$lng['error']['nowildcardwithletsencrypt'] = 'Let\'s Encrypt cannot (yet) handle wildcard-domains. Please set the ServerAlias to WWW or disable it completely'; $lng['error']['nowildcardwithletsencrypt'] = 'Let\'s Encrypt cannot (yet) handle wildcard-domains. Please set the ServerAlias to WWW or disable it completely';
$lng['error']['letsencryptdoesnotworkwithaliasdomains'] = "Usage of Let's Encrypt is not possible for aliasdomains at the moment. Please disable Let's Encrypt or AliasDomain";
$lng['panel']['letsencrypt'] = 'Using Let\'s encrypt'; $lng['panel']['letsencrypt'] = 'Using Let\'s encrypt';
$lng['crondesc']['cron_letsencrypt'] = 'updating Let\'s Encrypt certificates'; $lng['crondesc']['cron_letsencrypt'] = 'updating Let\'s Encrypt certificates';
$lng['serversettings']['letsencryptca']['title'] = "Let's Encrypt environment"; $lng['serversettings']['letsencryptca']['title'] = "Let's Encrypt environment";
@@ -1950,8 +1948,8 @@ $lng['serversettings']['letsencryptchallengepath']['title'] = "Path for Let's En
$lng['serversettings']['letsencryptchallengepath']['description'] = "Directory where the Let's Encrypt challenges should be offered from via a global alias.<br><strong class=\"red\">ATTENTION:</strong> Let's Encrypt is still in beta</strong>"; $lng['serversettings']['letsencryptchallengepath']['description'] = "Directory where the Let's Encrypt challenges should be offered from via a global alias.<br><strong class=\"red\">ATTENTION:</strong> Let's Encrypt is still in beta</strong>";
$lng['serversettings']['letsencryptkeysize']['title'] = "Key size for new Let's Encrypt certificates"; $lng['serversettings']['letsencryptkeysize']['title'] = "Key size for new Let's Encrypt certificates";
$lng['serversettings']['letsencryptkeysize']['description'] = "Size of the key in Bits for new Let's Encrypt certificates.<br><strong class=\"red\">ATTENTION:</strong> Let's Encrypt is still in beta</strong>"; $lng['serversettings']['letsencryptkeysize']['description'] = "Size of the key in Bits for new Let's Encrypt certificates.<br><strong class=\"red\">ATTENTION:</strong> Let's Encrypt is still in beta</strong>";
$lng['serversettings']['letsencryptreuseold']['title'] = "Re-use Let's Encrypt key / CSR"; $lng['serversettings']['letsencryptreuseold']['title'] = "Re-use Let's Encrypt key";
$lng['serversettings']['letsencryptreuseold']['description'] = "If activated, the same key and CSR will be used for every renew, otherwise a new key / CSR will be generated every time.<br><strong class=\"red\">ATTENTION:</strong> Let's Encrypt is still in beta</strong>"; $lng['serversettings']['letsencryptreuseold']['description'] = "If activated, the same key will be used for every renew, otherwise a new key will be generated every time.<br><strong class=\"red\">ATTENTION:</strong> Let's Encrypt is still in beta</strong>";
$lng['serversettings']['leenabled']['title'] = "Enable Let's Encrypt"; $lng['serversettings']['leenabled']['title'] = "Enable Let's Encrypt";
$lng['serversettings']['leenabled']['description'] = "If activated, customers are able to let froxlor automatically generate and renew Let's Encrypt ssl-certificates for domains with a ssl IP/port.<br /><br />Please remember that you need to go through the webserver-configuration when eabled because this feature needs a special configuration."; $lng['serversettings']['leenabled']['description'] = "If activated, customers are able to let froxlor automatically generate and renew Let's Encrypt ssl-certificates for domains with a ssl IP/port.<br /><br />Please remember that you need to go through the webserver-configuration when eabled because this feature needs a special configuration.";
$lng['domains']['ssl_redirect_temporarilydisabled'] = "<br>The SSL redirect is temporarily deactivated while a new Let's Encrypt certificate is generated. It will be activated again after the certificate was generated."; $lng['domains']['ssl_redirect_temporarilydisabled'] = "<br>The SSL redirect is temporarily deactivated while a new Let's Encrypt certificate is generated. It will be activated again after the certificate was generated.";
@@ -1975,3 +1973,20 @@ $lng['domains']['termination_date_overview'] = 'canceled until ';
$lng['panel']['set'] = 'Apply'; $lng['panel']['set'] = 'Apply';
$lng['customer']['selectserveralias_addinfo'] = 'This option can be set when editing the domain. Its initial value is inherited from the parent-domain.'; $lng['customer']['selectserveralias_addinfo'] = 'This option can be set when editing the domain. Its initial value is inherited from the parent-domain.';
$lng['error']['mailaccistobedeleted'] = "Another account with the same name (%s) is currently being deleted and can therefore not be added at this moment."; $lng['error']['mailaccistobedeleted'] = "Another account with the same name (%s) is currently being deleted and can therefore not be added at this moment.";
$lng['menue']['extras']['backup'] = 'Backup';
$lng['extras']['backup'] = 'Create backup';
$lng['extras']['backup_web'] = 'Backup web-data';
$lng['extras']['backup_mail'] = 'Backup mail-data';
$lng['extras']['backup_dbs'] = 'Backup databases';
$lng['error']['customerhasongoingbackupjob'] = 'There is already a backup job waiting to be processed, please be patient.';
$lng['success']['backupscheduled'] = 'Your backup job has been scheduled. Please wait for it to be processed';
$lng['crondesc']['cron_backup'] = 'Process backup jobs';
$lng['error']['backupfunctionnotenabled'] = 'The backup function is not enabled';
$lng['serversettings']['backupenabled']['title'] = "Enable backup for customers";
$lng['serversettings']['backupenabled']['description'] = "If activated, the customer will be able to schedule backup jobs (cron-backup) which generates an archive within his docroot (subdirectory chosable by customer)";
$lng['extras']['path_protection_label'] = '<strong class="red">Important</strong>';
$lng['extras']['path_protection_info'] = '<strong class="red">We strongly recommend protecting the given path, see "Extras" -> "Directory protection"</strong>';
$lng['tasks']['backup_customerfiles'] = 'Backup job for customer %loginname%';
$lng['error']['domain_nopunycode'] = 'You must not specify punycode (IDNA). The domain will automatically be converted';

View File

@@ -344,8 +344,6 @@ $lng['serversettings']['bindconf_directory']['title'] = 'Emplacement du dossier
$lng['serversettings']['bindconf_directory']['description'] = 'Oû doit être stocké la configuration de Bind / Named ?'; $lng['serversettings']['bindconf_directory']['description'] = 'Oû doit être stocké la configuration de Bind / Named ?';
$lng['serversettings']['bindreload_command']['title'] = 'Commande de rechargement de Bind / Named'; $lng['serversettings']['bindreload_command']['title'] = 'Commande de rechargement de Bind / Named';
$lng['serversettings']['bindreload_command']['description'] = 'Quelle est la commande pour recharger / redémarrer Bind / Named ?'; $lng['serversettings']['bindreload_command']['description'] = 'Quelle est la commande pour recharger / redémarrer Bind / Named ?';
$lng['serversettings']['binddefaultzone']['title'] = 'Nom du fichier de zone par défaut Bind / Named';
$lng['serversettings']['binddefaultzone']['description'] = 'Quel est le nom du fichier de zone par défaut pour Bind / Named ?';
$lng['serversettings']['vmail_uid']['title'] = 'UID des e-mails'; $lng['serversettings']['vmail_uid']['title'] = 'UID des e-mails';
$lng['serversettings']['vmail_uid']['description'] = 'Quel UID doivent avoir les e-mails ?'; $lng['serversettings']['vmail_uid']['description'] = 'Quel UID doivent avoir les e-mails ?';
$lng['serversettings']['vmail_gid']['title'] = 'GID des e-mails'; $lng['serversettings']['vmail_gid']['title'] = 'GID des e-mails';

View File

@@ -315,6 +315,7 @@ $lng['admin']['templates']['COMPANY'] = 'Wird mit dem Firmennamen des Kunden ers
$lng['admin']['templates']['USERNAME'] = 'Wird mit dem Benutzernamen des neuen Kundenkontos ersetzt.'; $lng['admin']['templates']['USERNAME'] = 'Wird mit dem Benutzernamen des neuen Kundenkontos ersetzt.';
$lng['admin']['templates']['PASSWORD'] = 'Wird mit dem Passwort des neuen Kundenkontos ersetzt.'; $lng['admin']['templates']['PASSWORD'] = 'Wird mit dem Passwort des neuen Kundenkontos ersetzt.';
$lng['admin']['templates']['EMAIL'] = 'Wird mit der Adresse des neuen E-Mail-Kontos ersetzt.'; $lng['admin']['templates']['EMAIL'] = 'Wird mit der Adresse des neuen E-Mail-Kontos ersetzt.';
$lng['admin']['bindzonewarning'] = $lng['panel']['emptyfordefault'] . '<br /><strong class="red">WARNUNG:</strong> Bei der Verwendung einer Zonendatei müssen alle benötigten Records aller Subdomains ebenfalls manuell verwaltet werden.';
/** /**
* Serversettings * Serversettings
@@ -344,8 +345,6 @@ $lng['serversettings']['bindconf_directory']['title'] = 'Bind-Config-Directory';
$lng['serversettings']['bindconf_directory']['description'] = 'Wo liegen die Bind-Konfigurationsdateien?'; $lng['serversettings']['bindconf_directory']['description'] = 'Wo liegen die Bind-Konfigurationsdateien?';
$lng['serversettings']['bindreload_command']['title'] = 'Bind-Reload-Command'; $lng['serversettings']['bindreload_command']['title'] = 'Bind-Reload-Command';
$lng['serversettings']['bindreload_command']['description'] = 'Wie heißt das Skript zum Neuladen der Bind-Konfigurationsdateien?'; $lng['serversettings']['bindreload_command']['description'] = 'Wie heißt das Skript zum Neuladen der Bind-Konfigurationsdateien?';
$lng['serversettings']['binddefaultzone']['title'] = 'Bind-Default-Zone';
$lng['serversettings']['binddefaultzone']['description'] = 'Wie heißt die Default-Zone für alle Domains?';
$lng['serversettings']['vmail_uid']['title'] = 'Mail-UID'; $lng['serversettings']['vmail_uid']['title'] = 'Mail-UID';
$lng['serversettings']['vmail_uid']['description'] = 'Welche UID sollen die E-Mails haben?'; $lng['serversettings']['vmail_uid']['description'] = 'Welche UID sollen die E-Mails haben?';
$lng['serversettings']['vmail_gid']['title'] = 'Mail-GID'; $lng['serversettings']['vmail_gid']['title'] = 'Mail-GID';
@@ -1591,7 +1590,6 @@ $lng['customer']['letsencrypt']['title'] = 'Benutze Let\'s Encrypt';
$lng['customer']['letsencrypt']['description'] = 'Holt ein kostenloses Zertifikat von <a href="https://letsencrypt.org">Let\'s Encrypt</a>. Das Zertifikat wird automatisch erstellt und verlängert.<br><strong class="red">ACHTUNG:</strong> Dieses Feature befindet sich noch im Test.'; $lng['customer']['letsencrypt']['description'] = 'Holt ein kostenloses Zertifikat von <a href="https://letsencrypt.org">Let\'s Encrypt</a>. Das Zertifikat wird automatisch erstellt und verlängert.<br><strong class="red">ACHTUNG:</strong> Dieses Feature befindet sich noch im Test.';
$lng['error']['sslredirectonlypossiblewithsslipport'] = 'Die Nutzung von Let\'s Encrypt ist nur möglich, wenn die Domain mindestens eine IP/Port - Kombination mit aktiviertem SSL zugewiesen hat.'; $lng['error']['sslredirectonlypossiblewithsslipport'] = 'Die Nutzung von Let\'s Encrypt ist nur möglich, wenn die Domain mindestens eine IP/Port - Kombination mit aktiviertem SSL zugewiesen hat.';
$lng['error']['nowildcardwithletsencrypt'] = 'Let\'s Encrypt kann (noch) nicht mit Wildcard-Domains umgehen. Bitte den ServerAlias auf WWW setzen oder deaktivieren'; $lng['error']['nowildcardwithletsencrypt'] = 'Let\'s Encrypt kann (noch) nicht mit Wildcard-Domains umgehen. Bitte den ServerAlias auf WWW setzen oder deaktivieren';
$lng['error']['letsencryptdoesnotworkwithaliasdomains'] = "Die Nutzung von Let's Encrypt ist mit AliasDomains derzeit nicht möglich. Bitte Let's Encrypt oder AliasDomain deaktivieren";
$lng['panel']['letsencrypt'] = 'Benutzt Let\'s encrypt'; $lng['panel']['letsencrypt'] = 'Benutzt Let\'s encrypt';
$lng['crondesc']['cron_letsencrypt'] = 'aktualisiert Let\'s Encrypt Zertifikate'; $lng['crondesc']['cron_letsencrypt'] = 'aktualisiert Let\'s Encrypt Zertifikate';
$lng['serversettings']['letsencryptca']['title'] = "Let's Encrypt Umgebung"; $lng['serversettings']['letsencryptca']['title'] = "Let's Encrypt Umgebung";
@@ -1604,8 +1602,8 @@ $lng['serversettings']['letsencryptchallengepath']['title'] = "Verzeichnis für
$lng['serversettings']['letsencryptchallengepath']['description'] = "Let's Encrypt challenges werden aus diesem Verzeichnis über einen globalen Alias ausgeliefert.<br><strong class=\"red\">ACHTUNG:</strong> Let's Encrypt befindet sich noch im Test"; $lng['serversettings']['letsencryptchallengepath']['description'] = "Let's Encrypt challenges werden aus diesem Verzeichnis über einen globalen Alias ausgeliefert.<br><strong class=\"red\">ACHTUNG:</strong> Let's Encrypt befindet sich noch im Test";
$lng['serversettings']['letsencryptkeysize']['title'] = "Schlüsselgröße für neue Let's Encrypt Zertifikate"; $lng['serversettings']['letsencryptkeysize']['title'] = "Schlüsselgröße für neue Let's Encrypt Zertifikate";
$lng['serversettings']['letsencryptkeysize']['description'] = "Größe des Schlüssels in Bit für neue Let's Encrypt Zertifikate.<br><strong class=\"red\">ACHTUNG:</strong> Let's Encrypt befindet sich noch im Test"; $lng['serversettings']['letsencryptkeysize']['description'] = "Größe des Schlüssels in Bit für neue Let's Encrypt Zertifikate.<br><strong class=\"red\">ACHTUNG:</strong> Let's Encrypt befindet sich noch im Test";
$lng['serversettings']['letsencryptreuseold']['title'] = "Let's Encrypt Schlüssel / CSR wiederverwenden"; $lng['serversettings']['letsencryptreuseold']['title'] = "Let's Encrypt Schlüssel wiederverwenden";
$lng['serversettings']['letsencryptreuseold']['description'] = "Wenn dies aktiviert ist, werden der alte Schlüssel und CSR bei jeder Verlängerung verwendet, andernfalls wird ein neues Paar generiert.<br><strong class=\"red\">ACHTUNG:</strong> Let's Encrypt befindet sich noch im Test"; $lng['serversettings']['letsencryptreuseold']['description'] = "Wenn dies aktiviert ist, wird der alte Schlüssel bei jeder Verlängerung verwendet, andernfalls wird ein neues Paar generiert.<br><strong class=\"red\">ACHTUNG:</strong> Let's Encrypt befindet sich noch im Test";
$lng['serversettings']['leenabled']['title'] = "Let's Encrypt verwenden"; $lng['serversettings']['leenabled']['title'] = "Let's Encrypt verwenden";
$lng['serversettings']['leenabled']['description'] = "Wenn dies aktiviert ist, können Kunden durch Froxlor automatisch generierte und verlängerbare Let's Encrypt SSL-Zertifikate für Domains mit SSL IP/port nutzen.<br /><br />Bitte die Webserver-Konfiguration beachten wenn aktiviert, da dieses Feature eine spezielle Konfiguration benötigt."; $lng['serversettings']['leenabled']['description'] = "Wenn dies aktiviert ist, können Kunden durch Froxlor automatisch generierte und verlängerbare Let's Encrypt SSL-Zertifikate für Domains mit SSL IP/port nutzen.<br /><br />Bitte die Webserver-Konfiguration beachten wenn aktiviert, da dieses Feature eine spezielle Konfiguration benötigt.";
$lng['domains']['ssl_redirect_temporarilydisabled'] = "<br>Die SSL-Umleitung ist, während ein neues Let's Encrypt - Zertifikat erstellt wird, temporär deaktiviert. Die Umleitung wird nach der Zertifikatserstellung wieder aktiviert."; $lng['domains']['ssl_redirect_temporarilydisabled'] = "<br>Die SSL-Umleitung ist, während ein neues Let's Encrypt - Zertifikat erstellt wird, temporär deaktiviert. Die Umleitung wird nach der Zertifikatserstellung wieder aktiviert.";
@@ -1628,3 +1626,20 @@ $lng['domains']['termination_date_overview'] = 'gekündigt zum ';
$lng['panel']['set'] = 'Setzen'; $lng['panel']['set'] = 'Setzen';
$lng['customer']['selectserveralias_addinfo'] = 'Diese Option steht beim Bearbeiten der Domain zur Verfügung. Als Initial-Wert wird die Einstellung der Hauptdomain vererbt.'; $lng['customer']['selectserveralias_addinfo'] = 'Diese Option steht beim Bearbeiten der Domain zur Verfügung. Als Initial-Wert wird die Einstellung der Hauptdomain vererbt.';
$lng['error']['mailaccistobedeleted'] = "Ein vorheriges Konto mit dem gleichen Namen (%s) wird aktuell noch gelöscht und kann daher derzeit nicht angelegt werden"; $lng['error']['mailaccistobedeleted'] = "Ein vorheriges Konto mit dem gleichen Namen (%s) wird aktuell noch gelöscht und kann daher derzeit nicht angelegt werden";
$lng['menue']['extras']['backup'] = 'Sicherung';
$lng['extras']['backup'] = 'Sicherung erstellen';
$lng['extras']['backup_web'] = 'Web-Daten sichern';
$lng['extras']['backup_mail'] = 'E-Mail Daten sichern';
$lng['extras']['backup_dbs'] = 'Datenbanken sichern';
$lng['error']['customerhasongoingbackupjob'] = 'Es gibt noch einen austehenden Backup-Job. Bitte haben Sie etwas Geduld.';
$lng['success']['backupscheduled'] = 'Ihre Sicherung wurde erfolgreich geplant. Bitte warten Sie nun, bis diese abgearbeitet wurde.';
$lng['crondesc']['cron_backup'] = 'Ausstehende Sicherungen erstellen';
$lng['error']['backupfunctionnotenabled'] = 'Die Sicherungs-Funktion is nicht aktiviert';
$lng['serversettings']['backupenabled']['title'] = "Backup für Kunden aktivieren";
$lng['serversettings']['backupenabled']['description'] = "Wenn dies aktiviert ist, kann der Kunde Sicherungen planen (cron-backup) welche ein Archiv in sein Heimatverzeichnis ablegt (Unterordner vom Kunden wählbar)";
$lng['extras']['path_protection_label'] = '<strong class="red">Wichtig</strong>';
$lng['extras']['path_protection_info'] = '<strong class="red">Wir raten dringend dazu den angegebenen Pfad zu schützen, siehe "Extras" -> "Verzeichnisschutz"</strong>';
$lng['tasks']['backup_customerfiles'] = 'Datensicherung für Kunde %loginname%';
$lng['error']['domain_nopunycode'] = 'Die Eingabe von Punycode (IDNA) ist nicht notwendig. Die Domain wird automatisch konvertiert.';

View File

@@ -336,8 +336,6 @@ $lng['serversettings']['bindconf_directory']['title'] = 'Cartella configurazione
$lng['serversettings']['bindconf_directory']['description'] = 'Dove sono i file di configurazione per Bind?'; $lng['serversettings']['bindconf_directory']['description'] = 'Dove sono i file di configurazione per Bind?';
$lng['serversettings']['bindreload_command']['title'] = 'Comando riavvio Bind'; $lng['serversettings']['bindreload_command']['title'] = 'Comando riavvio Bind';
$lng['serversettings']['bindreload_command']['description'] = 'Qual\'è il comando per riavviare Bind?'; $lng['serversettings']['bindreload_command']['description'] = 'Qual\'è il comando per riavviare Bind?';
$lng['serversettings']['binddefaultzone']['title'] = 'Zona di default Bind';
$lng['serversettings']['binddefaultzone']['description'] = 'Qual\'è il nome della zona di default Bind?';
$lng['serversettings']['vmail_uid']['title'] = 'UID Email'; $lng['serversettings']['vmail_uid']['title'] = 'UID Email';
$lng['serversettings']['vmail_uid']['description'] = 'Che UserID dovrebbe avere l\'utente che gestisce le Email?'; $lng['serversettings']['vmail_uid']['description'] = 'Che UserID dovrebbe avere l\'utente che gestisce le Email?';
$lng['serversettings']['vmail_gid']['title'] = 'GID Email'; $lng['serversettings']['vmail_gid']['title'] = 'GID Email';

View File

@@ -341,8 +341,6 @@ $lng['serversettings']['bindconf_directory']['title'] = 'Diretório de configura
$lng['serversettings']['bindconf_directory']['description'] = 'Aonde estão os arquivos de configuração do bind?'; $lng['serversettings']['bindconf_directory']['description'] = 'Aonde estão os arquivos de configuração do bind?';
$lng['serversettings']['bindreload_command']['title'] = 'Comando de reiniciar o Bind'; $lng['serversettings']['bindreload_command']['title'] = 'Comando de reiniciar o Bind';
$lng['serversettings']['bindreload_command']['description'] = 'Qual o comando para reiniciar o bind?'; $lng['serversettings']['bindreload_command']['description'] = 'Qual o comando para reiniciar o bind?';
$lng['serversettings']['binddefaultzone']['title'] = 'Bind default zone';
$lng['serversettings']['binddefaultzone']['description'] = 'Qual o nome da default zone?';
$lng['serversettings']['vmail_uid']['title'] = 'Mails-Uid'; $lng['serversettings']['vmail_uid']['title'] = 'Mails-Uid';
$lng['serversettings']['vmail_uid']['description'] = 'Qual UserID os e-mails devem ter?'; $lng['serversettings']['vmail_uid']['description'] = 'Qual UserID os e-mails devem ter?';
$lng['serversettings']['vmail_gid']['title'] = 'Mails-Gid'; $lng['serversettings']['vmail_gid']['title'] = 'Mails-Gid';

View File

@@ -328,8 +328,6 @@ $lng['serversettings']['bindconf_directory']['title'] = 'Bind konfigurationskata
$lng['serversettings']['bindconf_directory']['description'] = 'Vilken sökväg skall det vara till bind:s konfigurationsfiler?'; $lng['serversettings']['bindconf_directory']['description'] = 'Vilken sökväg skall det vara till bind:s konfigurationsfiler?';
$lng['serversettings']['bindreload_command']['title'] = 'Ange sökvägen till programmet som laddar om Bind (reload bind) konfigurationsfiler?'; $lng['serversettings']['bindreload_command']['title'] = 'Ange sökvägen till programmet som laddar om Bind (reload bind) konfigurationsfiler?';
$lng['serversettings']['bindreload_command']['description'] = 'Ange sökvägen till programmet som laddar om Bind (reload bind) konfigurationsfiler?'; $lng['serversettings']['bindreload_command']['description'] = 'Ange sökvägen till programmet som laddar om Bind (reload bind) konfigurationsfiler?';
$lng['serversettings']['binddefaultzone']['title'] = 'Bind standard zone';
$lng['serversettings']['binddefaultzone']['description'] = 'Vad är namnet på standard zonen?';
$lng['serversettings']['vmail_uid']['title'] = 'Mails-UID'; $lng['serversettings']['vmail_uid']['title'] = 'Mails-UID';
$lng['serversettings']['vmail_uid']['description'] = 'Vilket användarID (UserID) ska E-posten ha?'; $lng['serversettings']['vmail_uid']['description'] = 'Vilket användarID (UserID) ska E-posten ha?';
$lng['serversettings']['vmail_gid']['title'] = 'Mails-GID'; $lng['serversettings']['vmail_gid']['title'] = 'Mails-GID';

View File

@@ -0,0 +1,114 @@
<?php if (!defined('MASTER_CRONJOB')) die('You cannot access this file directly!');
/**
* This file is part of the Froxlor project.
* Copyright (c) 2016 the Froxlor Team (see authors).
*
* For the full copyright and license information, please view the COPYING
* file that was distributed with this source code. You can also view the
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
*
* @copyright (c) the authors
* @author Michael Kaufmann <mkaufmann@nutime.de>
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Cron
*
* @since 0.9.35.1
*
*/
// Check Traffic-Lock
if (function_exists('pcntl_fork')) {
$BackupLock = makeCorrectFile(dirname($lockfile)."/froxlor_cron_backup.lock");
if (file_exists($BackupLock)
&& is_numeric($BackupPid=file_get_contents($BackupLock))
) {
if (function_exists('posix_kill')) {
$BackupPidStatus = @posix_kill($BackupPid,0);
} else {
system("kill -CHLD " . $BackupPid . " 1> /dev/null 2> /dev/null", $BackupPidStatus);
$BackupPidStatus = $BackupPidStatus ? false : true;
}
if ($BackupPidStatus) {
$cronlog->logAction(CRON_ACTION, LOG_INFO, 'Backup run already in progress');
return 1;
}
}
// Create Backup Log and Fork
// We close the database - connection before we fork, so we don't share resources with the child
Database::needRoot(false); // this forces the connection to be set to null
$BackupPid = pcntl_fork();
// Parent
if ($BackupPid) {
file_put_contents($BackupLock, $BackupPid);
// unnecessary to recreate database connection here
return 0;
}
//Child
elseif ($BackupPid == 0) {
posix_setsid();
fclose($debugHandler);
// re-create db
Database::needRoot(false);
}
//Fork failed
else {
return 1;
}
} else {
if (extension_loaded('pcntl')) {
$msg = "PHP compiled with pcntl but pcntl_fork function is not available.";
} else {
$msg = "PHP compiled without pcntl.";
}
$cronlog->logAction(CRON_ACTION, LOG_WARNING, $msg." Not forking backup-cron, this may take a long time!");
}
$cronlog->logAction(CRON_ACTION, LOG_INFO, 'cron_backup: started - creating customer backup');
$result_tasks_stmt = Database::query("
SELECT * FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` = '20' ORDER BY `id` ASC
");
$del_stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_TASKS . "` WHERE `id` = :id");
$all_jobs = $result_tasks_stmt->fetchAll();
foreach ($all_jobs as $row) {
if ($row['data'] != '') {
$row['data'] = unserialize($row['data']);
}
if (is_array($row['data'])) {
if (isset($row['data']['customerid'])
&& isset($row['data']['loginname'])
&& isset($row['data']['destdir'])
) {
$row['data']['destdir'] = makeCorrectDir($row['data']['destdir']);
$customerdocroot = makeCorrectDir(Settings::Get('system.documentroot_prefix').'/'.$row['data']['loginname'].'/');
if (!file_exists($row['data']['destdir'])
&& $row['data']['destdir'] != '/'
&& $row['data']['destdir'] != Settings::Get('system.documentroot_prefix')
&& $row['data']['destdir'] != $customerdocroot
) {
$cronlog->logAction(CRON_ACTION, LOG_NOTICE, 'Creating backup-destination path for customer: ' . escapeshellarg($row['data']['destdir']));
safe_exec('mkdir -p '.escapeshellarg($row['data']['destdir']));
}
createCustomerBackup($row['data'], $customerdocroot, $cronlog);
}
}
// remove entry
Database::pexecute($del_stmt, array('id' => $row['id']));
}
if (function_exists('pcntl_fork')) {
@unlink($BackupLock);
die();
}

View File

@@ -1,4 +1,6 @@
<?php if (!defined('MASTER_CRONJOB')) die('You cannot access this file directly!'); <?php
if (! defined('MASTER_CRONJOB'))
die('You cannot access this file directly!');
/** /**
* This file is part of the Froxlor project. * This file is part of the Froxlor project.
@@ -20,51 +22,112 @@
$cronlog->logAction(CRON_ACTION, LOG_INFO, "Updating Let's Encrypt certificates"); $cronlog->logAction(CRON_ACTION, LOG_INFO, "Updating Let's Encrypt certificates");
$certificates_stmt = Database::query(" if (! extension_loaded('curl')) {
SELECT domssl.`id`, domssl.`domainid`, domssl.expirationdate, domssl.`ssl_cert_file`, domssl.`ssl_key_file`, domssl.`ssl_ca_file`, domssl.`ssl_csr_file`, dom.`domain`, dom.`iswildcarddomain`, dom.`wwwserveralias`, $cronlog->logAction(CRON_ACTION, LOG_ERR, "Let's Encrypt requires the php cURL extension to be installed.");
dom.`documentroot`, dom.`id` as 'domainid', dom.`ssl_redirect`, cust.`leprivatekey`, cust.`lepublickey`, cust.customerid, cust.loginname exit();
FROM `".TABLE_PANEL_CUSTOMERS."` as cust, `".TABLE_PANEL_DOMAINS."` dom LEFT JOIN `".TABLE_PANEL_DOMAIN_SSL_SETTINGS."` domssl ON (dom.id = domssl.domainid) }
WHERE dom.customerid = cust.customerid AND dom.letsencrypt = 1 AND (domssl.expirationdate < DATE_ADD(NOW(), INTERVAL 30 DAY) OR domssl.expirationdate IS NULL)
");
$updcert_stmt = Database::prepare(" $certificates_stmt = Database::query(
REPLACE INTO `".TABLE_PANEL_DOMAIN_SSL_SETTINGS."` SET `id` = :id, `domainid` = :domainid, `ssl_cert_file` = :crt, `ssl_key_file` = :key, `ssl_ca_file` = :ca, `ssl_cert_chainfile` = :chain, `ssl_csr_file` = :csr, expirationdate = :expirationdate "
"); SELECT
domssl.`id`,
domssl.`domainid`,
domssl.expirationdate,
domssl.`ssl_cert_file`,
domssl.`ssl_key_file`,
domssl.`ssl_ca_file`,
domssl.`ssl_csr_file`,
dom.`domain`,
dom.`wwwserveralias`,
dom.`documentroot`,
dom.`id` AS 'domainid',
dom.`ssl_redirect`,
cust.`leprivatekey`,
cust.`lepublickey`,
cust.`customerid`,
cust.`loginname`
FROM
`" . TABLE_PANEL_CUSTOMERS . "` AS cust,
`" . TABLE_PANEL_DOMAINS . "` AS dom
LEFT JOIN
`" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "` AS domssl ON
dom.`id` = domssl.`domainid`
WHERE
dom.`customerid` = cust.`customerid`
AND dom.`letsencrypt` = 1
AND dom.`aliasdomain` IS NULL
AND dom.`iswildcarddomain` = 0
AND (
domssl.`expirationdate` < DATE_ADD(NOW(), INTERVAL 30 DAY)
OR domssl.`expirationdate` IS NULL
)
");
$upddom_stmt = Database::prepare(" $aliasdomains_stmt = Database::prepare(
UPDATE `".TABLE_PANEL_DOMAINS."` SET `ssl_redirect` = '1' WHERE `id` = :domainid "
"); SELECT
dom.`id` as domainid,
dom.`domain`,
dom.`wwwserveralias`
FROM `" . TABLE_PANEL_DOMAINS . "` AS dom
WHERE
dom.`aliasdomain` = :id
AND dom.`letsencrypt` = 1
AND dom.`iswildcarddomain` = 0
");
$updcert_stmt = Database::prepare(
"
REPLACE INTO
`" . TABLE_PANEL_DOMAIN_SSL_SETTINGS . "`
SET
`id` = :id,
`domainid` = :domainid,
`ssl_cert_file` = :crt,
`ssl_key_file` = :key,
`ssl_ca_file` = :ca,
`ssl_cert_chainfile` = :chain,
`ssl_csr_file` = :csr,
`expirationdate` = :expirationdate
");
$upddom_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `ssl_redirect` = '1' WHERE `id` = :domainid");
$changedetected = 0; $changedetected = 0;
$certrows = $certificates_stmt->fetchAll(PDO::FETCH_ASSOC); $certrows = $certificates_stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($certrows AS $certrow) { foreach ($certrows as $certrow) {
// set logger to corresponding loginname for the log to appear in the users system-log // set logger to corresponding loginname for the log to appear in the users system-log
$cronlog = FroxlorLogger::getInstanceOf(array('loginname' => $certrow['loginname'])); $cronlog = FroxlorLogger::getInstanceOf(array(
'loginname' => $certrow['loginname']
));
// Only renew let's encrypt certificate if no broken ssl_redirect is enabled // Only renew let's encrypt certificate if no broken ssl_redirect is enabled
if ($certrow['ssl_redirect'] != 2) if ($certrow['ssl_redirect'] != 2) {
{
$cronlog->logAction(CRON_ACTION, LOG_DEBUG, "Updating " . $certrow['domain']); $cronlog->logAction(CRON_ACTION, LOG_DEBUG, "Updating " . $certrow['domain']);
if ($certrow['ssl_cert_file']) { $cronlog->logAction(CRON_ACTION, LOG_DEBUG, "Adding SAN entry: " . $certrow['domain']);
$cronlog->logAction(CRON_ACTION, LOG_DEBUG, "letsencrypt using old key / SAN for " . $certrow['domain']); $domains = array(
// Parse the old certificate $certrow['domain']
$x509data = openssl_x509_parse($certrow['ssl_cert_file']); );
// add www.<domain> to SAN list
// We are interessted in the old SAN - data
$san = explode(', ', $x509data['extensions']['subjectAltName']);
$domains = array();
foreach($san as $dnsname) {
$domains[] = substr($dnsname, 4);
}
} else {
$cronlog->logAction(CRON_ACTION, LOG_DEBUG, "letsencrypt generating new key / SAN for " . $certrow['domain']);
$domains = array($certrow['domain']);
// Add www.<domain> for SAN
if ($certrow['wwwserveralias'] == 1) { if ($certrow['wwwserveralias'] == 1) {
$cronlog->logAction(CRON_ACTION, LOG_DEBUG, "Adding SAN entry: www." . $certrow['domain']);
$domains[] = 'www.' . $certrow['domain']; $domains[] = 'www.' . $certrow['domain'];
} }
// add alias domains (and possibly www.<aliasdomain>) to SAN list
Database::pexecute($aliasdomains_stmt, array(
'id' => $certrow['domainid']
));
$aliasdomains = $aliasdomains_stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($aliasdomains as $aliasdomain) {
$cronlog->logAction(CRON_ACTION, LOG_DEBUG, "Adding SAN entry: " . $aliasdomain['domain']);
$domains[] = $aliasdomain['domain'];
if ($aliasdomain['wwwserveralias'] == 1) {
$cronlog->logAction(CRON_ACTION, LOG_DEBUG, "Adding SAN entry: www." . $aliasdomain['domain']);
$domains[] = 'www.' . $aliasdomain['domain'];
}
} }
try { try {
@@ -81,7 +144,8 @@ foreach($certrows AS $certrow) {
$newcert = openssl_x509_parse($return['crt']); $newcert = openssl_x509_parse($return['crt']);
// Store the new data // Store the new data
Database::pexecute($updcert_stmt, array( Database::pexecute($updcert_stmt,
array(
'id' => $certrow['id'], 'id' => $certrow['id'],
'domainid' => $certrow['domainid'], 'domainid' => $certrow['domainid'],
'crt' => $return['crt'], 'crt' => $return['crt'],
@@ -90,25 +154,24 @@ foreach($certrows AS $certrow) {
'chain' => $return['chain'], 'chain' => $return['chain'],
'csr' => $return['csr'], 'csr' => $return['csr'],
'expirationdate' => date('Y-m-d H:i:s', $newcert['validTo_time_t']) 'expirationdate' => date('Y-m-d H:i:s', $newcert['validTo_time_t'])
) ));
);
if ($certrow['ssl_redirect'] == 3) { if ($certrow['ssl_redirect'] == 3) {
Database::pexecute($upddom_stmt, array( Database::pexecute($upddom_stmt, array(
'domainid' => $certrow['domainid'] 'domainid' => $certrow['domainid']
) ));
);
} }
$cronlog->logAction(CRON_ACTION, LOG_INFO, "Updated Let's Encrypt certificate for " . $certrow['domain']); $cronlog->logAction(CRON_ACTION, LOG_INFO, "Updated Let's Encrypt certificate for " . $certrow['domain']);
$changedetected = 1; $changedetected = 1;
} catch (Exception $e) { } catch (Exception $e) {
$cronlog->logAction(CRON_ACTION, LOG_ERR, "Could not get Let's Encrypt certificate for " . $certrow['domain'] . ": " . $e->getMessage()); $cronlog->logAction(CRON_ACTION, LOG_ERR,
"Could not get Let's Encrypt certificate for " . $certrow['domain'] . ": " . $e->getMessage());
} }
} else { } else {
$cronlog->logAction(CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $certrow['domain'] . " due to an enabled ssl_redirect"); $cronlog->logAction(CRON_ACTION, LOG_WARNING,
"Skipping Let's Encrypt generation for " . $certrow['domain'] . " due to an enabled ssl_redirect");
} }
} }
@@ -119,5 +182,7 @@ if ($changedetected) {
} }
// reset logger // reset logger
$cronlog = FroxlorLogger::getInstanceOf(array('loginname' => 'cronjob')); $cronlog = FroxlorLogger::getInstanceOf(array(
'loginname' => 'cronjob'
));
$cronlog->logAction(CRON_ACTION, LOG_INFO, "Let's Encrypt certificates have been updated"); $cronlog->logAction(CRON_ACTION, LOG_INFO, "Let's Encrypt certificates have been updated");

View File

@@ -203,7 +203,8 @@ class bind {
$subzones.= $this->walkDomainList($domains[$child_domain_id], $domains); $subzones.= $this->walkDomainList($domains[$child_domain_id], $domains);
} }
if ($domain['ismainbutsubto'] == 0 && $domain['zonefile'] == '') { if ($domain['zonefile'] == '') {
if ($domain['ismainbutsubto'] == 0) {
$zonefile = $this->generateZone($domain); $zonefile = $this->generateZone($domain);
$domain['zonefile'] = 'domains/' . $domain['domain'] . '.zone'; $domain['zonefile'] = 'domains/' . $domain['domain'] . '.zone';
$zonefile_name = makeCorrectFile(Settings::Get('system.bindconf_directory') . '/' . $domain['zonefile']); $zonefile_name = makeCorrectFile(Settings::Get('system.bindconf_directory') . '/' . $domain['zonefile']);
@@ -212,11 +213,13 @@ class bind {
fwrite($zonefile_handler, $zonefile.$subzones); fwrite($zonefile_handler, $zonefile.$subzones);
fclose($zonefile_handler); fclose($zonefile_handler);
$this->logger->logAction(CRON_ACTION, LOG_INFO, '`' . $zonefile_name . '` zone written'); $this->logger->logAction(CRON_ACTION, LOG_INFO, '`' . $zonefile_name . '` zone written');
$this->_bindconf_file .= $this->_generateDomainConfig($domain);
} else { } else {
return $this->generateZone($domain); return $this->generateZone($domain);
} }
} else {
if ($zonefile !== '') { $this->logger->logAction(CRON_ACTION, LOG_INFO, 'Added zonefile ' . $domain['zonefile'] . ' for domain ' . $domain['domain'] .
' - Note that you will also have to handle ALL records for ALL subdomains.');
$this->_bindconf_file .= $this->_generateDomainConfig($domain); $this->_bindconf_file .= $this->_generateDomainConfig($domain);
} }
} }

View File

@@ -155,7 +155,7 @@ class nginx extends HttpConfigBase {
/** /**
* this HAS to be set for the default host in nginx or else no vhost will work * this HAS to be set for the default host in nginx or else no vhost will work
*/ */
$this->nginx_data[$vhost_filename] .= "\t". 'listen ' . $ip . ':' . $port . ' default'. ($ssl_vhost == true ? ' ssl' : '') . ';' . "\n"; $this->nginx_data[$vhost_filename] .= "\t". 'listen ' . $ip . ':' . $port . ' default_server'. ($ssl_vhost == true ? ' ssl' : '') . ';' . "\n";
$this->nginx_data[$vhost_filename] .= "\t".'# Froxlor default vhost' . "\n"; $this->nginx_data[$vhost_filename] .= "\t".'# Froxlor default vhost' . "\n";
$this->nginx_data[$vhost_filename] .= "\t".'server_name ' . Settings::Get('system.hostname') . ';' . "\n"; $this->nginx_data[$vhost_filename] .= "\t".'server_name ' . Settings::Get('system.hostname') . ';' . "\n";
@@ -422,7 +422,11 @@ class nginx extends HttpConfigBase {
) { ) {
$vhost_content.= "\n" . $this->composeSslSettings($domain) . "\n"; $vhost_content.= "\n" . $this->composeSslSettings($domain) . "\n";
} }
if (Settings::Get('system.use_ssl') == '1' && Settings::Get('system.leenabled') == '1')
{
$vhost_content.= "\t".'include /etc/nginx/acme.conf;'."\n"; $vhost_content.= "\t".'include /etc/nginx/acme.conf;'."\n";
}
// if the documentroot is an URL we just redirect // if the documentroot is an URL we just redirect
if (preg_match('/^https?\:\/\//', $domain['documentroot'])) { if (preg_match('/^https?\:\/\//', $domain['documentroot'])) {

View File

@@ -30,8 +30,9 @@ require_once makeCorrectFile(dirname(__FILE__) . '/cron_tasks.inc.http.35.nginx_
* LOOK INTO TASKS TABLE TO SEE IF THERE ARE ANY UNDONE JOBS * LOOK INTO TASKS TABLE TO SEE IF THERE ARE ANY UNDONE JOBS
*/ */
$cronlog->logAction(CRON_ACTION, LOG_INFO, "cron_tasks: Searching for tasks to do"); $cronlog->logAction(CRON_ACTION, LOG_INFO, "cron_tasks: Searching for tasks to do");
// no type 99 (regenerate cron.d-file) and no type 20 (customer backup)
$result_tasks_stmt = Database::query(" $result_tasks_stmt = Database::query("
SELECT `id`, `type`, `data` FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` <> '99' ORDER BY `id` ASC SELECT `id`, `type`, `data` FROM `" . TABLE_PANEL_TASKS . "` WHERE `type` <> '99' AND `type` <> '20' ORDER BY `id` ASC
"); ");
$num_results = Database::num_rows(); $num_results = Database::num_rows();
$resultIDs = array(); $resultIDs = array();
@@ -165,6 +166,12 @@ while ($row = $result_tasks_stmt->fetch(PDO::FETCH_ASSOC)) {
} }
$cronlog->logAction(CRON_ACTION, LOG_NOTICE, 'Running: chown -R ' . (int)Settings::Get('system.vmail_uid') . ':' . (int)Settings::Get('system.vmail_gid') . ' ' . escapeshellarg($usermaildir)); $cronlog->logAction(CRON_ACTION, LOG_NOTICE, 'Running: chown -R ' . (int)Settings::Get('system.vmail_uid') . ':' . (int)Settings::Get('system.vmail_gid') . ' ' . escapeshellarg($usermaildir));
safe_exec('chown -R ' . (int)Settings::Get('system.vmail_uid') . ':' . (int)Settings::Get('system.vmail_gid') . ' ' . escapeshellarg($usermaildir)); safe_exec('chown -R ' . (int)Settings::Get('system.vmail_uid') . ':' . (int)Settings::Get('system.vmail_gid') . ' ' . escapeshellarg($usermaildir));
// clear NSCD cache if using fcgid or fpm, #1570
if (Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) {
$false_val = false;
safe_exec('nscd -i group 1> /dev/null', $false_val, array('>'));
}
} }
} }

View File

@@ -1,11 +1,9 @@
<if $row['termination_date'] != ''> <if $row['termination_css'] != ''>
<tr class="{$row['termination_css']}"> <tr class="{$row['termination_css']}">
</if> </if>
<if $row['termination_date'] == ''> <if $row['termination_css'] == ''>
<tr> <tr>
</if> </if>
<td>{$row['domain']} <td>{$row['domain']}
<if (isset($row['standardsubdomain']) && $row['standardsubdomain'] == $row['id'])> <if (isset($row['standardsubdomain']) && $row['standardsubdomain'] == $row['id'])>
&nbsp;({$lng['admin']['stdsubdomain']}) &nbsp;({$lng['admin']['stdsubdomain']})
@@ -13,11 +11,10 @@
<if $row['termination_date'] != ''> <if $row['termination_date'] != ''>
<br><small><div class="red">({$lng['domains']['termination_date_overview']} {$row['termination_date']})</div></small> <br><small><div class="red">({$lng['domains']['termination_date_overview']} {$row['termination_date']})</div></small>
</if> </if>
</td> </td>
<td>{$row['ipandport']}</td> <td>{$row['ipandport']}</td>
<td>{$row['customername']}&nbsp; <td>{$row['customername']}&nbsp;
(<a href="{$linker->getLink(array('section' => 'customers', 'page' => 'customers', 'action' => 'su', 'id' => $row['customerid']))}" rel="external">{$row['loginname']}</a>) <if !empty($row['loginname'])>(<a href="{$linker->getLink(array('section' => 'customers', 'page' => 'customers', 'action' => 'su', 'id' => $row['customerid']))}" rel="external">{$row['loginname']}</a>)</if>
</td> </td>
<td> <td>
<a href="{$linker->getLink(array('section' => 'domains', 'page' => $page, 'action' => 'edit', 'id' => $row['id']))}"> <a href="{$linker->getLink(array('section' => 'domains', 'page' => $page, 'action' => 'edit', 'id' => $row['id']))}">
@@ -26,7 +23,7 @@
<if $row['letsencrypt'] == '1'> <if $row['letsencrypt'] == '1'>
<img src="templates/{$theme}/assets/img/icons/ssl_letsencrypt.png" alt="{$lng['panel']['letsencrypt']}" title="{$lng['panel']['letsencrypt']}" /> <img src="templates/{$theme}/assets/img/icons/ssl_letsencrypt.png" alt="{$lng['panel']['letsencrypt']}" title="{$lng['panel']['letsencrypt']}" />
</if> </if>
<if !(isset($row['domainaliasid']) && $row['domainaliasid'] != 0)> <if !(isset($row['domainaliasid']) && $row['domainaliasid'] != 0) && $row['id'] != Settings::Get('system.hostname_id')>
<if !(isset($row['standardsubdomain']) && $row['standardsubdomain'] == $row['id'])> <if !(isset($row['standardsubdomain']) && $row['standardsubdomain'] == $row['id'])>
&nbsp;<a href="{$linker->getLink(array('section' => 'domains', 'page' => $page, 'action' => 'delete', 'id' => $row['id']))}"> &nbsp;<a href="{$linker->getLink(array('section' => 'domains', 'page' => $page, 'action' => 'delete', 'id' => $row['id']))}">
<img src="templates/{$theme}/assets/img/icons/delete.png" alt="{$lng['panel']['delete']}" title="{$lng['panel']['delete']}" /> <img src="templates/{$theme}/assets/img/icons/delete.png" alt="{$lng['panel']['delete']}" title="{$lng['panel']['delete']}" />

View File

@@ -1503,3 +1503,13 @@ fieldset.file {
/* Color copied from .errorcontainer */ /* Color copied from .errorcontainer */
background-color: rgb(242, 222, 222); background-color: rgb(242, 222, 222);
} }
.domain-hostname {
background-color: rgb(53, 106, 160);
color: #ddd;
font-weight: bold;
}
table.hl tbody tr.domain-hostname:hover {
background-color: rgb(64, 150, 238);
}

View File

@@ -70,7 +70,7 @@ $(document).ready(function() {
var snheight = $('#sidenavigation').height(); var snheight = $('#sidenavigation').height();
var mainheight = $('#maincontent').height(); var mainheight = $('#maincontent').height();
if (snheight > mainheight && !$('#newsfeed').length) { if (snheight > mainheight && !$('#newsfeed').length) {
$('#maincontent').height(snheight); $('#maincontent').css("min-height", snheight);
} }
// this is necessary for the special setting feature (ref #1010) // this is necessary for the special setting feature (ref #1010)
$.getQueryVariable = function(key) { $.getQueryVariable = function(key) {

View File

@@ -0,0 +1,26 @@
$header
<article>
<header>
<h2>
<img src="templates/{$theme}/assets/img/icons/backup_big.png" alt="{$title}" />&nbsp;
{$title}
</h2>
</header>
<section>
<form action="{$linker->getLink(array('section' => 'extras'))}" method="post" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />
<input type="hidden" name="action" value="$action" />
<input type="hidden" name="send" value="send" />
<table class="full">
{$backup_form}
</table>
</form>
</section>
</article>
$footer