Rotate uploaded images based on the orientation stored in the exif data
authorMarcel Werk <burntime@woltlab.com>
Sat, 23 Mar 2019 22:26:01 +0000 (23:26 +0100)
committerMarcel Werk <burntime@woltlab.com>
Sat, 23 Mar 2019 22:26:01 +0000 (23:26 +0100)
Closes #2876

wcfsetup/install/files/lib/data/user/UserProfileAction.class.php
wcfsetup/install/files/lib/data/user/avatar/UserAvatarAction.class.php
wcfsetup/install/files/lib/system/upload/AvatarUploadFileSaveStrategy.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/upload/UserCoverPhotoUploadFileSaveStrategy.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/util/ImageUtil.class.php

index 2406e7c23728c92eeb64fcbcb25d87e4187699f3..718a7c27546cd0cd2dd4b70be59d9b2997bdc022 100644 (file)
@@ -1,27 +1,24 @@
 <?php
 namespace wcf\data\user;
 use wcf\data\object\type\ObjectTypeCache;
-use wcf\data\user\cover\photo\UserCoverPhoto;
 use wcf\data\user\group\UserGroup;
 use wcf\system\bbcode\BBCodeHandler;
 use wcf\system\cache\runtime\UserProfileRuntimeCache;
 use wcf\system\database\util\PreparedStatementConditionBuilder;
 use wcf\system\exception\PermissionDeniedException;
-use wcf\system\exception\SystemException;
 use wcf\system\exception\UserInputException;
 use wcf\system\html\input\HtmlInputProcessor;
 use wcf\system\html\output\HtmlOutputProcessor;
-use wcf\system\image\ImageHandler;
 use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
 use wcf\system\option\user\UserOptionHandler;
 use wcf\system\upload\UploadFile;
 use wcf\system\upload\UploadHandler;
+use wcf\system\upload\UserCoverPhotoUploadFileSaveStrategy;
 use wcf\system\upload\UserCoverPhotoUploadFileValidationStrategy;
 use wcf\system\user\group\assignment\UserGroupAssignmentHandler;
 use wcf\system\user\storage\UserStorageHandler;
 use wcf\system\WCF;
 use wcf\util\ArrayUtil;
-use wcf\util\FileUtil;
 use wcf\util\MessageUtil;
 use wcf\util\StringUtil;
 
@@ -557,6 +554,10 @@ class UserProfileAction extends UserAction {
         * @since       3.1
         */
        public function uploadCoverPhoto() {
+               $saveStrategy = new UserCoverPhotoUploadFileSaveStrategy((!empty($this->parameters['userID']) ? intval($this->parameters['userID']) : WCF::getUser()->userID));
+               /** @noinspection PhpUndefinedMethodInspection */
+               $this->parameters['__files']->saveFiles($saveStrategy);
+               
                if ($this->uploadFile->getValidationErrorType()) {
                        return [
                                'filesize' => $this->uploadFile->getFilesize(),
@@ -566,58 +567,9 @@ class UserProfileAction extends UserAction {
                                'errorType' => $this->uploadFile->getValidationErrorType()
                        ];
                }
-               
-               try {
-                       // shrink cover photo if necessary
-                       $fileLocation = $this->enforceCoverPhotoDimensions($this->uploadFile->getLocation());
-               }
-               catch (UserInputException $e) {
-                       return [
-                               'filesize' => $this->uploadFile->getFilesize(),
-                               'errorMessage' => WCF::getLanguage()->getDynamicVariable('wcf.user.coverPhoto.upload.error.' . $e->getType(), [
-                                       'file' => $this->uploadFile
-                               ]),
-                               'errorType' => $e->getType()
-                       ];
-               }
-               
-               // delete old cover photo
-               if ($this->user->coverPhotoHash) {
-                       UserProfileRuntimeCache::getInstance()->getObject($this->user->userID)->getCoverPhoto()->delete();
-               }
-               
-               // update user
-               (new UserEditor($this->user))->update([
-                       // always generate a new hash to invalidate the browser cache and to avoid filename guessing
-                       'coverPhotoHash' => StringUtil::getRandomID(),
-                       'coverPhotoExtension' => $this->uploadFile->getFileExtension()
-               ]);
-               
-               // force-reload the user profile to use a predictable code-path to fetch the cover photo
-               UserProfileRuntimeCache::getInstance()->removeObject($this->user->userID);
-               $userProfile = UserProfileRuntimeCache::getInstance()->getObject($this->user->userID);
-               $coverPhoto = $userProfile->getCoverPhoto();
-               
-               // check images directory and create subdirectory if necessary
-               $dir = dirname($coverPhoto->getLocation());
-               if (!@file_exists($dir)) {
-                       FileUtil::makePath($dir);
-               }
-               
-               if (@copy($fileLocation, $coverPhoto->getLocation())) {
-                       @unlink($fileLocation);
-                       
-                       return [
-                               'url' => $coverPhoto->getURL()
-                       ];
-               }
                else {
                        return [
-                               'filesize' => $this->uploadFile->getFilesize(),
-                               'errorMessage' => WCF::getLanguage()->getDynamicVariable('wcf.user.coverPhoto.upload.error.uploadFailed', [
-                                       'file' => $this->uploadFile
-                               ]),
-                               'errorType' => 'uploadFailed'
+                               'url' => $saveStrategy->getCoverPhoto()->getURL()
                        ];
                }
        }
@@ -688,40 +640,4 @@ class UserProfileAction extends UserAction {
                
                return $optionHandler;
        }
-       
-       /**
-        * Enforces dimensions for given cover photo.
-        *
-        * @param       string          $filename
-        * @return      string
-        * @throws      UserInputException
-        */
-       protected function enforceCoverPhotoDimensions($filename) {
-               $imageData = getimagesize($filename);
-               if ($imageData[0] > UserCoverPhoto::MAX_WIDTH || $imageData[1] > UserCoverPhoto::MAX_HEIGHT) {
-                       try {
-                               $adapter = ImageHandler::getInstance()->getAdapter();
-                               $adapter->loadFile($filename);
-                               $filename = FileUtil::getTemporaryFilename();
-                               $thumbnail = $adapter->createThumbnail(UserCoverPhoto::MAX_WIDTH, UserCoverPhoto::MAX_HEIGHT);
-                               $adapter->writeImage($thumbnail, $filename);
-                       }
-                       catch (SystemException $e) {
-                               throw new UserInputException('coverPhoto', 'maxSize');
-                       }
-                       
-                       // check dimensions (after shrink)
-                       $imageData = getimagesize($filename);
-                       if ($imageData[0] < UserCoverPhoto::MIN_WIDTH || $imageData[1] < UserCoverPhoto::MIN_HEIGHT) {
-                               throw new UserInputException('coverPhoto', 'maxSize');
-                       }
-                       
-                       // check filesize (after shrink)
-                       if (@filesize($filename) > WCF::getSession()->getPermission('user.profile.coverPhoto.maxSize')) {
-                               throw new UserInputException('coverPhoto', 'maxSize');
-                       }
-               }
-               
-               return $filename;
-       }
 }
index b96cb3ca43604b44c744883f4d782f82c3db24c2..94682ae161552392a3c0dc51cbcca99fabc870a3 100644 (file)
@@ -7,7 +7,7 @@ use wcf\system\exception\IllegalLinkException;
 use wcf\system\exception\PermissionDeniedException;
 use wcf\system\exception\SystemException;
 use wcf\system\exception\UserInputException;
-use wcf\system\image\ImageHandler;
+use wcf\system\upload\AvatarUploadFileSaveStrategy;
 use wcf\system\upload\AvatarUploadFileValidationStrategy;
 use wcf\system\upload\UploadFile;
 use wcf\system\user\storage\UserStorageHandler;
@@ -72,77 +72,21 @@ class UserAvatarAction extends AbstractDatabaseObjectAction {
         * Handles uploaded attachments.
         */
        public function upload() {
-               /** @var UploadFile[] $files */
+               /** @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 */
-               $files = $this->parameters['__files']->getFiles();
-               $userID = (!empty($this->parameters['userID']) ? intval($this->parameters['userID']) : WCF::getUser()->userID);
-               $user = ($userID != WCF::getUser()->userID ? new User($userID) : WCF::getUser());
-               $file = $files[0];
+               $this->parameters['__files']->saveFiles($saveStrategy);
                
-               try {
-                       if (!$file->getValidationErrorType()) {
-                               // shrink avatar if necessary
-                               $fileLocation = $this->enforceDimensions($file->getLocation());
-                               $imageData = getimagesize($fileLocation);
-                               
-                               $data = [
-                                       'avatarName' => $file->getFilename(),
-                                       'avatarExtension' => $file->getFileExtension(),
-                                       'width' => $imageData[0],
-                                       'height' => $imageData[1],
-                                       'userID' => $userID,
-                                       'fileHash' => sha1_file($fileLocation)
-                               ];
-                               
-                               // 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($fileLocation, $avatar->getLocation())) {
-                                       @unlink($fileLocation);
-                                       
-                                       // delete old avatar
-                                       if ($user->avatarID) {
-                                               $action = new UserAvatarAction([$user->avatarID], 'delete');
-                                               $action->executeAction();
-                                       }
-                                       
-                                       // update user
-                                       $userEditor = new UserEditor($user);
-                                       $userEditor->update([
-                                               'avatarID' => $avatar->avatarID,
-                                               'enableGravatar' => 0
-                                       ]);
-                                       
-                                       // reset user storage
-                                       UserStorageHandler::getInstance()->reset([$userID], 'avatar');
-                                       
-                                       // return result
-                                       return [
-                                               'avatarID' => $avatar->avatarID,
-                                               'url' => $avatar->getURL(96)
-                                       ];
-                               }
-                               else {
-                                       // moving failed; delete avatar
-                                       $editor = new UserAvatarEditor($avatar);
-                                       $editor->delete();
-                                       throw new UserInputException('avatar', 'uploadFailed');
-                               }
-                       }
+               if ($file->getValidationErrorType()) {
+                       return ['errorType' => $file->getValidationErrorType()];
                }
-               catch (UserInputException $e) {
-                       $file->setValidationErrorType($e->getType());
+               else {
+                       return [
+                               'avatarID' => $saveStrategy->getAvatar()->avatarID,
+                               'url' => $saveStrategy->getAvatar()->getURL(96)
+                       ];
                }
-               
-               return ['errorType' => $file->getValidationErrorType()];
        }
        
        /**
@@ -276,23 +220,17 @@ class UserAvatarAction extends AbstractDatabaseObjectAction {
         * @throws      UserInputException
         */
        protected function enforceDimensions($filename) {
-               $imageData = getimagesize($filename);
-               if ($imageData[0] > UserAvatar::AVATAR_SIZE || $imageData[1] > UserAvatar::AVATAR_SIZE) {
-                       try {
-                               $adapter = ImageHandler::getInstance()->getAdapter();
-                               $adapter->loadFile($filename);
-                               $filename = FileUtil::getTemporaryFilename();
-                               $thumbnail = $adapter->createThumbnail(UserAvatar::AVATAR_SIZE, UserAvatar::AVATAR_SIZE, false);
-                               $adapter->writeImage($thumbnail, $filename);
-                       }
-                       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');
-                       }
+               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;
diff --git a/wcfsetup/install/files/lib/system/upload/AvatarUploadFileSaveStrategy.class.php b/wcfsetup/install/files/lib/system/upload/AvatarUploadFileSaveStrategy.class.php
new file mode 100644 (file)
index 0000000..9dcfe38
--- /dev/null
@@ -0,0 +1,130 @@
+<?php
+namespace wcf\system\upload;
+use wcf\data\user\avatar\UserAvatar;
+use wcf\data\user\avatar\UserAvatarAction;
+use wcf\data\user\avatar\UserAvatarEditor;
+use wcf\data\user\User;
+use wcf\data\user\UserEditor;
+use wcf\system\exception\SystemException;
+use wcf\system\user\storage\UserStorageHandler;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+use wcf\util\ImageUtil;
+
+/**
+ * Save strategy for avatar uploads. 
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2019 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    WoltLabSuite\Core\System\Upload
+ * @since      5.2
+ */
+class AvatarUploadFileSaveStrategy implements IUploadFileSaveStrategy {
+       /**
+        * @var integer
+        */
+       protected $userID = 0;
+       
+       /**
+        * @var User
+        */
+       protected $user;
+       
+       /**
+        * @var UserAvatar
+        */
+       protected $avatar;
+       
+       /**
+        * Creates a new instance of AvatarUploadFileSaveStrategy.
+        *
+        * @param       integer         $userID
+        */
+       public function __construct($userID = null) {
+               $this->userID = ($userID ?: WCF::getUser()->userID);
+               $this->user = ($this->userID != WCF::getUser()->userID ? new User($userID) : WCF::getUser());
+       }
+       
+       /**
+        * @return UserAvatar
+        */
+       public function getAvatar() {
+               return $this->avatar;
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function save(UploadFile $uploadFile) {
+               if (!$uploadFile->getValidationErrorType()) {
+                       // rotate avatar if necessary
+                       /** @noinspection PhpUnusedLocalVariableInspection */
+                       $fileLocation = ImageUtil::fixOrientation($uploadFile->getLocation());
+                       
+                       // shrink avatar if necessary
+                       try {
+                               $fileLocation = ImageUtil::enforceDimensions($fileLocation, UserAvatar::AVATAR_SIZE, UserAvatar::AVATAR_SIZE, false);
+                       }
+                       /** @noinspection PhpRedundantCatchClauseInspection */
+                       catch (SystemException $e) {
+                               $uploadFile->setValidationErrorType('tooLarge');
+                               return;
+                       }
+                       
+                       // check filesize (after shrink)
+                       if (@filesize($fileLocation) > WCF::getSession()->getPermission('user.profile.avatar.maxSize')) {
+                               $uploadFile->setValidationErrorType('tooLarge');
+                               return;
+                       }
+                       
+                       $imageData = getimagesize($fileLocation);
+                       $data = [
+                               'avatarName' => $uploadFile->getFilename(),
+                               'avatarExtension' => $uploadFile->getFileExtension(),
+                               'width' => $imageData[0],
+                               'height' => $imageData[1],
+                               'userID' => $this->userID,
+                               'fileHash' => sha1_file($fileLocation)
+                       ];
+                       
+                       // create avatar
+                       $this->avatar = UserAvatarEditor::create($data);
+                       
+                       // check avatar directory
+                       // and create subdirectory if necessary
+                       $dir = dirname($this->avatar->getLocation());
+                       if (!@file_exists($dir)) {
+                               FileUtil::makePath($dir);
+                       }
+                       
+                       // move uploaded file
+                       if (@copy($fileLocation, $this->avatar->getLocation())) {
+                               @unlink($fileLocation);
+                               
+                               // delete old avatar
+                               if ($this->user->avatarID) {
+                                       $action = new UserAvatarAction([$this->user->avatarID], 'delete');
+                                       $action->executeAction();
+                               }
+                               
+                               // update user
+                               $userEditor = new UserEditor($this->user);
+                               $userEditor->update([
+                                       'avatarID' => $this->avatar->avatarID,
+                                       'enableGravatar' => 0
+                               ]);
+                               
+                               // reset user storage
+                               UserStorageHandler::getInstance()->reset([$this->userID], 'avatar');
+                       }
+                       else {
+                               // moving failed; delete avatar
+                               $editor = new UserAvatarEditor($this->avatar);
+                               $editor->delete();
+                               
+                               $uploadFile->setValidationErrorType('uploadFailed');
+                       }
+               }
+       }
+}
diff --git a/wcfsetup/install/files/lib/system/upload/UserCoverPhotoUploadFileSaveStrategy.class.php b/wcfsetup/install/files/lib/system/upload/UserCoverPhotoUploadFileSaveStrategy.class.php
new file mode 100644 (file)
index 0000000..c7d5785
--- /dev/null
@@ -0,0 +1,128 @@
+<?php
+namespace wcf\system\upload;
+use wcf\data\user\cover\photo\IUserCoverPhoto;
+use wcf\data\user\cover\photo\UserCoverPhoto;
+use wcf\data\user\User;
+use wcf\data\user\UserEditor;
+use wcf\system\cache\runtime\UserProfileRuntimeCache;
+use wcf\system\exception\SystemException;
+use wcf\system\WCF;
+use wcf\util\FileUtil;
+use wcf\util\ImageUtil;
+use wcf\util\StringUtil;
+
+/**
+ * Save strategy for user cover photos.
+ *
+ * @author     Marcel Werk
+ * @copyright  2001-2019 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    WoltLabSuite\Core\System\Upload
+ * @since      5.2
+ */
+class UserCoverPhotoUploadFileSaveStrategy implements IUploadFileSaveStrategy {
+       /**
+        * @var integer
+        */
+       protected $userID = 0;
+       
+       /**
+        * @var User
+        */
+       protected $user;
+       
+       /**
+        * @var IUserCoverPhoto
+        */
+       protected $coverPhoto;
+       
+       /**
+        * Creates a new instance of UserCoverPhotoUploadFileSaveStrategy.
+        *
+        * @param       integer         $userID
+        */
+       public function __construct($userID = null) {
+               $this->userID = ($userID ?: WCF::getUser()->userID);
+               $this->user = ($this->userID != WCF::getUser()->userID ? new User($userID) : WCF::getUser());
+       }
+       
+       /**
+        * @return IUserCoverPhoto
+        */
+       public function getCoverPhoto() {
+               return $this->coverPhoto;
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function save(UploadFile $uploadFile) {
+               if (!$uploadFile->getValidationErrorType()) {
+                       // rotate image if necessary
+                       /** @noinspection PhpUnusedLocalVariableInspection */
+                       $fileLocation = ImageUtil::fixOrientation($uploadFile->getLocation());
+                       
+                       // shrink cover photo if necessary
+                       try {
+                               $newFileLocation = ImageUtil::enforceDimensions($fileLocation, UserCoverPhoto::MAX_WIDTH, UserCoverPhoto::MAX_HEIGHT);
+                       }
+                       /** @noinspection PhpRedundantCatchClauseInspection */
+                       catch (SystemException $e) {
+                               $uploadFile->setValidationErrorType('maxSize');
+                               return;
+                       }
+                       
+                       if ($newFileLocation != $fileLocation) {
+                               // check dimensions (after shrink)
+                               $imageData = getimagesize($newFileLocation);
+                               if ($imageData[0] < UserCoverPhoto::MIN_WIDTH || $imageData[1] < UserCoverPhoto::MIN_HEIGHT) {
+                                       $uploadFile->setValidationErrorType('tooLarge');
+                                       return;
+                               }
+                               
+                               // check filesize (after shrink)
+                               if (@filesize($newFileLocation) > WCF::getSession()->getPermission('user.profile.coverPhoto.maxSize')) {
+                                       $uploadFile->setValidationErrorType('tooLarge');
+                                       return;
+                               }
+                       }
+                       $fileLocation = $newFileLocation;
+                       
+                       // delete old cover photo
+                       if ($this->user->coverPhotoHash) {
+                               UserProfileRuntimeCache::getInstance()->getObject($this->user->userID)->getCoverPhoto()->delete();
+                       }
+                       
+                       // update user
+                       (new UserEditor($this->user))->update([
+                               // always generate a new hash to invalidate the browser cache and to avoid filename guessing
+                               'coverPhotoHash' => StringUtil::getRandomID(),
+                               'coverPhotoExtension' => $uploadFile->getFileExtension()
+                       ]);
+                       
+                       // force-reload the user profile to use a predictable code-path to fetch the cover photo
+                       UserProfileRuntimeCache::getInstance()->removeObject($this->user->userID);
+                       $userProfile = UserProfileRuntimeCache::getInstance()->getObject($this->user->userID);
+                       $this->coverPhoto = $userProfile->getCoverPhoto();
+                       
+                       // check images directory and create subdirectory if necessary
+                       $dir = dirname($this->coverPhoto->getLocation());
+                       if (!@file_exists($dir)) {
+                               FileUtil::makePath($dir);
+                       }
+                       
+                       // move uploaded file
+                       if (!@copy($fileLocation, $this->coverPhoto->getLocation())) {
+                               // copy failed
+                               @unlink($fileLocation);
+                               (new UserEditor($this->user))->update([
+                                       'coverPhotoHash' => '',
+                                       'coverPhotoExtension' => ''
+                               ]);
+                               $uploadFile->setValidationErrorType('uploadFailed');
+                       }
+                       
+                       @unlink($fileLocation);
+               }
+       }
+}
index 0e0cb3822dc9538a801dce00b4395c9248f040c2..b0e89beeec89304d34475e49861ded1f9bde256d 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 namespace wcf\util;
+use wcf\system\exception\SystemException;
+use wcf\system\image\ImageHandler;
 
 /**
  * Contains image-related functions.
@@ -95,6 +97,82 @@ final class ImageUtil {
                }
        }
        
+       /**
+        * Enforces dimensions for given image.
+        *
+        * @param       string          $filename
+        * @param       integer         $maxWidth
+        * @param       integer         $maxHeight
+        * @param       boolean         $obtainDimensions
+        * @return      string          new filename if file was changed, otherwise old filename
+        * @since       5.2
+        */
+       public static function enforceDimensions($filename, $maxWidth, $maxHeight, $obtainDimensions = true) {
+               $imageData = getimagesize($filename);
+               if ($imageData[0] > $maxWidth || $imageData[1] > $maxHeight) {
+                       $adapter = ImageHandler::getInstance()->getAdapter();
+                       $adapter->loadFile($filename);
+                       $filename = FileUtil::getTemporaryFilename();
+                       $thumbnail = $adapter->createThumbnail($maxWidth, $maxHeight, $obtainDimensions);
+                       $adapter->writeImage($thumbnail, $filename);
+               }
+               
+               return $filename;
+       }
+       
+       /**
+        * Rotates the given image based on the orientation stored in the exif data.
+        *
+        * @param       string          $filename
+        * @return      string          new filename if file was changed, otherwise old filename
+        * @since       5.2
+        */
+       public static function fixOrientation($filename) {
+               try {
+                       $exifData = ExifUtil::getExifData($filename);
+                       if (!empty($exifData)) {
+                               $orientation = ExifUtil::getOrientation($exifData);
+                               if ($orientation != ExifUtil::ORIENTATION_ORIGINAL) {
+                                       $adapter = ImageHandler::getInstance()->getAdapter();
+                                       $adapter->loadFile($filename);
+                                       
+                                       $newImage = null;
+                                       switch ($orientation) {
+                                               case ExifUtil::ORIENTATION_180_ROTATE:
+                                                       $newImage = $adapter->rotate(180);
+                                                       break;
+                                               
+                                               case ExifUtil::ORIENTATION_90_ROTATE:
+                                                       $newImage = $adapter->rotate(90);
+                                                       break;
+                                               
+                                               case ExifUtil::ORIENTATION_270_ROTATE:
+                                                       $newImage = $adapter->rotate(270);
+                                                       break;
+                                               
+                                               case ExifUtil::ORIENTATION_HORIZONTAL_FLIP:
+                                               case ExifUtil::ORIENTATION_VERTICAL_FLIP:
+                                               case ExifUtil::ORIENTATION_VERTICAL_FLIP_270_ROTATE:
+                                               case ExifUtil::ORIENTATION_HORIZONTAL_FLIP_270_ROTATE:
+                                                       // unsupported
+                                                       break;
+                                       }
+                                       
+                                       if ($newImage !== null) {
+                                               $adapter->load($newImage, $adapter->getType());
+                                       }
+                                       
+                                       $newFilename = FileUtil::getTemporaryFilename();
+                                       $adapter->writeImage($newFilename);
+                                       $filename = $newFilename;
+                               }
+                       }
+               }
+               catch (SystemException $e) {}
+               
+               return $filename;
+       }
+       
        /**
         * Forbid creation of ImageUtil objects.
         */