From f23f8578ac7f976053e8f782cbe1dfc4b97e2ac8 Mon Sep 17 00:00:00 2001 From: Damian Taggart Date: Mon, 22 Feb 2016 10:24:17 -0700 Subject: [PATCH] 3.0.1 updates --- README.md | 8 +- mthumb.php | 577 +++++++++++++++++++++++++++-------------------------- 2 files changed, 295 insertions(+), 290 deletions(-) diff --git a/README.md b/README.md index 9c2f8a2..6460660 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,10 @@ Like many WordPress developers we've been making use of the old TimThumb script Get Involved ======== -You can help out by testing this and reporting bugs. We ARE NOT interested in preserving 100% compatibility with all of Timthumb's less frequently used features as mentioned above but we ARE VERY motivated to make sure this code is secure. So any security issues will be dealt with immediately. +You can help out by testing this and reporting bugs. We ARE NOT interested in preserving 100% compatibility with all of TimThumb's less frequently used features as mentioned above but we ARE VERY motivated to make sure this code is secure. So any security issues will be dealt with immediately. Pull requests are most welcome. Cheers. - mThumb Parameters ======== @@ -209,5 +208,6 @@ There are a whole bunch of settings that are not controlled by the normal query Changelog ======== -* 3.0 - version number update to calm down some automated scanners that think this is an old version of TimThumb -* 1.0 - first proper release +* 3.0.1 - Bugfix for unwritable cache folder +* 3.0 - Version number update to calm down some automated scanners that think this is an old version of TimThumb +* 1.0 - First proper release diff --git a/mthumb.php b/mthumb.php index 320bb10..f2745a6 100644 --- a/mthumb.php +++ b/mthumb.php @@ -17,7 +17,7 @@ * @copyright Copyright (c) 2013-2015 * @link https://mindsharelabs.com/ * - * Copyright 2013-2015 Mindshare Studios, Inc. (https://mind.sh/are/) + * Copyright 2013-2016 Mindshare Studios, Inc. (https://mind.sh/are/) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 3, as @@ -47,43 +47,43 @@ /** * Version of this script * */ -define ('VERSION', '3.0.1'); +define('VERSION', '3.0.1'); //Load a config file if it exists. Otherwise, use the values below -if(file_exists(dirname(__FILE__).'/mthumb-config.php')) { +if (file_exists(dirname(__FILE__) . '/mthumb-config.php')) { require_once('mthumb-config.php'); } -if(!defined('DEBUG_ON')) { +if (!defined('DEBUG_ON')) { /** * Enable debug logging to web server error log (STDERR) */ - define ('DEBUG_ON', FALSE); + define('DEBUG_ON', FALSE); } -if(!defined('DEBUG_LEVEL')) { +if (!defined('DEBUG_LEVEL')) { /** * Debug level 1 is less noisy and 3 is the most noisy * */ - define ('DEBUG_LEVEL', 1); + define('DEBUG_LEVEL', 1); } -if(!defined('DISPLAY_ERROR_MESSAGES')) { +if (!defined('DISPLAY_ERROR_MESSAGES')) { /** * Display error messages. Set to false to turn off errors (good for production websites) */ - define ('DISPLAY_ERROR_MESSAGES', FALSE); + define('DISPLAY_ERROR_MESSAGES', FALSE); } -if(!defined('ALLOW_EXTERNAL')) { +if (!defined('ALLOW_EXTERNAL')) { /** * Allow image fetching from external websites. Will check against ALLOWED_SITES always. * */ - define ('ALLOW_EXTERNAL', FALSE); + define('ALLOW_EXTERNAL', FALSE); } -if(!isset($ALLOWED_SITES)) { +if (!isset($ALLOWED_SITES)) { /** * If ALLOW_EXTERNAL is true then external images will only be fetched from these domains and their subdomains. */ @@ -98,159 +98,159 @@ ); } -if(!defined('FILE_CACHE_ENABLED')) { +if (!defined('FILE_CACHE_ENABLED')) { /** * Should we store resized/modified images on disk to speed things up? */ - define ('FILE_CACHE_ENABLED', TRUE); + define('FILE_CACHE_ENABLED', TRUE); } -if(!defined('DAY_IN_SECONDS')) { +if (!defined('DAY_IN_SECONDS')) { define('DAY_IN_SECONDS', 24 * 60 * 60); } -if(!defined('FILE_CACHE_TIME_BETWEEN_CLEANS')) { +if (!defined('FILE_CACHE_TIME_BETWEEN_CLEANS')) { /** * How often the cache is cleaned */ - define ('FILE_CACHE_TIME_BETWEEN_CLEANS', DAY_IN_SECONDS * 30); + define('FILE_CACHE_TIME_BETWEEN_CLEANS', DAY_IN_SECONDS * 30); } -if(!defined('FILE_CACHE_MAX_FILE_AGE')) { +if (!defined('FILE_CACHE_MAX_FILE_AGE')) { /** * How old does a file have to be to be deleted from the cache */ - define ('FILE_CACHE_MAX_FILE_AGE', DAY_IN_SECONDS * 60); + define('FILE_CACHE_MAX_FILE_AGE', DAY_IN_SECONDS * 60); } -if(!defined('FILE_CACHE_SUFFIX')) { +if (!defined('FILE_CACHE_SUFFIX')) { /** * What to put at the end of all files in the cache directory so we can identify them */ - define ('FILE_CACHE_SUFFIX', '.txt'); + define('FILE_CACHE_SUFFIX', '.txt'); } -if(!defined('FILE_CACHE_PREFIX')) { +if (!defined('FILE_CACHE_PREFIX')) { /** * What to put at the beg of all files in the cache directory so we can identify them */ - define ('FILE_CACHE_PREFIX', 'mthumb'); + define('FILE_CACHE_PREFIX', 'mthumb'); } -if(!defined('FILE_CACHE_DIRECTORY')) { +if (!defined('FILE_CACHE_DIRECTORY')) { /** * Directory where images are cached. Left blank it will use the system temporary directory (which is better for security) * */ //define ('FILE_CACHE_DIRECTORY', './cache'); - define ('FILE_CACHE_DIRECTORY', FALSE); // @todo test on more deployments + define('FILE_CACHE_DIRECTORY', FALSE); // @todo test on more deployments } -if(!defined('TEN_MB_IN_BTYES')) { - define ('TEN_MB_IN_BTYES', 10485760); +if (!defined('TEN_MB_IN_BTYES')) { + define('TEN_MB_IN_BTYES', 10485760); } // -if(!defined('MAX_FILE_SIZE')) { +if (!defined('MAX_FILE_SIZE')) { /** * This is the max internal or external file size that we'll process. */ - define ('MAX_FILE_SIZE', TEN_MB_IN_BTYES * 2); + define('MAX_FILE_SIZE', TEN_MB_IN_BTYES * 2); } -if(!defined('CURL_TIMEOUT')) { +if (!defined('CURL_TIMEOUT')) { /** * Timeout duration for Curl. This only applies if you have Curl installed and aren't using PHP's default URL fetching mechanism. * */ - define ('CURL_TIMEOUT', 20); + define('CURL_TIMEOUT', 20); } -if(!defined('WAIT_BETWEEN_FETCH_ERRORS')) { +if (!defined('WAIT_BETWEEN_FETCH_ERRORS')) { /** * Time to wait between errors fetching remote file */ - define ('WAIT_BETWEEN_FETCH_ERRORS', 3600); + define('WAIT_BETWEEN_FETCH_ERRORS', 3600); } -if(!defined('BROWSER_CACHE_MAX_AGE')) { +if (!defined('BROWSER_CACHE_MAX_AGE')) { /** * Time to cache in the browser * */ - define ('BROWSER_CACHE_MAX_AGE', DAY_IN_SECONDS * 30); + define('BROWSER_CACHE_MAX_AGE', DAY_IN_SECONDS * 30); } -if(!defined('BROWSER_CACHE_DISABLE')) { +if (!defined('BROWSER_CACHE_DISABLE')) { /** * Use for testing if you want to disable all browser caching */ - define ('BROWSER_CACHE_DISABLE', FALSE); + define('BROWSER_CACHE_DISABLE', FALSE); } -if(!defined('MAX_WIDTH')) { - define ('MAX_WIDTH', 3200); +if (!defined('MAX_WIDTH')) { + define('MAX_WIDTH', 3200); } -if(!defined('MAX_HEIGHT')) { - define ('MAX_HEIGHT', 3200); +if (!defined('MAX_HEIGHT')) { + define('MAX_HEIGHT', 3200); } -if(!defined('PNG_IS_TRANSPARENT')) { +if (!defined('PNG_IS_TRANSPARENT')) { /** * Define if a png image should have a transparent background color. Use False value if you want to display a custom coloured canvas_colour * */ - define ('PNG_IS_TRANSPARENT', TRUE); + define('PNG_IS_TRANSPARENT', TRUE); } -if(!defined('DEFAULT_Q')) { +if (!defined('DEFAULT_Q')) { /** * Default image quality. Allows override in mthumb-config.php * */ - define ('DEFAULT_Q', 85); + define('DEFAULT_Q', 85); } -if(!defined('DEFAULT_ZC')) { +if (!defined('DEFAULT_ZC')) { /** * Default zoom/crop setting. Allows override in mthumb-config.php */ - define ('DEFAULT_ZC', 1); + define('DEFAULT_ZC', 1); } -if(!defined('DEFAULT_F')) { +if (!defined('DEFAULT_F')) { /** * Default image filters. Allows override in mthumb-config.php */ - define ('DEFAULT_F', ''); + define('DEFAULT_F', ''); } // -if(!defined('DEFAULT_S')) { +if (!defined('DEFAULT_S')) { /** * Default sharpen value. Allows override in mthumb-config.php */ - define ('DEFAULT_S', 0); + define('DEFAULT_S', 0); } -if(!defined('DEFAULT_CC')) { +if (!defined('DEFAULT_CC')) { /** * Default canvas colour. Allows override in mthumb-config.php */ - define ('DEFAULT_CC', 'ffffff'); + define('DEFAULT_CC', 'ffffff'); } -if(!defined('DEFAULT_WIDTH')) { +if (!defined('DEFAULT_WIDTH')) { /** * Default thumbnail width. Allows override in mthumb-config.php */ - define ('DEFAULT_WIDTH', 125); + define('DEFAULT_WIDTH', 125); } -if(!defined('DEFAULT_HEIGHT')) { +if (!defined('DEFAULT_HEIGHT')) { /** * Default thumbnail height. Allows override in mthumb-config.php */ - define ('DEFAULT_HEIGHT', 125); + define('DEFAULT_HEIGHT', 125); } /** @@ -258,38 +258,39 @@ * LOCAL_FILE_BASE_DIRECTORY = Override the DOCUMENT_ROOT. This is best used in mthumb-config.php */ -if(!defined('OPTIPNG_ENABLED')) { +if (!defined('OPTIPNG_ENABLED')) { /** * Image compression is enabled if either of these point to valid paths. They only work for PNGs. GIFs and JPEGs are not affected. */ - define ('OPTIPNG_ENABLED', TRUE); + define('OPTIPNG_ENABLED', TRUE); } -if(!defined('OPTIPNG_PATH')) { +if (!defined('OPTIPNG_PATH')) { /** * This will run first because it gives better compression than pngcrush. * */ - define ('OPTIPNG_PATH', '/usr/bin/optipng'); + define('OPTIPNG_PATH', '/usr/bin/optipng'); } -if(!defined('PNGCRUSH_ENABLED')) { - define ('PNGCRUSH_ENABLED', TRUE); +if (!defined('PNGCRUSH_ENABLED')) { + define('PNGCRUSH_ENABLED', TRUE); } -if(!defined('PNGCRUSH_PATH')) { +if (!defined('PNGCRUSH_PATH')) { /** * This will only run if OPTIPNG_PATH is not set or is not valid */ - define ('PNGCRUSH_PATH', '/usr/bin/pngcrush'); + define('PNGCRUSH_PATH', '/usr/bin/pngcrush'); } // -------------- STOP EDITING CONFIGURATION HERE -------------- -if(!class_exists('mthumb')) : /** +if (!class_exists('mthumb')) : /** * Class mthumb */ { class mthumb { + /** * @var mixed|string */ @@ -387,11 +388,11 @@ public static function start() { $mthumb = new mthumb(); $mthumb->handleErrors(); - if($mthumb->tryBrowserCache()) { + if ($mthumb->tryBrowserCache()) { exit(0); } $mthumb->handleErrors(); - if(FILE_CACHE_ENABLED && $mthumb->tryServerCache()) { + if (FILE_CACHE_ENABLED && $mthumb->tryServerCache()) { exit(0); } $mthumb->handleErrors(); @@ -407,22 +408,22 @@ public function __construct() { global $ALLOWED_SITES; $this->startTime = microtime(TRUE); date_default_timezone_set('UTC'); - $this->debug(1, "Starting new request from ".$this->getIP()." to ".$_SERVER['REQUEST_URI']); + $this->debug(1, "Starting new request from " . $this->getIP() . " to " . $_SERVER[ 'REQUEST_URI' ]); $this->calcDocRoot(); //On windows systems I'm assuming fileinode returns an empty string or a number that doesn't change. Check this. - $this->salt = @filemtime(__FILE__).'-'.@fileinode(__FILE__); - $this->debug(3, "Salt is: ".$this->salt); - if(FILE_CACHE_DIRECTORY) { - if(!is_dir(FILE_CACHE_DIRECTORY)) { + $this->salt = @filemtime(__FILE__) . '-' . @fileinode(__FILE__); + $this->debug(3, "Salt is: " . $this->salt); + if (FILE_CACHE_DIRECTORY) { + if (!is_dir(FILE_CACHE_DIRECTORY)) { @mkdir(FILE_CACHE_DIRECTORY); - if(!is_dir(FILE_CACHE_DIRECTORY)) { + if (!is_dir(FILE_CACHE_DIRECTORY)) { $this->error("Could not create the file cache directory."); return FALSE; } } $this->cacheDirectory = FILE_CACHE_DIRECTORY; - if(!touch($this->cacheDirectory.'/index.html')) { + if (!touch($this->cacheDirectory . '/index.html')) { $this->error("Could not create the index.html file - to fix this create an empty file named index.html file in the cache directory."); } } else { @@ -431,15 +432,15 @@ public function __construct() { // Clean the cache before we do anything because we don't want the first visitor after FILE_CACHE_TIME_BETWEEN_CLEANS expires to get a stale image. $this->cleanCache(); - $this->myHost = preg_replace('/^www\./i', '', $_SERVER['HTTP_HOST']); + $this->myHost = preg_replace('/^www\./i', '', $_SERVER[ 'HTTP_HOST' ]); // start mindshare fix for tilde's, check if tilde is found in src - if(strstr($this->param('src'), '~')) { + if (strstr($this->param('src'), '~')) { $url_parts = explode('/', $this->param('src')); - foreach($url_parts as $url_part) { + foreach ($url_parts as $url_part) { //do not include any part with a ~ when building new url - if(!strstr($url_part, '~')) { - $new_dev_url .= $url_part.'/'; + if (!strstr($url_part, '~')) { + $new_dev_url .= $url_part . '/'; } } //remove trailing slash @@ -450,63 +451,63 @@ public function __construct() { } // end mindshare fix for tilde's $this->url = parse_url($this->src); - $this->src = preg_replace('/https?:\/\/(?:www\.)?'.$this->myHost.'/i', '', $this->src); + $this->src = preg_replace('/https?:\/\/(?:www\.)?' . $this->myHost . '/i', '', $this->src); - if(strlen($this->src) <= 3) { + if (strlen($this->src) <= 3) { $this->error("No image specified"); return FALSE; } // Always block external sites from using this script - if(array_key_exists('HTTP_REFERER', $_SERVER) && (!preg_match('/^https?:\/\/(?:www\.)?'.$this->myHost.'(?:$|\/)/i', $_SERVER['HTTP_REFERER']))) { + if (array_key_exists('HTTP_REFERER', $_SERVER) && (!preg_match('/^https?:\/\/(?:www\.)?' . $this->myHost . '(?:$|\/)/i', $_SERVER[ 'HTTP_REFERER' ]))) { // base64 encoded red image that says 'no hotlinkers' nothing to worry about! :) $imgData = base64_decode("R0lGODlhUAAMAIAAAP8AAP///yH5BAAHAP8ALAAAAABQAAwAAAJpjI+py+0Po5y0OgAMjjv01YUZ\nOGplhWXfNa6JCLnWkXplrcBmW+spbwvaVr/cDyg7IoFC2KbYVC2NQ5MQ4ZNao9Ynzjl9ScNYpneb\nDULB3RP6JuPuaGfuuV4fumf8PuvqFyhYtjdoeFgAADs="); header('Content-Type: image/gif'); - header('Content-Length: '.strlen($imgData)); + header('Content-Length: ' . strlen($imgData)); header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); header("Pragma: no-cache"); - header('Expires: '.gmdate('D, d M Y H:i:s', time())); + header('Expires: ' . gmdate('D, d M Y H:i:s', time())); echo $imgData; return FALSE; exit(0); } - if(preg_match('/^https?:\/\/[^\/]+/i', $this->src)) { - $this->debug(2, "Is a request for an external URL: ".$this->src); + if (preg_match('/^https?:\/\/[^\/]+/i', $this->src)) { + $this->debug(2, "Is a request for an external URL: " . $this->src); $this->isURL = TRUE; } else { - $this->debug(2, "Is a request for an internal file: ".$this->src); + $this->debug(2, "Is a request for an internal file: " . $this->src); } - if($this->isURL && (!ALLOW_EXTERNAL)) { + if ($this->isURL && (!ALLOW_EXTERNAL)) { $this->error("You are not allowed to fetch images from an external website."); return FALSE; } - if($this->isURL) { + if ($this->isURL) { $this->debug(2, "Fetching only from selected external sites is enabled."); $allowed = FALSE; - foreach($ALLOWED_SITES as $site) { - if((strtolower(substr($this->url['host'], -strlen($site) - 1)) === strtolower(".$site")) || (strtolower($this->url['host']) === strtolower($site))) { + foreach ($ALLOWED_SITES as $site) { + if ((strtolower(substr($this->url[ 'host' ], -strlen($site) - 1)) === strtolower(".$site")) || (strtolower($this->url[ 'host' ]) === strtolower($site))) { $this->debug(3, "URL hostname {$this->url['host']} matches $site so allowing."); $allowed = TRUE; } } - if(!$allowed) { + if (!$allowed) { return $this->error("You may not fetch images from that site. To enable this site in mthumb, you can either add it to \$ALLOWED_SITES and set ALLOW_EXTERNAL=true."); } } $cachePrefix = ($this->isURL ? '_ext_' : '_int_'); - if($this->isURL) { - $arr = explode('&', $_SERVER ['QUERY_STRING']); + if ($this->isURL) { + $arr = explode('&', $_SERVER [ 'QUERY_STRING' ]); asort($arr); - $this->cachefile = $this->cacheDirectory.'/'.FILE_CACHE_PREFIX.$cachePrefix.md5($this->salt.implode('', $arr).$this->fileCacheVersion).FILE_CACHE_SUFFIX; + $this->cachefile = $this->cacheDirectory . '/' . FILE_CACHE_PREFIX . $cachePrefix . md5($this->salt . implode('', $arr) . $this->fileCacheVersion) . FILE_CACHE_SUFFIX; } else { $this->localImage = $this->getLocalImagePath($this->src); - if(!$this->localImage) { + if (!$this->localImage) { $this->debug(1, "Could not find the local image: {$this->localImage}"); $this->error("Could not find the internal image you specified."); $this->set404(); @@ -516,9 +517,9 @@ public function __construct() { $this->debug(1, "Local image path is {$this->localImage}"); $this->localImageMTime = @filemtime($this->localImage); //We include the mtime of the local file in case in changes on disk. - $this->cachefile = $this->cacheDirectory.'/'.FILE_CACHE_PREFIX.$cachePrefix.md5($this->salt.$this->localImageMTime.$_SERVER ['QUERY_STRING'].$this->fileCacheVersion).FILE_CACHE_SUFFIX; + $this->cachefile = $this->cacheDirectory . '/' . FILE_CACHE_PREFIX . $cachePrefix . md5($this->salt . $this->localImageMTime . $_SERVER [ 'QUERY_STRING' ] . $this->fileCacheVersion) . FILE_CACHE_SUFFIX; } - $this->debug(2, "Cache file is: ".$this->cachefile); + $this->debug(2, "Cache file is: " . $this->cachefile); return TRUE; } @@ -527,7 +528,7 @@ public function __construct() { * */ public function __destruct() { - foreach($this->toDeletes as $del) { + foreach ($this->toDeletes as $del) { $this->debug(2, "Deleting temp file $del"); @unlink($del); } @@ -537,8 +538,8 @@ public function __destruct() { * @return bool */ public function run() { - if($this->isURL) { - if(!ALLOW_EXTERNAL) { + if ($this->isURL) { + if (!ALLOW_EXTERNAL) { $this->debug(1, "Got a request for an external image but ALLOW_EXTERNAL is disabled so returning error msg."); $this->error("You are not allowed to fetch images from an external website."); @@ -558,7 +559,7 @@ public function run() { * @return bool */ protected function handleErrors() { - if($this->haveErrors()) { + if ($this->haveErrors()) { $this->serveErrors(); exit(0); } @@ -570,47 +571,47 @@ protected function handleErrors() { * @return bool */ protected function tryBrowserCache() { - if(BROWSER_CACHE_DISABLE) { + if (BROWSER_CACHE_DISABLE) { $this->debug(3, "Browser caching is disabled"); return FALSE; } - if(!empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { + if (!empty($_SERVER[ 'HTTP_IF_MODIFIED_SINCE' ])) { $this->debug(3, "Got a conditional get"); $mtime = FALSE; //We've already checked if the real file exists in the constructor - if(!is_file($this->cachefile)) { + if (!is_file($this->cachefile)) { //If we don't have something cached, regenerate the cached image. return FALSE; } - if($this->localImageMTime) { + if ($this->localImageMTime) { $mtime = $this->localImageMTime; $this->debug(3, "Local real file's modification time is $mtime"); } else { - if(is_file($this->cachefile)) { //If it's not a local request then use the mtime of the cached file to determine the 304 + if (is_file($this->cachefile)) { //If it's not a local request then use the mtime of the cached file to determine the 304 $mtime = @filemtime($this->cachefile); $this->debug(3, "Cached file's modification time is $mtime"); } } - if(!$mtime) { + if (!$mtime) { return FALSE; } - $iftime = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']); + $iftime = strtotime($_SERVER[ 'HTTP_IF_MODIFIED_SINCE' ]); $this->debug(3, "The conditional get's if-modified-since unixtime is $iftime"); - if($iftime < 1) { + if ($iftime < 1) { $this->debug(3, "Got an invalid conditional get modified since time. Returning false."); return FALSE; } // Real file or cache file has been modified since last request, so force refetch. - if($iftime < $mtime) { + if ($iftime < $mtime) { $this->debug(3, "File has been modified since last fetch."); return FALSE; } else { //Otherwise serve a 304 $this->debug(3, "File has not been modified since last get, so serving a 304."); - header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified'); + header($_SERVER[ 'SERVER_PROTOCOL' ] . ' 304 Not Modified'); $this->debug(1, "Returning 304 not modified"); return TRUE; @@ -625,15 +626,15 @@ protected function tryBrowserCache() { */ protected function tryServerCache() { $this->debug(3, "Trying server cache"); - if(file_exists($this->cachefile)) { + if (file_exists($this->cachefile)) { $this->debug(3, "Cachefile {$this->cachefile} exists"); - if($this->isURL) { + if ($this->isURL) { $this->debug(3, "This is an external request, so checking if the cachefile is empty which means the request failed previously."); - if(filesize($this->cachefile) < 1) { + if (filesize($this->cachefile) < 1) { $this->debug(3, "Found an empty cachefile indicating a failed earlier request. Checking how old it is."); //Fetching error occured previously - if(time() - @filemtime($this->cachefile) > WAIT_BETWEEN_FETCH_ERRORS) { - $this->debug(3, "File is older than ".WAIT_BETWEEN_FETCH_ERRORS." seconds. Deleting and returning false so app can try and load file."); + if (time() - @filemtime($this->cachefile) > WAIT_BETWEEN_FETCH_ERRORS) { + $this->debug(3, "File is older than " . WAIT_BETWEEN_FETCH_ERRORS . " seconds. Deleting and returning false so app can try and load file."); @unlink($this->cachefile); return FALSE; //to indicate we didn't serve from cache and app should try and load @@ -648,7 +649,7 @@ protected function tryServerCache() { } else { $this->debug(3, "Trying to serve cachefile {$this->cachefile}"); } - if($this->serveCacheFile()) { + if ($this->serveCacheFile()) { $this->debug(3, "Succesfully served cachefile {$this->cachefile}"); return TRUE; @@ -678,7 +679,7 @@ protected function error($err) { * @return bool */ protected function haveErrors() { - if(sizeof($this->errors) > 0) { + if (sizeof($this->errors) > 0) { return TRUE; } @@ -689,17 +690,17 @@ protected function haveErrors() { * */ protected function serveErrors() { - if(!DISPLAY_ERROR_MESSAGES) { + if (!DISPLAY_ERROR_MESSAGES) { return; } - header($_SERVER['SERVER_PROTOCOL'].' 400 Bad Request'); + header($_SERVER[ 'SERVER_PROTOCOL' ] . ' 400 Bad Request'); $html = ''; - echo '

An error has occured

The following error(s) occured:
'.$html.'
'; - echo '
Query String: '.htmlentities($_SERVER['QUERY_STRING'], ENT_QUOTES); + echo '

An error has occured

The following error(s) occured:
' . $html . '
'; + echo '
Query String: ' . htmlentities($_SERVER[ 'QUERY_STRING' ], ENT_QUOTES); } /** @@ -707,24 +708,24 @@ protected function serveErrors() { */ protected function serveInternalImage() { $this->debug(3, "Local image path is $this->localImage"); - if(!$this->localImage) { + if (!$this->localImage) { $this->sanityFail("localImage not set after verifying it earlier in the code."); return FALSE; } $fileSize = filesize($this->localImage); - if($fileSize > MAX_FILE_SIZE) { + if ($fileSize > MAX_FILE_SIZE) { $this->error("The file you specified is greater than the maximum allowed file size."); return FALSE; } - if($fileSize <= 0) { + if ($fileSize <= 0) { $this->error("The file you specified is <= 0 bytes."); return FALSE; } $this->debug(3, "Calling processImageAndWriteToCache() for local image."); - if($this->processImageAndWriteToCache($this->localImage)) { + if ($this->processImageAndWriteToCache($this->localImage)) { $this->serveCacheFile(); return TRUE; @@ -737,7 +738,7 @@ protected function serveInternalImage() { * @return bool */ protected function serveExternalImage() { - if(!preg_match('/^https?:\/\/[a-zA-Z0-9\-\.]+/i', $this->src)) { + if (!preg_match('/^https?:\/\/[a-zA-Z0-9\-\.]+/i', $this->src)) { $this->error("Invalid URL supplied."); return FALSE; @@ -746,25 +747,25 @@ protected function serveExternalImage() { $this->debug(3, "Fetching external image into temporary file $tempfile"); $this->toDelete($tempfile); // fetch file here - if(!$this->getURL($this->src, $tempfile)) { + if (!$this->getURL($this->src, $tempfile)) { @unlink($this->cachefile); touch($this->cachefile); - $this->debug(3, "Error fetching URL: ".$this->lastURLError); - $this->error("Error reading the URL you specified from remote host.".$this->lastURLError); + $this->debug(3, "Error fetching URL: " . $this->lastURLError); + $this->error("Error reading the URL you specified from remote host." . $this->lastURLError); return FALSE; } $mimeType = $this->getMimeType($tempfile); - if(!preg_match("/^image\/(?:jpg|jpeg|gif|png)$/i", $mimeType)) { + if (!preg_match("/^image\/(?:jpg|jpeg|gif|png)$/i", $mimeType)) { $this->debug(3, "Remote file has invalid mime type: $mimeType"); @unlink($this->cachefile); touch($this->cachefile); - $this->error("The remote file is not a valid image. Mimetype = '".$mimeType."'".$tempfile); + $this->error("The remote file is not a valid image. Mimetype = '" . $mimeType . "'" . $tempfile); return FALSE; } - if($this->processImageAndWriteToCache($tempfile)) { + if ($this->processImageAndWriteToCache($tempfile)) { $this->debug(3, "Image processed succesfully. Serving from cache"); return $this->serveCacheFile(); @@ -777,33 +778,37 @@ protected function serveExternalImage() { * @return bool */ protected function cleanCache() { - if(FILE_CACHE_TIME_BETWEEN_CLEANS < 0) { + if (FILE_CACHE_TIME_BETWEEN_CLEANS < 0) { return; } $this->debug(3, "cleanCache() called"); - $lastCleanFile = $this->cacheDirectory.'/mthumb_cacheLastCleanTime.touch'; + $lastCleanFile = $this->cacheDirectory . '/mthumb_cacheLastCleanTime.touch'; + // If the cache dir isn't writable, exit + if (!is_writable($lastCleanFile)) { + return; + } //If this is a new mthumb installation we need to create the file - if(!is_file($lastCleanFile)) { + if (!is_file($lastCleanFile)) { $this->debug(1, "File tracking last clean doesn't exist. Creating $lastCleanFile"); - if(!touch($lastCleanFile)) { + if (!touch($lastCleanFile)) { $this->error("Could not create cache clean timestamp file."); } return; } - if(@filemtime($lastCleanFile) < (time() - FILE_CACHE_TIME_BETWEEN_CLEANS)) { //Cache was last cleaned more than 1 day ago - $this->debug(1, "Cache was last cleaned more than ".FILE_CACHE_TIME_BETWEEN_CLEANS." seconds ago. Cleaning now."); + if (@filemtime($lastCleanFile) < (time() - FILE_CACHE_TIME_BETWEEN_CLEANS)) { //Cache was last cleaned more than 1 day ago + $this->debug(1, "Cache was last cleaned more than " . FILE_CACHE_TIME_BETWEEN_CLEANS . " seconds ago. Cleaning now."); // Very slight race condition here, but worst case we'll have 2 or 3 servers cleaning the cache simultaneously once a day. - if(!touch($lastCleanFile)) { + if (!touch($lastCleanFile)) { $this->error("Could not create cache clean timestamp file."); } - $files = glob($this->cacheDirectory.'/*'.FILE_CACHE_SUFFIX); - if($files) { + $files = glob($this->cacheDirectory . '/*' . FILE_CACHE_SUFFIX); + if ($files) { $timeAgo = time() - FILE_CACHE_MAX_FILE_AGE; - foreach($files as $file) { - if(@filemtime($file) < $timeAgo) { - $this->debug(3, "Deleting cache file $file older than max age: ".FILE_CACHE_MAX_FILE_AGE." seconds"); + foreach ($files as $file) { + if (@filemtime($file) < $timeAgo) { + $this->debug(3, "Deleting cache file $file older than max age: " . FILE_CACHE_MAX_FILE_AGE . " seconds"); @unlink($file); } } @@ -811,7 +816,7 @@ protected function cleanCache() { return TRUE; } else { - $this->debug(3, "Cache was cleaned less than ".FILE_CACHE_TIME_BETWEEN_CLEANS." seconds ago so no cleaning needed."); + $this->debug(3, "Cache was cleaned less than " . FILE_CACHE_TIME_BETWEEN_CLEANS . " seconds ago so no cleaning needed."); } return FALSE; @@ -824,19 +829,19 @@ protected function cleanCache() { */ protected function processImageAndWriteToCache($localImage) { $sData = getimagesize($localImage); - $origType = $sData[2]; - $mimeType = $sData['mime']; + $origType = $sData[ 2 ]; + $mimeType = $sData[ 'mime' ]; $this->debug(3, "Mime type of image is $mimeType"); - if(!preg_match('/^image\/(?:gif|jpg|jpeg|png)$/i', $mimeType)) { + if (!preg_match('/^image\/(?:gif|jpg|jpeg|png)$/i', $mimeType)) { return $this->error("The image being resized is not a valid gif, jpg or png."); } - if(!function_exists('imagecreatetruecolor')) { + if (!function_exists('imagecreatetruecolor')) { return $this->error('GD Library Error: imagecreatetruecolor does not exist - please contact your webhost and ask them to install the GD library'); } - if(function_exists('imagefilter') && defined('IMG_FILTER_NEGATE')) { + if (function_exists('imagefilter') && defined('IMG_FILTER_NEGATE')) { $imageFilters = array( 1 => array(IMG_FILTER_NEGATE, 0), 2 => array(IMG_FILTER_GRAYSCALE, 0), @@ -864,7 +869,7 @@ protected function processImageAndWriteToCache($localImage) { $canvas_trans = (bool) $this->param('ct', '1'); // set default width and height if neither are set already - if($new_width == 0 && $new_height == 0) { + if ($new_width == 0 && $new_height == 0) { $new_width = (int) DEFAULT_WIDTH; $new_height = (int) DEFAULT_HEIGHT; } @@ -875,7 +880,7 @@ protected function processImageAndWriteToCache($localImage) { // open the existing image $image = $this->openImage($mimeType, $localImage); - if($image === FALSE) { + if ($image === FALSE) { return $this->error('Unable to open image.'); } @@ -886,20 +891,20 @@ protected function processImageAndWriteToCache($localImage) { $origin_y = 0; // generate new w/h if not provided - if($new_width && !$new_height) { + if ($new_width && !$new_height) { $new_height = floor($height * ($new_width / $width)); } else { - if($new_height && !$new_width) { + if ($new_height && !$new_width) { $new_width = floor($width * ($new_height / $height)); } } // scale down and add borders - if($zoom_crop == 3) { + if ($zoom_crop == 3) { $final_height = $height * ($new_width / $width); - if($final_height > $new_height) { + if ($final_height > $new_height) { $new_width = $width * ($new_height / $height); } else { $new_height = $final_height; @@ -910,10 +915,10 @@ protected function processImageAndWriteToCache($localImage) { $canvas = imagecreatetruecolor($new_width, $new_height); imagealphablending($canvas, FALSE); - if(strlen($canvas_color) == 3) { //if is 3-char notation, edit string into 6-char notation - $canvas_color = str_repeat(substr($canvas_color, 0, 1), 2).str_repeat(substr($canvas_color, 1, 1), 2).str_repeat(substr($canvas_color, 2, 1), 2); + if (strlen($canvas_color) == 3) { //if is 3-char notation, edit string into 6-char notation + $canvas_color = str_repeat(substr($canvas_color, 0, 1), 2) . str_repeat(substr($canvas_color, 1, 1), 2) . str_repeat(substr($canvas_color, 2, 1), 2); } else { - if(strlen($canvas_color) != 6) { + if (strlen($canvas_color) != 6) { $canvas_color = DEFAULT_CC; // on error return default canvas color } } @@ -925,7 +930,7 @@ protected function processImageAndWriteToCache($localImage) { // Create a new transparent color for image // If is a png and PNG_IS_TRANSPARENT is false then remove the alpha transparency // (and if is set a canvas color show it in the background) - if(preg_match('/^image\/png$/i', $mimeType) && !PNG_IS_TRANSPARENT && $canvas_trans) { + if (preg_match('/^image\/png$/i', $mimeType) && !PNG_IS_TRANSPARENT && $canvas_trans) { $color = imagecolorallocatealpha($canvas, $canvas_color_R, $canvas_color_G, $canvas_color_B, 127); } else { $color = imagecolorallocatealpha($canvas, $canvas_color_R, $canvas_color_G, $canvas_color_B, 0); @@ -935,11 +940,11 @@ protected function processImageAndWriteToCache($localImage) { imagefill($canvas, 0, 0, $color); // scale down and add borders - if($zoom_crop == 2) { + if ($zoom_crop == 2) { $final_height = $height * ($new_width / $width); - if($final_height > $new_height) { + if ($final_height > $new_height) { $origin_x = $new_width / 2; $new_width = $width * ($new_height / $height); @@ -955,7 +960,7 @@ protected function processImageAndWriteToCache($localImage) { // Restore transparency blending imagesavealpha($canvas, TRUE); - if($zoom_crop > 0) { + if ($zoom_crop > 0) { $src_x = $src_y = 0; $src_w = $width; @@ -965,12 +970,12 @@ protected function processImageAndWriteToCache($localImage) { $cmp_y = $height / $new_height; // calculate x or y coordinate and width or height of source - if($cmp_x > $cmp_y) { + if ($cmp_x > $cmp_y) { $src_w = round($width / $cmp_x * $cmp_y); $src_x = round(($width - ($width / $cmp_x * $cmp_y)) / 2); } else { - if($cmp_y > $cmp_x) { + if ($cmp_y > $cmp_x) { $src_h = round($height / $cmp_y * $cmp_x); $src_y = round(($height - ($height / $cmp_y * $cmp_x)) / 2); @@ -978,17 +983,17 @@ protected function processImageAndWriteToCache($localImage) { } // positional cropping! - if($align) { - if(strpos($align, 't') !== FALSE) { + if ($align) { + if (strpos($align, 't') !== FALSE) { $src_y = 0; } - if(strpos($align, 'b') !== FALSE) { + if (strpos($align, 'b') !== FALSE) { $src_y = $height - $src_h; } - if(strpos($align, 'l') !== FALSE) { + if (strpos($align, 'l') !== FALSE) { $src_x = 0; } - if(strpos($align, 'r') !== FALSE) { + if (strpos($align, 'r') !== FALSE) { $src_x = $width - $src_w; } } @@ -1000,47 +1005,47 @@ protected function processImageAndWriteToCache($localImage) { imagecopyresampled($canvas, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height); } - if($filters != '' && function_exists('imagefilter') && defined('IMG_FILTER_NEGATE')) { + if ($filters != '' && function_exists('imagefilter') && defined('IMG_FILTER_NEGATE')) { // apply filters to image $filterList = explode('|', $filters); - foreach($filterList as $fl) { + foreach ($filterList as $fl) { $filterSettings = explode(',', $fl); - if(isset ($imageFilters[$filterSettings[0]])) { + if (isset ($imageFilters[ $filterSettings[ 0 ] ])) { - for($i = 0; $i < 4; $i++) { - if(!isset ($filterSettings[$i])) { - $filterSettings[$i] = NULL; + for ($i = 0; $i < 4; $i++) { + if (!isset ($filterSettings[ $i ])) { + $filterSettings[ $i ] = NULL; } else { - $filterSettings[$i] = (int) $filterSettings[$i]; + $filterSettings[ $i ] = (int) $filterSettings[ $i ]; } } - switch($imageFilters[$filterSettings[0]][1]) { + switch ($imageFilters[ $filterSettings[ 0 ] ][ 1 ]) { case 1: - imagefilter($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1]); + imagefilter($canvas, $imageFilters[ $filterSettings[ 0 ] ][ 0 ], $filterSettings[ 1 ]); break; case 2: - imagefilter($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2]); + imagefilter($canvas, $imageFilters[ $filterSettings[ 0 ] ][ 0 ], $filterSettings[ 1 ], $filterSettings[ 2 ]); break; case 3: - imagefilter($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2], $filterSettings[3]); + imagefilter($canvas, $imageFilters[ $filterSettings[ 0 ] ][ 0 ], $filterSettings[ 1 ], $filterSettings[ 2 ], $filterSettings[ 3 ]); break; case 4: - imagefilter($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2], $filterSettings[3], $filterSettings[4]); + imagefilter($canvas, $imageFilters[ $filterSettings[ 0 ] ][ 0 ], $filterSettings[ 1 ], $filterSettings[ 2 ], $filterSettings[ 3 ], $filterSettings[ 4 ]); break; default: - imagefilter($canvas, $imageFilters[$filterSettings[0]][0]); + imagefilter($canvas, $imageFilters[ $filterSettings[ 0 ] ][ 0 ]); break; } } @@ -1048,7 +1053,7 @@ protected function processImageAndWriteToCache($localImage) { } // sharpen image - if($sharpen && function_exists('imageconvolution')) { + if ($sharpen && function_exists('imageconvolution')) { $sharpenMatrix = array( array(-1, -1, -1), @@ -1062,20 +1067,20 @@ protected function processImageAndWriteToCache($localImage) { imageconvolution($canvas, $sharpenMatrix, $divisor, $offset); } //Straight from Wordpress core code. Reduces filesize by up to 70% for PNG's - if((IMAGETYPE_PNG == $origType || IMAGETYPE_GIF == $origType) && function_exists('imageistruecolor') && !imageistruecolor($image) && imagecolortransparent($image) > 0) { + if ((IMAGETYPE_PNG == $origType || IMAGETYPE_GIF == $origType) && function_exists('imageistruecolor') && !imageistruecolor($image) && imagecolortransparent($image) > 0) { imagetruecolortopalette($canvas, FALSE, imagecolorstotal($image)); } $tempfile = tempnam($this->cacheDirectory, 'mthumb_tmpimg_'); - if(preg_match('/^image\/(?:jpg|jpeg)$/i', $mimeType)) { + if (preg_match('/^image\/(?:jpg|jpeg)$/i', $mimeType)) { $imgType = 'jpg'; imagejpeg($canvas, $tempfile, $quality); } else { - if(preg_match('/^image\/png$/i', $mimeType)) { + if (preg_match('/^image\/png$/i', $mimeType)) { $imgType = 'png'; imagepng($canvas, $tempfile, floor($quality * 0.09)); } else { - if(preg_match('/^image\/gif$/i', $mimeType)) { + if (preg_match('/^image\/gif$/i', $mimeType)) { $imgType = 'gif'; imagegif($canvas, $tempfile); } else { @@ -1084,7 +1089,7 @@ protected function processImageAndWriteToCache($localImage) { } } - if($imgType == 'png' && OPTIPNG_ENABLED && OPTIPNG_PATH && @is_file(OPTIPNG_PATH)) { + if ($imgType == 'png' && OPTIPNG_ENABLED && OPTIPNG_PATH && @is_file(OPTIPNG_PATH)) { $exec = OPTIPNG_PATH; $this->debug(3, "optipng'ing $tempfile"); $presize = filesize($tempfile); @@ -1092,25 +1097,25 @@ protected function processImageAndWriteToCache($localImage) { clearstatcache(); $aftersize = filesize($tempfile); $sizeDrop = $presize - $aftersize; - if($sizeDrop > 0) { + if ($sizeDrop > 0) { $this->debug(1, "optipng reduced size by $sizeDrop"); } else { - if($sizeDrop < 0) { + if ($sizeDrop < 0) { $this->debug(1, "optipng increased size! Difference was: $sizeDrop"); } else { $this->debug(1, "optipng did not change image size."); } } } else { - if($imgType == 'png' && PNGCRUSH_ENABLED && PNGCRUSH_PATH && @is_file(PNGCRUSH_PATH)) { + if ($imgType == 'png' && PNGCRUSH_ENABLED && PNGCRUSH_PATH && @is_file(PNGCRUSH_PATH)) { $exec = PNGCRUSH_PATH; $tempfile2 = tempnam($this->cacheDirectory, 'mthumb_tmpimg_'); $this->debug(3, "pngcrush'ing $tempfile to $tempfile2"); $out = `$exec $tempfile $tempfile2`; - if(is_file($tempfile2)) { + if (is_file($tempfile2)) { $sizeDrop = filesize($tempfile) - filesize($tempfile2); - if($sizeDrop > 0) { + if ($sizeDrop > 0) { $this->debug(1, "pngcrush was succesful and gave a $sizeDrop byte size reduction"); $todel = $tempfile; $tempfile = $tempfile2; @@ -1130,17 +1135,17 @@ protected function processImageAndWriteToCache($localImage) { $tempfile4 = tempnam($this->cacheDirectory, 'mthumb_tmpimg_'); $context = stream_context_create(); $fp = fopen($tempfile, 'r', 0, $context); - file_put_contents($tempfile4, $this->filePrependSecurityBlock.$imgType.' ?'.'>'); //6 extra bytes, first 3 being image type + file_put_contents($tempfile4, $this->filePrependSecurityBlock . $imgType . ' ?' . '>'); //6 extra bytes, first 3 being image type file_put_contents($tempfile4, $fp, FILE_APPEND); fclose($fp); @unlink($tempfile); $this->debug(3, "Locking and replacing cache file."); - $lockFile = $this->cachefile.'.lock'; + $lockFile = $this->cachefile . '.lock'; $fh = fopen($lockFile, 'w'); - if(!$fh) { + if (!$fh) { return $this->error("Could not open the lockfile for writing an image."); } - if(flock($fh, LOCK_EX)) { + if (flock($fh, LOCK_EX)) { @unlink($this->cachefile); //rename generally overwrites, but doing this in case of platform specific quirks. File might not exist yet. rename($tempfile4, $this->cachefile); flock($fh, LOCK_UN); @@ -1164,28 +1169,28 @@ protected function processImageAndWriteToCache($localImage) { * */ protected function calcDocRoot() { - $docRoot = @$_SERVER['DOCUMENT_ROOT']; - if(defined('LOCAL_FILE_BASE_DIRECTORY')) { + $docRoot = @$_SERVER[ 'DOCUMENT_ROOT' ]; + if (defined('LOCAL_FILE_BASE_DIRECTORY')) { $docRoot = LOCAL_FILE_BASE_DIRECTORY; } - if(!isset($docRoot)) { + if (!isset($docRoot)) { $this->debug(3, "DOCUMENT_ROOT is not set. This is probably windows. Starting search 1."); - if(isset($_SERVER['SCRIPT_FILENAME'])) { - $docRoot = str_replace('\\', '/', substr($_SERVER['SCRIPT_FILENAME'], 0, 0 - strlen($_SERVER['PHP_SELF']))); + if (isset($_SERVER[ 'SCRIPT_FILENAME' ])) { + $docRoot = str_replace('\\', '/', substr($_SERVER[ 'SCRIPT_FILENAME' ], 0, 0 - strlen($_SERVER[ 'PHP_SELF' ]))); $this->debug(3, "Generated docRoot using SCRIPT_FILENAME and PHP_SELF as: $docRoot"); } } - if(!isset($docRoot)) { + if (!isset($docRoot)) { $this->debug(3, "DOCUMENT_ROOT still is not set. Starting search 2."); - if(isset($_SERVER['PATH_TRANSLATED'])) { - $docRoot = str_replace('\\', '/', substr(str_replace('\\\\', '\\', $_SERVER['PATH_TRANSLATED']), 0, 0 - strlen($_SERVER['PHP_SELF']))); + if (isset($_SERVER[ 'PATH_TRANSLATED' ])) { + $docRoot = str_replace('\\', '/', substr(str_replace('\\\\', '\\', $_SERVER[ 'PATH_TRANSLATED' ]), 0, 0 - strlen($_SERVER[ 'PHP_SELF' ]))); $this->debug(3, "Generated docRoot using PATH_TRANSLATED and PHP_SELF as: $docRoot"); } } - if($docRoot && $_SERVER['DOCUMENT_ROOT'] != '/') { + if ($docRoot && $_SERVER[ 'DOCUMENT_ROOT' ] != '/') { $docRoot = preg_replace('/\/$/', '', $docRoot); } - $this->debug(3, "Doc root is: ".$docRoot); + $this->debug(3, "Doc root is: " . $docRoot); $this->docRoot = $docRoot; } @@ -1196,17 +1201,17 @@ protected function calcDocRoot() { */ protected function getLocalImagePath($src) { $src = ltrim($src, '/'); //strip off the leading '/' - if(!$this->docRoot) { + if (!$this->docRoot) { $this->debug(3, "We have no document root set, so as a last resort, lets check if the image is in the current dir and serve that."); //We don't support serving images outside the current dir if we don't have a doc root for security reasons. $file = preg_replace('/^.*?([^\/\\\\]+)$/', '$1', $src); //strip off any path info and just leave the filename. - if(is_file($file)) { + if (is_file($file)) { return $this->realpath($file); } return $this->error("Could not find your website document root and the file specified doesn't exist in mThumb's directory. We don't support serving files outside mThumb's directory without a document root for security reasons."); } else { - if(!is_dir($this->docRoot)) { + if (!is_dir($this->docRoot)) { $this->error("Server path does not exist. Ensure variable \$_SERVER['DOCUMENT_ROOT'] is set correctly"); } } @@ -1214,10 +1219,10 @@ protected function getLocalImagePath($src) { //Do not go past this point without docRoot set //Try src under docRoot - if(file_exists($this->docRoot.'/'.$src)) { - $this->debug(3, "Found file as ".$this->docRoot.'/'.$src); - $real = $this->realpath($this->docRoot.'/'.$src); - if(stripos($real, $this->docRoot) === 0) { + if (file_exists($this->docRoot . '/' . $src)) { + $this->debug(3, "Found file as " . $this->docRoot . '/' . $src); + $real = $this->realpath($this->docRoot . '/' . $src); + if (stripos($real, $this->docRoot) === 0) { return $real; } else { $this->debug(1, "Security block: The file specified occurs outside the document root."); @@ -1225,13 +1230,13 @@ protected function getLocalImagePath($src) { } } //Check absolute paths and then verify the real path is under doc root - $absolute = $this->realpath('/'.$src); - if($absolute && file_exists($absolute)) { //realpath does file_exists check, so can probably skip the exists check here + $absolute = $this->realpath('/' . $src); + if ($absolute && file_exists($absolute)) { //realpath does file_exists check, so can probably skip the exists check here $this->debug(3, "Found absolute path: $absolute"); - if(!$this->docRoot) { + if (!$this->docRoot) { $this->sanityFail("docRoot not set when checking absolute path."); } - if(stripos($absolute, $this->docRoot) === 0) { + if (stripos($absolute, $this->docRoot) === 0) { return $absolute; } else { $this->debug(1, "Security block: The file specified occurs outside the document root."); @@ -1242,19 +1247,19 @@ protected function getLocalImagePath($src) { $base = $this->docRoot; // account for Windows directory structure - if(strstr($_SERVER['SCRIPT_FILENAME'], ':')) { - $sub_directories = explode('\\', str_replace($this->docRoot, '', $_SERVER['SCRIPT_FILENAME'])); + if (strstr($_SERVER[ 'SCRIPT_FILENAME' ], ':')) { + $sub_directories = explode('\\', str_replace($this->docRoot, '', $_SERVER[ 'SCRIPT_FILENAME' ])); } else { - $sub_directories = explode('/', str_replace($this->docRoot, '', $_SERVER['SCRIPT_FILENAME'])); + $sub_directories = explode('/', str_replace($this->docRoot, '', $_SERVER[ 'SCRIPT_FILENAME' ])); } - foreach($sub_directories as $sub) { - $base .= $sub.'/'; - $this->debug(3, "Trying file as: ".$base.$src); - if(file_exists($base.$src)) { - $this->debug(3, "Found file as: ".$base.$src); - $real = $this->realpath($base.$src); - if(stripos($real, $this->realpath($this->docRoot)) === 0) { + foreach ($sub_directories as $sub) { + $base .= $sub . '/'; + $this->debug(3, "Trying file as: " . $base . $src); + if (file_exists($base . $src)) { + $this->debug(3, "Found file as: " . $base . $src); + $real = $this->realpath($base . $src); + if (stripos($real, $this->realpath($this->docRoot)) === 0) { return $real; } else { $this->debug(1, "Security block: The file specified occurs outside the document root."); @@ -1274,7 +1279,7 @@ protected function getLocalImagePath($src) { protected function realpath($path) { // try to remove any relative paths $remove_relatives = '/\w+\/\.\.\//'; - while(preg_match($remove_relatives, $path)) { + while (preg_match($remove_relatives, $path)) { $path = preg_replace($remove_relatives, '', $path); } // if any remain use PHP realpath to strip them out, otherwise return $path @@ -1299,7 +1304,7 @@ protected function toDelete($name) { public static function curlWrite($h, $d) { fwrite(self::$curlFH, $d); self::$curlDataWritten += strlen($d); - if(self::$curlDataWritten > MAX_FILE_SIZE) { + if (self::$curlDataWritten > MAX_FILE_SIZE) { return 0; } else { return strlen($d); @@ -1311,19 +1316,19 @@ public static function curlWrite($h, $d) { */ protected function serveCacheFile() { $this->debug(3, "Serving {$this->cachefile}"); - if(!is_file($this->cachefile)) { + if (!is_file($this->cachefile)) { $this->error("serveCacheFile called in mthumb but we couldn't find the cached file."); return FALSE; } $fp = fopen($this->cachefile, 'rb'); - if(!$fp) { + if (!$fp) { return $this->error("Could not open cachefile."); } fseek($fp, strlen($this->filePrependSecurityBlock), SEEK_SET); $imgType = fread($fp, 3); fseek($fp, 3, SEEK_CUR); - if(ftell($fp) != strlen($this->filePrependSecurityBlock) + 6) { + if (ftell($fp) != strlen($this->filePrependSecurityBlock) + 6) { @unlink($this->cachefile); return $this->error("The cached image file seems to be corrupt."); @@ -1332,11 +1337,11 @@ protected function serveCacheFile() { $this->sendImageHeaders($imgType, $imageDataSize); $bytesSent = @fpassthru($fp); fclose($fp); - if($bytesSent > 0) { + if ($bytesSent > 0) { return TRUE; } $content = file_get_contents($this->cachefile); - if($content != FALSE) { + if ($content != FALSE) { $content = substr($content, strlen($this->filePrependSecurityBlock) + 6); echo $content; $this->debug(3, "Served using file_get_contents and echo"); @@ -1356,28 +1361,28 @@ protected function serveCacheFile() { * @return bool */ protected function sendImageHeaders($mimeType, $dataSize) { - if(!preg_match('/^image\//i', $mimeType)) { - $mimeType = 'image/'.$mimeType; + if (!preg_match('/^image\//i', $mimeType)) { + $mimeType = 'image/' . $mimeType; } - if(strtolower($mimeType) == 'image/jpg') { + if (strtolower($mimeType) == 'image/jpg') { $mimeType = 'image/jpeg'; } - $gmdate_expires = gmdate('D, d M Y H:i:s', strtotime('now +10 days')).' GMT'; - $gmdate_modified = gmdate('D, d M Y H:i:s').' GMT'; + $gmdate_expires = gmdate('D, d M Y H:i:s', strtotime('now +10 days')) . ' GMT'; + $gmdate_modified = gmdate('D, d M Y H:i:s') . ' GMT'; // send content headers then display image - header('Content-Type: '.$mimeType); + header('Content-Type: ' . $mimeType); header('Accept-Ranges: none'); //Changed this because we don't accept range requests - header('Last-Modified: '.$gmdate_modified); - header('Content-Length: '.$dataSize); - if(BROWSER_CACHE_DISABLE) { + header('Last-Modified: ' . $gmdate_modified); + header('Content-Length: ' . $dataSize); + if (BROWSER_CACHE_DISABLE) { $this->debug(3, "Browser cache is disabled so setting non-caching headers."); header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); header("Pragma: no-cache"); - header('Expires: '.gmdate('D, d M Y H:i:s', time())); + header('Expires: ' . gmdate('D, d M Y H:i:s', time())); } else { $this->debug(3, "Browser caching is enabled"); - header('Cache-Control: max-age='.BROWSER_CACHE_MAX_AGE.', must-revalidate'); - header('Expires: '.$gmdate_expires); + header('Cache-Control: max-age=' . BROWSER_CACHE_MAX_AGE . ', must-revalidate'); + header('Expires: ' . $gmdate_expires); } return TRUE; @@ -1390,8 +1395,8 @@ protected function sendImageHeaders($mimeType, $dataSize) { * @return string */ protected function param($property, $default = '') { - if(isset ($_GET[$property])) { - return $_GET[$property]; + if (isset ($_GET[ $property ])) { + return $_GET[ $property ]; } else { return $default; } @@ -1404,7 +1409,7 @@ protected function param($property, $default = '') { * @return resource */ protected function openImage($mimeType, $src) { - switch($mimeType) { + switch ($mimeType) { case 'image/jpeg': $image = imagecreatefromjpeg($src); break; @@ -1430,26 +1435,26 @@ protected function openImage($mimeType, $src) { * @return string */ protected function getIP() { - $rem = @$_SERVER["REMOTE_ADDR"]; - $ff = @$_SERVER["HTTP_X_FORWARDED_FOR"]; - $ci = @$_SERVER["HTTP_CLIENT_IP"]; - if(preg_match('/^(?:192\.168|172\.16|10\.|127\.)/', $rem)) { - if($ff) { + $rem = @$_SERVER[ "REMOTE_ADDR" ]; + $ff = @$_SERVER[ "HTTP_X_FORWARDED_FOR" ]; + $ci = @$_SERVER[ "HTTP_CLIENT_IP" ]; + if (preg_match('/^(?:192\.168|172\.16|10\.|127\.)/', $rem)) { + if ($ff) { return $ff; } - if($ci) { + if ($ci) { return $ci; } return $rem; } else { - if($rem) { + if ($rem) { return $rem; } - if($ff) { + if ($ff) { return $ff; } - if($ci) { + if ($ci) { return $ci; } @@ -1462,14 +1467,14 @@ protected function getIP() { * @param $msg */ protected function debug($level, $msg) { - if(DEBUG_ON && $level <= DEBUG_LEVEL) { + if (DEBUG_ON && $level <= DEBUG_LEVEL) { $execTime = sprintf('%.6f', microtime(TRUE) - $this->startTime); $tick = sprintf('%.6f', 0); - if($this->lastBenchTime > 0) { + if ($this->lastBenchTime > 0) { $tick = sprintf('%.6f', microtime(TRUE) - $this->lastBenchTime); } $this->lastBenchTime = microtime(TRUE); - error_log("mThumb Debug line ".__LINE__." [$execTime : $tick]: $msg"); + error_log("mThumb Debug line " . __LINE__ . " [$execTime : $tick]: $msg"); } } @@ -1489,8 +1494,8 @@ protected function sanityFail($msg) { */ protected function getMimeType($file) { $info = getimagesize($file); - if(is_array($info) && $info['mime']) { - return $info['mime']; + if (is_array($info) && $info[ 'mime' ]) { + return $info[ 'mime' ]; } return ''; @@ -1502,7 +1507,7 @@ protected function getMimeType($file) { * @return int */ protected static function returnBytes($size_str) { - switch(substr($size_str, -1)) { + switch (substr($size_str, -1)) { case 'M': case 'm': return (int) $size_str * 1048576; @@ -1526,10 +1531,10 @@ protected static function returnBytes($size_str) { protected function getURL($url, $tempfile) { $this->lastURLError = FALSE; $url = preg_replace('/ /', '%20', $url); - if(function_exists('curl_init')) { + if (function_exists('curl_init')) { $this->debug(3, "Curl is installed so using it to fetch URL."); self::$curlFH = fopen($tempfile, 'w'); - if(!self::$curlFH) { + if (!self::$curlFH) { $this->error("Could not open $tempfile for writing."); return FALSE; @@ -1549,15 +1554,15 @@ protected function getURL($url, $tempfile) { $curlResult = curl_exec($curl); fclose(self::$curlFH); $httpStatus = curl_getinfo($curl, CURLINFO_HTTP_CODE); - if($httpStatus == 404) { + if ($httpStatus == 404) { $this->set404(); } - if($httpStatus == 302) { + if ($httpStatus == 302) { $this->error("External Image is Redirecting. Try alternate image URL."); return FALSE; } - if($curlResult) { + if ($curlResult) { curl_close($curl); return TRUE; @@ -1569,20 +1574,20 @@ protected function getURL($url, $tempfile) { } } else { $img = @file_get_contents($url); - if($img === FALSE) { + if ($img === FALSE) { $err = error_get_last(); - if(is_array($err) && $err['message']) { - $this->lastURLError = $err['message']; + if (is_array($err) && $err[ 'message' ]) { + $this->lastURLError = $err[ 'message' ]; } else { $this->lastURLError = $err; } - if(preg_match('/404/', $this->lastURLError)) { + if (preg_match('/404/', $this->lastURLError)) { $this->set404(); } return FALSE; } - if(!file_put_contents($tempfile, $img)) { + if (!file_put_contents($tempfile, $img)) { $this->error("Could not write to $tempfile."); return FALSE; @@ -1599,19 +1604,19 @@ protected function getURL($url, $tempfile) { */ protected function serveImg($file) { $s = getimagesize($file); - if(!($s && $s['mime'])) { + if (!($s && $s[ 'mime' ])) { return FALSE; } - header('Content-Type: '.$s['mime']); - header('Content-Length: '.filesize($file)); + header('Content-Type: ' . $s[ 'mime' ]); + header('Content-Length: ' . filesize($file)); header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); header("Pragma: no-cache"); $bytes = @readfile($file); - if($bytes > 0) { + if ($bytes > 0) { return TRUE; } $content = @file_get_contents($file); - if($content != FALSE) { + if ($content != FALSE) { echo $content; return TRUE;