1<?php
2//////////////////////////////////////////////////////////////
3//   phpThumb() by James Heinrich <info@silisoftware.com>   //
4//        available at http://phpthumb.sourceforge.net      //
5//         and/or https://github.com/JamesHeinrich/phpThumb //
6//////////////////////////////////////////////////////////////
7///                                                         //
8// phpThumb.demo.check.php                                  //
9// James Heinrich <info@silisoftware.com>                   //
10//                                                          //
11// Configuration analyzer for phpThumb settings and server  //
12// settings that may affect phpThumb performance            //
13// Live demo is at http://phpthumb.sourceforge.net/demo/    //
14//                                                          //
15//////////////////////////////////////////////////////////////
16die('For security reasons, this demo is disabled by default. Please comment out line '.__LINE__.' in '.basename(__FILE__));
17
18$ServerInfo['gd_string']  = 'unknown';
19$ServerInfo['gd_numeric'] = 0;
20//ob_start();
21if (!include_once '../phpthumb.functions.php' ) {
22	ob_end_flush();
23	die('failed to include_once("../phpthumb.functions.php")');
24}
25if (!include_once '../phpthumb.class.php' ) {
26	//ob_end_flush();
27	die('failed to include_once("../phpthumb.class.php")');
28}
29//ob_end_clean();
30$phpThumb = new phpThumb();
31if (file_exists('../phpThumb.config.php') && include_once '../phpThumb.config.php' ) {
32	foreach ($PHPTHUMB_CONFIG as $key => $value) {
33		$phpThumb->setParameter('config_'.$key, $value);
34	}
35} else {
36	echo '<div style="color: red; border: 1px red dashed; font-weight: bold; padding: 10px; margin: 10px; display: inline-block;">Error reading ../phpThumb.config.php</div><br>';
37}
38
39$ServerInfo['gd_string']  = phpthumb_functions::gd_version(true);
40$ServerInfo['gd_numeric'] = phpthumb_functions::gd_version(false);
41$ServerInfo['im_version'] = $phpThumb->ImageMagickVersion();
42$gd_info                  = gd_info();
43
44?>
45
46<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
47<html>
48<head>
49	<title>phpThumb configuration analyzer</title>
50	<link rel="stylesheet" type="text/css" href="/style.css" title="style sheet">
51</head>
52<body style="background-color: #CCCCCC;">
53
54This demo analyzes your settings (phpThumb.config.php and server/PHP) for <a href="http://phpthumb.sourceforge.net"><b>phpThumb()</b></a>.<br>
55<br>
56<table border="1">
57	<tr><th colspan="8">&lt;-- bad . . . . . good --&gt;</th></tr>
58	<tr>
59		<td style="background-color: red;"       >&nbsp;&nbsp;&nbsp;&nbsp;</td>
60		<td style="background-color: orange;"    >&nbsp;&nbsp;&nbsp;&nbsp;</td>
61		<td style="background-color: yellow;"    >&nbsp;&nbsp;&nbsp;&nbsp;</td>
62		<td style="background-color: olive;"     >&nbsp;&nbsp;&nbsp;&nbsp;</td>
63		<td style="background-color: darkgreen;" >&nbsp;&nbsp;&nbsp;&nbsp;</td>
64		<td style="background-color: green;"     >&nbsp;&nbsp;&nbsp;&nbsp;</td>
65		<td style="background-color: lightgreen;">&nbsp;&nbsp;&nbsp;&nbsp;</td>
66		<td style="background-color: lime;"      >&nbsp;&nbsp;&nbsp;&nbsp;</td>
67	</tr>
68</table>
69<table border="1" cellspacing="0" cellpadding="2">
70<tr style="background-color: #EEEEEE;"><th>Setting</th><th colspan="2">Value</th><th>Comments</th></tr>
71<?php
72
73$versions['raw'] = array(
74	'latest' => phpthumb_functions::SafeURLread('http://phpthumb.sourceforge.net/?latestversion=1', $dummy),
75	'this'   => $phpThumb->phpthumb_version,
76);
77foreach ($versions['raw'] as $key => $value) {
78	preg_match('#^([0-9\\.]+)\\-?(([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2}))?#i', $value, $matches);
79	@list($huge, $major, $minor) = @explode('.', @$matches[1]);
80	@list($year, $month, $day, $hour, $min) = @$matches[3];
81	$versions['base'][$key]  = $matches[1];
82	$versions['huge'][$key]  = $huge;
83	$versions['major'][$key] = $major;
84	$versions['minor'][$key] = $minor;
85	$versions['stamp'][$key] = $matches[2];
86	$versions['year'][$key]  = $year;
87	$versions['month'][$key] = $month;
88	$versions['day'][$key]   = $day;
89	$versions['hour'][$key]  = $hour;
90	$versions['min'][$key]   = $min;
91	$versions['date'][$key]  = @mktime($hour, $min, 0, $month, $day, $year);
92}
93$downloadlatest = 'Download the latest version from <a href="https://github.com/JamesHeinrich/phpThumb/">https://github.com/JamesHeinrich/phpThumb/</a>';
94echo '<tr><th nowrap>Latest phpThumb version:</th><th colspan="2">'.$versions['raw']['latest'].'</th><td>'.$downloadlatest.'</td></tr>';
95echo '<tr><th nowrap>This phpThumb version:</th><th colspan="2" style="background-color: ';
96
97if (!$versions['base']['latest']) {
98	// failed to get latest version number
99	echo 'white';
100	$message = 'Latest version unknown.<br>'.$downloadlatest;
101} elseif (phpthumb_functions::version_compare_replacement($versions['base']['this'], $versions['base']['latest'], '>')) {
102	// new than latest, must be beta version
103	echo 'lightblue';
104	$message = 'This must be a pre-release beta version. Please report bugs to <a href="mailto:info@silisoftware.com">info@silisoftware.com</a>';
105} elseif (($versions['base']['latest'] == $versions['base']['this']) && ($versions['stamp']['this'] > $versions['stamp']['latest'])) {
106	// new than latest, must be beta version
107	echo 'lightblue';
108	$message = 'You must be using a pre-release beta version. Please report bugs to <a href="mailto:info@silisoftware.com">info@silisoftware.com</a>';
109} elseif ($versions['base']['latest'] == $versions['base']['this']) {
110	// latest version
111	echo 'lime';
112	$message = 'You are using the latest released version.';
113} elseif ($versions['huge']['latest'].$versions['major']['latest'] == $versions['huge']['this'].$versions['major']['this']) {
114	echo 'olive';
115	$message = 'One (or more) minor version(s) have been released since this version.<br>'.$downloadlatest;
116} elseif ((float) ($versions[ 'huge'][ 'latest'].str_pad($versions[ 'major'][ 'latest'], 2, '0', STR_PAD_LEFT)) < (float) ($versions[ 'huge'][ 'this'].str_pad($t_major, 2, '0', STR_PAD_LEFT))) {
117	echo 'yellow';
118	$message = 'One (or more) major version(s) have been released since this version, you really should upgrade.<br>'.$downloadlatest;
119} else {
120	echo 'orange';
121	$message = 'Fundamental changes have been made since this version.<br>'.$downloadlatest;
122}
123echo ';">'.$phpThumb->phpthumb_version;
124echo '</th><td>'.$message.'.<br></td></tr>';
125
126
127echo '<tr><th>phpThumb.config.php:</th><th colspan="2" style="background-color: ';
128if (file_exists('../phpThumb.config.php') && !file_exists('../phpThumb.config.php.default')) {
129	if (!defined('phpThumbConfigFileVersion') || phpthumb_functions::version_compare_replacement($versions['base']['this'], phpThumbConfigFileVersion, '>')) {
130		echo 'red;">"phpThumb.config.php" version does not match phpThumb version. Please be sure to use the config file from the phpThumb distribution (copy any customized settings to the .default file, then rename "phpThumb.config.php.default" to "phpThumb.config.php")';
131	} else {
132		echo 'lime;">"phpThumb.config.php" exists and "phpThumb.config.php.default" does not';
133	}
134} elseif (file_exists('../phpThumb.config.php') && file_exists('../phpThumb.config.php.default')) {
135	echo 'yellow;">"phpThumb.config.php" and "phpThumb.config.php.default" both exist';
136} elseif (!file_exists('../phpThumb.config.php') && file_exists('../phpThumb.config.php.default')) {
137	echo 'red;">rename "phpThumb.config.php.default" to "phpThumb.config.php"';
138} else {
139	echo 'red;">"phpThumb.config.php" not found';
140}
141echo '</th><td>"phpThumb.config.php.default" that comes in the distribution must be renamed to "phpThumb.config.php" before phpThumb.php can be used. Avoid having both files present to minimize confusion.</td></tr>';
142
143
144echo '<tr><th>phpThumb.config.php<br>[disable_debug]</th>';
145echo '<th colspan="2" style="background-color: '.($PHPTHUMB_CONFIG['disable_debug'] ? 'lime' : 'red').'">'.($PHPTHUMB_CONFIG['disable_debug'] ? 'true' : 'false').'</th>';
146echo '<td>DO NOT DISABLE THIS ON ANY PUBLIC-ACCESSIBLE SERVER. Prevents phpThumb from displaying any information about your system. If true, phpThumbDebug and error messages will be disabled. If set to false (debug messages enabled) then debug mode will be FORCED -- ONLY debug output will be presented, no actual thumbnail (to avoid accidentally leaving debug mode enabled on a production server).</td></tr>';
147
148echo '<tr><th>phpThumb.config.php<br>[high_security_enabled]</th>';
149echo '<th colspan="2" style="background-color: '.($PHPTHUMB_CONFIG['high_security_enabled'] ? 'lime' : 'red').'">'.($PHPTHUMB_CONFIG['high_security_enabled'] ? 'true' : 'false').'</th>';
150echo '<td>DO NOT DISABLE THIS ON ANY PUBLIC-ACCESSIBLE SERVER. If disabled, your server is more vulnerable to hacking attempts, both on your server and via your server to other servers. When enabled, requires "high_security_password" set to be set and requires the use of phpThumbURL() function (at the bottom of phpThumb.config.php) to generate hashed URLs.</td></tr>';
151
152echo '<tr><th>phpThumb.config.php<br>[high_security_password]</th>';
153$password_complexity = phpthumb_functions::PasswordStrength($PHPTHUMB_CONFIG['high_security_password']);
154echo '<th colspan="2" style="background-color: '.(($password_complexity >= 20) ? 'lime' : ((strlen($PHPTHUMB_CONFIG['high_security_password']) > 0) ? 'orange' : 'red')).'">'.(($password_complexity >= 20) ? 'sufficiently complex' : ((strlen($PHPTHUMB_CONFIG['high_security_password']) > 0) ? 'not complex enough' : 'not set')).'</th>';
155echo '<td>DO NOT DISABLE THIS ON ANY PUBLIC-ACCESSIBLE SERVER. If disabled, your server is more vulnerable to hacking attempts, both on your server and via your server to other servers. When enabled, requires "high_security_password" set to be set and requires the use of phpThumbURL() function (at the bottom of phpThumb.config.php) to generate hashed URLs.</td></tr>';
156
157
158echo '<tr><th>cache directory:</th><th colspan="2">';
159$orig_config_cache_directory = $phpThumb->config_cache_directory;
160$phpThumb->setCacheDirectory();
161echo '<div style="background-color: '.(     is_dir($phpThumb->config_cache_directory) ? 'lime;">exists'   : 'red;">does NOT exist').'</div>';
162echo '<div style="background-color: '.(is_readable($phpThumb->config_cache_directory) ? 'lime;">readable' : 'red;">NOT readable'  ).'</div>';
163echo '<div style="background-color: '.(is_writable($phpThumb->config_cache_directory) ? 'lime;">writable' : 'red;">NOT writable'  ).'</div>';
164echo '</th><td>Original: "'.htmlspecialchars($orig_config_cache_directory).'"<br>Resolved: "'.htmlspecialchars($phpThumb->config_cache_directory).'"<br>Must exist and be both readable and writable by PHP.</td></tr>';
165
166
167echo '<tr><th>cache write test:</th><th colspan="2">';
168$phpThumb->rawImageData = 'phpThumb.demo.check.php_cachetest';
169$phpThumb->SetCacheFilename();
170echo '<div>'.htmlspecialchars($phpThumb->cache_filename ? implode(' / ', preg_split('#[/\\\\]#', $phpThumb->cache_filename)) : 'NO CACHE FILENAME RESOLVED').'</div>';
171echo '<div>directory '.(is_dir(dirname($phpThumb->cache_filename)) ? 'exists' : 'does NOT exist').' (before EnsureDirectoryExists())</div>';
172phpthumb_functions::EnsureDirectoryExists(dirname($phpThumb->cache_filename));
173echo '<div style="background-color: '.(is_dir(dirname($phpThumb->cache_filename)) ? 'lime;">directory exists' : 'red;">directory does NOT exist').' (after EnsureDirectoryExists())</div>';
174if ($fp = @fopen($phpThumb->cache_filename, 'wb')) {
175	fwrite($fp, 'this is a test from '.__FILE__);
176	fclose($fp);
177	echo '<div style="background-color: lime;">write test succeeded</div>';
178
179	$old_perms = substr(sprintf('%o', fileperms($phpThumb->cache_filename)), -4);
180	@chmod($phpThumb->cache_filename, 0644);
181	clearstatcache();
182	$new_perms = substr(sprintf('%o', fileperms($phpThumb->cache_filename)), -4);
183	echo '<div style="background-color: '.(($new_perms == '0644') ? 'lime' : (($new_perms > '0644') ? 'orange' : 'red')).';">chmod($phpThumb->cache_filename, 0644) from "'.htmlspecialchars($old_perms).'" resulted in permissions "'.htmlspecialchars($new_perms).'"</div>';
184
185	if (@unlink($phpThumb->cache_filename)) {
186		echo '<div style="background-color: lime;">delete test succeeded</div>';
187	} else {
188		echo '<div style="background-color: red;">delete test FAILED</div>';
189	}
190	$phpThumb->CleanUpCacheDirectory();
191} else {
192	echo '<div style="background-color: red;">write test FAILED</div>';
193}
194//echo '</th><td>Original: "'.htmlspecialchars($orig_config_cache_directory).'"<br>Resolved: "'.htmlspecialchars($phpThumb->config_cache_directory).'"<br>Must exist and be both readable and writable by PHP.</td></tr>';
195echo '</th><td>Created and deletes a sample cache file to see if you actually have create/delete permission.<br>If <i>Safe Mode</i> is enabled this is often broken.</td></tr>';
196
197
198echo '<tr><th>temp directory:</th><th colspan="2">';
199$orig_config_temp_directory = $phpThumb->config_temp_directory;
200echo $phpThumb->phpThumb_tempnam();
201echo '<div style="background-color: '.(     is_dir($phpThumb->config_temp_directory) ? 'lime;">exists'   : 'red;">does NOT exist').'</div>';
202echo '<div style="background-color: '.(is_readable($phpThumb->config_temp_directory) ? 'lime;">readable' : 'red;">NOT readable'  ).'</div>';
203echo '<div style="background-color: '.(is_writable($phpThumb->config_temp_directory) ? 'lime;">writable' : 'red;">NOT writable'  ).'</div>';
204echo '</th><td>Original: "'.htmlspecialchars($orig_config_temp_directory).'"<br>Resolved: "'.htmlspecialchars($phpThumb->config_temp_directory).'"<br>Must exist and be both readable and writable by PHP.</td></tr>';
205
206
207echo '<tr><th>PHP version:</th><th colspan="2" style="background-color: ';
208if (phpthumb_functions::version_compare_replacement(PHP_VERSION, '5.0.0', '>=')) {
209	echo 'lime';
210} elseif (phpthumb_functions::version_compare_replacement(PHP_VERSION, '4.4.2', '=')) {
211	echo 'darkgreen';
212} elseif (phpthumb_functions::version_compare_replacement(PHP_VERSION, '4.3.3', '>=')) {
213	echo 'lightgreen';
214} elseif (phpthumb_functions::version_compare_replacement(PHP_VERSION, '4.2.0', '>=')) {
215	echo 'green';
216} elseif (phpthumb_functions::version_compare_replacement(PHP_VERSION, '4.1.0', '>=')) {
217	echo 'yellow';
218} elseif (phpthumb_functions::version_compare_replacement(PHP_VERSION, '4.0.6', '>=')) {
219	echo 'orange';
220} else {
221	echo 'red';
222}
223echo ';">'. PHP_VERSION;
224echo '</th><td>PHP5 is ideal (support for numerous built-in filters which are much faster than my code).<br>PHP v4.4.2 contains a bug in fopen over HTTP (phpThumb has a workaround)<br>PHP v4.3.2+ supports imagesavealpha which is required for proper PNG/ICO output.<br>imagerotate requires PHP v4.3.0+ (but buggy before v4.3.3).<br>EXIF thumbnail extraction requires PHP v4.2.0+.<br>Most things will work back to PHP v4.1.0, and mostly (perhaps buggy) back to v4.0.6, but no guarantees for any version older than that.</td></tr>';
225
226
227echo '<tr><th>GD version:</th><th colspan="2" style="background-color: ';
228if ($ServerInfo['gd_numeric'] >= 2) {
229	if (!empty($ServerInfo['gd_string']) && false !== stripos($ServerInfo[ 'gd_string' ], 'bundled')) {
230		echo 'lime';
231	} else {
232		echo 'yellow';
233	}
234} elseif (!empty($ServerInfo['im_version'])) {
235	echo 'orange';
236} else {
237	echo 'red';
238}
239echo ';">'.(!empty($ServerInfo['gd_string']) ? $ServerInfo['gd_string'] : 'n/a');
240echo '</th><td>GD2-bundled version is ideal.<br>GD2 (non-bundled) is second choice, but there are a number of bugs in the non-bundled version. imagerotate is only available in the bundled version of GD2.<br>GD1 will also (mostly) work, at much-reduced image quality and several features disabled. phpThumb can perform most operations with ImageMagick only, even if GD is not available.</td></tr>';
241
242
243$IMreleaseDate = 0;
244if (preg_match('# ([0-9]{2})/([0-9]{2})/([0-9]{2}) #', $ServerInfo['im_version'], $matches)) {
245	list($dummy, $m, $d, $y) = $matches;
246	if ($y < 70) {
247		$y += 2000;
248	} elseif ($y < 100) {
249		$y += 1900;
250	}
251	$IMreleaseDate = mktime(12, 0, 0, $m, $d, $y);
252} elseif (preg_match('# ([0-9]{4})\\-([0-9]{2})\\-([0-9]{2}) #', $ServerInfo['im_version'], $matches)) {
253	list($dummy, $y, $m, $d) = $matches;
254	$IMreleaseDate = mktime(12, 0, 0, $m, $d, $y);
255}
256$IMversionAge = time() - $IMreleaseDate;
257echo '<tr><th>ImageMagick version:</th><th colspan="2" style="background-color: ';
258if ($ServerInfo['im_version']) {
259	if ($IMversionAge < (86400 * 365 * 1)) {
260		echo 'lime';
261	} elseif ($IMversionAge < (86400 * 365 * 2)) {
262		echo 'lightgreen';
263	} elseif ($IMversionAge < (86400 * 365 * 3)) {
264		echo 'green';
265	} elseif ($IMversionAge < (86400 * 365 * 4)) {
266		echo 'darkgreen';
267	} else {
268		echo 'olive';
269	}
270} elseif (!empty($ServerInfo['gd_string'])) {
271	echo 'orange';
272} else {
273	echo 'red';
274}
275echo ';">';
276echo '<div style="color: navy; font-family: monospace;">'.htmlspecialchars($phpThumb->config_imagemagick_path);
277echo ' <span style="cursor: help;" title="file_exists"                  >['. (int) (@file_exists($phpThumb->config_imagemagick_path)) .']</span> ';
278echo ' <span style="cursor: help;" title="file_exists_ignoreopenbasedir">['. (int) $phpThumb->file_exists_ignoreopenbasedir($phpThumb->config_imagemagick_path) .']</span> ';
279echo ' <span style="cursor: help;" title="is_file"                      >['. (int) (@is_file($phpThumb->config_imagemagick_path)) .']</span> ';
280echo ' <span style="cursor: help;" title="is_readable"                  >['. (int) (@is_readable($phpThumb->config_imagemagick_path)) .']</span> ';
281echo ' <span style="cursor: help;" title="is_executable"                >['. (int) (@is_executable($phpThumb->config_imagemagick_path)) .']</span> ';
282echo '</div>';
283echo '<div style="color: blue; font-family: monospace;">'.htmlspecialchars($phpThumb->ImageMagickCommandlineBase()).'</div>';
284echo ($ServerInfo['im_version'] ?: 'n/a');
285echo ($IMreleaseDate ? '<br><br>This version of ImageMagick is '.NiceTimeFormatting($IMversionAge).' old<br>(see <a href="http://www.imagemagick.org/">www.imagemagick.org</a> for new versions)' : '');
286echo '</th><td>ImageMagick is faster than GD, can process larger images without PHP memory_limit issues, can resize animated GIFs. phpThumb can perform most operations with ImageMagick only, even if GD is not available.</td></tr>';
287
288
289echo '<tr><th>ImageMagick features:</th>';
290if ($ServerInfo['im_version']) {
291	$GDfeatures['red']    = array('help', 'thumbnail', 'resize', 'crop', 'repage', 'coalesce', 'gravity', 'background', 'interlace', 'flatten', 'border', 'bordercolor', 'dither', 'quality');
292	$GDfeatures['orange'] = array('version', 'blur', 'colorize', 'colors', 'colorspace', 'contrast', 'contrast-stretch', 'edge', 'emboss', 'fill', 'flip', 'flop', 'gamma', array('gaussian','gaussian-blur'), 'level', 'modulate', 'monochrome', 'negate', 'normalize', 'rotate', 'sepia-tone', 'threshold', 'unsharp');
293	echo '<th colspan="2">|';
294	foreach ($GDfeatures as $missingcolor => $features) {
295		foreach ($features as $dummy => $feature) {
296			$foundOneThatWorks = false;
297			if (is_array($feature)) {
298				// sometimes feature names change, e.g. "gaussian" -> "gaussian-blur". They won't both exist in the same version of ImageMagick, but as long as one of them does then the feature will work
299				foreach ($feature as $alternate_feature_name) {
300					if ($phpThumb->ImageMagickSwitchAvailable($alternate_feature_name)) {
301						$foundOneThatWorks = true;
302						$feature = $alternate_feature_name;
303						break;
304					}
305					echo '| <span style="background-color: '.($foundOneThatWorks ? 'lime' : $missingcolor).';">'.htmlspecialchars($alternate_feature_name).'</span> |';
306				}
307			} else {
308				$foundOneThatWorks = $phpThumb->ImageMagickSwitchAvailable($feature);
309				echo '| <span style="background-color: '.($foundOneThatWorks ? 'lime' : $missingcolor).';">'.htmlspecialchars($feature).'</span> |';
310			}
311		}
312	}
313	echo '|</th>';
314} else {
315	echo '<th colspan="2" style="background-color: orange;">ImageMagick not found</th>';
316}
317echo '<td>All of these parameters may be called by phpThumb, depending on parameters used.  Green means the feature is available; red means a critical feature is missing; orange means an optional filter/feature is missing.</td></tr>';
318
319
320echo '<tr><th>ImageMagick formats:</th>';
321if ($ServerInfo['im_version']) {
322	echo '<td colspan="2"><div style="width: 100%; height: 200px; overflow: auto; font-family: monospace; white-space: pre; background-color: #FFFFFF;">'.htmlspecialchars($phpThumb->ImageMagickFormatsList()).'</div></td>';
323} else {
324	echo '<th colspan="2" style="background-color: orange;">ImageMagick not found</th>';
325}
326echo '<td>ImageMagick can only read/write formats as listed here. You may need to recompile ImageMagick if you need to use a format not listed</td></tr>';
327
328echo '<tr><th>GD features:</th><th colspan="2">';
329$GDfeatures['red']    = array('JPEG Support', 'JPG Support', 'PNG Support'); // older versions would report "JPG Support", newer versions report "JPEG Support"
330$GDfeatures['orange'] = array('GIF Read Support', 'GIF Create Support', 'FreeType Support');
331foreach ($GDfeatures as $missingcolor => $features) {
332	foreach ($features as $dummy => $feature) {
333		if (isset($gd_info[$feature])) {
334			echo '<div style="background-color: '.($gd_info[$feature] ? 'lime' : $missingcolor).';">'.htmlspecialchars($feature).'</div>';
335		}
336	}
337}
338echo '</th><td>PNG support is required for watermarks, overlays, calls to ImageMagick and other internal operations.<br>JPG support is obviously quite useful, but ImageMagick can substitute<br>GIF read support can be bypassed with ImageMagick and/or internal GIF routines.<br>GIF create support can be bypassed with ImageMagick (if no filters are applied)<br>FreeType support is needed for TTF overlays.</td></tr>';
339
340
341echo '<tr><th>GD extension "EXIF"</th><th colspan="2" style="background-color: ';
342if (extension_loaded('exif')) {
343	echo 'lime';
344} elseif (!empty($ServerInfo['gd_string'])) {
345	echo 'orange';
346}
347echo ';">'.(extension_loaded('exif') ? 'TRUE' : 'FALSE');
348echo '</th><td>EXIF extension required for auto-rotate images. Also required to extract EXIF thumbnail to use as source if source image is too large for PHP memory_limit and ImageMagick is unavailable.</td></tr>';
349
350
351echo '<tr><th>php_sapi_name()</th><th colspan="2" style="background-color: ';
352$php_sapi_name = strtolower(function_exists('php_sapi_name') ? PHP_SAPI : '');
353if (!$php_sapi_name || (preg_match('#~#', dirname($_SERVER['PHP_SELF'])) && ($php_sapi_name != 'apache'))) {
354	echo 'red';
355} elseif ($php_sapi_name == 'cgi-fcgi') {
356	echo 'orange';
357} elseif ($php_sapi_name == 'cgi') {
358	echo 'yellow';
359} elseif ($php_sapi_name == 'apache') {
360	echo 'lime';
361} else {
362	echo 'green';
363}
364echo ';">'.htmlspecialchars($php_sapi_name).'</th>';
365echo '<td>SAPI mode preferred to CGI mode. FCGI mode has unconfirmed strange behavior (notably more than one space in "wmt" filter text causes errors). If not working in "apache" (SAPI) mode, <i>apache_lookup_uri()</i> will not work.</td></tr>';
366
367
368echo '<tr><th>Server Software</th><th colspan="2" style="background-color: ';
369$server_software = getenv('SERVER_SOFTWARE');
370if (!$server_software) {
371	echo 'red';
372} elseif (preg_match('#^Apache/([0-9\\.]+)#i', $server_software, $matches)) {
373	if (phpthumb_functions::version_compare_replacement($matches[1], '2.0.0', '>=')) {
374		echo 'lightgreen';
375	} else {
376		echo 'lime';
377	}
378} else {
379	echo 'darkgreen';
380}
381echo ';">'.$server_software.'</th>';
382echo '<td>Apache v1.x has the fewest compatibility problems. IIS has numerous annoyances. Apache v2.x is broken when lookup up <i>/~user/filename.jpg</i> style relative filenames using <i>apache_lookup_uri()</i>.</td></tr>';
383
384
385echo '<tr><th>curl_version:</th><th colspan="2" style="background-color: ';
386$curl_version = (function_exists('curl_version') ? curl_version() : '');
387if (is_array($curl_version)) {
388	$curl_version = @$curl_version['version'];
389}
390if ($curl_version) {
391	echo 'lime';
392} else {
393	echo 'yellow';
394}
395echo ';">'.$curl_version.'</th>';
396echo '<td>Best if available. HTTP source images will be unavailable if CURL unavailable and <i>allow_url_fopen</i> is also disabled.</td></tr>';
397
398echo '<tr style="background-color: #EEEEEE;"><th colspan="4">&nbsp;</th></tr>';
399echo '<tr style="background-color: #EEEEEE;"><th>function_exists:</th><th colspan="2">Value</th><th>Comments</th></tr>';
400
401$FunctionsExist = array(
402	'imagerotate'           => array('orange',     'required for "ra" and "ar" filters.'),
403	'exif_read_data'        => array('yellow',     'required for "ar" filter.'),
404	'exif_thumbnail'        => array('yellow',     'required to extract EXIF thumbnails.'),
405	'memory_get_usage'      => array('lightgreen', 'mostly used for troubleshooting.'),
406	'version_compare'       => array('darkgreen',  'available in PHP v4.1.0+, internal workaround available'),
407	'file_get_contents'     => array('darkgreen',  'available in PHP v4.3.0+, internal workaround available'),
408	'file_put_contents'     => array('darkgreen',  'available in PHP v5.0.0+, internal workaround available'),
409	'is_executable'         => array('yellow',     'available in PHP3, except only PHP5 for Windows. poor internal workaround available'),
410	'gd_info'               => array('olive',      'available in PHP v4.3.0+ (with bundled GD2), internal workaround available'),
411	'imagetypes'            => array('red',        'required for GD image output.'),
412	'imagecreatefromjpeg'   => array('orange',     'required for JPEG source images using GD.'),
413	'imagecreatefromgif'    => array('yellow',     'useful for GIF source images using GD.'),
414	'imagecreatefrompng'    => array('orange',     'required for PNG source images using GD and other source image formats using ImageMagick.'),
415	'imagecreatefromwbmp'   => array('yellow',     'required for WBMP source images using GD.'),
416	'imagecreatefromstring' => array('orange',     'required for HTTP and non-file image sources.'),
417	'imagecreatetruecolor'  => array('orange',     'required for all non-ImageMagick filters.'),
418	'imageistruecolor'      => array('olive',      'available in PHP v4.3.2+ with GD v2.0.1+'),
419	'imagefilter'           => array('yellow',     'PHP5 only. Required for some filters (but most can use ImageMagick instead)'),
420	'imageautocrop'         => array('yellow',     'PHP v5.5.0+, required for "ica" filter'),
421);
422foreach ($FunctionsExist as $function => $details) {
423	list($color, $description) = $details;
424	echo '<tr><th>'.$function.'</th><th colspan="2" style="background-color: ';
425	if (function_exists(strtolower($function))) {
426		echo 'lime;">TRUE';
427	} else {
428		echo $color.';">FALSE';
429	}
430	echo '</th><td>'.htmlspecialchars($description).'</td></tr>';
431}
432
433
434echo '<tr style="background-color: #EEEEEE;"><th colspan="4">&nbsp;</th></tr>';
435echo '<tr style="background-color: #EEEEEE;"><th>Setting</th><th>Master Value</th><th>Local Value</th><th>Comments</th></tr>';
436
437
438$SettingFeatures = array(
439	'magic_quotes_runtime' => array('red',    'lime',   'This setting is evil. Turn it off.'),
440	'magic_quotes_gpc'     => array('yellow', 'lime',   'This setting is bad. Turn it off, if possible. phpThumb will attempt to work around it if it is enabled.'),
441	'safe_mode'            => array('orange', 'lime',   'Best if off. Calls to ImageMagick will be disabled if safe_mode is set to prevent writing temp files (limiting max image resolution, no animated GIF resize). Raw image data sources (e.g. from MySQL database) may not work. Temp files may be disabled. Features will be limited. If disabled in Master but enabled in Local, edit httpd.conf and set (php_admin_value safe_mode "Off") between <VirtualHost> tags'),
442	'allow_url_fopen'      => array('lime',   'yellow', 'Best if on. HTTP source images will be unavailable if disabled and CURL is unavailable.'),
443);
444
445foreach ($SettingFeatures as $feature => $FeaturesDetails) {
446	list($color_true, $color_false, $reason) = $FeaturesDetails;
447	echo '<tr><th>'.$feature.':</th>';
448	echo '<th style="background-color: '.(@get_cfg_var($feature)                      ? $color_true : $color_false).';">'.$phpThumb->phpThumbDebugVarDump((bool) @get_cfg_var($feature)).'</th>';
449	echo '<th style="background-color: '.(preg_match('#(1|ON)#i', @ini_get($feature)) ? $color_true : $color_false).';">'.$phpThumb->phpThumbDebugVarDump((bool) preg_match('#(1|ON)#i', ini_get($feature))).'</th>';
450	echo '<td>'.htmlspecialchars($reason).'</td></tr>';
451}
452
453$MissingFunctionSeverity = array(
454	'shell_exec' => 'red',
455	'system'     => 'red',
456	'passthru'   => 'red',
457	'exec'       => 'red',
458	'curl_exec'  => 'orange',
459);
460$DisabledFunctions[0] = explode(',', @get_cfg_var('disable_functions'));
461$DisabledFunctions[1] = explode(',',     @ini_get('disable_functions'));
462echo '<tr><th>disable_functions:</th>';
463for ($i = 0; $i <= 1; $i++) {
464	foreach ($DisabledFunctions[$i] as $key => $value) {
465		if (!empty($MissingFunctionSeverity[$value])) {
466			$DisabledFunctions[$i][$key] = '<span style="background-color: '.$MissingFunctionSeverity[$value].';">'.$value.'</span>';
467		}
468	}
469	$disabled_functions = implode(', ', $DisabledFunctions[$i]);
470	echo '<th style="background-color: '.($disabled_functions ? 'yellow' : 'lime').';">'.htmlspecialchars($disabled_functions).'</th>';
471}
472echo '<td>Best if nothing disabled. Calls to ImageMagick will be prevented if exec+system+shell_exec+passthru are disabled.</td></tr>';
473
474
475echo '<tr><th>memory_limit:</th><th style="background-color: ';
476$memory_limit = @get_cfg_var('memory_limit');
477if (!$memory_limit) {
478	echo 'lime';
479} elseif ($memory_limit >= 256) {
480	echo 'lime';
481} elseif ($memory_limit >= 128) {
482	echo 'lightgreen';
483} elseif ($memory_limit >= 64) {
484	echo 'green';
485} elseif ($memory_limit >= 32) {
486	echo 'darkgreen';
487} elseif ($memory_limit >= 16) {
488	echo 'olive';
489} elseif ($memory_limit >= 8) {
490	echo 'yellow';
491} elseif ($memory_limit >= 4) {
492	echo 'orange';
493} else {
494	echo 'red';
495}
496echo ';">'.($memory_limit ?: '<i>unlimited</i>').'</th><th style="background-color: ';
497$memory_limit_bytes = 0;
498if ($memory_limit = @ini_get('memory_limit')) {
499	$memory_limit_bytes = intval($memory_limit);
500	if (strtoupper(substr($memory_limit, -1, 1)) == 'M') {
501		$memory_limit_bytes = substr($memory_limit, 0, -1) * 1024 * 1024;
502	} elseif (strtoupper(substr($memory_limit, -1, 1)) == 'G') {
503		$memory_limit_bytes = substr($memory_limit, 0, -1) * 1024 * 1024 * 1024;
504	}
505}
506if (!$memory_limit) {
507	echo 'lime';
508} elseif ($memory_limit >= 256) {
509	echo 'lime';
510} elseif ($memory_limit >= 128) {
511	echo 'lightgreen';
512} elseif ($memory_limit >= 64) {
513	echo 'green';
514} elseif ($memory_limit >= 32) {
515	echo 'darkgreen';
516} elseif ($memory_limit >= 16) {
517	echo 'olive';
518} elseif ($memory_limit >= 8) {
519	echo 'yellow';
520} elseif ($memory_limit >= 4) {
521	echo 'orange';
522} else {
523	echo 'red';
524}
525echo ';">'.($memory_limit ?: '<i>unlimited</i>').'</th>';
526echo '<td>The higher the better. Divide by 5 to get maximum megapixels of source image that can be thumbnailed (without ImageMagick).'.($memory_limit ? ' Your setting ('.$memory_limit.') allows images up to approximately '.number_format($memory_limit_bytes / (5*1024*1024), 1).' megapixels' : '').'</td></tr>';
527
528echo '</table>';
529
530
531function NiceTimeFormatting($seconds, $precision=1, $returnparts=false) {
532	$sign = (($seconds < 0) ? -1 : 1);
533	$seconds = abs($seconds);
534	do {
535		if ($seconds < 100) {
536			$value = number_format($seconds, 0);
537			$unit  = 'second'.(($seconds > 1) ? 's' : '');
538			break;
539		}
540		$minutes = $seconds / 60;
541		if ($minutes < 60) {
542			$value = number_format($minutes, $precision);
543			$unit  = 'minutes';
544			break;
545		}
546		$hours = $seconds / 3600;
547		if ($hours < 24) {
548			$value = number_format($hours, $precision);
549			$unit  = 'hours';
550			break;
551		}
552		$days = $seconds / 86400;
553		if ($days < 60) {
554			$value = number_format($days, $precision);
555			$unit  = 'days';
556			break;
557		}
558		$months = $seconds / (30 * 86400);
559		if ($months < 12) {
560			$value = number_format($months, $precision);
561			$unit  = 'months';
562			break;
563		}
564		$years = $seconds / (365 * 86400);
565		if (true) {
566			$value = number_format($years, $precision);
567			$unit  = 'years';
568			break;
569		}
570	} while (false);
571	$value *= $sign;
572	if ($returnparts) {
573		return array($value, $unit);
574	}
575	return $value.' '.$unit;
576}
577
578?>
579</body>
580</html>