X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=classes%2FFile.php;h=69aee7fcee1962c7b302dd893390e43eab469642;hb=1776c90cb98d5ca738db143703fb998612ada31e;hp=a5914b506e670f414e23a33b5de65a87fdbeebeb;hpb=73fe8a81b7def91113332a3ec55567d67b25f2d5;p=quix0rs-gnu-social.git diff --git a/classes/File.php b/classes/File.php index a5914b506e..69aee7fcee 100644 --- a/classes/File.php +++ b/classes/File.php @@ -24,9 +24,6 @@ if (!defined('GNUSOCIAL')) { exit(1); } */ class File extends Managed_DataObject { - ###START_AUTOCODE - /* the code below is auto generated do not remove the above tag */ - public $__table = 'file'; // table name public $id; // int(4) primary_key not_null public $url; // varchar(255) unique_key @@ -38,9 +35,6 @@ class File extends Managed_DataObject public $filename; // varchar(255) public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP - /* the code above is auto generated do not remove the tag below */ - ###END_AUTOCODE - public static function schemaDef() { return array( @@ -53,6 +47,8 @@ class File extends Managed_DataObject 'date' => array('type' => 'int', 'description' => 'date of resource according to http query'), 'protected' => array('type' => 'int', 'description' => 'true when URL is private (needs login)'), 'filename' => array('type' => 'varchar', 'length' => 255, 'description' => 'if a local file, name of the file'), + 'width' => array('type' => 'int', 'description' => 'width in pixels, if it can be described as such and data is available'), + 'height' => array('type' => 'int', 'description' => 'height in pixels, if it can be described as such and data is available'), 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'), ), @@ -74,65 +70,31 @@ class File extends Managed_DataObject * @param string $given_url * @return File */ - function saveNew(array $redir_data, $given_url) { + public static function saveNew(array $redir_data, $given_url) { // I don't know why we have to keep doing this but I'm adding this last check to avoid // uniqueness bugs. - $x = File::getKV('url', $given_url); + $file = File::getKV('url', $given_url); - if (!$x instanceof File) { - $x = new File; - $x->url = $given_url; - if (!empty($redir_data['protected'])) $x->protected = $redir_data['protected']; - if (!empty($redir_data['title'])) $x->title = $redir_data['title']; - if (!empty($redir_data['type'])) $x->mimetype = $redir_data['type']; - if (!empty($redir_data['size'])) $x->size = intval($redir_data['size']); - if (isset($redir_data['time']) && $redir_data['time'] > 0) $x->date = intval($redir_data['time']); - $file_id = $x->insert(); + if (!$file instanceof File) { + $file = new File; + $file->url = $given_url; + if (!empty($redir_data['protected'])) $file->protected = $redir_data['protected']; + if (!empty($redir_data['title'])) $file->title = $redir_data['title']; + if (!empty($redir_data['type'])) $file->mimetype = $redir_data['type']; + if (!empty($redir_data['size'])) $file->size = intval($redir_data['size']); + if (isset($redir_data['time']) && $redir_data['time'] > 0) $file->date = intval($redir_data['time']); + $file_id = $file->insert(); } - $x->saveOembed($redir_data, $given_url); - return $x; - } - - /** - * Save embedding information for this file, if applicable. - * - * Normally this won't need to be called manually, as File::saveNew() - * takes care of it. - * - * @param array $redir_data lookup data eg from File_redirection::where() - * @param string $given_url - * @return boolean success - */ - public function saveOembed(array $redir_data, $given_url) - { - if (isset($redir_data['type']) - && (('text/html' === substr($redir_data['type'], 0, 9) - || 'application/xhtml+xml' === substr($redir_data['type'], 0, 21)))) { - try { - $oembed_data = File_oembed::_getOembed($given_url); - } catch (Exception $e) { - return false; - } - - $fo = File_oembed::getKV('file_id', $this->id); - - if ($fo instanceof File_oembed) { - common_log(LOG_WARNING, "Strangely, a File_oembed object exists for new file $file_id", __FILE__); - } else { - File_oembed::saveNew($oembed_data, $this->id); - return true; - } - } - return false; + Event::handle('EndFileSaveNew', array($file, $redir_data, $given_url)); + return $file; } /** * Go look at a URL and possibly save data about it if it's new: * - follow redirect chains and store them in file_redirection - * - look up oEmbed data and save it in file_oembed * - if a thumbnail is available, save it in file_thumbnail * - save file record with basic info * - optionally save a file_to_post record @@ -261,26 +223,32 @@ class File extends Managed_DataObject // where should the file go? - static function filename($profile, $basename, $mimetype) + static function filename(Profile $profile, $origname, $mimetype) { - require_once 'MIME/Type/Extension.php'; - - // We have to temporarily disable auto handling of PEAR errors... - PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); - - $mte = new MIME_Type_Extension(); - $ext = $mte->getExtension($mimetype); - if (PEAR::isError($ext)) { - $ext = strtolower(preg_replace('/\W/', '', $mimetype)); + try { + $ext = common_supported_mime_to_ext($mimetype); + } catch (Exception $e) { + // We don't support this mimetype, but let's guess the extension + $ext = substr(strrchr($mimetype, '/'), 1); } - // Restore error handling. - PEAR::staticPopErrorHandling(); + // Normalize and make the original filename more URL friendly. + $origname = basename($origname); + if (class_exists('Normalizer')) { + // http://php.net/manual/en/class.normalizer.php + // http://www.unicode.org/reports/tr15/ + $origname = Normalizer::normalize($origname, Normalizer::FORM_KC); + } + $origname = preg_replace('/[^A-Za-z0-9\.\_]/', '_', $origname); $nickname = $profile->nickname; - $datestamp = strftime('%Y%m%dT%H%M%S', time()); - $random = strtolower(common_confirmation_code(32)); - return "$nickname-$datestamp-$random.$ext"; + $datestamp = strftime('%Y%m%d', time()); + do { + // generate new random strings until we don't run into a filename collision. + $random = strtolower(common_confirmation_code(16)); + $filename = "$nickname-$datestamp-$origname-$random.$ext"; + } while (file_exists(self::path($filename))); + return $filename; } /** @@ -380,7 +348,7 @@ class File extends Managed_DataObject $enclosure->size=$this->size; $enclosure->mimetype=$this->mimetype; - if(! isset($this->filename)){ + if (!isset($this->filename)) { $notEnclosureMimeTypes = array(null,'text/html','application/xhtml+xml'); $mimetype = $this->mimetype; if($mimetype != null){ @@ -390,32 +358,8 @@ class File extends Managed_DataObject if($semicolon){ $mimetype = substr($mimetype,0,$semicolon); } - if(in_array($mimetype,$notEnclosureMimeTypes)){ - // Never treat generic HTML links as an enclosure type! - // But if we have oEmbed info, we'll consider it golden. - $oembed = File_oembed::getKV('file_id',$this->id); - if($oembed && in_array($oembed->type, array('photo', 'video'))){ - $mimetype = strtolower($oembed->mimetype); - $semicolon = strpos($mimetype,';'); - if($semicolon){ - $mimetype = substr($mimetype,0,$semicolon); - } - // @fixme uncertain if this is right. - // we want to expose things like YouTube videos as - // viewable attachments, but don't expose them as - // downloadable enclosures.....? - //if (in_array($mimetype, $notEnclosureMimeTypes)) { - // return false; - //} else { - if($oembed->mimetype) $enclosure->mimetype=$oembed->mimetype; - if($oembed->url) $enclosure->url=$oembed->url; - if($oembed->title) $enclosure->title=$oembed->title; - if($oembed->modified) $enclosure->modified=$oembed->modified; - unset($oembed->size); - //} - } else { - return false; - } + if (in_array($mimetype, $notEnclosureMimeTypes)) { + Event::handle('FileEnclosureMetadata', array($file, &$enclosure)); } } return $enclosure; @@ -430,12 +374,99 @@ class File extends Managed_DataObject /** * Get the attachment's thumbnail record, if any. + * Make sure you supply proper 'int' typed variables (or null). + * + * @param $width int Max width of thumbnail in pixels. (if null, use common_config values) + * @param $height int Max height of thumbnail in pixels. (if null, square-crop to $width) + * @param $crop bool Crop to the max-values' aspect ratio * * @return File_thumbnail */ - function getThumbnail() + public function getThumbnail($width=null, $height=null, $crop=false) + { + if (intval($this->width) < 1 || intval($this->height) < 1) { + // Old files may have 0 until migrated with scripts/upgrade.php + // For any legitimately unrepresentable ones, we could generate our + // own image (like a square with MIME type in text) + throw new UnsupportedMediaException('No image geometry available.'); + } + + if ($width === null) { + $width = common_config('thumbnail', 'width'); + $height = common_config('thumbnail', 'height'); + $crop = common_config('thumbnail', 'crop'); + } + + if ($height === null) { + $height = $width; + $crop = true; + } + + // Get proper aspect ratio width and height before lookup + list($width, $height, $x, $y, $w2, $h2) = + ImageFile::getScalingValues($this->width, $this->height, $width, $height, $crop); + + // Doublecheck that parameters are sane and integers. + if ($width < 1 || $width > common_config('thumbnail', 'maxsize') + || $height < 1 || $height > common_config('thumbnail', 'maxsize')) { + // Fail on bad width parameter. If this occurs, it's due to algorithm in ImageFile::getScalingValues + throw new ServerException('Bad thumbnail size parameters.'); + } + + $params = array('file_id'=> $this->id, + 'width' => $width, + 'height' => $height); + $thumb = File_thumbnail::pkeyGet($params); + if ($thumb === null) { + // throws exception on failure to generate thumbnail + $thumb = $this->generateThumbnail($width, $height, $crop); + } + return $thumb; + } + + /** + * Generate and store a thumbnail image for the uploaded file, if applicable. + * Call this only if you know what you're doing. + * + * @param $width int Maximum thumbnail width in pixels + * @param $height int Maximum thumbnail height in pixels, if null, crop to $width + * + * @return File_thumbnail or null + */ + protected function generateThumbnail($width, $height, $crop) + { + $width = intval($width); + if ($height === null) { + $height = $width; + $crop = true; + } + + $image = ImageFile::fromFileObject($this); + + list($width, $height, $x, $y, $w2, $h2) = + $image->scaleToFit($width, $height, $crop); + + $outname = "thumb-{$width}x{$height}-" . $this->filename; + $outpath = self::path($outname); + + $image->resizeTo($outpath, $width, $height, $x, $y, $w2, $h2); + + // Avoid deleting the original + if ($image->getPath() != $this->getPath()) { + $image->unlink(); + } + return File_thumbnail::saveThumbnail($this->id, + self::url($outname), + $width, $height); + } + + public function getPath() + { + return self::path($this->filename); + } + public function getUrl() { - return File_thumbnail::getKV('file_id', $this->id); + return $this->url; } /**