var $height;
var $width;
var $rotate=0; // degrees to rotate for properly oriented image (extrapolated from EXIF etc.)
- var $animated = false; // Animated image? (has more than 2 frames)
+ var $animated = null; // Animated image? (has more than 1 frame). null means untested
function __construct($id=null, $filepath=null, $type=null, $width=null, $height=null)
{
$info = @getimagesize($this->filepath);
- if (!(
- ($info[2] == IMAGETYPE_GIF && function_exists('imagecreatefromgif')) ||
- ($info[2] == IMAGETYPE_JPEG && function_exists('imagecreatefromjpeg')) ||
- $info[2] == IMAGETYPE_BMP ||
- ($info[2] == IMAGETYPE_WBMP && function_exists('imagecreatefromwbmp')) ||
- ($info[2] == IMAGETYPE_XBM && function_exists('imagecreatefromxbm')) ||
- ($info[2] == IMAGETYPE_PNG && function_exists('imagecreatefrompng')))) {
+ if (
+ ($info[2] == IMAGETYPE_GIF && !function_exists('imagecreatefromgif')) ||
+ ($info[2] == IMAGETYPE_JPEG && !function_exists('imagecreatefromjpeg')) ||
+ ($info[2] == IMAGETYPE_WBMP && !function_exists('imagecreatefromwbmp')) ||
+ ($info[2] == IMAGETYPE_XBM && !function_exists('imagecreatefromxbm')) ||
+ ($info[2] == IMAGETYPE_PNG && !function_exists('imagecreatefrompng'))) {
// TRANS: Exception thrown when trying to upload an unsupported image file format.
throw new UnsupportedMediaException(_('Unsupported image format.'), $this->filepath);
}
// If we ever write this back, Orientation should be set to '1'
}
+ } elseif ($this->type === IMAGETYPE_GIF) {
+ $this->animated = $this->isAnimatedGif();
}
Event::handle('FillImageFileMetadata', array($this));
$imgPath = null;
$media = common_get_mime_media($file->mimetype);
if (Event::handle('CreateFileImageThumbnailSource', array($file, &$imgPath, $media))) {
+ if (empty($file->filename)) {
+ throw new UnsupportedMediaException(_('File without filename could not get a thumbnail source.'));
+ }
switch ($media) {
case 'image':
$imgPath = $file->getPath();
if ($this->rotate == 0) {
// No rotational difference, just copy it as-is
@copy($this->filepath, $outpath);
+
+ // And set chmod
+ @chmod($outpath, common_config('attachments', 'chmod'));
return $outpath;
} elseif (abs($this->rotate) == 90) {
// Box is rotated 90 degrees in either direction,
throw new Exception(_('Unknown file type'));
}
+ // Always chmod 0644 (default) to have other processes (e.g. queue daemon read it)
+ @chmod($outpath, common_config('attachments', 'chmod'));
+
imagedestroy($image_src);
imagedestroy($image_dest);
}
is_null($cw) ? $width : intval($cw),
is_null($ch) ? $height : intval($ch));
}
+
+ /**
+ * Animated GIF test, courtesy of frank at huddler dot com et al:
+ * http://php.net/manual/en/function.imagecreatefromgif.php#104473
+ * Modified so avoid landing inside of a header (and thus not matching our regexp).
+ */
+ protected function isAnimatedGif()
+ {
+ if (!($fh = @fopen($this->filepath, 'rb'))) {
+ return false;
+ }
+
+ $count = 0;
+ //an animated gif contains multiple "frames", with each frame having a
+ //header made up of:
+ // * a static 4-byte sequence (\x00\x21\xF9\x04)
+ // * 4 variable bytes
+ // * a static 2-byte sequence (\x00\x2C)
+ // In total the header is maximum 10 bytes.
+
+ // We read through the file til we reach the end of the file, or we've found
+ // at least 2 frame headers
+ while(!feof($fh) && $count < 2) {
+ $chunk = fread($fh, 1024 * 100); //read 100kb at a time
+ $count += preg_match_all('#\x00\x21\xF9\x04.{4}\x00\x2C#s', $chunk, $matches);
+ // rewind in case we ended up in the middle of the header, but avoid
+ // infinite loop (i.e. don't rewind if we're already in the end).
+ if (!feof($fh) && ftell($fh) >= 9) {
+ fseek($fh, -9, SEEK_CUR);
+ }
+ }
+
+ fclose($fh);
+ return $count > 1;
+ }
}
//PHP doesn't (as of 2/24/2010) have an imagecreatefrombmp so conditionally define one