From 48da97f204800d9e972be66d4a2b8426ab0b01f1 Mon Sep 17 00:00:00 2001 From: Mikael Nordfeldth Date: Sat, 5 Oct 2013 18:43:41 +0200 Subject: [PATCH] MediaFile code improvements, preparing to implement multi-attachments Maybe in the future we can use this for anonymous file uploads too? With some kind of anonymous/pseudonymous profile. That'd be neat. --- actions/apimediaupload.php | 2 +- actions/apistatusesupdate.php | 2 +- actions/newnotice.php | 3 +- classes/File.php | 34 +++--- lib/mailhandler.php | 2 +- lib/mediafile.php | 120 ++++++-------------- plugins/YammerImport/lib/yammerimporter.php | 2 +- 7 files changed, 59 insertions(+), 106 deletions(-) diff --git a/actions/apimediaupload.php b/actions/apimediaupload.php index 9c888ce3ed..b4f8709fe2 100644 --- a/actions/apimediaupload.php +++ b/actions/apimediaupload.php @@ -85,7 +85,7 @@ class ApiMediaUploadAction extends ApiAuthAction $upload = null; try { - $upload = MediaFile::fromUpload('media', $this->auth_user); + $upload = MediaFile::fromUpload('media', $this->auth_user->getProfile()); } catch (Exception $e) { $this->clientError($e->getMessage(), $e->getCode()); return; diff --git a/actions/apistatusesupdate.php b/actions/apistatusesupdate.php index 7209ae3333..374930fff0 100644 --- a/actions/apistatusesupdate.php +++ b/actions/apistatusesupdate.php @@ -269,7 +269,7 @@ class ApiStatusesUpdateAction extends ApiAuthAction $upload = null; try { - $upload = MediaFile::fromUpload('media', $this->auth_user); + $upload = MediaFile::fromUpload('media', $this->auth_user->getProfile()); } catch (Exception $e) { $this->clientError($e->getMessage(), $e->getCode(), $this->format); return; diff --git a/actions/newnotice.php b/actions/newnotice.php index 7c324aaded..0d441c0431 100644 --- a/actions/newnotice.php +++ b/actions/newnotice.php @@ -114,8 +114,7 @@ class NewnoticeAction extends FormAction $options['reply_to'] = $replyto; } - $upload = null; - $upload = MediaFile::fromUpload('attach'); + $upload = MediaFile::fromUpload('attach', $this->scoped); if (isset($upload)) { diff --git a/classes/File.php b/classes/File.php index 7e59bf2b8a..e3300e7e68 100644 --- a/classes/File.php +++ b/classes/File.php @@ -211,8 +211,7 @@ class File extends Managed_DataObject return $x; } - function isRespectsQuota($user,$fileSize) { - + public static function respectsQuota(Profile $scoped, $fileSize) { if ($fileSize > common_config('attachments', 'file_quota')) { // TRANS: Message used to be inserted as %2$s in the text "No file may // TRANS: be larger than %1$d byte and the file you sent was %2$s.". @@ -224,35 +223,40 @@ class File extends Managed_DataObject // TRANS: %1$d (used for plural) is the byte limit for uploads, // TRANS: %2$s is the proper form of "n bytes". This is the only ways to have // TRANS: gettext support multiple plurals in the same message, unfortunately... - return sprintf(_m('No file may be larger than %1$d byte and the file you sent was %2$s. Try to upload a smaller version.', + throw new ClientException( + sprintf(_m('No file may be larger than %1$d byte and the file you sent was %2$s. Try to upload a smaller version.', 'No file may be larger than %1$d bytes and the file you sent was %2$s. Try to upload a smaller version.', $fileQuota), - $fileQuota, $fileSizeText); + $fileQuota, $fileSizeText)); } - $query = "select sum(size) as total from file join file_to_post on file_to_post.file_id = file.id join notice on file_to_post.post_id = notice.id where profile_id = {$user->id} and file.url like '%/notice/%/file'"; - $this->query($query); - $this->fetch(); - $total = $this->total + $fileSize; + $file = new File; + + $query = "select sum(size) as total from file join file_to_post on file_to_post.file_id = file.id join notice on file_to_post.post_id = notice.id where profile_id = {$scoped->id} and file.url like '%/notice/%/file'"; + $file->query($query); + $file->fetch(); + $total = $file->total + $fileSize; if ($total > common_config('attachments', 'user_quota')) { // TRANS: Message given if an upload would exceed user quota. // TRANS: %d (number) is the user quota in bytes and is used for plural. - return sprintf(_m('A file this large would exceed your user quota of %d byte.', + throw new ClientException( + sprintf(_m('A file this large would exceed your user quota of %d byte.', 'A file this large would exceed your user quota of %d bytes.', common_config('attachments', 'user_quota')), - common_config('attachments', 'user_quota')); + common_config('attachments', 'user_quota'))); } $query .= ' AND EXTRACT(month FROM file.modified) = EXTRACT(month FROM now()) and EXTRACT(year FROM file.modified) = EXTRACT(year FROM now())'; - $this->query($query); - $this->fetch(); - $total = $this->total + $fileSize; + $file->query($query); + $file->fetch(); + $total = $file->total + $fileSize; if ($total > common_config('attachments', 'monthly_quota')) { // TRANS: Message given id an upload would exceed a user's monthly quota. // TRANS: $d (number) is the monthly user quota in bytes and is used for plural. - return sprintf(_m('A file this large would exceed your monthly quota of %d byte.', + throw new ClientException( + sprintf(_m('A file this large would exceed your monthly quota of %d byte.', 'A file this large would exceed your monthly quota of %d bytes.', common_config('attachments', 'monthly_quota')), - common_config('attachments', 'monthly_quota')); + common_config('attachments', 'monthly_quota'))); } return true; } diff --git a/lib/mailhandler.php b/lib/mailhandler.php index 188e848703..a716335193 100644 --- a/lib/mailhandler.php +++ b/lib/mailhandler.php @@ -73,7 +73,7 @@ class MailHandler $mf = null; try { - $mf = MediaFile::fromFileHandle($attachment, $user); + $mf = MediaFile::fromFilehandle($attachment, $user->getProfile()); } catch(ClientException $ce) { $this->error($from, $ce->getMessage()); } diff --git a/lib/mediafile.php b/lib/mediafile.php index e5d699b5d2..ad696ccca6 100644 --- a/lib/mediafile.php +++ b/lib/mediafile.php @@ -36,21 +36,17 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { class MediaFile { + protected $scoped = null; var $filename = null; var $fileRecord = null; - var $user = null; var $fileurl = null; var $short_fileurl = null; var $mimetype = null; - function __construct($user = null, $filename = null, $mimetype = null) + function __construct(Profile $scoped, $filename = null, $mimetype = null) { - if ($user == null) { - $this->user = common_current_user(); - } else { - $this->user = $user; - } + $this->scoped = $scoped; $this->filename = $filename; $this->mimetype = $mimetype; @@ -124,7 +120,7 @@ class MediaFile return null; } - $outname = File::filename($this->user->getProfile(), 'thumb-' . $this->filename, $this->mimetype); + $outname = File::filename($this->scoped, 'thumb-' . $this->filename, $this->mimetype); $outpath = File::path($outname); $maxWidth = common_config('attachments', 'thumb_width'); @@ -176,10 +172,10 @@ class MediaFile } } - static function fromUpload($param = 'media', $user = null) + static function fromUpload($param = 'media', Profile $scoped) { - if (empty($user)) { - $user = common_current_user(); + if (is_null($scoped)) { + $scoped = Profile::current(); } if (!isset($_FILES[$param]['error'])){ @@ -229,85 +225,49 @@ class MediaFile return; } - if (!MediaFile::respectsQuota($user, $_FILES[$param]['size'])) { - - // Should never actually get here - - @unlink($_FILES[$param]['tmp_name']); - // TRANS: Client exception thrown when a file upload operation would cause a user to exceed a set quota. - throw new ClientException(_('File exceeds user\'s quota.')); - return; - } + // Throws exception if additional size does not respect quota + File::respectsQuota($scoped, $_FILES[$param]['size']); $mimetype = MediaFile::getUploadedFileType($_FILES[$param]['tmp_name'], $_FILES[$param]['name']); - $filename = null; + $basename = basename($_FILES[$param]['name']); + $filename = File::filename($scoped, $basename, $mimetype); + $filepath = File::path($filename); - if (isset($mimetype)) { + $result = move_uploaded_file($_FILES[$param]['tmp_name'], $filepath); - $basename = basename($_FILES[$param]['name']); - $filename = File::filename($user->getProfile(), $basename, $mimetype); - $filepath = File::path($filename); - - $result = move_uploaded_file($_FILES[$param]['tmp_name'], $filepath); - - if (!$result) { - // TRANS: Client exception thrown when a file upload operation fails because the file could - // TRANS: not be moved from the temporary folder to the permanent file location. - throw new ClientException(_('File could not be moved to destination directory.')); - return; - } - - } else { - // TRANS: Client exception thrown when a file upload operation has been stopped because the MIME - // TRANS: type of the uploaded file could not be determined. - throw new ClientException(_('Could not determine file\'s MIME type.')); - return; + if (!$result) { + // TRANS: Client exception thrown when a file upload operation fails because the file could + // TRANS: not be moved from the temporary folder to the permanent file location. + throw new ClientException(_('File could not be moved to destination directory.')); } - return new MediaFile($user, $filename, $mimetype); + return new MediaFile($scoped, $filename, $mimetype); } - static function fromFilehandle($fh, $user) { + static function fromFilehandle($fh, Profile $scoped) { $stream = stream_get_meta_data($fh); - if (!MediaFile::respectsQuota($user, filesize($stream['uri']))) { - - // Should never actually get here - - // TRANS: Client exception thrown when a file upload operation would cause a user to exceed a set quota. - throw new ClientException(_('File exceeds user\'s quota.')); - return; - } + File::respectsQuota($scoped, filesize($stream['uri'])); $mimetype = MediaFile::getUploadedFileType($fh); - $filename = null; + $filename = File::filename($scoped, "email", $mimetype); - if (isset($mimetype)) { + $filepath = File::path($filename); - $filename = File::filename($user->getProfile(), "email", $mimetype); + $result = copy($stream['uri'], $filepath) && chmod($filepath, 0664); - $filepath = File::path($filename); - - $result = copy($stream['uri'], $filepath) && chmod($filepath, 0664); - - if (!$result) { - // TRANS: Client exception thrown when a file upload operation fails because the file could - // TRANS: not be moved from the temporary folder to the permanent file location. - throw new ClientException(_('File could not be moved to destination directory.' . - $stream['uri'] . ' ' . $filepath)); - } - } else { - // TRANS: Client exception thrown when a file upload operation has been stopped because the MIME - // TRANS: type of the uploaded file could not be determined. - throw new ClientException(_('Could not determine file\'s MIME type.')); - return; + if (!$result) { + // TRANS: Client exception thrown when a file upload operation fails because the file could + // TRANS: not be moved from the temporary folder to the permanent file location. + throw new ClientException(_('File could not be moved to destination directory.' . + $stream['uri'] . ' ' . $filepath)); } - return new MediaFile($user, $filename, $mimetype); + return new MediaFile($scoped, $filename, $mimetype); } /** @@ -325,14 +285,16 @@ class MediaFile * @throws ClientException if type is known, but not supported for local uploads */ static function getUploadedFileType($f, $originalFilename=false) { + global $_PEAR; + require_once 'MIME/Type.php'; require_once 'MIME/Type/Extension.php'; // We have to disable auto handling of PEAR errors - PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); + $_PEAR->staticPushErrorHandling(PEAR_ERROR_RETURN); $mte = new MIME_Type_Extension(); - $cmd = &PEAR::getStaticProperty('MIME_Type', 'fileCmd'); + $cmd = &$_PEAR->getStaticProperty('MIME_Type', 'fileCmd'); $cmd = common_config('attachments', 'filecommand'); $filetype = null; @@ -385,7 +347,7 @@ class MediaFile } if ($supported === true || in_array($filetype, $supported)) { // Restore PEAR error handlers for our DB code... - PEAR::staticPopErrorHandling(); + $_PEAR->staticPopErrorHandling(); return $filetype; } $media = MIME_Type::getMedia($filetype); @@ -401,19 +363,7 @@ class MediaFile $hint = sprintf(_('"%s" is not a supported file type on this server.'), $filetype); } // Restore PEAR error handlers for our DB code... - PEAR::staticPopErrorHandling(); + $_PEAR->staticPopErrorHandling(); throw new ClientException($hint); } - - static function respectsQuota($user, $filesize) - { - $file = new File; - $result = $file->isRespectsQuota($user, $filesize); - if ($result === true) { - return true; - } else { - throw new ClientException($result); - } - } - } diff --git a/plugins/YammerImport/lib/yammerimporter.php b/plugins/YammerImport/lib/yammerimporter.php index 1542b5909d..f4084c9d59 100644 --- a/plugins/YammerImport/lib/yammerimporter.php +++ b/plugins/YammerImport/lib/yammerimporter.php @@ -492,7 +492,7 @@ class YammerImporter $temp = tmpfile(); fwrite($temp, $body); try { - $upload = MediaFile::fromFileHandle($temp, $user); + $upload = MediaFile::fromFilehandle($temp, $user->getProfile()); fclose($temp); return $upload; } catch (Exception $e) {