From: <be...@us...> - 2012-04-15 00:39:07
|
Revision: 9327 http://xoops.svn.sourceforge.net/xoops/?rev=9327&view=rev Author: beckmi Date: 2012-04-15 00:38:58 +0000 (Sun, 15 Apr 2012) Log Message: ----------- Updating phpThumb to 1.7.11 Modified Paths: -------------- XoopsCore/branches/2.5.x/2.5.5/docs/changelog.250.txt XoopsCore/branches/2.5.x/2.5.5/htdocs/modules/system/class/thumbs/phpThumb.php XoopsCore/branches/2.5.x/2.5.5/htdocs/modules/system/class/thumbs/phpthumb.class.php XoopsCore/branches/2.5.x/2.5.5/htdocs/modules/system/class/thumbs/phpthumb.filters.php XoopsCore/branches/2.5.x/2.5.5/htdocs/modules/system/class/thumbs/phpthumb.functions.php XoopsCore/branches/2.5.x/2.5.5/htdocs/modules/system/class/thumbs/phpthumb.unsharp.php Modified: XoopsCore/branches/2.5.x/2.5.5/docs/changelog.250.txt =================================================================== --- XoopsCore/branches/2.5.x/2.5.5/docs/changelog.250.txt 2012-04-14 21:53:58 UTC (rev 9326) +++ XoopsCore/branches/2.5.x/2.5.5/docs/changelog.250.txt 2012-04-15 00:38:58 UTC (rev 9327) @@ -5,8 +5,10 @@ =============================== Bugfixes: - preventing division by zero in pagenav.php (timgno) + +Updated: + - phpThumb to 1.7.11 (mamba) - =============================== 2011/03/14: Version 2.5.5 RC =============================== Modified: XoopsCore/branches/2.5.x/2.5.5/htdocs/modules/system/class/thumbs/phpThumb.php =================================================================== --- XoopsCore/branches/2.5.x/2.5.5/htdocs/modules/system/class/thumbs/phpThumb.php 2012-04-14 21:53:58 UTC (rev 9326) +++ XoopsCore/branches/2.5.x/2.5.5/htdocs/modules/system/class/thumbs/phpThumb.php 2012-04-15 00:38:58 UTC (rev 9327) @@ -12,7 +12,7 @@ error_reporting(E_ALL); ini_set('display_errors', '1'); ini_set('magic_quotes_runtime', '0'); -if (@ini_get('magic_quotes_runtime')) { +if (ini_get('magic_quotes_runtime')) { die('"magic_quotes_runtime" is set in php.ini, cannot run phpThumb with this enabled'); } $starttime = array_sum(explode(' ', microtime())); @@ -23,6 +23,88 @@ $_GET = $HTTP_GET_VARS; } +function SendSaveAsFileHeaderIfNeeded() { + if (headers_sent()) { + return false; + } + global $phpThumb; + $downloadfilename = phpthumb_functions::SanitizeFilename(@$_GET['sia'] ? $_GET['sia'] : (@$_GET['down'] ? $_GET['down'] : 'phpThumb_generated_thumbnail'.(@$_GET['f'] ? $_GET['f'] : 'jpg'))); + if (@$downloadfilename) { + $phpThumb->DebugMessage('SendSaveAsFileHeaderIfNeeded() sending header: Content-Disposition: '.(@$_GET['down'] ? 'attachment' : 'inline').'; filename="'.$downloadfilename.'"', __FILE__, __LINE__); + header('Content-Disposition: '.(@$_GET['down'] ? 'attachment' : 'inline').'; filename="'.$downloadfilename.'"'); + } + return true; +} + +function PasswordStrength($password) { + $strength = 0; + $strength += strlen(preg_replace('#[^a-z]#', '', $password)) * 0.5; // lowercase characters are weak + $strength += strlen(preg_replace('#[^A-Z]#', '', $password)) * 0.8; // uppercase characters are somewhat better + $strength += strlen(preg_replace('#[^0-9]#', '', $password)) * 1.0; // numbers are somewhat better + $strength += strlen(preg_replace('#[a-zA-Z0-9]#', '', $password)) * 2.0; // other non-alphanumeric characters are best + return $strength; +} + +function RedirectToCachedFile() { + global $phpThumb, $PHPTHUMB_CONFIG; + + $nice_cachefile = str_replace(DIRECTORY_SEPARATOR, '/', $phpThumb->cache_filename); + $nice_docroot = str_replace(DIRECTORY_SEPARATOR, '/', rtrim($PHPTHUMB_CONFIG['document_root'], '/\\')); + + $parsed_url = phpthumb_functions::ParseURLbetter(@$_SERVER['HTTP_REFERER']); + + $nModified = filemtime($phpThumb->cache_filename); + + if ($phpThumb->config_nooffsitelink_enabled && @$_SERVER['HTTP_REFERER'] && !in_array(@$parsed_url['host'], $phpThumb->config_nooffsitelink_valid_domains)) { + + $phpThumb->DebugMessage('Would have used cached (image/'.$phpThumb->thumbnailFormat.') file "'.$phpThumb->cache_filename.'" (Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT), but skipping because $_SERVER[HTTP_REFERER] ('.@$_SERVER['HTTP_REFERER'].') is not in $phpThumb->config_nooffsitelink_valid_domains ('.implode(';', $phpThumb->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__); + + } elseif ($phpThumb->phpThumbDebug) { + + $phpThumb->DebugTimingMessage('skipped using cached image', __FILE__, __LINE__); + $phpThumb->DebugMessage('Would have used cached file, but skipping due to phpThumbDebug', __FILE__, __LINE__); + $phpThumb->DebugMessage('* Would have sent headers (1): Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT', __FILE__, __LINE__); + if ($getimagesize = @GetImageSize($phpThumb->cache_filename)) { + $phpThumb->DebugMessage('* Would have sent headers (2): Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($getimagesize[2]), __FILE__, __LINE__); + } + if (preg_match('#^'.preg_quote($nice_docroot).'(.*)$#', $nice_cachefile, $matches)) { + $phpThumb->DebugMessage('* Would have sent headers (3): Location: '.dirname($matches[1]).'/'.urlencode(basename($matches[1])), __FILE__, __LINE__); + } else { + $phpThumb->DebugMessage('* Would have sent data: readfile('.$phpThumb->cache_filename.')', __FILE__, __LINE__); + } + + } else { + + if (headers_sent()) { + $phpThumb->ErrorImage('Headers already sent ('.basename(__FILE__).' line '.__LINE__.')'); + exit; + } + SendSaveAsFileHeaderIfNeeded(); + + header('Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT'); + if (@$_SERVER['HTTP_IF_MODIFIED_SINCE'] && ($nModified == strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])) && @$_SERVER['SERVER_PROTOCOL']) { + header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified'); + exit; + } + + if ($getimagesize = @GetImageSize($phpThumb->cache_filename)) { + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($getimagesize[2])); + } elseif (preg_match('#\\.ico$#i', $phpThumb->cache_filename)) { + header('Content-Type: image/x-icon'); + } + if (!@$PHPTHUMB_CONFIG['cache_force_passthru'] && preg_match('#^'.preg_quote($nice_docroot).'(.*)$#', $nice_cachefile, $matches)) { + header('Location: '.dirname($matches[1]).'/'.urlencode(basename($matches[1]))); + } else { + @readfile($phpThumb->cache_filename); + } + exit; + + } + return true; +} + + + // instantiate a new phpThumb() object ob_start(); if (!include_once(dirname(__FILE__).'/phpthumb.class.php')) { @@ -48,16 +130,19 @@ // great } else { ob_end_flush(); + $phpThumb->config_disable_debug = false; // otherwise error message won't print $phpThumb->ErrorImage('failed to include_once('.dirname(__FILE__).'/phpThumb.config.php) - realpath="'.realpath(dirname(__FILE__).'/phpThumb.config.php').'"'); } ob_end_clean(); } elseif (file_exists(dirname(__FILE__).'/phpThumb.config.php.default')) { + $phpThumb->config_disable_debug = false; // otherwise error message won't print $phpThumb->ErrorImage('Please rename "phpThumb.config.php.default" to "phpThumb.config.php"'); } else { + $phpThumb->config_disable_debug = false; // otherwise error message won't print $phpThumb->ErrorImage('failed to include_once('.dirname(__FILE__).'/phpThumb.config.php) - realpath="'.realpath(dirname(__FILE__).'/phpThumb.config.php').'"'); } -if (!@$PHPTHUMB_CONFIG['disable_pathinfo_parsing'] && (empty($_GET) || isset($_GET['phpThumbDebug'])) && !empty($_SERVER['PATH_INFO'])) { +if (empty($PHPTHUMB_CONFIG['disable_pathinfo_parsing']) && (empty($_GET) || isset($_GET['phpThumbDebug'])) && !empty($_SERVER['PATH_INFO'])) { $_SERVER['PHP_SELF'] = str_replace($_SERVER['PATH_INFO'], '', @$_SERVER['PHP_SELF']); $args = explode(';', substr($_SERVER['PATH_INFO'], 1)); @@ -65,12 +150,12 @@ if (!empty($args)) { $_GET['src'] = @$args[count($args) - 1]; $phpThumb->DebugMessage('PATH_INFO."src" = "'.$_GET['src'].'"', __FILE__, __LINE__); - if (eregi('^new\=([a-z0-9]+)', $_GET['src'], $matches)) { + if (preg_match('#^new\=([a-z0-9]+)#i', $_GET['src'], $matches)) { unset($_GET['src']); $_GET['new'] = $matches[1]; } } - if (eregi('^([0-9]*)x?([0-9]*)$', @$args[count($args) - 2], $matches)) { + if (preg_match('#^([0-9]*)x?([0-9]*)$#i', @$args[count($args) - 2], $matches)) { $_GET['w'] = $matches[1]; $_GET['h'] = $matches[2]; $phpThumb->DebugMessage('PATH_INFO."w"x"h" set to "'.$_GET['w'].'"x"'.$_GET['h'].'"', __FILE__, __LINE__); @@ -88,12 +173,16 @@ } } -if (@$PHPTHUMB_CONFIG['high_security_enabled']) { - if (!@$_GET['hash']) { +if (!empty($PHPTHUMB_CONFIG['high_security_enabled'])) { + if (empty($_GET['hash'])) { + $phpThumb->config_disable_debug = false; // otherwise error message won't print $phpThumb->ErrorImage('ERROR: missing hash'); - } elseif (strlen($PHPTHUMB_CONFIG['high_security_password']) < 5) { - $phpThumb->ErrorImage('ERROR: strlen($PHPTHUMB_CONFIG[high_security_password]) < 5'); + } elseif (PasswordStrength($PHPTHUMB_CONFIG['high_security_password']) < 20) { + $phpThumb->config_disable_debug = false; // otherwise error message won't print + $phpThumb->ErrorImage('ERROR: $PHPTHUMB_CONFIG[high_security_password] is not complex enough'); } elseif ($_GET['hash'] != md5(str_replace('&hash='.$_GET['hash'], '', $_SERVER['QUERY_STRING']).$PHPTHUMB_CONFIG['high_security_password'])) { + sleep(10); // deliberate delay to discourage password-guessing + $phpThumb->config_disable_debug = false; // otherwise error message won't print $phpThumb->ErrorImage('ERROR: invalid hash'); } } @@ -101,7 +190,7 @@ //////////////////////////////////////////////////////////////// // Debug output, to try and help me diagnose problems $phpThumb->DebugTimingMessage('phpThumbDebug[0]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '0') { +if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '0')) { $phpThumb->phpThumbDebug(); } //////////////////////////////////////////////////////////////// @@ -121,12 +210,13 @@ } } -if (!@$_SERVER['PATH_INFO'] && !@$_SERVER['QUERY_STRING']) { - $phpThumb->ErrorImage('phpThumb() v'.$phpThumb->phpthumb_version.'<br><a href="http://phpthumb.sourceforge.net">http://phpthumb.sourceforge.net</a><br><br>ERROR: no parameters specified'); +if (empty($_SERVER['PATH_INFO']) && empty($_SERVER['QUERY_STRING'])) { + $phpThumb->config_disable_debug = false; // otherwise error message won't print + $phpThumb->ErrorImage('ERROR: no parameters specified'); } if (@$_GET['src'] && isset($_GET['md5s']) && empty($_GET['md5s'])) { - if (eregi('^(f|ht)tps?://', $_GET['src'])) { + if (preg_match('#^(f|ht)tps?://#i', $_GET['src'])) { if ($rawImageData = phpthumb_functions::SafeURLread($_GET['src'], $error, $phpThumb->config_http_fopen_timeout, $phpThumb->config_http_follow_redirect)) { $md5s = md5($rawImageData); } @@ -149,7 +239,7 @@ foreach ($PHPTHUMB_CONFIG as $key => $value) { $keyname = 'config_'.$key; $phpThumb->setParameter($keyname, $value); - if (!eregi('password|mysql', $key)) { + if (!preg_match('#(password|mysql)#i', $key)) { $phpThumb->DebugMessage('setParameter('.$keyname.', '.$phpThumb->phpThumbDebugVarDump($value).')', __FILE__, __LINE__); } } @@ -157,14 +247,14 @@ $phpThumb->DebugMessage('$PHPTHUMB_CONFIG is empty', __FILE__, __LINE__); } -if (@$_GET['src'] && !@$PHPTHUMB_CONFIG['allow_local_http_src'] && eregi('^http://'.@$_SERVER['HTTP_HOST'].'(.+)', @$_GET['src'], $matches)) { +if (@$_GET['src'] && !@$PHPTHUMB_CONFIG['allow_local_http_src'] && preg_match('#^http://'.@$_SERVER['HTTP_HOST'].'(.+)#i', @$_GET['src'], $matches)) { $phpThumb->ErrorImage('It is MUCH better to specify the "src" parameter as "'.$matches[1].'" instead of "'.$matches[0].'".'."\n\n".'If you really must do it this way, enable "allow_local_http_src" in phpThumb.config.php'); } //////////////////////////////////////////////////////////////// // Debug output, to try and help me diagnose problems $phpThumb->DebugTimingMessage('phpThumbDebug[1]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '1') { +if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '1')) { $phpThumb->phpThumbDebug(); } //////////////////////////////////////////////////////////////// @@ -174,7 +264,7 @@ $phpThumb->ErrorImage('config_nooffsitelink_require_refer enabled and '.(@$parsed_url_referer['host'] ? '"'.$parsed_url_referer['host'].'" is not an allowed referer' : 'no HTTP_REFERER exists')); } $parsed_url_src = phpthumb_functions::ParseURLbetter(@$_GET['src']); -if ($phpThumb->config_nohotlink_enabled && $phpThumb->config_nohotlink_erase_image && eregi('^(f|ht)tps?://', @$_GET['src']) && !in_array(@$parsed_url_src['host'], $phpThumb->config_nohotlink_valid_domains)) { +if ($phpThumb->config_nohotlink_enabled && $phpThumb->config_nohotlink_erase_image && preg_match('#^(f|ht)tps?://#i', @$_GET['src']) && !in_array(@$parsed_url_src['host'], $phpThumb->config_nohotlink_valid_domains)) { $phpThumb->ErrorImage($phpThumb->config_nohotlink_text_message); } @@ -211,7 +301,7 @@ //////////////////////////////////////////////////////////////// // Debug output, to try and help me diagnose problems $phpThumb->DebugTimingMessage('phpThumbDebug[2]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '2') { +if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '2')) { $phpThumb->phpThumbDebug(); } //////////////////////////////////////////////////////////////// @@ -231,7 +321,7 @@ // deprecated: 'err', 'file', 'goto', $allowedGETparameters = array('src', 'new', 'w', 'h', 'wp', 'hp', 'wl', 'hl', 'ws', 'hs', 'f', 'q', 'sx', 'sy', 'sw', 'sh', 'zc', 'bc', 'bg', 'bgt', 'fltr', 'xto', 'ra', 'ar', 'aoe', 'far', 'iar', 'maxb', 'down', 'phpThumbDebug', 'hash', 'md5s', 'sfn', 'dpi', 'sia', 'nocache'); foreach ($_GET as $key => $value) { - if (@$PHPTHUMB_DEFAULTS_DISABLEGETPARAMS && ($key != 'src')) { + if (!empty($PHPTHUMB_DEFAULTS_DISABLEGETPARAMS) && ($key != 'src')) { // disabled, do not set parameter $phpThumb->DebugMessage('ignoring $_GET['.$key.'] because of $PHPTHUMB_DEFAULTS_DISABLEGETPARAMS', __FILE__, __LINE__); } elseif (in_array($key, $allowedGETparameters)) { @@ -245,7 +335,7 @@ //////////////////////////////////////////////////////////////// // Debug output, to try and help me diagnose problems $phpThumb->DebugTimingMessage('phpThumbDebug[3]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '3') { +if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '3')) { $phpThumb->phpThumbDebug(); } //////////////////////////////////////////////////////////////// @@ -266,14 +356,17 @@ $CanPassThroughDirectly = true; if ($phpThumb->rawImageData) { // data from SQL, should be fine -} elseif (eregi('^http\://.+\.(jpe?g|gif|png)$', $phpThumb->src)) { +} elseif (preg_match('#^http\://[^\\?&]+\\.(jpe?g|gif|png)$#i', $phpThumb->src)) { // assume is ok to passthru if no other parameters specified -} elseif (!@is_file($phpThumb->sourceFilename)) { - $phpThumb->DebugMessage('$CanPassThroughDirectly=false because !@is_file('.$phpThumb->sourceFilename.')', __FILE__, __LINE__); +} elseif (preg_match('#^(f|ht)tp\://#i', $phpThumb->src)) { + $phpThumb->DebugMessage('$CanPassThroughDirectly=false because preg_match("#^(f|ht)tp\://#i", '.$phpThumb->src.')', __FILE__, __LINE__); $CanPassThroughDirectly = false; } elseif (!@is_readable($phpThumb->sourceFilename)) { $phpThumb->DebugMessage('$CanPassThroughDirectly=false because !@is_readable('.$phpThumb->sourceFilename.')', __FILE__, __LINE__); $CanPassThroughDirectly = false; +} elseif (!@is_file($phpThumb->sourceFilename)) { + $phpThumb->DebugMessage('$CanPassThroughDirectly=false because !@is_file('.$phpThumb->sourceFilename.')', __FILE__, __LINE__); + $CanPassThroughDirectly = false; } foreach ($_GET as $key => $value) { switch ($key) { @@ -284,7 +377,7 @@ case 'w': case 'h': // might be OK if exactly matches original - if (eregi('^http\://.+\.(jpe?g|gif|png)$', $phpThumb->src)) { + if (preg_match('#^http\://[^\\?&]+\\.(jpe?g|gif|png)$#i', $phpThumb->src)) { // assume it is not ok for direct-passthru of remote image $CanPassThroughDirectly = false; } @@ -309,29 +402,16 @@ //////////////////////////////////////////////////////////////// // Debug output, to try and help me diagnose problems $phpThumb->DebugTimingMessage('phpThumbDebug[4]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '4') { +if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '4')) { $phpThumb->phpThumbDebug(); } //////////////////////////////////////////////////////////////// -function SendSaveAsFileHeaderIfNeeded() { - if (headers_sent()) { - return false; - } - global $phpThumb; - $downloadfilename = phpthumb_functions::SanitizeFilename(@$_GET['sia'] ? $_GET['sia'] : (@$_GET['down'] ? $_GET['down'] : 'phpThumb_generated_thumbnail'.(@$_GET['f'] ? $_GET['f'] : 'jpg'))); - if (@$downloadfilename) { - $phpThumb->DebugMessage('SendSaveAsFileHeaderIfNeeded() sending header: Content-Disposition: '.(@$_GET['down'] ? 'attachment' : 'inline').'; filename="'.$downloadfilename.'"', __FILE__, __LINE__); - header('Content-Disposition: '.(@$_GET['down'] ? 'attachment' : 'inline').'; filename="'.$downloadfilename.'"'); - } - return true; -} - $phpThumb->DebugMessage('$CanPassThroughDirectly="'.intval($CanPassThroughDirectly).'" && $phpThumb->src="'.$phpThumb->src.'"', __FILE__, __LINE__); while ($CanPassThroughDirectly && $phpThumb->src) { // no parameters set, passthru - if (eregi('^http\://.+\.(jpe?g|gif|png)$', $phpThumb->src)) { + if (preg_match('#^http\://[^\\?&]+\.(jpe?g|gif|png)$#i', $phpThumb->src)) { $phpThumb->DebugMessage('Passing HTTP source through directly as Location: redirect ('.$phpThumb->src.')', __FILE__, __LINE__); header('Location: '.$phpThumb->src); exit; @@ -346,7 +426,7 @@ if (!@$_GET['w'] && !@$_GET['wp'] && !@$_GET['wl'] && !@$_GET['ws'] && !@$_GET['h'] && !@$_GET['hp'] && !@$_GET['hl'] && !@$_GET['hs']) { // no resizing needed $phpThumb->DebugMessage('Passing "'.$SourceFilename.'" through directly, no resizing required ("'.$phpThumb->getimagesizeinfo[0].'"x"'.$phpThumb->getimagesizeinfo[1].'")', __FILE__, __LINE__); - } elseif ((($phpThumb->getimagesizeinfo[0] <= @$_GET['w']) || ($phpThumb->getimagesizeinfo[1] <= @$_GET['h'])) && ((@$_GET['w'] == $phpThumb->getimagesizeinfo[0]) || (@$_GET['h'] == $phpThumb->getimagesizeinfo[1]))) { + } elseif (($phpThumb->getimagesizeinfo[0] <= @$_GET['w']) && ($phpThumb->getimagesizeinfo[1] <= @$_GET['h']) && ((@$_GET['w'] == $phpThumb->getimagesizeinfo[0]) || (@$_GET['h'] == $phpThumb->getimagesizeinfo[1]))) { // image fits into 'w'x'h' box, and at least one dimension matches exactly, therefore no resizing needed $phpThumb->DebugMessage('Passing "'.$SourceFilename.'" through directly, no resizing required ("'.$phpThumb->getimagesizeinfo[0].'"x"'.$phpThumb->getimagesizeinfo[1].'" fits inside "'.@$_GET['w'].'"x"'.@$_GET['h'].'")', __FILE__, __LINE__); } else { @@ -407,72 +487,14 @@ //////////////////////////////////////////////////////////////// // Debug output, to try and help me diagnose problems $phpThumb->DebugTimingMessage('phpThumbDebug[5]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '5') { +if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '5')) { $phpThumb->phpThumbDebug(); } //////////////////////////////////////////////////////////////// -function RedirectToCachedFile() { - global $phpThumb, $PHPTHUMB_CONFIG; - - $nice_cachefile = str_replace(DIRECTORY_SEPARATOR, '/', $phpThumb->cache_filename); - $nice_docroot = str_replace(DIRECTORY_SEPARATOR, '/', rtrim($PHPTHUMB_CONFIG['document_root'], '/\\')); - - $parsed_url = phpthumb_functions::ParseURLbetter(@$_SERVER['HTTP_REFERER']); - - $nModified = filemtime($phpThumb->cache_filename); - - if ($phpThumb->config_nooffsitelink_enabled && @$_SERVER['HTTP_REFERER'] && !in_array(@$parsed_url['host'], $phpThumb->config_nooffsitelink_valid_domains)) { - - $phpThumb->DebugMessage('Would have used cached (image/'.$phpThumb->thumbnailFormat.') file "'.$phpThumb->cache_filename.'" (Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT), but skipping because $_SERVER[HTTP_REFERER] ('.@$_SERVER['HTTP_REFERER'].') is not in $phpThumb->config_nooffsitelink_valid_domains ('.implode(';', $phpThumb->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__); - - } elseif ($phpThumb->phpThumbDebug) { - - $phpThumb->DebugTimingMessage('skipped using cached image', __FILE__, __LINE__); - $phpThumb->DebugMessage('Would have used cached file, but skipping due to phpThumbDebug', __FILE__, __LINE__); - $phpThumb->DebugMessage('* Would have sent headers (1): Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT', __FILE__, __LINE__); - if ($getimagesize = @GetImageSize($phpThumb->cache_filename)) { - $phpThumb->DebugMessage('* Would have sent headers (2): Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($getimagesize[2]), __FILE__, __LINE__); - } - if (ereg('^'.preg_quote($nice_docroot).'(.*)$', $nice_cachefile, $matches)) { - $phpThumb->DebugMessage('* Would have sent headers (3): Location: '.dirname($matches[1]).'/'.urlencode(basename($matches[1])), __FILE__, __LINE__); - } else { - $phpThumb->DebugMessage('* Would have sent data: readfile('.$phpThumb->cache_filename.')', __FILE__, __LINE__); - } - - } else { - - if (headers_sent()) { - $phpThumb->ErrorImage('Headers already sent ('.basename(__FILE__).' line '.__LINE__.')'); - exit; - } - SendSaveAsFileHeaderIfNeeded(); - - header('Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT'); - if (@$_SERVER['HTTP_IF_MODIFIED_SINCE'] && ($nModified == strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])) && @$_SERVER['SERVER_PROTOCOL']) { - header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified'); - exit; - } - - if ($getimagesize = @GetImageSize($phpThumb->cache_filename)) { - header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($getimagesize[2])); - } elseif (eregi('\.ico$', $phpThumb->cache_filename)) { - header('Content-Type: image/x-icon'); - } - if (!@$PHPTHUMB_CONFIG['cache_force_passthru'] && ereg('^'.preg_quote($nice_docroot).'(.*)$', $nice_cachefile, $matches)) { - header('Location: '.dirname($matches[1]).'/'.urlencode(basename($matches[1]))); - } else { - @readfile($phpThumb->cache_filename); - } - exit; - - } - return true; -} - // check to see if file already exists in cache, and output it with no processing if it does $phpThumb->SetCacheFilename(); -if (@is_file($phpThumb->cache_filename)) { +if (@is_readable($phpThumb->cache_filename)) { RedirectToCachedFile(); } else { $phpThumb->DebugMessage('Cached file "'.$phpThumb->cache_filename.'" does not exist, processing as normal', __FILE__, __LINE__); @@ -481,7 +503,7 @@ //////////////////////////////////////////////////////////////// // Debug output, to try and help me diagnose problems $phpThumb->DebugTimingMessage('phpThumbDebug[6]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '6') { +if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '6')) { $phpThumb->phpThumbDebug(); } //////////////////////////////////////////////////////////////// @@ -490,7 +512,7 @@ // great -} elseif (@$_GET['new']) { +} elseif (!empty($_GET['new'])) { // generate a blank image resource of the specified size/background color/opacity if (($phpThumb->w <= 0) || ($phpThumb->h <= 0)) { @@ -518,7 +540,7 @@ $phpThumb->ErrorImage('Usage: '.$_SERVER['PHP_SELF'].'?src=/path/and/filename.jpg'."\n".'read Usage comments for details'); -} elseif (eregi('^(f|ht)tp\://', $phpThumb->src)) { +} elseif (preg_match('#^(f|ht)tp\://#i', $phpThumb->src)) { $phpThumb->DebugMessage('$phpThumb->src ('.$phpThumb->src.') is remote image, attempting to download', __FILE__, __LINE__); if ($phpThumb->config_http_user_agent) { @@ -541,7 +563,7 @@ //////////////////////////////////////////////////////////////// // Debug output, to try and help me diagnose problems $phpThumb->DebugTimingMessage('phpThumbDebug[7]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '7') { +if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '7')) { $phpThumb->phpThumbDebug(); } //////////////////////////////////////////////////////////////// @@ -551,28 +573,19 @@ //////////////////////////////////////////////////////////////// // Debug output, to try and help me diagnose problems $phpThumb->DebugTimingMessage('phpThumbDebug[8]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '8') { +if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '8')) { $phpThumb->phpThumbDebug(); } //////////////////////////////////////////////////////////////// -if ($phpThumb->config_allow_parameter_file && $phpThumb->file) { +if (!empty($PHPTHUMB_CONFIG['high_security_enabled']) && !empty($_GET['nocache'])) { - $phpThumb->RenderToFile($phpThumb->ResolveFilenameToAbsolute($phpThumb->file)); - if ($phpThumb->config_allow_parameter_goto && $phpThumb->goto && eregi('^(f|ht)tps?://', $phpThumb->goto)) { - // redirect to another URL after image has been rendered to file - header('Location: '.$phpThumb->goto); - exit; - } - -} elseif (@$PHPTHUMB_CONFIG['high_security_enabled'] && @$_GET['nocache']) { - // cache disabled, don't write cachefile } else { phpthumb_functions::EnsureDirectoryExists(dirname($phpThumb->cache_filename)); - if ((file_exists($phpThumb->cache_filename) && is_writable($phpThumb->cache_filename)) || is_writable(dirname($phpThumb->cache_filename))) { + if (is_writable(dirname($phpThumb->cache_filename)) || (file_exists($phpThumb->cache_filename) && is_writable($phpThumb->cache_filename))) { $phpThumb->CleanUpCacheDirectory(); if ($phpThumb->RenderToFile($phpThumb->cache_filename) && is_readable($phpThumb->cache_filename)) { @@ -593,7 +606,7 @@ //////////////////////////////////////////////////////////////// // Debug output, to try and help me diagnose problems $phpThumb->DebugTimingMessage('phpThumbDebug[9]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '9') { +if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '9')) { $phpThumb->phpThumbDebug(); } //////////////////////////////////////////////////////////////// @@ -605,7 +618,7 @@ //////////////////////////////////////////////////////////////// // Debug output, to try and help me diagnose problems $phpThumb->DebugTimingMessage('phpThumbDebug[10]', __FILE__, __LINE__); -if (@$_GET['phpThumbDebug'] == '10') { +if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '10')) { $phpThumb->phpThumbDebug(); } //////////////////////////////////////////////////////////////// Modified: XoopsCore/branches/2.5.x/2.5.5/htdocs/modules/system/class/thumbs/phpthumb.class.php =================================================================== --- XoopsCore/branches/2.5.x/2.5.5/htdocs/modules/system/class/thumbs/phpthumb.class.php 2012-04-14 21:53:58 UTC (rev 9326) +++ XoopsCore/branches/2.5.x/2.5.5/htdocs/modules/system/class/thumbs/phpthumb.class.php 2012-04-15 00:38:58 UTC (rev 9327) @@ -138,11 +138,9 @@ // * Security var $config_high_security_enabled = false; var $config_high_security_password = null; - var $config_disable_debug = false; + var $config_disable_debug = true; var $config_allow_src_above_docroot = false; var $config_allow_src_above_phpthumb = true; - var $config_allow_parameter_file = false; - var $config_allow_parameter_goto = false; // * HTTP fopen var $config_http_fopen_timeout = 10; @@ -199,14 +197,16 @@ var $thumbnail_image_width = null; var $thumbnail_image_height = null; - var $cache_filename = null; + var $tempFilesToDelete = array(); + var $cache_filename = null; var $AlphaCapableFormats = array('png', 'ico', 'gif'); var $is_alpha = false; - var $iswindows = null; + var $iswindows = null; + var $issafemode = null; - var $phpthumb_version = '1.7.9-200805132119'; + var $phpthumb_version = '1.7.11-201108081537'; ////////////////////////////////////////////////////////////////////// @@ -215,17 +215,36 @@ $this->DebugTimingMessage('phpThumb() constructor', __FILE__, __LINE__); $this->DebugMessage('phpThumb() v'.$this->phpthumb_version, __FILE__, __LINE__); $this->config_max_source_pixels = round(max(intval(ini_get('memory_limit')), intval(get_cfg_var('memory_limit'))) * 1048576 * 0.20); // 20% of memory_limit - $this->iswindows = (bool) (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'); - $this->config_document_root = (@$_SERVER['DOCUMENT_ROOT'] ? $_SERVER['DOCUMENT_ROOT'] : $this->config_document_root); - $this->config_cache_prefix = 'phpThumb_cache_'.@$_SERVER['SERVER_NAME']; + $this->iswindows = (bool) (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'); + $this->issafemode = (bool) preg_match('#(1|ON)#i', ini_get('safe_mode')); + $this->config_document_root = (!empty($_SERVER['DOCUMENT_ROOT']) ? $_SERVER['DOCUMENT_ROOT'] : $this->config_document_root); + $this->config_cache_prefix = ( isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'].'_' : ''); + $this->purgeTempFiles(); // purge existing temp files if re-initializing object + $php_sapi_name = strtolower(function_exists('php_sapi_name') ? php_sapi_name() : ''); if ($php_sapi_name == 'cli') { $this->config_allow_src_above_docroot = true; } } + function __destruct() { + $this->purgeTempFiles(); + } + // public: + function purgeTempFiles() { + foreach ($this->tempFilesToDelete as $tempFileToDelete) { + if (file_exists($tempFileToDelete)) { + $this->DebugMessage('Deleting temp file "'.$tempFileToDelete.'"', __FILE__, __LINE__); + @unlink($tempFileToDelete); + } + } + $this->tempFilesToDelete = array(); + return true; + } + + // public: function setSourceFilename($sourceFilename) { //$this->resetObject(); //$this->rawImageData = null; @@ -233,7 +252,7 @@ $this->src = $sourceFilename; if (is_null($this->config_output_format)) { $sourceFileExtension = strtolower(substr(strrchr($sourceFilename, '.'), 1)); - if (ereg('^[a-z]{3,4}$', $sourceFileExtension)) { + if (preg_match('#^[a-z]{3,4}$#', $sourceFileExtension)) { $this->config_output_format = $sourceFileExtension; $this->DebugMessage('setSourceFilename('.$sourceFilename.') set $this->config_output_format to "'.$sourceFileExtension.'"', __FILE__, __LINE__); } else { @@ -364,7 +383,7 @@ // $borderThickness = 0; // if (!empty($this->fltr)) { // foreach ($this->fltr as $key => $value) { -// if (ereg('^bord\|([0-9]+)', $value, $matches)) { +// if (preg_match('#^bord\|([0-9]+)#', $value, $matches)) { // $borderThickness = $matches[1]; // break; // } @@ -517,7 +536,7 @@ // public: function RenderToFile($filename) { - if (eregi('^(f|ht)tps?\://', $filename)) { + if (preg_match('#^(f|ht)tps?\://#i', $filename)) { $this->DebugMessage('RenderToFile() failed because $filename ('.$filename.') is a URL', __FILE__, __LINE__); return false; } @@ -553,6 +572,8 @@ // public: function OutputThumbnail() { + $this->purgeTempFiles(); + if (!$this->useRawIMoutput && !is_resource($this->gdimg_output)) { $this->DebugMessage('OutputThumbnail() failed because !is_resource($this->gdimg_output)', __FILE__, __LINE__); return false; @@ -649,7 +670,21 @@ // public: function CleanUpCacheDirectory() { - $this->DebugMessage('skipping CleanUpCacheDirectory() set to purge ('.number_format($this->config_cache_maxage / 86400, 1).' days; '.number_format($this->config_cache_maxsize / 1048576, 2).'MB; '.number_format($this->config_cache_maxfiles).' files)', __FILE__, __LINE__); + $this->DebugMessage('CleanUpCacheDirectory() set to purge ('.(is_null($this->config_cache_maxage) ? 'NULL' : number_format($this->config_cache_maxage / 86400, 1)).' days; '.(is_null($this->config_cache_maxsize) ? 'NULL' : number_format($this->config_cache_maxsize / 1048576, 2)).' MB; '.(is_null($this->config_cache_maxfiles) ? 'NULL' : number_format($this->config_cache_maxfiles)).' files)', __FILE__, __LINE__); + + if (!is_writable($this->config_cache_directory)) { + $this->DebugMessage('CleanUpCacheDirectory() skipped because "'.$this->config_cache_directory.'" is not writable', __FILE__, __LINE__); + return true; + } + + // cache status of cache directory for 1 hour to avoid hammering the filesystem functions + $phpThumbCacheStats_filename = $this->config_cache_directory.DIRECTORY_SEPARATOR.'phpThumbCacheStats.txt'; + if (file_exists($phpThumbCacheStats_filename) && is_readable($phpThumbCacheStats_filename) && (filemtime($phpThumbCacheStats_filename) >= (time() - 3600))) { + $this->DebugMessage('CleanUpCacheDirectory() skipped because "'.$phpThumbCacheStats_filename.'" is recently modified', __FILE__, __LINE__); + return true; + } + touch($phpThumbCacheStats_filename); + $DeletedKeys = array(); $AllFilesInCacheDirectory = array(); if (($this->config_cache_maxage > 0) || ($this->config_cache_maxsize > 0) || ($this->config_cache_maxfiles > 0)) { @@ -657,7 +692,7 @@ $CacheDirOldFilesSize = array(); $AllFilesInCacheDirectory = phpthumb_functions::GetAllFilesInSubfolders($this->config_cache_directory); foreach ($AllFilesInCacheDirectory as $fullfilename) { - if (eregi('^phpThumb_cache_', basename($fullfilename)) && file_exists($fullfilename)) { + if (preg_match('#^'.preg_quote($this->config_cache_prefix).'#i', $fullfilename) && file_exists($fullfilename)) { $CacheDirOldFilesAge[$fullfilename] = @fileatime($fullfilename); if ($CacheDirOldFilesAge[$fullfilename] == 0) { $CacheDirOldFilesAge[$fullfilename] = @filemtime($fullfilename); @@ -792,7 +827,7 @@ $class_vars = get_class_vars(get_class($this)); foreach ($class_vars as $key => $value) { // do not clobber debug or config info - if (!eregi('^(config_|debug|fatalerror)', $key)) { + if (!preg_match('#^(config_|debug|fatalerror)#i', $key)) { $this->$key = $value; } } @@ -823,7 +858,7 @@ } if ($this->iswindows && ((substr($this->sourceFilename, 0, 2) == '//') || (substr($this->sourceFilename, 0, 2) == '\\\\'))) { // Windows \\share\filename.ext - } elseif (eregi('^(f|ht)tps?\://', $this->sourceFilename)) { + } elseif (preg_match('#^(f|ht)tps?\://#i', $this->sourceFilename)) { // URL if ($this->config_http_user_agent) { ini_set('user_agent', $this->config_http_user_agent); @@ -887,7 +922,7 @@ $AvailableImageOutputFormats = array_unique($AvailableImageOutputFormats); $this->DebugMessage('$AvailableImageOutputFormats = array('.implode(';', $AvailableImageOutputFormats).')', __FILE__, __LINE__); - $this->f = ereg_replace('[^a-z]', '', strtolower($this->f)); + $this->f = preg_replace('#[^a-z]#', '', strtolower($this->f)); if (strtolower($this->config_output_format) == 'jpg') { $this->config_output_format = 'jpeg'; } @@ -912,7 +947,7 @@ // for JPEG images, quality 1 (worst) to 99 (best) // quality < 25 is nasty, with not much size savings - not recommended // problems with 100 - invalid JPEG? - $this->thumbnailQuality = max(1, min(99, ($this->q ? $this->q : 75))); + $this->thumbnailQuality = max(1, min(99, ($this->q ? intval($this->q) : 75))); $this->DebugMessage('$this->thumbnailQuality set to "'.$this->thumbnailQuality.'"', __FILE__, __LINE__); return true; @@ -922,7 +957,7 @@ // resolve cache directory to absolute pathname $this->DebugMessage('setCacheDirectory() starting with config_cache_directory = "'.$this->config_cache_directory.'"', __FILE__, __LINE__); if (substr($this->config_cache_directory, 0, 1) == '.') { - if (eregi('^(f|ht)tps?\://', $this->src)) { + if (preg_match('#^(f|ht)tps?\://#i', $this->src)) { if (!$this->config_cache_disable_warning) { $this->ErrorImage('$this->config_cache_directory ('.$this->config_cache_directory.') cannot be used for remote images. Adjust "cache_directory" or "cache_disable_warning" in phpThumb.config.php'); } @@ -972,12 +1007,11 @@ function ResolveFilenameToAbsolute($filename) { - if (!$filename) { + if (empty($filename)) { return false; } - //if (eregi('^(f|ht)tps?\://', $filename)) { - if (eregi('^[a-z0-9]+\:/{1,2}', $filename)) { + if (preg_match('#^[a-z0-9]+\:/{1,2}#i', $filename)) { // eg: http://host/path/file.jpg (HTTP URL) // eg: ftp://host/path/file.jpg (FTP URL) // eg: data1:/path/file.jpg (Netware path) @@ -985,7 +1019,7 @@ //$AbsoluteFilename = $filename; return $filename; - } elseif ($this->iswindows && ($filename{1} == ':')) { + } elseif ($this->iswindows && isset($filename{1}) && ($filename{1} == ':')) { // absolute pathname (Windows) $AbsoluteFilename = $filename; @@ -1002,7 +1036,7 @@ // absolute filename (*nix) $AbsoluteFilename = $filename; - } elseif ($filename{1} == '~') { + } elseif (isset($filename{1}) && ($filename{1} == '~')) { // /~user/path if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray($filename)) { @@ -1021,7 +1055,7 @@ } else { // relative filename (any OS) - if (ereg('^'.preg_quote($this->config_document_root), $filename)) { + if (preg_match('#^'.preg_quote($this->config_document_root).'#', $filename)) { $AbsoluteFilename = $filename; $this->DebugMessage('ResolveFilenameToAbsolute() NOT prepending $this->config_document_root ('.$this->config_document_root.') to $filename ('.$filename.') resulting in ($AbsoluteFilename = "'.$AbsoluteFilename.'")', __FILE__, __LINE__); } else { @@ -1034,7 +1068,9 @@ } else { // relative to current directory (any OS) - $AbsoluteFilename = $this->config_document_root.dirname(@$_SERVER['PHP_SELF']).DIRECTORY_SEPARATOR.$filename; + //$AbsoluteFilename = $this->config_document_root.preg_replace('#[/\\\\]#', DIRECTORY_SEPARATOR, dirname(@$_SERVER['PHP_SELF'])).DIRECTORY_SEPARATOR.preg_replace('#[/\\\\]#', DIRECTORY_SEPARATOR, $filename); + $AbsoluteFilename = dirname(__FILE__).DIRECTORY_SEPARATOR.preg_replace('#[/\\\\]#', DIRECTORY_SEPARATOR, $filename); + //if (!@file_exists($AbsoluteFilename) && @file_exists(realpath($this->DotPadRelativeDirectoryPath($filename)))) { // $AbsoluteFilename = realpath($this->DotPadRelativeDirectoryPath($filename)); //} @@ -1063,20 +1099,40 @@ $AbsoluteFilename = realpath($AbsoluteFilename); } if ($this->iswindows) { - $AbsoluteFilename = eregi_replace('^'.preg_quote(realpath($this->config_document_root)), realpath($this->config_document_root), $AbsoluteFilename); + $AbsoluteFilename = preg_replace('#^'.preg_quote(realpath($this->config_document_root)).'#i', realpath($this->config_document_root), $AbsoluteFilename); $AbsoluteFilename = str_replace(DIRECTORY_SEPARATOR, '/', $AbsoluteFilename); } - if (!$this->config_allow_src_above_docroot && !ereg('^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', realpath($this->config_document_root))), $AbsoluteFilename)) { + if (!$this->config_allow_src_above_docroot && !preg_match('#^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', realpath($this->config_document_root))).'#', $AbsoluteFilename)) { $this->DebugMessage('!$this->config_allow_src_above_docroot therefore setting "'.$AbsoluteFilename.'" (outside "'.realpath($this->config_document_root).'") to null', __FILE__, __LINE__); return false; } - if (!$this->config_allow_src_above_phpthumb && !ereg('^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', dirname(__FILE__))), $AbsoluteFilename)) { + if (!$this->config_allow_src_above_phpthumb && !preg_match('#^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', dirname(__FILE__))).'#', $AbsoluteFilename)) { $this->DebugMessage('!$this->config_allow_src_above_phpthumb therefore setting "'.$AbsoluteFilename.'" (outside "'.dirname(__FILE__).'") to null', __FILE__, __LINE__); return false; } return $AbsoluteFilename; } + function file_exists_ignoreopenbasedir($filename, $cached=true) { + static $open_basedirs = null; + static $file_exists_cache = array(); + if (!$cached || !isset($file_exists_cache[$filename])) { + if (is_null($open_basedirs)) { + $open_basedirs = explode(';', ini_get('open_basedir')); + } + if (empty($open_basedirs) || in_array(dirname($filename), $open_basedirs)) { + $file_exists_cache[$filename] = file_exists($filename); + } elseif ($this->iswindows) { + $ls_filename = trim(phpthumb_functions::SafeExec('dir '.escapeshellarg($filename))); + $file_exists_cache[$filename] = !preg_match('#File Not Found#i', $ls_filename); + } else { + $ls_filename = trim(phpthumb_functions::SafeExec('ls '.escapeshellarg($filename))); + $file_exists_cache[$filename] = ($ls_filename == $filename); + } + } + return $file_exists_cache[$filename]; + } + function ImageMagickWhichConvert() { static $WhichConvert = null; if (is_null($WhichConvert)) { @@ -1092,6 +1148,10 @@ function ImageMagickCommandlineBase() { static $commandline = null; if (is_null($commandline)) { + if ($this->issafemode) { + $commandline = ''; + return $commandline; + } $commandline = (!is_null($this->config_imagemagick_path) ? $this->config_imagemagick_path : ''); if ($this->config_imagemagick_path && ($this->config_imagemagick_path != realpath($this->config_imagemagick_path))) { @@ -1102,14 +1162,17 @@ $this->DebugMessage('Leaving $this->config_imagemagick_path as ('.$this->config_imagemagick_path.') because !is_execuatable(realpath($this->config_imagemagick_path)) ('.realpath($this->config_imagemagick_path).')', __FILE__, __LINE__); } } - $this->DebugMessage(' file_exists('.$this->config_imagemagick_path.') = '.intval( @file_exists($this->config_imagemagick_path)), __FILE__, __LINE__); - $this->DebugMessage('is_executable('.$this->config_imagemagick_path.') = '.intval(@is_executable($this->config_imagemagick_path)), __FILE__, __LINE__); - if (@file_exists($this->config_imagemagick_path)) { + $this->DebugMessage(' file_exists('.$this->config_imagemagick_path.') = '.intval( @file_exists($this->config_imagemagick_path)), __FILE__, __LINE__); + $this->DebugMessage('file_exists_ignoreopenbasedir('.$this->config_imagemagick_path.') = '.intval($this->file_exists_ignoreopenbasedir($this->config_imagemagick_path)), __FILE__, __LINE__); + $this->DebugMessage(' is_file('.$this->config_imagemagick_path.') = '.intval( @is_file($this->config_imagemagick_path)), __FILE__, __LINE__); + $this->DebugMessage(' is_executable('.$this->config_imagemagick_path.') = '.intval( @is_executable($this->config_imagemagick_path)), __FILE__, __LINE__); + + if ($this->file_exists_ignoreopenbasedir($this->config_imagemagick_path)) { $this->DebugMessage('using ImageMagick path from $this->config_imagemagick_path ('.$this->config_imagemagick_path.')', __FILE__, __LINE__); if ($this->iswindows) { - $commandline = substr($this->config_imagemagick_path, 0, 2).' && cd "'.str_replace('/', DIRECTORY_SEPARATOR, substr(dirname($this->config_imagemagick_path), 2)).'" && '.basename($this->config_imagemagick_path); + $commandline = substr($this->config_imagemagick_path, 0, 2).' && cd '.escapeshellarg(str_replace('/', DIRECTORY_SEPARATOR, substr(dirname($this->config_imagemagick_path), 2))).' && '.escapeshellarg(basename($this->config_imagemagick_path)); } else { - $commandline = '"'.$this->config_imagemagick_path.'"'; + $commandline = escapeshellarg($this->config_imagemagick_path); } return $commandline; } @@ -1117,7 +1180,7 @@ $which_convert = $this->ImageMagickWhichConvert(); $IMversion = $this->ImageMagickVersion(); - if ($which_convert && ($which_convert{0} == '/') && @file_exists($which_convert)) { + if ($which_convert && ($which_convert{0} == '/') && $this->file_exists_ignoreopenbasedir($which_convert)) { // `which convert` *should* return the path if "convert" exist, or nothing if it doesn't // other things *may* get returned, like "sh: convert: not found" or "no convert in /usr/local/bin /usr/sbin /usr/bin /usr/ccs/bin" @@ -1143,24 +1206,24 @@ function ImageMagickVersion($returnRAW=false) { static $versionstring = null; if (is_null($versionstring)) { + $versionstring = array(0=>false, 1=>false); $commandline = $this->ImageMagickCommandlineBase(); $commandline = (!is_null($commandline) ? $commandline : ''); - $versionstring = array(0=>'', 1=>''); if ($commandline) { $commandline .= ' --version'; $this->DebugMessage('ImageMagick version checked with "'.$commandline.'"', __FILE__, __LINE__); $versionstring[1] = trim(phpthumb_functions::SafeExec($commandline)); - if (eregi('^Version: [^0-9]*([ 0-9\\.\\:Q/]+) (http|file)\:', $versionstring[1], $matches)) { + if (preg_match('#^Version: [^0-9]*([ 0-9\\.\\:Q/\\-]+) (http|file)\:#i', $versionstring[1], $matches)) { $versionstring[0] = $matches[1]; } else { $versionstring[0] = false; $this->DebugMessage('ImageMagick did not return recognized version string ('.$versionstring[1].')', __FILE__, __LINE__); } - $this->DebugMessage('ImageMagick convert --version says "'.$matches[0].'"', __FILE__, __LINE__); + $this->DebugMessage('ImageMagick convert --version says "'.@$matches[0].'"', __FILE__, __LINE__); } } - return @$versionstring[intval($returnRAW)]; + return $versionstring[intval($returnRAW)]; } function ImageMagickSwitchAvailable($switchname) { @@ -1172,7 +1235,7 @@ $commandline .= ' -help'; $IMhelp_lines = explode("\n", phpthumb_functions::SafeExec($commandline)); foreach ($IMhelp_lines as $line) { - if (ereg('^[\+\-]([a-z\-]+) ', trim($line), $matches)) { + if (preg_match('#^[\\+\\-]([a-z\\-]+) #', trim($line), $matches)) { $IMoptions[$matches[1]] = true; } } @@ -1288,14 +1351,26 @@ } } + // http://freealter.org/doc_distrib/ImageMagick-5.1.1/www/convert.html if (!$this->sourceFilename && $this->rawImageData) { - !$this->SourceDataToTempFile(); + $this->SourceDataToTempFile(); } if (!$this->sourceFilename) { $this->DebugMessage('ImageMagickThumbnailToGD() aborting because $this->sourceFilename is empty', __FILE__, __LINE__); $this->useRawIMoutput = false; return false; } + if ($this->issafemode) { + $this->DebugMessage('ImageMagickThumbnailToGD() aborting because safe_mode is enabled', __FILE__, __LINE__); + $this->useRawIMoutput = false; + return false; + } +// TO BE FIXED +//if (true) { +// $this->DebugMessage('ImageMagickThumbnailToGD() aborting it is broken right now', __FILE__, __LINE__); +// $this->useRawIMoutput = false; +// return false; +//} $commandline = $this->ImageMagickCommandlineBase(); if ($commandline) { @@ -1309,9 +1384,9 @@ $IMresizeParameter = 'resize'; // some (older? around 2002) versions of IM won't accept "-resize 100x" but require "-resize 100x100" - $commandline_test = $this->ImageMagickCommandlineBase().' logo: -resize 1x "'.$IMtempfilename.'" 2>&1'; + $commandline_test = $this->ImageMagickCommandlineBase().' logo: -resize 1x '.escapeshellarg($IMtempfilename).' 2>&1'; $IMresult_test = phpthumb_functions::SafeExec($commandline_test); - $IMuseExplicitImageOutputDimensions = eregi('image dimensions are zero', $IMresult_test); + $IMuseExplicitImageOutputDimensions = preg_match('#image dimensions are zero#i', $IMresult_test); $this->DebugMessage('IMuseExplicitImageOutputDimensions = '.intval($IMuseExplicitImageOutputDimensions), __FILE__, __LINE__); if ($fp_im_temp = @fopen($IMtempfilename, 'wb')) { // erase temp image so ImageMagick logo doesn't get output if other processing fails @@ -1322,7 +1397,7 @@ if (!is_null($this->dpi) && $this->ImageMagickSwitchAvailable('density')) { // for raster source formats only (WMF, PDF, etc) - $commandline .= ' -density '.$this->dpi; + $commandline .= ' -density '.escapeshellarg($this->dpi); } ob_start(); $getimagesize = GetImageSize($this->sourceFilename); @@ -1340,16 +1415,14 @@ $this->DebugMessage('source dimensions set to '.$this->source_width.'x'.$this->source_height, __FILE__, __LINE__); $this->SetOrientationDependantWidthHeight(); - if (!eregi('('.implode('|', $this->AlphaCapableFormats).')', $outputFormat)) { + if (!preg_match('#('.implode('|', $this->AlphaCapableFormats).')#i', $outputFormat)) { // not a transparency-capable format - $commandline .= ' -background "#'.($this->bg ? $this->bg : 'FFFFFF').'"'; - if ($getimagesize[2] == 1) { - // GIF + $commandline .= ' -background '.escapeshellarg('#'.($this->bg ? $this->bg : 'FFFFFF')); + if ($getimagesize[2] == IMAGETYPE_GIF) { $commandline .= ' -flatten'; } } - if ($getimagesize[2] == 1) { - // GIF + if ($getimagesize[2] == IMAGETYPE_GIF) { $commandline .= ' -coalesce'; // may be needed for animated GIFs } if ($this->source_width || $this->source_height) { @@ -1358,7 +1431,7 @@ $borderThickness = 0; if (!empty($this->fltr)) { foreach ($this->fltr as $key => $value) { - if (ereg('^bord\|([0-9]+)', $value, $matches)) { + if (preg_match('#^bord\|([0-9]+)#', $value, $matches)) { $borderThickness = $matches[1]; break; } @@ -1373,11 +1446,7 @@ $sideY = phpthumb_functions::nonempty_min( $this->source_height, $hAll, round($wAll / $zcAR)); $thumbnailH = round(max($sideY, ($sideY * $zcAR) / $imAR)); - if ($IMuseExplicitImageOutputDimensions) { - $commandline .= ' -'.$IMresizeParameter.' '.$thumbnailH.'x'.$thumbnailH; - } else { - $commandline .= ' -'.$IMresizeParameter.' x'.$thumbnailH; - } + $commandline .= ' -'.$IMresizeParameter.' '.escapeshellarg(($IMuseExplicitImageOutputDimensions ? $thumbnailH : '').'x'.$thumbnailH); switch (strtoupper($this->zc)) { case 'T': @@ -1412,9 +1481,9 @@ } if (($wAll > 0) && ($hAll > 0)) { - $commandline .= ' -crop '.$wAll.'x'.$hAll.'+0+0'; + $commandline .= ' -crop '.escapeshellarg($wAll.'x'.$hAll.'+0+0'); } else { - $commandline .= ' -crop '.$side.'x'.$side.'+0+0'; + $commandline .= ' -crop '.escapeshellarg($side.'x'.$side.'+0+0'); } if ($this->ImageMagickSwitchAvailable('repage')) { $commandline .= ' +repage'; @@ -1424,10 +1493,23 @@ } elseif ($this->sw || $this->sh || $this->sx || $this->sy) { - $commandline .= ' -crop '.($this->sw ? $this->sw : $this->source_width).'x'.($this->sh ? $this->sh : $this->source_height).'+'.$this->sx.'+'.$this->sy; + $crop_param = ''; + $crop_param .= ($this->sw ? (($this->sw < 2) ? round($this->sw * $this->source_width) : $this->sw) : $this->source_width); + $crop_param .= 'x'.($this->sh ? (($this->sh < 2) ? round($this->sh * $this->source_height) : $this->sh) : $this->source_height); + $crop_param .= '+'.(($this->sx < 2) ? round($this->sx * $this->source_width) : $this->sx); + $crop_param .= '+'.(($this->sy < 2) ? round($this->sy * $this->source_height) : $this->sy); +// TO BE FIXED +// makes 1x1 output +// http://trainspotted.com/phpThumb/phpThumb.php?src=/content/CNR/47/CNR-4728-LD-L-20110723-898.jpg&w=100&h=100&far=1&f=png&fltr[]=lvl&sx=0.05&sy=0.25&sw=0.92&sh=0.42 +// '/usr/bin/convert' -density 150 -thumbnail 100x100 -contrast-stretch '0.1%' '/var/www/vhosts/trainspotted.com/httpdocs/content/CNR/47/CNR-4728-LD-L-20110723-898.jpg[0]' png:'/var/www/vhosts/trainspotted.com/httpdocs/phpThumb/_cache/pThumbIIUlvj' +// $commandline .= ' -crop '.escapeshellarg($crop_param); + // this is broken for aoe=1, but unsure how to fix. Send advice to in...@si... if ($this->w || $this->h) { - if ($this->ImageMagickSwitchAvailable('repage')) { + //if ($this->ImageMagickSwitchAvailable('repage')) { +if (false) { +// TO BE FIXED +// newer versions of ImageMagick require -repage <geometry> $commandline .= ' -repage'; } else { $this->DebugMessage('Skipping "-repage" because ImageMagick (v'.$this->ImageMagickVersion().') does not support it', __FILE__, __LINE__); @@ -1439,17 +1521,16 @@ $this->w = ceil($this->h * ($this->source_width / $this->source_height)); } } - $commandline .= ' -'.$IMresizeParameter.' '.$this->w.'x'.$this->h; + $commandline .= ' -'.$IMresizeParameter.' '.escapeshellarg($this->w.'x'.$this->h); } } else { if ($this->iar && (intval($this->w) > 0) && (intval($this->h) > 0)) { - //$commandline .= ' -'.$IMresizeParameter.' '.$this->w.'x'.$this->h.'!'; list($nw, $nh) = phpthumb_functions::TranslateWHbyAngle($this->w, $this->h, $this->ra); $nw = ((round($nw) != 0) ? round($nw) : ''); $nh = ((round($nh) != 0) ? round($nh) : ''); - $commandline .= ' -'.$IMresizeParameter.' '.$nw.'x'.$nh.'!'; + $commandline .= ' -'.$IMresizeParameter.' '.escapeshellarg($nw.'x'.$nh.'!'); } else { $this->w = ((($this->aoe || $this->far) && $this->w) ? $this->w : ($this->w ? phpthumb_functions::nonempty_min($this->w, $getimagesize[0]) : '')); $this->h = ((($this->aoe || $this->far) && $this->h) ? $this->h : ($this->h ? phpthumb_functions::nonempty_min($this->h, $getimagesize[1]) : '')); @@ -1461,11 +1542,10 @@ $this->w = ceil($this->h * ($this->source_width / $this->source_height)); } } - //$commandline .= ' -'.$IMresizeParameter.' '.$this->w.'x'.$this->h; list($nw, $nh) = phpthumb_functions::TranslateWHbyAngle($this->w, $this->h, $this->ra); $nw = ((round($nw) != 0) ? round($nw) : ''); $nh = ((round($nh) != 0) ? round($nh) : ''); - $commandline .= ' -'.$IMresizeParameter.' '.$nw.'x'.$nh; + $commandline .= ' -'.$IMresizeParameter.' '.escapeshellarg($nw.'x'.$nh); } } } @@ -1475,15 +1555,13 @@ $this->DebugMessage('GetImageSize('.$this->sourceFilename.') failed', __FILE__, __LINE__); if ($this->w || $this->h) { + $exactDimensionsBang = (($this->iar && (intval($this->w) > 0) && (intval($this->h) > 0)) ? '!' : ''); if ($IMuseExplicitImageOutputDimensions) { - // unknown source aspect ration, just put large number and hope IM figures it out - $commandline .= ' -'.$IMresizeParameter.' '.($this->w ? $this->w : '9999').'x'.($this->h ? $this->h : '9999'); + // unknown source aspect ratio, just put large number and hope IM figures it out + $commandline .= ' -'.$IMresizeParameter.' '.escapeshellarg(($this->w ? $this->w : '9999').'x'.($this->h ? $this->h : '9999').$exactDimensionsBang); } else { - $commandline .= ' -'.$IMresizeParameter.' '.$this->w.'x'.$this->h; + $commandline .= ' -'.$IMresizeParameter.' '.escapeshellarg($this->w.'x'.$this->h.$exactDimensionsBang); } - if ($this->iar && (intval($this->w) > 0) && (intval($this->h) > 0)) { - $commandline .= '!'; - } } } @@ -1491,15 +1569,15 @@ if ($this->ra) { $this->ra = intval($this->ra); if ($this->ImageMagickSwitchAvailable('rotate')) { - if (!eregi('('.implode('|', $this->AlphaCapableFormats).')', $outputFormat) || phpthumb_functions::version_compare_replacement($this->ImageMagickVersion(), '6.3.7', '>=')) { + if (!preg_match('#('.implode('|', $this->AlphaCapableFormats).')#i', $outputFormat) || phpthumb_functions::version_compare_replacement($this->ImageMagickVersion(), '6.3.7', '>=')) { $this->DebugMessage('Using ImageMagick rotate', __FILE__, __LINE__); - $commandline .= ' -rotate '.$this->ra; + $commandline .= ' -rotate '.escapeshellarg($this->ra); if (($this->ra % 90) != 0) { - if (eregi('('.implode('|', $this->AlphaCapableFormats).')', $outputFormat)) { + if (preg_match('#('.implode('|', $this->AlphaCapableFormats).')#i', $outputFormat)) { // alpha-capable format $commandline .= ' -background rgba(255,255,255,0)'; } else { - $commandline .= ' -background "#'.($this->bg ? $this->bg : 'FFFFFF').'"'; + $commandline .= ' -background '.escapeshellarg('#'.($this->bg ? $this->bg : 'FFFFFF')); } } $this->ra = 0; @@ -1517,19 +1595,21 @@ switch ($command) { case 'brit': if ($this->ImageMagickSwitchAvailable('modulate')) { - $commandline .= ' -modulate '.(100 + $parameter).',100,100'; + $commandline .= ' -modulate '.escapeshellarg((100 + intval($parameter)).',100,100'); $successfullyProcessedFilters[] = $filterkey; } break; case 'cont': if ($this->ImageMagickSwitchAvailable('contrast')) { - $contDiv10 = round($parameter / 10); + $contDiv10 = round(intval($parameter) / 10); if ($contDiv10 > 0) { + $contDiv10 = min($contDiv10, 100); for ($i = 0; $i < $contDiv10; $i++) { $commandline .= ' -contrast'; // increase contrast by 10% } } elseif ($contDiv10 < 0) { + $contDiv10 = max($contDiv10, -100); for ($i = $contDiv10; $i < 0; $i++) { $commandline .= ' +contrast'; // decrease contrast by 10% } @@ -1543,9 +1623,10 @@ case 'ds': if ($this->ImageMagickSwitchAvailable(array('colorspace', 'modulate'))) { if ($parameter == 100) { - $commandline .= ' -colorspace GRAY -modulate 100,0,100'; + $commandline .= ' -colorspace GRAY'; + $commandline .= ' -modulate 100,0,100'; } else { - $commandline .= ' -modulate 100,'.(100 - $parameter).',100'; + $commandline .= ' -modulate '.escapeshellarg('100,'.(100 - intval($parameter)).',100'); } $successfullyProcessedFilters[] = $filterkey; } @@ -1554,9 +1635,10 @@ case 'sat': if ($this->ImageMagickSwitchAvailable(array('colorspace', 'modulate'))) { if ($parameter == -100) { - $commandline .= ' -colorspace GRAY -modulate 100,0,100'; + $commandline .= ' -colorspace GRAY'; + $commandline .= ' -modulate 100,0,100'; } else { - $commandline .= ' -modulate 100,'.(100 + $parameter).',100'; + $commandline .= ' -modulate '.escapeshellarg('100,'.(100 + intval($parameter)).',100'); } $successfullyProcessedFilters[] = $filterkey; } @@ -1564,8 +1646,8 @@ case 'gray': if ($this->ImageMagickSwitchAvailable(array('colorspace', 'modulate'))) { - $commandline .= ' -colorspace GRAY -modulate 100,0,100'; - //$commandline .= ' -colorspace GRAY'; + $commandline .= ' -colorspace GRAY'; + $commandline .= ' -modulate 100,0,100'; $successfullyProcessedFilters[] = $filterkey; } break; @@ -1573,7 +1655,8 @@ case 'clr': if ($this->ImageMagickSwitchAvailable(array('fill', 'colorize'))) { @list($amount, $color) = explode('|', $parameter); - $commandline .= ' -fill "#'.$color.'" -colorize '.$amount; + $commandline .= ' -fill '.escapeshellarg('#'.preg_replace('#[^0-9A-F]#i', '', $color)); + $commandline .= ' -colorize '.escapeshellarg(min(max(intval($amount), 0), 100)); } break; @@ -1582,16 +1665,20 @@ @list($amount, $color) = explode('|', $parameter); $amount = ($amount ? $amount : 80); if (!$color) { - $commandline .= ' -sepia-tone '.$amount.'%'; + $commandline .= ' -sepia-tone '.escapeshellarg(min(max(intval($amount), 0), 100).'%'); $successfullyProcessedFilters[] = $filterkey; } } break; case 'gam': - if ($this->ImageMagickSwitchAvailable('gamma')) { - $commandline .= ' -gamma '.$parameter; - $successfullyProcessedFilters[] = $filterkey; + @list($amount) = explode('|', $parameter); + $amount = min(max(floatval($amount), 0.001), 10); + if (number_format($amount, 3) != '1.000') { + if ($this->ImageMagickS... [truncated message content] |