From 38bdef2b74632ad60dff690985d14ff973b4063d Mon Sep 17 00:00:00 2001 From: flashwave Date: Sun, 16 Sep 2018 20:45:49 +0200 Subject: [PATCH] More background stuff [laptop] --- assets/less/mio/classes/container.less | 2 +- public/settings.php | 61 +++++++++++++-- src/Application.php | 11 ++- src/Users/user.php | 101 ++++++++++++++++++++++++- templates/settings/account.twig | 26 ++++--- 5 files changed, 179 insertions(+), 22 deletions(-) diff --git a/assets/less/mio/classes/container.less b/assets/less/mio/classes/container.less index 84a2a233..d1730c95 100644 --- a/assets/less/mio/classes/container.less +++ b/assets/less/mio/classes/container.less @@ -13,7 +13,7 @@ &__title { display: block; text-decoration: none; - background-color: var(--accent-colour); + background-image: linear-gradient(0deg, transparent, var(--accent-colour)); color: var(--text-colour-header); font-size: 1.17em; font-weight: 700; diff --git a/public/settings.php b/public/settings.php index 1dffaf61..593f45f3 100644 --- a/public/settings.php +++ b/public/settings.php @@ -70,6 +70,7 @@ $settingsErrors = []; $disableAccountOptions = !$app->inDebugMode() && $app->disableRegistration(); $avatarFileName = "{$app->getUserId()}.msz"; $avatarProps = $app->getAvatarProps(); +$backgroundProps = $app->getBackgroundProps(); if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (!tmp_csrf_verify($_POST['csrf'] ?? '')) { @@ -112,8 +113,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { case 'upload': if (empty($_FILES['avatar']) - || !is_array($_FILES['avatar']) - || empty($_FILES['avatar']['name']['file'])) { + || !is_array($_FILES['avatar']) + || empty($_FILES['avatar']['name']['file'])) { break; } @@ -131,7 +132,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $setAvatar = user_avatar_set_from_path( $app->getUserId(), - $_FILES['avatar']['tmp_name']['file'] + $_FILES['avatar']['tmp_name']['file'], + $avatarProps ); if ($setAvatar !== MSZ_USER_AVATAR_NO_ERRORS) { @@ -148,6 +150,51 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } } + if (!empty($_POST['background']) && is_array($_POST['background'])) { + switch ($_POST['background']['mode'] ?? '') { + case 'delete': + user_background_delete($app->getUserId()); + break; + + case 'upload': + if (empty($_FILES['background']) + || !is_array($_FILES['background']) + || empty($_FILES['background']['name']['file'])) { + break; + } + + if ($_FILES['background']['error']['file'] !== UPLOAD_ERR_OK) { + $settingsErrors[] = sprintf( + $avatarErrorStrings['upload'][$_FILES['background']['error']['file']] + ?? $avatarErrorStrings['upload']['default'], + $_FILES['background']['error']['file'], + byte_symbol($backgroundProps['max_filesize'], true), + $backgroundProps['max_width'], + $backgroundProps['max_height'] + ); + break; + } + + $setBackground = user_background_set_from_path( + $app->getUserId(), + $_FILES['background']['tmp_name']['file'], + $backgroundProps + ); + + if ($setBackground !== MSZ_USER_BACKGROUND_NO_ERRORS) { + $settingsErrors[] = sprintf( + $avatarErrorStrings['set'][$setBackground] + ?? $avatarErrorStrings['set']['default'], + $setBackground, + byte_symbol($backgroundProps['max_filesize'], true), + $backgroundProps['max_width'], + $backgroundProps['max_height'] + ); + } + break; + } + } + if (!empty($_POST['session_action'])) { switch ($_POST['session_action']) { case 'kill-all': @@ -305,13 +352,13 @@ switch ($settingsMode) { $getMail->bindValue('user_id', $app->getUserId()); $currentEmail = $getMail->execute() ? $getMail->fetchColumn() : 'Failed to fetch e-mail address.'; $userHasAvatar = is_file(build_path($app->getStoragePath(), 'avatars/original', $avatarFileName)); + $userHasBackground = is_file(build_path($app->getStoragePath(), 'backgrounds/original', $avatarFileName)); tpl_vars([ - 'avatar_user_id' => $app->getUserId(), - 'avatar_max_width' => $avatarProps['max_width'], - 'avatar_max_height' => $avatarProps['max_height'], - 'avatar_max_filesize' => $avatarProps['max_filesize'], + 'avatar' => $avatarProps, + 'background' => $backgroundProps, 'user_has_avatar' => $userHasAvatar, + 'user_has_background' => $userHasBackground, 'settings_profile_fields' => $profileFields, 'settings_profile_values' => $userFields, 'settings_disable_account_options' => $disableAccountOptions, diff --git a/src/Application.php b/src/Application.php index 2332d6ed..8979bc5a 100644 --- a/src/Application.php +++ b/src/Application.php @@ -365,7 +365,16 @@ final class Application return [ 'max_width' => intval($this->config['Avatar']['max_width'] ?? 4000), 'max_height' => intval($this->config['Avatar']['max_height'] ?? 4000), - 'max_filesize' => intval($this->config['Avatar']['max_filesize'] ?? 1000000), + 'max_size' => intval($this->config['Avatar']['max_filesize'] ?? 1000000), + ]; + } + + public function getBackgroundProps(): array + { + return [ + 'max_width' => intval($this->config['Background']['max_width'] ?? 3840), + 'max_height' => intval($this->config['Background']['max_height'] ?? 2160), + 'max_size' => intval($this->config['Background']['max_filesize'] ?? 1000000), ]; } diff --git a/src/Users/user.php b/src/Users/user.php index d16fa106..e0fc1cee 100644 --- a/src/Users/user.php +++ b/src/Users/user.php @@ -60,9 +60,8 @@ define('MSZ_USER_AVATAR_FORMAT', '%d.msz'); function user_avatar_delete(int $userId): void { - $app = Application::getInstance(); $avatarFileName = sprintf(MSZ_USER_AVATAR_FORMAT, $userId); - $storePath = $app->getStoragePath(); + $storePath = Application::getInstance()->getStoragePath(); $deleteThis = [ build_path($storePath, 'avatars/original', $avatarFileName), @@ -164,3 +163,101 @@ function user_avatar_set_from_data(int $userId, string $data, array $options = [ return $result; } + +define('MSZ_USER_BACKGROUND_FORMAT', '%d.msz'); + +function user_background_delete(int $userId): void +{ + $backgroundFileName = sprintf(MSZ_USER_BACKGROUND_FORMAT, $userId); + $storePath = Application::getInstance()->getStoragePath(); + safe_delete(build_path($storePath, 'backgrounds/original', $backgroundFileName)); +} + +define('MSZ_USER_BACKGROUND_TYPE_PNG', IMAGETYPE_PNG); +define('MSZ_USER_BACKGROUND_TYPE_JPG', IMAGETYPE_JPEG); +define('MSZ_USER_BACKGROUND_TYPES', [ + MSZ_USER_BACKGROUND_TYPE_PNG, + MSZ_USER_BACKGROUND_TYPE_JPG, +]); + +function user_background_is_allowed_type(int $type): bool +{ + return in_array($type, MSZ_USER_BACKGROUND_TYPES, true); +} + +define('MSZ_USER_BACKGROUND_OPTIONS', [ + 'max_width' => 3840, + 'max_height' => 2160, + 'max_size' => 1000000, +]); + +define('MSZ_USER_BACKGROUND_NO_ERRORS', 0); +define('MSZ_USER_BACKGROUND_ERROR_INVALID_IMAGE', 1); +define('MSZ_USER_BACKGROUND_ERROR_PROHIBITED_TYPE', 2); +define('MSZ_USER_BACKGROUND_ERROR_DIMENSIONS_TOO_LARGE', 3); +define('MSZ_USER_BACKGROUND_ERROR_DATA_TOO_LARGE', 4); +define('MSZ_USER_BACKGROUND_ERROR_TMP_FAILED', 5); +define('MSZ_USER_BACKGROUND_ERROR_STORE_FAILED', 6); +define('MSZ_USER_BACKGROUND_ERROR_FILE_NOT_FOUND', 7); + +function user_background_set_from_path(int $userId, string $path, array $options = []): int +{ + if (!file_exists($path)) { + return MSZ_USER_BACKGROUND_ERROR_FILE_NOT_FOUND; + } + + $options = array_merge(MSZ_USER_BACKGROUND_OPTIONS, $options); + + // 0 => width, 1 => height, 2 => type + $imageInfo = getimagesize($path); + + if ($imageInfo === false + || count($imageInfo) < 3 + || $imageInfo[0] < 1 + || $imageInfo[1] < 1) { + return MSZ_USER_BACKGROUND_ERROR_INVALID_IMAGE; + } + + if (!user_background_is_allowed_type($imageInfo[2])) { + return MSZ_USER_BACKGROUND_ERROR_PROHIBITED_TYPE; + } + + if ($imageInfo[0] > $options['max_width'] + || $imageInfo[1] > $options['max_height']) { + return MSZ_USER_BACKGROUND_ERROR_DIMENSIONS_TOO_LARGE; + } + + if (filesize($path) > $options['max_size']) { + return MSZ_USER_BACKGROUND_ERROR_DATA_TOO_LARGE; + } + + user_background_delete($userId); + + $fileName = sprintf(MSZ_USER_BACKGROUND_FORMAT, $userId); + $backgroundPath = build_path( + create_directory(build_path(Application::getInstance()->getStoragePath(), 'backgrounds/original')), + $fileName + ); + + if (!copy($path, $backgroundPath)) { + return MSZ_USER_BACKGROUND_ERROR_STORE_FAILED; + } + + return MSZ_USER_BACKGROUND_NO_ERRORS; +} + +function user_background_set_from_data(int $userId, string $data, array $options = []): int +{ + $tmp = tempnam(sys_get_temp_dir(), 'msz'); + + if ($tmp === false || !file_exists($tmp)) { + return MSZ_USER_BACKGROUND_ERROR_TMP_FAILED; + } + + chmod($tmp, 644); + file_put_contents($tmp, $data); + $result = user_background_set_from_path($userId, $tmp, $options); + safe_delete($tmp); + + return $result; +} diff --git a/templates/settings/account.twig b/templates/settings/account.twig index 79a3939e..7c5492e4 100644 --- a/templates/settings/account.twig +++ b/templates/settings/account.twig @@ -1,5 +1,9 @@ {% extends 'settings/master.twig' %} +{% if user_has_background %} + {% set site_background_url = '/profile.php?m=background&u=' ~ current_user.user_id %} +{% endif %} + {% block settings_content %}
Account
@@ -125,7 +129,7 @@
Avatar
- +
@@ -133,8 +137,8 @@
  • Guidelines
  • Keep things sane and suitable for all ages.
  • -
  • Image may not exceed the {{ avatar_max_filesize|byte_symbol(true) }} filesize limit.
  • -
  • May not be larger than {{ avatar_max_width }}x{{ avatar_max_height }}.
  • +
  • Image may not exceed the {{ avatar.max_size|byte_symbol(true) }} filesize limit.
  • +
  • May not be larger than {{ avatar.max_width }}x{{ avatar.max_height }}.
  • Will be centre cropped to be 200x200.
  • Animated gif images are allowed.
@@ -146,7 +150,7 @@
+ style="background-image:url('/profile.php?u={{ current_user.user_id }}&m=avatar')">
function updateAvatarPreview(name, url, previewEl, nameEl) { - url = url || "/profile.php?u={{ avatar_user_id }}&m=avatar"; + url = url || "/profile.php?u={{ current_user.user_id }}&m=avatar"; previewEl = previewEl || document.getElementById('avatar-preview'); nameEl = nameEl || document.getElementById('avatar-name'); previewEl.style.backgroundImage = 'url(\'{0}\')'.replace('{0}', url); @@ -196,7 +200,7 @@
Background
- +
@@ -204,8 +208,8 @@
  • Guidelines
  • Keep things sane and suitable for all ages.
  • -
  • Image may not exceed the {{ avatar_max_filesize|byte_symbol(true) }} filesize limit.
  • -
  • May not be larger than {{ avatar_max_width }}x{{ avatar_max_height }}.
  • +
  • Image may not exceed the {{ background.max_size|byte_symbol(true) }} filesize limit.
  • +
  • May not be larger than {{ background.max_width }}x{{ background.max_height }}.
  • Animated gif images are not allowed.
@@ -232,8 +236,8 @@ Upload