_handle = $handle; $this->_filename = $filename; $this->_type = $type; } function get_filename() { return $this->_filename; } function get_handle() { return $this->_handle; } function get_type() { return $this->_type; } function sx() { if (!$this->_handle) { return 0; }; return imagesx($this->_handle); } function sy() { if (!$this->_handle) { return 0; }; return imagesy($this->_handle); } } class ImageFactory { // Static funcion; checks if given URL is already cached and either returns // cached object or downloads the requested image // function get($url, &$pipeline) { global $g_config; if (!$g_config['renderimages']) { return null; }; global $g_image_cache; // Check if this URL have been cached // if (isset($g_image_cache[$url])) { // return do_image_open($g_image_cache[$url]); return $g_image_cache[$url]; }; // Download image; we should do it before we call do_image_open, // as it tries to open image file twice: first to determine image type // and second to actually create the image - PHP url wrappers do no caching // at all // $filename = ImageFactory::make_cache_filename($url); // REQUIRES: PHP 4.3.0+ // we suppress warning messages, as missing image files will cause 'copy' to print // several warnings // // @TODO: change to fetcher class call // $data = $pipeline->fetch($url); //echo '~' . $url . '~' . print_R($data,1) . '~'; if (is_null($data)) { error_log("Cannot fetch image: ".$url); return null; }; $file = fopen($filename, 'wb'); fwrite($file, $data->content); fclose($file); $pipeline->pop_base_url(); // register it in the cached objects array // $handle = do_image_open($filename, $type); if ($handle) { $g_image_cache[$url] =& new Image($handle, $filename, $type); } else { $g_image_cache[$url] = null; }; // return image // // return do_image_open($filename); return $g_image_cache[$url]; } // Makes the filename to contain the cached version of URL // function make_cache_filename($url) { // We cannot use the $url as an cache image name as it could be longer than // allowed file name length (especially after escaping specialy symbols) // thus, we generate long almost random 32-character name using the md5 hash function // return CACHE_DIR.md5(time() + $url + rand()); } // Checks if cache directory is available // function check_cache_dir() { // TODO: some cool easily understandable error message for the case // image cache directory cannot be created or accessed // Check if CACHE_DIR exists // if (!is_dir(CACHE_DIR)) { // Cache directory does not exists; try to create it (with read/write rightss for the owner only) // if (!mkdir(CACHE_DIR, 0700)) { die("Cache directory cannot be created"); } }; // Check if we can read and write to the CACHE_DIR // // Note that directory should have 'rwx' (7) permission, so the script will // be able to list directory contents; under Windows is_executable always returns false // for directories, so we need to drop this check in this case. // // A user's note for 'is_executable' function on PHP5: // "The change doesn't appear to be documented, so I thought I would mention it. // In php5, as opposed to php4, you can no longer rely on is_executable to check the executable bit // on a directory in 'nix. You can still use the first note's method to check if a directory is traversable: // @file_exists("adirectory/.");" // if (!is_readable(CACHE_DIR) || !is_writeable(CACHE_DIR) || (!@file_exists(CACHE_DIR.'.'))) { // omg. Cache directory exists, but useless // die("Check cache directory permissions; cannot either read or write to directory cache"); }; return; } // Clears the image cache (as we're neither implemented checking of Last-Modified HTTP header nor // provided the means of limiting the cache size // // TODO: Will cause problems with simultaneous access to the same images // function clear_cache() { foreach ($GLOBALS['g_image_cache'] as $key => $value) { if (!is_null($value)) { unlink($value->get_filename()); }; }; $g_image_cache = array(); } } ?>