<?php\r
/*\r
* Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)\r
- * Copyright (C) 2002-2009 The Nucleus Group\r
+ * Copyright (C) 2002-2012 The Nucleus Group\r
*\r
* This program is free software; you can redistribute it and/or\r
* modify it under the terms of the GNU General Public License\r
* Media classes for nucleus\r
*\r
* @license http://nucleuscms.org/license.txt GNU General Public License\r
- * @copyright Copyright (C) 2002-2009 The Nucleus Group\r
- * @version $Id: MEDIA.php 1525 2011-06-21 10:20:19Z sakamocchi $\r
+ * @copyright Copyright (C) 2002-2012 The Nucleus Group\r
+ * @version $Id: MEDIA.php 1870 2012-05-22 14:57:15Z sakamocchi $\r
*/\r
\r
-define('PRIVATE_COLLECTION', 'Private Collection');\r
-define('READ_ONLY_MEDIA_FOLDER', '(Read Only)');\r
+define('PRIVATE_COLLECTION', 'Private Collection');\r
+define('READ_ONLY_MEDIA_FOLDER', '(Read Only)');\r
\r
-/**\r
- * Represents the media objects for a certain member\r
- */\r
class Media\r
{\r
+ static public $thumbdir = '.thumb';\r
+ static public $algorism = 'md5';\r
+ static public $image_mime = array(\r
+ 'image/jpeg' => '.jpeg',\r
+ 'image/png' => '.png',\r
+ 'image/gif' => '.gif',\r
+ );\r
+ \r
/**\r
+ * Media::getCollectionList()\r
* Gets the list of collections available to the currently logged\r
* in member\r
- *\r
- * @returns array of dirname => display name\r
+ * \r
+ * @param boolean $exceptReadOnly\r
+ * @return array dirname => display name\r
*/\r
- public function getCollectionList($exceptReadOnly = false)\r
+ static public function getCollectionList($exceptReadOnly = FALSE)\r
{\r
global $member, $DIR_MEDIA;\r
\r
\r
// add private directory for member\r
$collections[$member->getID()] = PRIVATE_COLLECTION;\r
-\r
+ \r
// add global collections\r
- if (!is_dir($DIR_MEDIA)) return $collections;\r
-\r
+ if ( !is_dir($DIR_MEDIA) )\r
+ {\r
+ return $collections;\r
+ }\r
+ \r
$dirhandle = opendir($DIR_MEDIA);\r
- while ($dirname = readdir($dirhandle)) {\r
+ while ( $dirname = readdir($dirhandle) )\r
+ {\r
// only add non-numeric (numeric=private) dirs\r
- if (@is_dir($DIR_MEDIA . $dirname) &&\r
+ if ( @is_dir($DIR_MEDIA . $dirname) &&\r
($dirname != '.') &&\r
($dirname != '..') &&\r
- ($dirname != 'CVS') &&\r
- (!is_numeric($dirname))) {\r
- if (@is_writable($DIR_MEDIA . $dirname))\r
+ ($dirname != self::$thumbdir) &&\r
+ (!is_numeric($dirname)) )\r
+ {\r
+ if ( @is_writable($DIR_MEDIA . $dirname) )\r
+ {\r
$collections[$dirname] = $dirname;\r
- else if ($exceptReadOnly == false)\r
+ }\r
+ else if ( $exceptReadOnly == FALSE )\r
+ {\r
$collections[$dirname] = $dirname . ' ' . READ_ONLY_MEDIA_FOLDER;\r
+ }\r
}\r
}\r
closedir($dirhandle);\r
-\r
+ \r
return $collections;\r
-\r
}\r
-\r
+ \r
/**\r
- * Returns an array of MediaObject objects for a certain collection\r
- *\r
- * @param $collection\r
- * name of the collection\r
- * @param $filter\r
- * filter on filename (defaults to none)\r
- */\r
- function getMediaListByCollection($collection, $filter = '') {\r
- global $DIR_MEDIA;\r
-\r
+ * Media::getMediaListByCollection()\r
+ * Returns an array of MediaObject objects for a certain collection\r
+ *\r
+ * @param string $collection name of the collection\r
+ * @param string $filter filter on filename (defaults to none)\r
+ * @return void\r
+ */\r
+ static public function getMediaListByCollection($collection, $filter = '')\r
+ {\r
+ global $CONF, $DIR_MEDIA;\r
+ \r
$filelist = array();\r
-\r
+ \r
// 1. go through all objects and add them to the filelist\r
-\r
$mediadir = $DIR_MEDIA . $collection . '/';\r
-\r
+ \r
// return if dir does not exist\r
- if (!is_dir($mediadir)) return $filelist;\r
-\r
+ if ( !is_dir($mediadir) )\r
+ {\r
+ return $filelist;\r
+ }\r
+ \r
$dirhandle = opendir($mediadir);\r
- while ($filename = readdir($dirhandle)) {\r
+ while ( $filename = readdir($dirhandle) )\r
+ {\r
// only add files that match the filter\r
- if (!@is_dir($filename) && Media::checkFilter($filename, $filter))\r
- array_push($filelist, new MediaObject($collection, $filename, filemtime($mediadir . $filename)));\r
+ if ( !is_dir($mediadir . $filename) && self::checkFilter($filename, $filter) )\r
+ {\r
+ array_push($filelist, new MediaObject($collection, $filename, $DIR_MEDIA));\r
+ }\r
}\r
closedir($dirhandle);\r
-\r
- // sort array so newer files are shown first\r
- usort($filelist, 'sort_media');\r
-\r
+ \r
+ /* sort array */\r
+ if ( !$CONF['MediaPrefix'] )\r
+ {\r
+ usort($filelist, array(__CLASS__, 'sort_media_by_timestamp'));\r
+ }\r
+ else\r
+ {\r
+ usort($filelist, array(__CLASS__, 'sort_media_by_filename'));\r
+ }\r
+ \r
return $filelist;\r
}\r
-\r
- function checkFilter($strText, $strFilter) {\r
- if ($strFilter == '')\r
+ \r
+ /**\r
+ * Media::checkFilter()\r
+ * \r
+ * @param string $strText\r
+ * @param string $strFilter\r
+ * @return boolean\r
+ */\r
+ static public function checkFilter($strText, $strFilter)\r
+ {\r
+ if ( $strFilter == '' )\r
+ {\r
return 1;\r
+ }\r
else\r
+ {\r
return is_integer(i18n::strpos(strtolower($strText), strtolower($strFilter)));\r
+ }\r
}\r
-\r
+ \r
/**\r
- * checks if a collection exists with the given name, and if it's\r
- * allowed for the currently logged in member to upload files to it\r
- */\r
- function isValidCollection($collectionName, $exceptReadOnly = false) {\r
+ * Media::isValidCollection()\r
+ * checks if a collection exists with the given name, and if it's\r
+ * allowed for the currently logged in member to upload files to it\r
+ * \r
+ * @param string $collectionName\r
+ * @param string $exceptReadOnly\r
+ * @return boolean\r
+ */\r
+ static public function isValidCollection($collectionName, $exceptReadOnly = FALSE)\r
+ {\r
global $member, $DIR_MEDIA;\r
-\r
+ \r
// allow creating new private directory\r
- if ($collectionName === (string)$member->getID())\r
- return true;\r
- \r
- $collections = Media::getCollectionList($exceptReadOnly);\r
+ if ( $collectionName === (string)$member->getID() )\r
+ {\r
+ return TRUE;\r
+ }\r
+ \r
+ $collections = self::getCollectionList($exceptReadOnly);\r
$dirname = $collections[$collectionName];\r
- if ($dirname == NULL || $dirname === PRIVATE_COLLECTION)\r
- return false; \r
-\r
+ \r
+ if ( $dirname == NULL || $dirname === PRIVATE_COLLECTION )\r
+ {\r
+ return FALSE;\r
+ }\r
+ \r
// other collections should exist and be writable\r
$collectionDir = $DIR_MEDIA . $collectionName;\r
- if ($exceptReadOnly)\r
- return (@is_dir($collectionDir) && @is_writable($collectionDir));\r
-\r
+ if ( $exceptReadOnly )\r
+ {\r
+ return ( @is_dir($collectionDir) && @is_writable($collectionDir) );\r
+ }\r
+ \r
// other collections should exist\r
return @is_dir($collectionDir);\r
- }\r
-\r
+ }\r
+ \r
/**\r
- * Adds an uploaded file to the media archive\r
- *\r
- * @param collection\r
- * collection\r
- * @param uploadfile\r
- * the postFileInfo(..) array\r
- * @param filename\r
- * the filename that should be used to save the file as\r
- * (date prefix should be already added here)\r
- */\r
- function addMediaObject($collection, $uploadfile, $filename) {\r
+ * Media::addMediaObject()\r
+ * Adds an uploaded file to the media archive\r
+ *\r
+ * @param string $collection collection\r
+ * @param array $uploadfile the postFileInfo(..) array\r
+ * @param string $filename the filename that should be used to save the file as\r
+ * (date prefix should be already added here)\r
+ * @return string blank if success, message if failed\r
+ */\r
+ static public function addMediaObject($collection, $uploadfile, $filename)\r
+ {\r
global $DIR_MEDIA, $manager;\r
-\r
+ \r
// clean filename of characters that may cause trouble in a filename using cleanFileName() function from globalfunctions.php\r
$filename = cleanFileName($filename);\r
+ \r
// should already have tested for allowable types before calling this method. This will only catch files with no extension at all\r
- if ($filename === false) \r
+ if ( $filename === FALSE )\r
+ {\r
return _ERROR_BADFILETYPE;\r
+ }\r
\r
// trigger PreMediaUpload event\r
$manager->notify('PreMediaUpload',array('collection' => &$collection, 'uploadfile' => $uploadfile, 'filename' => &$filename));\r
-\r
+ \r
// don't allow uploads to unknown or forbidden collections\r
- $exceptReadOnly = true;\r
- if (!Media::isValidCollection($collection,$exceptReadOnly))\r
+ $exceptReadOnly = TRUE;\r
+ if ( !self::isValidCollection($collection,$exceptReadOnly) )\r
+ {\r
return _ERROR_DISALLOWED;\r
-\r
+ }\r
+ \r
// check dir permissions (try to create dir if it does not exist)\r
$mediadir = $DIR_MEDIA . $collection;\r
-\r
+ \r
// try to create new private media directories if needed\r
- if (!@is_dir($mediadir) && is_numeric($collection)) {\r
+ if ( !@is_dir($mediadir) && is_numeric($collection) )\r
+ {\r
$oldumask = umask(0000);\r
- if (!@mkdir($mediadir, 0777))\r
+ if ( !@mkdir($mediadir, 0777) )\r
+ {\r
return _ERROR_BADPERMISSIONS;\r
+ }\r
umask($oldumask);\r
}\r
-\r
+ \r
// if dir still not exists, the action is disallowed\r
- if (!@is_dir($mediadir))\r
+ if ( !@is_dir($mediadir) )\r
+ {\r
return _ERROR_DISALLOWED;\r
-\r
- if (!is_writeable($mediadir))\r
+ }\r
+ \r
+ if ( !is_writeable($mediadir) )\r
+ {\r
return _ERROR_BADPERMISSIONS;\r
-\r
+ }\r
+ \r
// add trailing slash (don't add it earlier since it causes mkdir to fail on some systems)\r
$mediadir .= '/';\r
-\r
- if (file_exists($mediadir . $filename))\r
+ \r
+ if ( file_exists($mediadir . $filename) )\r
+ {\r
return _ERROR_UPLOADDUPLICATE;\r
-\r
+ }\r
+ \r
// move file to directory\r
- if (is_uploaded_file($uploadfile)) {\r
- if (!@move_uploaded_file($uploadfile, $mediadir . $filename))\r
+ if ( is_uploaded_file($uploadfile) )\r
+ {\r
+ if ( !@move_uploaded_file($uploadfile, $mediadir . $filename) )\r
+ {\r
return _ERROR_UPLOADMOVEP;\r
- } else {\r
- if (!copy($uploadfile, $mediadir . $filename))\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if ( !copy($uploadfile, $mediadir . $filename) )\r
+ {\r
return _ERROR_UPLOADCOPY ;\r
+ }\r
}\r
-\r
+ \r
// chmod uploaded file\r
$oldumask = umask(0000);\r
@chmod($mediadir . $filename, 0644);\r
umask($oldumask);\r
-\r
+ \r
$manager->notify('PostMediaUpload',array('collection' => $collection, 'mediadir' => $mediadir, 'filename' => $filename));\r
-\r
+ \r
return '';\r
-\r
}\r
-\r
+ \r
/**\r
+ * Media::addMediaObjectRaw()\r
* Adds an uploaded file to the media dir.\r
- *\r
- * @param $collection\r
- * collection to use\r
- * @param $filename\r
- * the filename that should be used to save the file as\r
- * (date prefix should be already added here)\r
- * @param &$data\r
- * File data (binary)\r
- *\r
+ * \r
* NOTE: does not check if $collection is valid.\r
+ * \r
+ * @param string $collection collection to use\r
+ * @param string $filename the filename that should be used to save the file\r
+ * as (date prefix should be already added here)\r
+ * @param &$data File data (binary)\r
+ * @return string blank if success, message if failed\r
*/\r
- function addMediaObjectRaw($collection, $filename, &$data) {\r
+ static public function addMediaObjectRaw($collection, $filename, &$data)\r
+ {\r
global $DIR_MEDIA;\r
-\r
+ \r
// check dir permissions (try to create dir if it does not exist)\r
$mediadir = $DIR_MEDIA . $collection;\r
-\r
+ \r
// try to create new private media directories if needed\r
- if (!@is_dir($mediadir) && is_numeric($collection)) {\r
+ if ( !@is_dir($mediadir) && is_numeric($collection) )\r
+ {\r
$oldumask = umask(0000);\r
- if (!@mkdir($mediadir, 0777))\r
+ if ( !@mkdir($mediadir, 0777) )\r
+ {\r
return _ERROR_BADPERMISSIONS;\r
+ }\r
umask($oldumask);\r
}\r
-\r
+ \r
// if dir still not exists, the action is disallowed\r
- if (!@is_dir($mediadir))\r
+ if ( !@is_dir($mediadir) )\r
+ {\r
return _ERROR_DISALLOWED;\r
-\r
- if (!is_writeable($mediadir))\r
+ }\r
+ \r
+ if ( !is_writeable($mediadir) )\r
+ {\r
return _ERROR_BADPERMISSIONS;\r
-\r
+ }\r
+ \r
// add trailing slash (don't add it earlier since it causes mkdir to fail on some systems)\r
$mediadir .= '/';\r
-\r
- if (file_exists($mediadir . $filename))\r
+ \r
+ if ( file_exists($mediadir . $filename) )\r
+ {\r
return _ERROR_UPLOADDUPLICATE;\r
-\r
+ }\r
+ \r
// create file\r
$fh = @fopen($mediadir . $filename, 'wb');\r
- if (!$fh)\r
+ if ( !$fh )\r
+ {\r
return _ERROR_UPLOADFAILED;\r
+ }\r
$ok = @fwrite($fh, $data);\r
@fclose($fh);\r
- if (!$ok)\r
+ if ( !$ok )\r
+ {\r
return _ERROR_UPLOADFAILED;\r
-\r
+ }\r
+ \r
// chmod uploaded file\r
$oldumask = umask(0000);\r
@chmod($mediadir . $filename, 0644);\r
umask($oldumask);\r
-\r
+ \r
return '';\r
-\r
}\r
-\r
+ \r
+ /**\r
+ * Media::responseResampledImage()\r
+ * send resampled image via HTTP\r
+ * \r
+ * @param object $medium Medium Object\r
+ * @exit\r
+ */\r
+ static public function responseResampledImage($medium, $maxwidth=0, $maxheight=0)\r
+ {\r
+ if ( get_class($medium) !== 'Medium' )\r
+ {\r
+ header("HTTP/1.1 500 Internal Server Error");\r
+ exit('Nucleus CMS: Fail to generate resampled image');\r
+ return;\r
+ }\r
+ \r
+ $resampledimage = $medium->getResampledBinary($maxwidth, $maxheight);\r
+ if ( $resampledimage === FALSE )\r
+ {\r
+ unset($resampledimage);\r
+ header("HTTP/1.1 503 Service Unavailable");\r
+ exit('Nucleus CMS: Fail to generate resampled image');\r
+ return;\r
+ }\r
+ \r
+ header("Content-type: {$medium->mime}");\r
+ echo $resampledimage;\r
+ \r
+ unset($resampledimage);\r
+ \r
+ exit;\r
+ }\r
+ \r
+ /**\r
+ * Media::storeResampledImage()\r
+ * Store resampled image binary to filesystem as file\r
+ * \r
+ * @param object $medium medium Object\r
+ * @param integer $maxwidth maximum width\r
+ * @param integer $maxheight maximum height\r
+ * @param string $path directory path for destination\r
+ * @param string $name file name for destination\r
+ * @return boolean\r
+ */\r
+ static public function storeResampledImage($medium, $maxwidth=0, $maxheight=0, $path='', $name='')\r
+ {\r
+ global $DIR_MEDIA;\r
+ \r
+ if ( get_class($medium) !== 'Medium' )\r
+ {\r
+ return FALSE;\r
+ }\r
+ \r
+ if ( $path !== '' )\r
+ {\r
+ $path = realpath($path);\r
+ if ( !file_exists($path)\r
+ || strpos($path, $DIR_MEDIA) !== 0 )\r
+ {\r
+ return FALSE;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ $path = '$DIR_MEDIA/' . self::$thumbdir;\r
+ }\r
+ \r
+ if ( $name === '' )\r
+ {\r
+ $name = $medium->getHashedname();\r
+ }\r
+ \r
+ $resampledimage = $medium->getResampledBinary($maxwidth, $maxheight);\r
+ if ( !$resampledimage )\r
+ {\r
+ unset($resampledimage);\r
+ return FALSE;\r
+ }\r
+ \r
+ $handle = @fopen("{$path}/{$name}", 'w');\r
+ if ( !$handle )\r
+ {\r
+ unset ($resampledimage);\r
+ return FALSE;\r
+ }\r
+ \r
+ if ( !@fwrite($handle, $resampledimage) )\r
+ {\r
+ unset($resampledimage);\r
+ @unlink("{$path}/{$name}");\r
+ return FALSE;\r
+ }\r
+ \r
+ unset($resampledimage);\r
+ fclose($handle);\r
+ \r
+ if ( !@chmod("{$path}/{$name}", 0774) )\r
+ {\r
+ @unlink("{$path}/{$name}");\r
+ return FALSE;\r
+ }\r
+ \r
+ return TRUE;\r
+ }\r
+ \r
+ /**\r
+ * Media::sort_media_by_timestamp()\r
+ * User-defined sort method to sort an array of MediaObjects\r
+ * \r
+ * @param object $a\r
+ * @param object $b\r
+ * @return boolean\r
+ */\r
+ static private function sort_media_by_timestamp($a, $b)\r
+ {\r
+ if ($a->timestamp == $b->timestamp) return 0;\r
+ return ($a->timestamp > $b->timestamp) ? -1 : 1;\r
+ }\r
+ \r
+ /**\r
+ * Media::sort_media_by_filename()\r
+ * User-defined sort method to sort an array of MediaObjects\r
+ * \r
+ * @param object $a\r
+ * @param object $b\r
+ * @return boolean\r
+ */\r
+ static private function sort_media_by_filename($a, $b)\r
+ {\r
+ if ($a->filename == $b->filename) return 0;\r
+ return ($a->filename > $b->filename) ? -1 : 1;\r
+ }\r
}\r
\r
-/**\r
- * Represents the characteristics of one single media-object\r
- *\r
- * Description of properties:\r
- * - filename: filename, without paths\r
- * - timestamp: last modification (unix timestamp)\r
- * - collection: collection to which the file belongs (can also be a owner ID, for private collections)\r
- * - private: true if the media belongs to a private member collection\r
- */\r
class MediaObject\r
{\r
+ public $mime = '';\r
+ \r
+ public $root = '';\r
+ public $path = '';\r
public $private;\r
public $collection;\r
- public $filename;\r
- public $timestamp;\r
+ public $filename = '';\r
+ \r
+ public $prefix = '';\r
+ public $name = '';\r
+ public $suffix = '';\r
+ \r
+ public $timestamp = 0;\r
+ public $size = 0;\r
+ \r
+ public $width = 0;\r
+ public $height = 0;\r
+ public $resampledwidth = 0;\r
+ public $resampledheight = 0;\r
\r
- public function __construct($collection, $filename, $timestamp)\r
+ /**\r
+ * MediaObject::__construct()\r
+ * \r
+ * @param string $collection \r
+ * @param string $filename \r
+ * @param string $root fullpath to media directory\r
+ */\r
+ public function __construct($collection, $filename, $root=0)\r
{\r
- $this->private = is_numeric($collection);\r
+ global $CONF, $DIR_MEDIA;\r
+ \r
+ /* for backward compatibility */\r
+ if ( is_numeric($root) )\r
+ {\r
+ $root = $DIR_MEDIA;\r
+ }\r
+ \r
+ $root = preg_replace('#/*$#', '', $root);\r
+ \r
+ /* get and validate fullpath for the medium */\r
+ if ( !file_exists($root)\r
+ || FALSE === ($fullpath = realpath("{$root}/{$collection}/{$filename}"))\r
+ || strpos($fullpath, $root) !== 0\r
+ || !file_exists($fullpath) )\r
+ {\r
+ return FALSE;\r
+ }\r
+ \r
+ /* store fundamentals */\r
+ $this->root = $root;\r
+ $this->private = (integer) $collection;\r
$this->collection = $collection;\r
- $this->filename = $filename;\r
- $this->timestamp = $timestamp;\r
+ $this->filename = basename($fullpath);\r
+ $this->timestamp = filemtime($fullpath);\r
+ \r
+ /* store relative directory path from root directory for media */\r
+ $this->path = preg_replace(array("#{$this->root}/#", "#/{$this->filename}#"), '', $fullpath);\r
+ if ( $this->path === $this->name )\r
+ {\r
+ $this->path = ''; \r
+ }\r
+ \r
return;\r
}\r
-}\r
-\r
-/**\r
- * User-defined sort method to sort an array of MediaObjects\r
- */\r
-function sort_media($a, $b) {\r
- if ($a->timestamp == $b->timestamp) return 0;\r
- return ($a->timestamp > $b->timestamp) ? -1 : 1;\r
+ \r
+ /**\r
+ * MediaObject::refine()\r
+ * refine data\r
+ * \r
+ * @param void\r
+ * @return void\r
+ */\r
+ public function refine()\r
+ {\r
+ global $CONF;\r
+ \r
+ /* store size (byte order) */\r
+ $this->size = filesize("{$this->root}/{$this->path}/{$this->filename}");\r
+ \r
+ /* get width and height if this is image binary */\r
+ if ( FALSE === ($info = @getimagesize ("{$this->root}/{$this->path}/{$this->filename}")) )\r
+ {\r
+ $this->mime = 'application/octet-stream';\r
+ $this->width = 0;\r
+ $this->height = 0;\r
+ }\r
+ else\r
+ {\r
+ $this->mime = $info['mime'];\r
+ $this->width = $info[0];\r
+ $this->height = $info[1];\r
+ }\r
+ \r
+ /* utilise Fileinfo subsystem if available */\r
+ if ( defined('FILEINFO_MIME_TYPE') && function_exists ('finfo_open')\r
+ && (FALSE !== ($info = finfo_open(FILEINFO_MIME_TYPE))) )\r
+ {\r
+ $this->mime = finfo_file($info, "{$this->root}/{$this->path}/{$this->filename}");\r
+ }\r
+ \r
+ /* store data with parsed filename */\r
+ if ( preg_match('#^(.*)\.([a-zA-Z0-9]{2,})$#', $this->filename, $info) === 1 )\r
+ {\r
+ $this->name = $info[1];\r
+ $this->suffix = $info[2];\r
+ \r
+ if ( $CONF['MediaPrefix'] && preg_match('#^([0-9]{8})\-(.*)$#', $this->name, $info) == 1 )\r
+ {\r
+ $this->prefix = preg_replace('#^([0-9]{4})([0-9]{2})([0-9]{2})$#', '$1/$2/$3', $info[1]);\r
+ $this->name = $info[2];\r
+ }\r
+ }\r
+ \r
+ return;\r
+ }\r
+ \r
+ /**\r
+ * MediaObject::setResampledSize()\r
+ * Set resampled size\r
+ * \r
+ * @param integer $maxwidth\r
+ * @param integer $maxheight\r
+ * @return boolean\r
+ */\r
+ public function setResampledSize($maxwidth=0, $maxheight=0)\r
+ {\r
+ if ( ($maxwidth == 0) && ($maxheight == 0) )\r
+ {\r
+ return FALSE;\r
+ }\r
+ else if ( $this->width == 0 || $this->height == 0 )\r
+ {\r
+ return FALSE;\r
+ }\r
+ else if ($this->width < $maxwidth && $this->height < $maxheight )\r
+ {\r
+ $this->resampledwidth = $this->width;\r
+ $this->resampledheight = $this->height;\r
+ }\r
+ else if ( $maxheight == 0 || $this->width > $this->height )\r
+ {\r
+ $this->resampledheight = intval ($this->height * $maxwidth / $this->width);\r
+ $this->resampledwidth = $maxwidth;\r
+ }\r
+ else if ( $maxwidth == 0 || $this->width <= $this->height )\r
+ {\r
+ $this->resampledwidth = intval ($this->width * $maxheight / $this->height);\r
+ $this->resampledheight = $maxheight;\r
+ }\r
+ return TRUE;\r
+ }\r
+ \r
+ /**\r
+ * MediaObject::getResampledBinary()\r
+ * Return resampled image binary\r
+ * \r
+ * @param void\r
+ * @return mixed binary if success, FALSE if failed\r
+ */\r
+ public function getResampledBinary($maxwidth=0, $maxheight=0)\r
+ {\r
+ static $gdinfo = array();\r
+ static $original;\r
+ static $resampledimage;\r
+ \r
+ if ( !$this->setResampledSize($maxwidth, $maxheight) )\r
+ {\r
+ return FALSE;\r
+ }\r
+ \r
+ if ( $gdinfo = array() )\r
+ {\r
+ $gdinfo = gd_info();\r
+ }\r
+ \r
+ if ( $this->path !== '' )\r
+ {\r
+ $fullpath = "{$this->root}/{$this->path}/{$this->name}";\r
+ }\r
+ else\r
+ {\r
+ $fullpath = "{$this->root}/{$this->name}";\r
+ }\r
+ if ( !file_exists($fullpath) )\r
+ {\r
+ return FALSE;\r
+ }\r
+ \r
+ if ( !array_key_exists($this->mime, Media::$image_mime)\r
+ || $this->width == 0\r
+ || $this->height == 0\r
+ || $this->resampledwidth == 0\r
+ || $this->resampledheight == 0 )\r
+ {\r
+ return FALSE;\r
+ }\r
+ \r
+ /* check current available memory */\r
+ $memorymax = trim(ini_get("memory_limit"));\r
+ switch ( strtolower ($memorymax[strlen($memorymax)-1]) )\r
+ {\r
+ case 'g':\r
+ $memorymax *= 1024;\r
+ case 'm':\r
+ $memorymax *= 1024;\r
+ case 'k':\r
+ $memorymax *= 1024;\r
+ }\r
+ \r
+ /*\r
+ * this code is based on analyze if gd.c in php source code\r
+ * if you can read C/C++, please check these elements and notify us if you have some ideas\r
+ */\r
+ if ( (memory_get_usage()\r
+ + ($this->resampledwidth * $this->resampledheight * 5 + $this->resampledheight * 24 + 10000)\r
+ + ($this->width * $this->height * 5 + $this->height * 24 + 10000))\r
+ > $memorymax )\r
+ {\r
+ return FALSE;\r
+ }\r
+ \r
+ switch ( $this->mime )\r
+ {\r
+ case 'image/gif':\r
+ if ( (!array_key_exists('GIF Read Support', $gdinfo) || !isset($gdinfo['GIF Read Support']))\r
+ || (!array_key_exists('GIF Create Support', $gdinfo) || !isset($gdinfo['GIF Create Support'])) )\r
+ {\r
+ return FALSE;\r
+ }\r
+ $function = 'imagecreatefromgif';\r
+ break;\r
+ case 'image/jpeg':\r
+ if ( (!array_key_exists('JPEG Support', $gdinfo) || !isset($gdinfo['JPEG Support']))\r
+ && (!array_key_exists('JPG Support', $gdinfo) || !isset($gdinfo['JPG Support'])) )\r
+ {\r
+ return FALSE;\r
+ }\r
+ $function = 'imagecreatefromjpeg';\r
+ break;\r
+ case 'image/png':\r
+ if ( !array_key_exists('PNG Support', $gdinfo) || !isset($gdinfo['PNG Support']) )\r
+ {\r
+ return FALSE;\r
+ }\r
+ $function = 'imagecreatefrompng';\r
+ break;\r
+ default:\r
+ return FALSE;\r
+ }\r
+ \r
+ if ( !is_callable($function) )\r
+ {\r
+ return FALSE;\r
+ }\r
+ \r
+ $original = call_user_func_array($function, array(&$fullpath));\r
+ if ( !$original )\r
+ {\r
+ return FALSE;\r
+ }\r
+ \r
+ $resampledimage = imagecreatetruecolor($this->resampledwidth, $this->resampledheight);\r
+ if ( !$resampledimage )\r
+ {\r
+ imagedestroy($original);\r
+ return FALSE;\r
+ }\r
+ \r
+ @set_time_limit(ini_get('max_execution_time'));\r
+ if ( !ImageCopyResampled($resampledimage, $original, 0, 0, 0, 0, $this->resampledwidth, $this->resampledheight, $this->width, $this->height) )\r
+ {\r
+ return FALSE;\r
+ }\r
+ \r
+ imagedestroy($original);\r
+ \r
+ ob_start();\r
+ \r
+ switch ( $this->mime )\r
+ {\r
+ case 'image/gif':\r
+ imagegif($resampledimage);\r
+ break;\r
+ case 'image/jpeg':\r
+ imagejpeg($resampledimage);\r
+ break;\r
+ case 'image/png':\r
+ imagepng($resampledimage);\r
+ break;\r
+ case 'image/bmp':\r
+ case 'image/x-ms-bmp':\r
+ imagepng($resampledimage);\r
+ break;\r
+ default:\r
+ return FALSE;\r
+ }\r
+ \r
+ imagedestroy($resampledimage);\r
+ \r
+ return ob_get_clean();\r
+ }\r
+ \r
+ public function getHashedName()\r
+ {\r
+ return (string) hash(Media::$algorism, "{$this->path}/{$this->name}", FALSE);\r
+ }\r
}\r