From: Tim Düsterhus Date: Tue, 2 Feb 2021 10:33:23 +0000 (+0100) Subject: Merge branch '5.3' X-Git-Tag: 5.4.0_Alpha_1~326 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=c4552ba881da356700127016d3f0b452921ab5b7;p=GitHub%2FWoltLab%2FWCF.git Merge branch '5.3' --- c4552ba881da356700127016d3f0b452921ab5b7 diff --cc com.woltlab.wcf/package.xml index 8ca2bdf808,83b3f025cd..4230236401 --- a/com.woltlab.wcf/package.xml +++ b/com.woltlab.wcf/package.xml @@@ -5,8 -5,8 +5,8 @@@ Free CMS and web-framework, designed for awesome websites and communities. Freies CMS und Web-Framework, das eindrucksvolle Websites und Communities ermöglicht. 1 - 5.3.4 + 5.4.0 Alpha 1 - 2021-01-29 + 2021-02-01 diff --cc wcfsetup/install/files/lib/data/user/avatar/UserAvatarAction.class.php index b5af458328,9097c1a9c3..6cc6b8f134 --- a/wcfsetup/install/files/lib/data/user/avatar/UserAvatarAction.class.php +++ b/wcfsetup/install/files/lib/data/user/avatar/UserAvatarAction.class.php @@@ -21,234 -19,221 +21,234 @@@ use wcf\util\Url /** * Executes avatar-related actions. - * - * @author Marcel Werk - * @copyright 2001-2019 WoltLab GmbH - * @license GNU Lesser General Public License - * @package WoltLabSuite\Core\Data\User\Avatar - * - * @method UserAvatar create() - * @method UserAvatarEditor[] getObjects() - * @method UserAvatarEditor getSingleObject() + * + * @author Marcel Werk + * @copyright 2001-2019 WoltLab GmbH + * @license GNU Lesser General Public License + * @package WoltLabSuite\Core\Data\User\Avatar + * + * @method UserAvatar create() + * @method UserAvatarEditor[] getObjects() + * @method UserAvatarEditor getSingleObject() */ -class UserAvatarAction extends AbstractDatabaseObjectAction { - /** - * currently edited avatar - * @var UserAvatarEditor - */ - public $avatar = null; - - /** - * Validates the upload action. - */ - public function validateUpload() { - $this->readInteger('userID', true); - - if ($this->parameters['userID']) { - if (!WCF::getSession()->getPermission('admin.user.canEditUser')) { - throw new PermissionDeniedException(); - } - - $user = new User($this->parameters['userID']); - if (!$user->userID) { - throw new IllegalLinkException(); - } - } - - // check upload permissions - if (!WCF::getSession()->getPermission('user.profile.avatar.canUploadAvatar') || WCF::getUser()->disableAvatar) { - throw new PermissionDeniedException(); - } - - /** @noinspection PhpUndefinedMethodInspection */ - if (count($this->parameters['__files']->getFiles()) != 1) { - throw new UserInputException('files'); - } - - // check max filesize, allowed file extensions etc. - /** @noinspection PhpUndefinedMethodInspection */ - $this->parameters['__files']->validateFiles(new AvatarUploadFileValidationStrategy(PHP_INT_MAX, explode("\n", WCF::getSession()->getPermission('user.profile.avatar.allowedFileExtensions')))); - } - - /** - * Handles uploaded attachments. - */ - public function upload() { - /** @var UploadFile $file */ - $file = $this->parameters['__files']->getFiles()[0]; - $saveStrategy = new AvatarUploadFileSaveStrategy((!empty($this->parameters['userID']) ? intval($this->parameters['userID']) : WCF::getUser()->userID)); - /** @noinspection PhpUndefinedMethodInspection */ - $this->parameters['__files']->saveFiles($saveStrategy); - - if ($file->getValidationErrorType()) { - return ['errorType' => $file->getValidationErrorType()]; - } - else { - return [ - 'avatarID' => $saveStrategy->getAvatar()->avatarID, - 'url' => $saveStrategy->getAvatar()->getURL(96) - ]; - } - } - - /** - * Fetches an avatar from a remote server and sets it for given user. - */ - public function fetchRemoteAvatar() { - $avatarID = 0; - $filename = ''; - - // fetch avatar from URL - $imageData = null; - try { - $request = new HTTPRequest($this->parameters['url']); - $request->execute(); - $reply = $request->getReply(); - $filename = FileUtil::getTemporaryFilename('avatar_'); - file_put_contents($filename, $reply['body']); - - $imageData = getimagesize($filename); - if ($imageData === false) throw new SystemException('Downloaded file is not an image'); - } - catch (\Exception $e) { - // log exception unless this was caused by a non-image file being supplied - if ($imageData !== false) { - \wcf\functions\exception\logThrowable($e); - } - - if (!empty($filename)) { - @unlink($filename); - } - return; - } - - // rescale avatar if required - try { - $newFilename = $this->enforceDimensions($filename); - if ($newFilename !== $filename) @unlink($filename); - $filename = $newFilename; - - $imageData = getimagesize($filename); - if ($imageData === false) throw new SystemException('Rescaled file is not an image'); - } - catch (\Exception $e) { - @unlink($filename); - return; - } - - $tmp = Url::parse($this->parameters['url']); - if (!isset($tmp['path'])) { - @unlink($filename); - return; - } - - $tmp = pathinfo($tmp['path']); - if (!isset($tmp['basename'])) { - $tmp['basename'] = basename($filename); - } - - $imageData = @getimagesize($filename); - if ($imageData !== false) { - $tmp['extension'] = ImageUtil::getExtensionByMimeType($imageData['mime']); - - if (!in_array($tmp['extension'], ['jpeg', 'jpg', 'png', 'gif'])) { - @unlink($filename); - return; - } - } - else { - @unlink($filename); - return; - } - - $data = [ - 'avatarName' => mb_substr($tmp['basename'], 0, 255), - 'avatarExtension' => $tmp['extension'], - 'width' => $imageData[0], - 'height' => $imageData[1], - 'userID' => $this->parameters['userEditor']->userID, - 'fileHash' => sha1_file($filename) - ]; - - // create avatar - $avatar = UserAvatarEditor::create($data); - - // check avatar directory - // and create subdirectory if necessary - $dir = dirname($avatar->getLocation()); - if (!@file_exists($dir)) { - FileUtil::makePath($dir); - } - - // move uploaded file - if (@copy($filename, $avatar->getLocation())) { - @unlink($filename); - - $avatarID = $avatar->avatarID; - } - else { - @unlink($filename); - - // moving failed; delete avatar - $editor = new UserAvatarEditor($avatar); - $editor->delete(); - } - - // update user - if ($avatarID) { - /** @var UserEditor $userEditor */ - $userEditor = $this->parameters['userEditor']; - - $userEditor->update([ - 'avatarID' => $avatarID, - 'enableGravatar' => 0 - ]); - - // delete old avatar - if ($userEditor->avatarID) { - $action = new UserAvatarAction([$userEditor->avatarID], 'delete'); - $action->executeAction(); - } - } - - // reset user storage - UserStorageHandler::getInstance()->reset([$this->parameters['userEditor']->userID], 'avatar'); - } - - /** - * Enforces dimensions for given avatar. - * - * @param string $filename - * @return string - * @throws UserInputException - */ - protected function enforceDimensions($filename) { - try { - $filename = ImageUtil::enforceDimensions($filename, UserAvatar::AVATAR_SIZE, UserAvatar::AVATAR_SIZE); - } - /** @noinspection PhpRedundantCatchClauseInspection */ - catch (SystemException $e) { - throw new UserInputException('avatar', 'tooLarge'); - } - - // check filesize (after shrink) - if (@filesize($filename) > WCF::getSession()->getPermission('user.profile.avatar.maxSize')) { - throw new UserInputException('avatar', 'tooLarge'); - } - - return $filename; - } +class UserAvatarAction extends AbstractDatabaseObjectAction +{ + /** + * currently edited avatar + * @var UserAvatarEditor + */ + public $avatar; + + /** + * Validates the upload action. + */ + public function validateUpload() + { + $this->readInteger('userID', true); + + if ($this->parameters['userID']) { + if (!WCF::getSession()->getPermission('admin.user.canEditUser')) { + throw new PermissionDeniedException(); + } + + $user = new User($this->parameters['userID']); + if (!$user->userID) { + throw new IllegalLinkException(); + } + } + + // check upload permissions + if (!WCF::getSession()->getPermission('user.profile.avatar.canUploadAvatar') || WCF::getUser()->disableAvatar) { + throw new PermissionDeniedException(); + } + + /** @noinspection PhpUndefinedMethodInspection */ + if (\count($this->parameters['__files']->getFiles()) != 1) { + throw new UserInputException('files'); + } + + // check max filesize, allowed file extensions etc. + /** @noinspection PhpUndefinedMethodInspection */ + $this->parameters['__files']->validateFiles(new AvatarUploadFileValidationStrategy( + \PHP_INT_MAX, + \explode("\n", WCF::getSession()->getPermission('user.profile.avatar.allowedFileExtensions')) + )); + } + + /** + * Handles uploaded attachments. + */ + public function upload() + { + /** @var UploadFile $file */ + $file = $this->parameters['__files']->getFiles()[0]; + $saveStrategy = new AvatarUploadFileSaveStrategy((!empty($this->parameters['userID']) ? \intval($this->parameters['userID']) : WCF::getUser()->userID)); + /** @noinspection PhpUndefinedMethodInspection */ + $this->parameters['__files']->saveFiles($saveStrategy); + + if ($file->getValidationErrorType()) { + return ['errorType' => $file->getValidationErrorType()]; + } else { + return [ + 'avatarID' => $saveStrategy->getAvatar()->avatarID, + 'url' => $saveStrategy->getAvatar()->getURL(96), + ]; + } + } + + /** + * Fetches an avatar from a remote server and sets it for given user. + */ + public function fetchRemoteAvatar() + { + $avatarID = 0; + $filename = ''; + + // fetch avatar from URL + $imageData = null; + try { + $request = new HTTPRequest($this->parameters['url']); + $request->execute(); + $reply = $request->getReply(); + $filename = FileUtil::getTemporaryFilename('avatar_'); + \file_put_contents($filename, $reply['body']); + + $imageData = \getimagesize($filename); + if ($imageData === false) { + throw new SystemException('Downloaded file is not an image'); + } + } catch (\Exception $e) { + // log exception unless this was caused by a non-image file being supplied + if ($imageData !== false) { + \wcf\functions\exception\logThrowable($e); + } + + if (!empty($filename)) { + @\unlink($filename); + } + + return; + } + + // rescale avatar if required + try { + $newFilename = $this->enforceDimensions($filename); + if ($newFilename !== $filename) { + @\unlink($filename); + } + $filename = $newFilename; + + $imageData = \getimagesize($filename); + if ($imageData === false) { + throw new SystemException('Rescaled file is not an image'); + } + } catch (\Exception $e) { + @\unlink($filename); + + return; + } + + $tmp = Url::parse($this->parameters['url']); + if (!isset($tmp['path'])) { + @\unlink($filename); + + return; + } + + $tmp = \pathinfo($tmp['path']); + if (!isset($tmp['basename'])) { + $tmp['basename'] = \basename($filename); + } + + $imageData = @\getimagesize($filename); + if ($imageData !== false) { + $tmp['extension'] = ImageUtil::getExtensionByMimeType($imageData['mime']); + + if (!\in_array($tmp['extension'], ['jpeg', 'jpg', 'png', 'gif', 'webp'])) { + @\unlink($filename); + + return; + } + } else { + @\unlink($filename); + + return; + } + + $data = [ - 'avatarName' => $tmp['basename'], ++ 'avatarName' => mb_substr($tmp['basename'], 0, 255), + 'avatarExtension' => $tmp['extension'], + 'width' => $imageData[0], + 'height' => $imageData[1], + 'userID' => $this->parameters['userEditor']->userID, + 'fileHash' => \sha1_file($filename), + ]; + + // create avatar + $avatar = UserAvatarEditor::create($data); + + // check avatar directory + // and create subdirectory if necessary + $dir = \dirname($avatar->getLocation()); + if (!@\file_exists($dir)) { + FileUtil::makePath($dir); + } + + // move uploaded file + if (@\copy($filename, $avatar->getLocation())) { + @\unlink($filename); + + $avatarID = $avatar->avatarID; + } else { + @\unlink($filename); + + // moving failed; delete avatar + $editor = new UserAvatarEditor($avatar); + $editor->delete(); + } + + // update user + if ($avatarID) { + /** @var UserEditor $userEditor */ + $userEditor = $this->parameters['userEditor']; + + $userEditor->update([ + 'avatarID' => $avatarID, + 'enableGravatar' => 0, + ]); + + // delete old avatar + if ($userEditor->avatarID) { + $action = new self([$userEditor->avatarID], 'delete'); + $action->executeAction(); + } + } + + // reset user storage + UserStorageHandler::getInstance()->reset([$this->parameters['userEditor']->userID], 'avatar'); + } + + /** + * Enforces dimensions for given avatar. + * + * @param string $filename + * @return string + * @throws UserInputException + */ + protected function enforceDimensions($filename) + { + try { + $filename = ImageUtil::enforceDimensions($filename, UserAvatar::AVATAR_SIZE, UserAvatar::AVATAR_SIZE); + } /** @noinspection PhpRedundantCatchClauseInspection */ + catch (SystemException $e) { + throw new UserInputException('avatar', 'tooLarge'); + } + + // check filesize (after shrink) + if (@\filesize($filename) > WCF::getSession()->getPermission('user.profile.avatar.maxSize')) { + throw new UserInputException('avatar', 'tooLarge'); + } + + return $filename; + } }