More background stuff [laptop]

This commit is contained in:
flash 2018-09-16 20:45:49 +02:00
parent be861868f2
commit 38bdef2b74
5 changed files with 179 additions and 22 deletions

View file

@ -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;

View file

@ -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,

View file

@ -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),
];
}

View file

@ -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;
}

View file

@ -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 %}
<div class="container">
<div class="container__title">Account</div>
@ -125,7 +129,7 @@
<div class="container">
<div class="container__title">Avatar</div>
<form action="" method="post" class="settings__images" enctype="multipart/form-data">
<input type="hidden" name="MAX_FILE_SIZE" value="{{ avatar_max_filesize }}">
<input type="hidden" name="MAX_FILE_SIZE" value="{{ background.max_size }}">
<input type="hidden" name="csrf" value="{{ csrf_token() }}">
<div class="settings__images__sections">
@ -133,8 +137,8 @@
<ul class="settings__images__requirements__list">
<li class="settings__images__requirement settings__images__requirement--header">Guidelines</li>
<li class="settings__images__requirement">Keep things sane and suitable for all ages.</li>
<li class="settings__images__requirement">Image may not exceed the <strong>{{ avatar_max_filesize|byte_symbol(true) }}</strong> filesize limit.</li>
<li class="settings__images__requirement">May not be larger than <strong>{{ avatar_max_width }}x{{ avatar_max_height }}</strong>.</li>
<li class="settings__images__requirement">Image may not exceed the <strong>{{ avatar.max_size|byte_symbol(true) }}</strong> filesize limit.</li>
<li class="settings__images__requirement">May not be larger than <strong>{{ avatar.max_width }}x{{ avatar.max_height }}</strong>.</li>
<li class="settings__images__requirement">Will be centre cropped to be <strong>200x200</strong>.</li>
<li class="settings__images__requirement">Animated gif images are allowed.</li>
</ul>
@ -146,7 +150,7 @@
<div
class="avatar settings__avatar__preview"
id="avatar-preview"
style="background-image:url('/profile.php?u={{ avatar_user_id }}&amp;m=avatar')"></div>
style="background-image:url('/profile.php?u={{ current_user.user_id }}&amp;m=avatar')"></div>
<input
class="settings__avatar__input"
accept="image/png,image/jpeg,image/gif"
@ -179,7 +183,7 @@
<script>
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 @@
<div class="container">
<div class="container__title">Background</div>
<form action="" method="post" class="settings__images" enctype="multipart/form-data">
<input type="hidden" name="MAX_FILE_SIZE" value="{{ avatar_max_filesize }}">
<input type="hidden" name="MAX_FILE_SIZE" value="{{ background.max_size }}">
<input type="hidden" name="csrf" value="{{ csrf_token() }}">
<div class="settings__images__sections">
@ -204,8 +208,8 @@
<ul class="settings__images__requirements__list">
<li class="settings__images__requirement settings__images__requirement--header">Guidelines</li>
<li class="settings__images__requirement">Keep things sane and suitable for all ages.</li>
<li class="settings__images__requirement">Image may not exceed the <strong>{{ avatar_max_filesize|byte_symbol(true) }}</strong> filesize limit.</li>
<li class="settings__images__requirement">May not be larger than <strong>{{ avatar_max_width }}x{{ avatar_max_height }}</strong>.</li>
<li class="settings__images__requirement">Image may not exceed the <strong>{{ background.max_size|byte_symbol(true) }}</strong> filesize limit.</li>
<li class="settings__images__requirement">May not be larger than <strong>{{ background.max_width }}x{{ background.max_height }}</strong>.</li>
<li class="settings__images__requirement">Animated gif images are <strong>not</strong> allowed.</li>
</ul>
</div>
@ -232,8 +236,8 @@
Upload
</button>
<button
class="settings__avatar__button settings__avatar__button--delete{{ user_has_avatar ? '' : ' settings__avatar__button--disabled' }}"
{{ user_has_avatar ? '' : 'disabled' }}
class="settings__avatar__button settings__avatar__button--delete{{ user_has_background ? '' : ' settings__avatar__button--disabled' }}"
{{ user_has_background ? '' : 'disabled' }}
name="background[mode]"
value="delete">
Delete
@ -245,7 +249,7 @@
<script>
function updateBackgroundPreview(name, url, previewEl, nameEl) {
url = url || "/profile.php?u={{ avatar_user_id }}&m=background";
url = url || "/profile.php?u={{ current_user.user_id }}&m=background";
previewEl = previewEl || document.body;
nameEl = nameEl || document.getElementById('background-name');
previewEl.style.setProperty('--site-background-image', 'url(\'{0}\')'.replace('{0}', url));