Merge branch 'master' of github.com:Froxlor/Froxlor

This commit is contained in:
Michael Kaufmann
2021-07-12 17:29:25 +02:00
21 changed files with 232 additions and 26 deletions

2
.gitignore vendored
View File

@@ -12,9 +12,9 @@ logs/*
.well-known
.idea
*.iml
img/
!templates/Froxlor/
!templates/Sparkle/
!templates/misc/
templates/Froxlor/assets/img/logo_custom.png
vendor/

View File

@@ -296,6 +296,24 @@ return array(
'default' => '',
'save_method' => 'storeSettingField'
),
'panel_logo_image_header' => array(
'label' => $lng['serversettings']['logo_image_header'],
'settinggroup' => 'panel',
'varname' => 'logo_image_header',
'type' => 'image',
'image_name' => 'logo_header',
'default' => '',
'save_method' => 'storeSettingImage'
),
'panel_logo_image_login' => array(
'label' => $lng['serversettings']['logo_image_login'],
'settinggroup' => 'panel',
'varname' => 'logo_image_login',
'type' => 'image',
'image_name' => 'logo_login',
'default' => '',
'save_method' => 'storeSettingImage'
),
)
)
)

View File

@@ -43,12 +43,13 @@
"ext-curl": "*",
"ext-json": "*",
"ext-openssl": "*",
"ext-fileinfo": "*",
"phpmailer/phpmailer": "~6.0",
"monolog/monolog": "^1.24",
"robthree/twofactorauth": "^1.6",
"froxlor/idna-convert-legacy": "^2.1",
"voku/anti-xss": "^4.1"
},
},
"require-dev": {
"phpunit/phpunit": "^9",
"php": ">=7.3",

View File

@@ -715,8 +715,10 @@ opcache.interned_strings_buffer'),
('panel', 'imprint_url', ''),
('panel', 'terms_url', ''),
('panel', 'privacy_url', ''),
('panel', 'logo_image_header', ''),
('panel', 'logo_image_login', ''),
('panel', 'version', '0.10.26'),
('panel', 'db_version', '202106270');
('panel', 'db_version', '202107070');
DROP TABLE IF EXISTS `panel_tasks`;
@@ -933,7 +935,7 @@ CREATE TABLE IF NOT EXISTS `ftp_quotalimits` (
INSERT INTO `ftp_quotalimits` (`name`, `quota_type`, `per_session`, `limit_type`, `bytes_in_avail`, `bytes_out_avail`, `bytes_xfer_avail`, `files_in_avail`, `files_out_avail`, `files_xfer_avail`) VALUES
INSERT INTO `ftp_quotalimits` (`name`, `quota_type`, `per_session`, `limit_type`, `bytes_in_avail`, `bytes_out_avail`, `bytes_xfer_avail`, `files_in_avail`, `files_out_avail`, `files_xfer_avail`) VALUES
('froxlor', 'user', 'false', 'hard', 0, 0, 0, 0, 0, 0);

View File

@@ -14,7 +14,7 @@ use Froxlor\Settings;
* @author Froxlor team <team@froxlor.org> (2010-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Install
*
*
*/
if (! defined('_CRON_UPDATE')) {
if (! defined('AREA') || (defined('AREA') && AREA != 'admin') || ! isset($userinfo['loginname']) || (isset($userinfo['loginname']) && $userinfo['loginname'] == '')) {
@@ -825,3 +825,40 @@ if (\Froxlor\Froxlor::isDatabaseVersion('202106160')) {
\Froxlor\Froxlor::updateToDbVersion('202106270');
}
if (\Froxlor\Froxlor::isDatabaseVersion('202106270')) {
showUpdateStep("Adding custom logo image settings", true);
Settings::AddNew("panel.logo_image_header", '');
Settings::AddNew("panel.logo_image_login", '');
lastStepStatus(0);
// Migrating old custom logo over, if exists
$custom_logo_file_old = \Froxlor\Froxlor::getInstallDir() . '/templates/Sparkle/assets/img/logo_custom.png';
if (file_exists($custom_logo_file_old)) {
showUpdateStep("Migrating existing custom logo to new settings", true);
$path = \Froxlor\Froxlor::getInstallDir().'/img/';
if (!is_dir($path) && !mkdir($path, 0775)) {
throw new \Exception("img directory does not exist and cannot be created");
}
if (!is_writable($path)) {
if (!chmod($path, '0775')) {
throw new \Exception("Cannot write to img directory");
}
}
// Save as new custom logo header
$save_to = 'logo_header.png';
copy($custom_logo_file_old, $path.$save_to);
Settings::Set("panel.logo_image_header", "img/{$save_to}?v=".time());
// Save as new custom logo login
$save_to = 'logo_login.png';
copy($custom_logo_file_old, $path.$save_to);
Settings::Set("panel.logo_image_login", "img/{$save_to}?v=".time());
lastStepStatus(0);
}
\Froxlor\Froxlor::updateToDbVersion('202107070');
}

View File

@@ -10,7 +10,7 @@ final class Froxlor
const VERSION = '0.10.26';
// Database version (YYYYMMDDC where C is a daily counter)
const DBVERSION = '202106270';
const DBVERSION = '202107070';
// Distribution branding-tag (used for Debian etc.)
const BRANDING = '';
@@ -63,7 +63,7 @@ final class Froxlor
*
* @param string $to_check
* version to check, if empty current version is used
*
*
* @return bool true if version to check does not match, else false
*/
public static function hasUpdates($to_check = null)
@@ -84,7 +84,7 @@ final class Froxlor
*
* @param int $to_check
* version to check, if empty current dbversion is used
*
*
* @return bool true if version to check does not match, else false
*/
public static function hasDbUpdates($to_check = null)
@@ -105,7 +105,7 @@ final class Froxlor
*
* @param int $to_check
* version to check
*
*
* @return bool true if version to check matches, else false
*/
public static function isDatabaseVersion($to_check = null)
@@ -124,7 +124,7 @@ final class Froxlor
*
* @param string $new_version
* new-version
*
*
* @return bool true on success, else false
*/
public static function updateToDbVersion($new_version = null)
@@ -150,7 +150,7 @@ final class Froxlor
*
* @param string $new_version
* new-version
*
*
* @return bool true on success, else false
*/
public static function updateToVersion($new_version = null)
@@ -191,7 +191,7 @@ final class Froxlor
*
* @param string $to_check
* version to check
*
*
* @return bool true if version to check matches, else false
*/
public static function isFroxlorVersion($to_check = null)

View File

@@ -16,9 +16,9 @@ use Froxlor\Database\Database;
* @author Froxlor team <team@froxlor.org> (2018-)
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
* @package Classes
*
*
* @since 0.9.39
*
*
*/
/**
@@ -60,6 +60,13 @@ class SImExporter
public static function export()
{
$settings_definitions = [];
foreach (\Froxlor\PhpHelper::loadConfigArrayDir('./actions/admin/settings/')['groups'] AS $group) {
foreach ($group['fields'] AS $field) {
$settings_definitions[$field['settinggroup']][$field['varname']] = $field;
}
}
$result_stmt = Database::query("
SELECT * FROM `" . TABLE_PANEL_SETTINGS . "` ORDER BY `settingid` ASC
");
@@ -69,13 +76,26 @@ class SImExporter
if (! in_array($index, self::$no_export)) {
$_data[$index] = $row['value'];
}
if (array_key_exists($row['settinggroup'], $settings_definitions) && array_key_exists($row['varname'], $settings_definitions[$row['settinggroup']])) {
// Export image file
if ($settings_definitions[$row['settinggroup']][$row['varname']]['type'] === "image") {
if ($row['value'] === "") {
continue;
}
$_data[$index.'.image_data'] = base64_encode(file_get_contents(explode('?', $row['value'], 2)[0]));
}
}
}
// add checksum for validation
$_data['_sha'] = sha1(var_export($_data, true));
$_export = json_encode($_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
if (! $_export) {
throw new \Exception("Error exporting settings: " . json_last_error_msg());
}
return $_export;
}
@@ -120,6 +140,26 @@ class SImExporter
}
// store new data
foreach ($_data as $index => $value) {
$index_split = explode('.', $index, 3);
// Catch image_data and save it
if (isset($index_split[2]) && $index_split[2] === 'image_data' && !empty($_data[$index_split[0].'.'.$index_split[1]])) {
$path = \Froxlor\Froxlor::getInstallDir().'/img/';
if (!is_dir($path) && !mkdir($path, '0775')) {
throw new \Exception("img directory does not exist and cannot be created");
}
// Make sure we can write to the upload directory
if (!is_writable($path)) {
if (!chmod($path, '0775')) {
throw new \Exception("Cannot write to img directory");
}
}
file_put_contents(\Froxlor\Froxlor::getInstallDir() . '/' . explode('?', $_data[$index_split[0].'.'.$index_split[1]], 2)[0], base64_decode($value));
continue;
}
Settings::Set($index, $value);
}
// save to DB

View File

@@ -367,4 +367,67 @@ class Store
return $returnvalue;
}
public static function storeSettingImage($fieldname, $fielddata)
{
if (isset($fielddata['settinggroup'], $fielddata['varname']) && is_array($fielddata) && $fielddata['settinggroup'] !== '' && $fielddata['varname'] !== '') {
$save_to = null;
$path = \Froxlor\Froxlor::getInstallDir().'/img/';
// New file?
if ($_FILES[$fieldname]['tmp_name']) {
// Make sure upload directory exists
if (!is_dir($path) && !mkdir($path, '0775')) {
throw new \Exception("img directory does not exist and cannot be created");
}
// Make sure we can write to the upload directory
if (!is_writable($path)) {
if (!chmod($path, '0775')) {
throw new \Exception("Cannot write to img directory");
}
}
// Make sure mime-type matches an image
if (!in_array(mime_content_type($_FILES[$fieldname]['tmp_name']), ['image/jpeg','image/jpg','image/png','image/gif'])) {
throw new \Exception("Uploaded file not a valid image");
}
// Determine file extension
$spl = explode('.', $_FILES[$fieldname]['name']);
$file_extension = strtolower(array_pop($spl));
unset($spl);
// Move file
if (!move_uploaded_file($_FILES[$fieldname]['tmp_name'], $path.$fielddata['image_name'].'.'.$file_extension)) {
throw new \Exception("Unable to save image to img folder");
}
$save_to = 'img/'.$fielddata['image_name'].'.'.$file_extension.'?v='.time();
}
// Delete file?
if ($fielddata['value'] !== "" && array_key_exists($fieldname.'_delete', $_POST) && $_POST[$fieldname.'_delete']) {
@unlink(\Froxlor\Froxlor::getInstallDir() . '/' . explode('?', $fielddata['value'], 2)[0]);
$save_to = '';
}
// Nothing changed
if ($save_to === null) {
return array(
$fielddata['settinggroup'] . '.' . $fielddata['varname'] => $fielddata['value']
);
}
if (Settings::Set($fielddata['settinggroup'] . '.' . $fielddata['varname'], $save_to) === false) {
return false;
}
return array(
$fielddata['settinggroup'] . '.' . $fielddata['varname'] => $save_to
);
}
return false;
}
}

View File

@@ -52,6 +52,12 @@ class Data
return $newfieldvalue;
}
public static function getFormFieldDataImage($fieldname, $fielddata, $input)
{
// We always make the system think we have new data to trigger the save function where we actually check everything
return time();
}
public static function manipulateFormFieldDataDate($fieldname, $fielddata, $newfieldvalue)
{
if (isset($fielddata['date_timestamp']) && $fielddata['date_timestamp'] === true) {

View File

@@ -89,6 +89,15 @@ class Fields
return $returnvalue;
}
public static function getFormFieldOutputImage($fieldname, $fielddata, $do_show = true)
{
global $lng;
$label = $fielddata['label'];
$value = htmlentities($fielddata['value']);
eval("\$returnvalue = \"" . \Froxlor\UI\Template::getTemplate("formfields/image", true) . "\";");
return $returnvalue;
}
public static function getFormFieldOutputDate($fieldname, $fielddata, $do_show = true)
{
if (isset($fielddata['date_timestamp']) && $fielddata['date_timestamp'] === true) {

View File

@@ -380,11 +380,8 @@ if (! array_key_exists('variants', $_themeoptions) || ! array_key_exists($themev
// check for custom header-graphic
$hl_path = 'templates/' . $theme . '/assets/img';
$header_logo = $hl_path . '/logo.png';
if (file_exists($hl_path . '/logo_custom.png')) {
$header_logo = $hl_path . '/logo_custom.png';
}
$header_logo = Settings::Get('panel.logo_image_header') ?: $hl_path . '/logo.png';
$header_logo_login = Settings::Get('panel.logo_image_login') ?: $hl_path . '/logo.png';
/**
* Redirects to index.php (login page) if no session exists

View File

@@ -2117,3 +2117,9 @@ $lng['privacy'] = 'Privacy policy';
$lng['serversettings']['privacy_url']['title'] = 'URL to privacy policy';
$lng['serversettings']['privacy_url']['description'] = 'Specify an URL to your privacy policy site / imprint site. The link will be visible on the login screen and on the footer when logged in.';
$lng['admin']['domaindefaultalias'] = 'Default ServerAlias value for new domains';
$lng['serversettings']['logo_image_header']['title'] = 'Logo Image (Header)';
$lng['serversettings']['logo_image_header']['description'] = 'Upload your own logo image to be shown in the header after login (recommended height 30px)';
$lng['serversettings']['logo_image_login']['title'] = 'Logo Image (Login)';
$lng['serversettings']['logo_image_login']['description'] = 'Upload your own logo image to be shown during login';
$lng['panel']['image_field_delete'] = 'Delete the existing current image';

View File

@@ -1763,3 +1763,9 @@ $lng['privacy'] = 'Datenschutzerklärung';
$lng['serversettings']['privacy_url']['title'] = 'URL zur Datenschutzerklärung';
$lng['serversettings']['privacy_url']['description'] = 'Die URL zur Datenschutzerklärungs-Seite. Der Link ist auf der Login-Seite und wenn eingeloggt, in der Fußzeile sichtbar.';
$lng['admin']['domaindefaultalias'] = 'Standard ServerAlias-Angabe für neue Domains';
$lng['serversettings']['logo_image_header']['title'] = 'Logo Bild (Header)';
$lng['serversettings']['logo_image_header']['description'] = 'Das hochgeladene Bild wird als Logo oben links nach dem Login angezeigt (empfohlene Höhe sind 30px)';
$lng['serversettings']['logo_image_login']['title'] = 'Logo Bild (Login)';
$lng['serversettings']['logo_image_login']['description'] = 'Das hochgeladene Bild wird als Logo während des Logins angezeigt';
$lng['panel']['image_field_delete'] = 'Das momentan vorhandene Bild löschen';

View File

@@ -1,7 +1,7 @@
$header
<article class="login bradius">
<header class="dark">
<img src="{$header_logo}" alt="Froxlor Server Management Panel" />
<img src="{$header_logo_login}" alt="Froxlor Server Management Panel" />
</header>
<section class="loginsec">
<form method="post" action="{$filename}" enctype="application/x-www-form-urlencoded">

View File

@@ -1,5 +1,5 @@
$header
<form method="post" action="$filename" enctype="application/x-www-form-urlencoded">
<form method="post" action="$filename" enctype="multipart/form-data">
<input type="hidden" name="send" value="send" />
<input type="hidden" name="s" value="$s" />
<input type="hidden" name="page" value="$page" />

View File

@@ -77,7 +77,11 @@ strong {
}
header img {
padding: 10px 0 10px 10px;
padding: 10px;
}
.login header img {
margin: 0 auto;
display: block;
}
img.small {
@@ -1745,3 +1749,9 @@ td.size-50 {
.footer-link:last-child:after {
content: "";
}
.field-image-preview {
max-width: 300px;
max-height: 500px;
margin-bottom: 10px;
}

11
templates/Sparkle/formfields/image.tpl vendored Normal file
View File

@@ -0,0 +1,11 @@
<tr>
<td>{$label}</td>
<td>
<if $value>
<img src="/{$value}" alt="Current Image" class="field-image-preview"><br>
<input type="checkbox" value="1" name="{$fieldname}_delete" /> {$lng['panel']['image_field_delete']}
<br><br>
</if>
<input <if $do_show == 0>disabled="disabled"</if> type="file" class="file" name="{$fieldname}" accept="image/jpeg, image/jpg, image/png, image/gif" />
</td>
</tr>

View File

@@ -1,7 +1,7 @@
$header
<article class="login bradius">
<header class="dark">
<img src="{$header_logo}" alt="Froxlor Server Management Panel" />
<img src="{$header_logo_login}" alt="Froxlor Server Management Panel" />
</header>
<if $message != ''>
<div class="errorcontainer bradius">

View File

@@ -1,7 +1,7 @@
$header
<article class="login bradius">
<header class="dark">
<img src="{$header_logo}" alt="Froxlor Server Management Panel" />
<img src="{$header_logo_login}" alt="Froxlor Server Management Panel" />
</header>
<if $update_in_progress !== ''>

View File

@@ -1,6 +1,6 @@
<article class="login bradius">
<header class="dark">
<img src="{$header_logo}" alt="{t}Froxlor Server Management Panel{/t}" />
<img src="{$header_logo_login}" alt="{t}Froxlor Server Management Panel{/t}" />
</header>
{if isset($successmessage)}

View File

@@ -1,7 +1,7 @@
$header
<article class="login bradius">
<header class="dark">
<img src="{$header_logo}" alt="Froxlor Server Management Panel" />
<img src="{$header_logo_login}" alt="Froxlor Server Management Panel" />
</header>
<if $message != ''>
<div class="errorcontainer bradius">