PageRenderTime 77ms CodeModel.GetById 6ms app.highlight 51ms RepoModel.GetById 2ms app.codeStats 1ms

/components/com_flexicontent/librairies/phpthumb/phpthumb.class.php

http://flexicontent.googlecode.com/
PHP | 4092 lines | 3414 code | 434 blank | 244 comment | 762 complexity | 140f75018c1b6da1098834441c276780 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2//////////////////////////////////////////////////////////////
   3///  phpThumb() by James Heinrich <info@silisoftware.com>   //
   4//        available at http://phpthumb.sourceforge.net     ///
   5//////////////////////////////////////////////////////////////
   6///                                                         //
   7// See: phpthumb.readme.txt for usage instructions          //
   8//                                                         ///
   9//////////////////////////////////////////////////////////////
  10
  11ob_start();
  12if (!include_once(dirname(__FILE__).'/phpthumb.functions.php')) {
  13	ob_end_flush();
  14	die('failed to include_once("'.realpath(dirname(__FILE__).'/phpthumb.functions.php').'")');
  15}
  16ob_end_clean();
  17
  18class phpthumb {
  19
  20	// public:
  21	// START PARAMETERS (for object mode and phpThumb.php)
  22	// See phpthumb.readme.txt for descriptions of what each of these values are
  23	var $src  = null;     // SouRCe filename
  24	var $new  = null;     // NEW image (phpThumb.php only)
  25	var $w    = null;     // Width
  26	var $h    = null;     // Height
  27	var $wp   = null;     // Width  (Portrait Images Only)
  28	var $hp   = null;     // Height (Portrait Images Only)
  29	var $wl   = null;     // Width  (Landscape Images Only)
  30	var $hl   = null;     // Height (Landscape Images Only)
  31	var $ws   = null;     // Width  (Square Images Only)
  32	var $hs   = null;     // Height (Square Images Only)
  33	var $f    = null;     // output image Format
  34	var $q    = 75;       // jpeg output Quality
  35	var $sx   = null;     // Source crop top-left X position
  36	var $sy   = null;     // Source crop top-left Y position
  37	var $sw   = null;     // Source crop Width
  38	var $sh   = null;     // Source crop Height
  39	var $zc   = null;     // Zoom Crop
  40	var $bc   = null;     // Border Color
  41	var $bg   = null;     // BackGround color
  42	var $fltr = array();  // FiLTeRs
  43	var $goto = null;     // GO TO url after processing
  44	var $err  = null;     // default ERRor image filename
  45	var $xto  = null;     // extract eXif Thumbnail Only
  46	var $ra   = null;     // Rotate by Angle
  47	var $ar   = null;     // Auto Rotate
  48	var $aoe  = null;     // Allow Output Enlargement
  49	var $far  = null;     // Fixed Aspect Ratio
  50	var $iar  = null;     // Ignore Aspect Ratio
  51	var $maxb = null;     // MAXimum Bytes
  52	var $down = null;     // DOWNload thumbnail filename
  53	var $md5s = null;     // MD5 hash of Source image
  54	var $sfn  = 0;        // Source Frame Number
  55	var $dpi  = 150;      // Dots Per Inch for vector source formats
  56	var $sia  = null;     // Save Image As filename
  57
  58	var $file = null;     // >>>deprecated, DO NOT USE, will be removed in future versions<<<
  59
  60	var $phpThumbDebug = null;
  61	// END PARAMETERS
  62
  63
  64	// public:
  65	// START CONFIGURATION OPTIONS (for object mode only)
  66	// See phpThumb.config.php for descriptions of what each of these settings do
  67
  68	// * Directory Configuration
  69	var $config_cache_directory                      = null;
  70	var $config_cache_directory_depth                = 0;
  71	var $config_cache_disable_warning                = true;
  72	var $config_cache_source_enabled                 = false;
  73	var $config_cache_source_directory               = null;
  74	var $config_temp_directory                       = null;
  75	var $config_document_root                        = null;
  76
  77	// * Default output configuration:
  78	var $config_output_format                        = 'jpeg';
  79	var $config_output_maxwidth                      = 0;
  80	var $config_output_maxheight                     = 0;
  81	var $config_output_interlace                     = true;
  82
  83	// * Error message configuration
  84	var $config_error_image_width                    = 400;
  85	var $config_error_image_height                   = 100;
  86	var $config_error_message_image_default          = '';
  87	var $config_error_bgcolor                        = 'CCCCFF';
  88	var $config_error_textcolor                      = 'FF0000';
  89	var $config_error_fontsize                       = 1;
  90	var $config_error_die_on_error                   = false;
  91	var $config_error_silent_die_on_error            = false;
  92	var $config_error_die_on_source_failure          = true;
  93
  94	// * Anti-Hotlink Configuration:
  95	var $config_nohotlink_enabled                    = true;
  96	var $config_nohotlink_valid_domains              = array();
  97	var $config_nohotlink_erase_image                = true;
  98	var $config_nohotlink_text_message               = 'Off-server thumbnailing is not allowed';
  99	// * Off-server Linking Configuration:
 100	var $config_nooffsitelink_enabled                = false;
 101	var $config_nooffsitelink_valid_domains          = array();
 102	var $config_nooffsitelink_require_refer          = false;
 103	var $config_nooffsitelink_erase_image            = true;
 104	var $config_nooffsitelink_watermark_src          = '';
 105	var $config_nooffsitelink_text_message           = 'Off-server linking is not allowed';
 106
 107	// * Border & Background default colors
 108	var $config_border_hexcolor                      = '000000';
 109	var $config_background_hexcolor                  = 'FFFFFF';
 110
 111	// * TrueType Fonts
 112	var $config_ttf_directory                        = './fonts';
 113
 114	var $config_max_source_pixels                    = null;
 115	var $config_use_exif_thumbnail_for_speed         = false;
 116	var $allow_local_http_src                        = false;
 117
 118	var $config_imagemagick_path                     = null;
 119	var $config_prefer_imagemagick                   = true;
 120	var $config_imagemagick_use_thumbnail            = true;
 121
 122	var $config_cache_maxage                         = null;
 123	var $config_cache_maxsize                        = null;
 124	var $config_cache_maxfiles                       = null;
 125	var $config_cache_source_filemtime_ignore_local  = false;
 126	var $config_cache_source_filemtime_ignore_remote = true;
 127	var $config_cache_default_only_suffix            = false;
 128	var $config_cache_force_passthru                 = true;
 129	var $config_cache_prefix                         = '';    // default value set in the constructor below
 130
 131	// * MySQL
 132	var $config_mysql_query                          = null;
 133	var $config_mysql_hostname                       = null;
 134	var $config_mysql_username                       = null;
 135	var $config_mysql_password                       = null;
 136	var $config_mysql_database                       = null;
 137
 138	// * Security
 139	var $config_high_security_enabled                = false;
 140	var $config_high_security_password               = null;
 141	var $config_disable_debug                        = true;
 142	var $config_allow_src_above_docroot              = false;
 143	var $config_allow_src_above_phpthumb             = true;
 144
 145	// * HTTP fopen
 146	var $config_http_fopen_timeout                   = 10;
 147	var $config_http_follow_redirect                 = true;
 148
 149	// * Compatability
 150	var $config_disable_pathinfo_parsing             = false;
 151	var $config_disable_imagecopyresampled           = false;
 152	var $config_disable_onlycreateable_passthru      = false;
 153
 154	var $config_http_user_agent                      = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7';
 155
 156	// END CONFIGURATION OPTIONS
 157
 158
 159	// public: error messages (read-only; persistant)
 160	var $debugmessages = array();
 161	var $debugtiming   = array();
 162	var $fatalerror    = null;
 163
 164
 165	// private: (should not be modified directly)
 166	var $thumbnailQuality = 75;
 167	var $thumbnailFormat  = null;
 168
 169	var $sourceFilename   = null;
 170	var $rawImageData     = null;
 171	var $IMresizedData    = null;
 172	var $outputImageData  = null;
 173
 174	var $useRawIMoutput   = false;
 175
 176	var $gdimg_output     = null;
 177	var $gdimg_source     = null;
 178
 179	var $getimagesizeinfo = null;
 180
 181	var $source_width  = null;
 182	var $source_height = null;
 183
 184	var $thumbnailCropX = null;
 185	var $thumbnailCropY = null;
 186	var $thumbnailCropW = null;
 187	var $thumbnailCropH = null;
 188
 189	var $exif_thumbnail_width  = null;
 190	var $exif_thumbnail_height = null;
 191	var $exif_thumbnail_type   = null;
 192	var $exif_thumbnail_data   = null;
 193	var $exif_raw_data         = null;
 194
 195	var $thumbnail_width        = null;
 196	var $thumbnail_height       = null;
 197	var $thumbnail_image_width  = null;
 198	var $thumbnail_image_height = null;
 199
 200	var $tempFilesToDelete = array();
 201	var $cache_filename    = null;
 202
 203	var $AlphaCapableFormats = array('png', 'ico', 'gif');
 204	var $is_alpha = false;
 205
 206	var $iswindows  = null;
 207	var $issafemode = null;
 208
 209	var $phpthumb_version = '1.7.11-201108081537';
 210
 211	//////////////////////////////////////////////////////////////////////
 212
 213	// public: constructor
 214	function phpThumb() {
 215		$this->DebugTimingMessage('phpThumb() constructor', __FILE__, __LINE__);
 216		$this->DebugMessage('phpThumb() v'.$this->phpthumb_version, __FILE__, __LINE__);
 217		$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
 218		$this->iswindows  = (bool) (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN');
 219		$this->issafemode = (bool) preg_match('#(1|ON)#i', ini_get('safe_mode'));
 220		$this->config_document_root = (!empty($_SERVER['DOCUMENT_ROOT']) ? $_SERVER['DOCUMENT_ROOT']   : $this->config_document_root);
 221		$this->config_cache_prefix  = ( isset($_SERVER['SERVER_NAME'])   ? $_SERVER['SERVER_NAME'].'_' : '');
 222
 223		$this->purgeTempFiles(); // purge existing temp files if re-initializing object
 224
 225		$php_sapi_name = strtolower(function_exists('php_sapi_name') ? php_sapi_name() : '');
 226		if ($php_sapi_name == 'cli') {
 227			$this->config_allow_src_above_docroot = true;
 228		}
 229	}
 230
 231	function __destruct() {
 232		$this->purgeTempFiles();
 233	}
 234
 235	// public:
 236	function purgeTempFiles() {
 237		foreach ($this->tempFilesToDelete as $tempFileToDelete) {
 238			if (file_exists($tempFileToDelete)) {
 239				$this->DebugMessage('Deleting temp file "'.$tempFileToDelete.'"', __FILE__, __LINE__);
 240				@unlink($tempFileToDelete);
 241			}
 242		}
 243		$this->tempFilesToDelete = array();
 244		return true;
 245	}
 246
 247	// public:
 248	function setSourceFilename($sourceFilename) {
 249		//$this->resetObject();
 250		//$this->rawImageData   = null;
 251		$this->sourceFilename = $sourceFilename;
 252		$this->src            = $sourceFilename;
 253		if (is_null($this->config_output_format)) {
 254			$sourceFileExtension = strtolower(substr(strrchr($sourceFilename, '.'), 1));
 255			if (preg_match('#^[a-z]{3,4}$#', $sourceFileExtension)) {
 256				$this->config_output_format = $sourceFileExtension;
 257				$this->DebugMessage('setSourceFilename('.$sourceFilename.') set $this->config_output_format to "'.$sourceFileExtension.'"', __FILE__, __LINE__);
 258			} else {
 259				$this->DebugMessage('setSourceFilename('.$sourceFilename.') did NOT set $this->config_output_format to "'.$sourceFileExtension.'" because it did not seem like an appropriate image format', __FILE__, __LINE__);
 260			}
 261		}
 262		$this->DebugMessage('setSourceFilename('.$sourceFilename.') set $this->sourceFilename to "'.$this->sourceFilename.'"', __FILE__, __LINE__);
 263		return true;
 264	}
 265
 266	// public:
 267	function setSourceData($rawImageData, $sourceFilename='') {
 268		//$this->resetObject();
 269		//$this->sourceFilename = null;
 270		$this->rawImageData   = $rawImageData;
 271		$this->DebugMessage('setSourceData() setting $this->rawImageData ('.strlen($this->rawImageData).' bytes; magic="'.substr($this->rawImageData, 0, 4).'" ('.phpthumb_functions::HexCharDisplay(substr($this->rawImageData, 0, 4)).'))', __FILE__, __LINE__);
 272		if ($this->config_cache_source_enabled) {
 273			$sourceFilename = ($sourceFilename ? $sourceFilename : md5($rawImageData));
 274			if (!is_dir($this->config_cache_source_directory)) {
 275				$this->ErrorImage('$this->config_cache_source_directory ('.$this->config_cache_source_directory.') is not a directory');
 276			} elseif (!@is_writable($this->config_cache_source_directory)) {
 277				$this->ErrorImage('$this->config_cache_source_directory ('.$this->config_cache_source_directory.') is not writable');
 278			}
 279			$this->DebugMessage('setSourceData() attempting to save source image to "'.$this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename).'"', __FILE__, __LINE__);
 280			if ($fp = @fopen($this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename), 'wb')) {
 281				fwrite($fp, $rawImageData);
 282				fclose($fp);
 283			} elseif (!$this->phpThumbDebug) {
 284				$this->ErrorImage('setSourceData() failed to write to source cache ('.$this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename).')');
 285			}
 286		}
 287		return true;
 288	}
 289
 290	// public:
 291	function setSourceImageResource($gdimg) {
 292		//$this->resetObject();
 293		$this->gdimg_source = $gdimg;
 294		return true;
 295	}
 296
 297	// public:
 298	function setParameter($param, $value) {
 299		if ($param == 'src') {
 300			$this->setSourceFilename($this->ResolveFilenameToAbsolute($value));
 301		} elseif (@is_array($this->$param)) {
 302			if (is_array($value)) {
 303				foreach ($value as $arraykey => $arrayvalue) {
 304					array_push($this->$param, $arrayvalue);
 305				}
 306			} else {
 307				array_push($this->$param, $value);
 308			}
 309		} else {
 310			$this->$param = $value;
 311		}
 312		return true;
 313	}
 314
 315	// public:
 316	function getParameter($param) {
 317		//if (property_exists('phpThumb', $param)) {
 318			return $this->$param;
 319		//}
 320		//$this->DebugMessage('setParameter() attempting to get non-existant parameter "'.$param.'"', __FILE__, __LINE__);
 321		//return false;
 322	}
 323
 324
 325	// public:
 326	function GenerateThumbnail() {
 327
 328		$this->setOutputFormat();
 329			$this->phpThumbDebug('8a');
 330		$this->ResolveSource();
 331			$this->phpThumbDebug('8b');
 332		$this->SetCacheFilename();
 333			$this->phpThumbDebug('8c');
 334		$this->ExtractEXIFgetImageSize();
 335			$this->phpThumbDebug('8d');
 336		if ($this->useRawIMoutput) {
 337			$this->DebugMessage('Skipping rest of GenerateThumbnail() because ($this->useRawIMoutput == true)', __FILE__, __LINE__);
 338			return true;
 339		}
 340			$this->phpThumbDebug('8e');
 341		if (!$this->SourceImageToGD()) {
 342			$this->DebugMessage('SourceImageToGD() failed', __FILE__, __LINE__);
 343			return false;
 344		}
 345			$this->phpThumbDebug('8f');
 346		$this->Rotate();
 347			$this->phpThumbDebug('8g');
 348		$this->CreateGDoutput();
 349			$this->phpThumbDebug('8h');
 350
 351		switch ($this->far) {
 352			case 'L':
 353			case 'TL':
 354			case 'BL':
 355				$destination_offset_x = 0;
 356				$destination_offset_y = round(($this->thumbnail_height - $this->thumbnail_image_height) / 2);
 357				break;
 358			case 'R':
 359			case 'TR':
 360			case 'BR':
 361				$destination_offset_x =  round($this->thumbnail_width  - $this->thumbnail_image_width);
 362				$destination_offset_y = round(($this->thumbnail_height - $this->thumbnail_image_height) / 2);
 363				break;
 364			case 'T':
 365			case 'TL':
 366			case 'TR':
 367				$destination_offset_x = round(($this->thumbnail_width  - $this->thumbnail_image_width)  / 2);
 368				$destination_offset_y = 0;
 369				break;
 370			case 'B':
 371			case 'BL':
 372			case 'BR':
 373				$destination_offset_x = round(($this->thumbnail_width  - $this->thumbnail_image_width)  / 2);
 374				$destination_offset_y =  round($this->thumbnail_height - $this->thumbnail_image_height);
 375				break;
 376			case 'C':
 377			default:
 378				$destination_offset_x = round(($this->thumbnail_width  - $this->thumbnail_image_width)  / 2);
 379				$destination_offset_y = round(($this->thumbnail_height - $this->thumbnail_image_height) / 2);
 380		}
 381
 382//		// copy/resize image to appropriate dimensions
 383//		$borderThickness = 0;
 384//		if (!empty($this->fltr)) {
 385//			foreach ($this->fltr as $key => $value) {
 386//				if (preg_match('#^bord\|([0-9]+)#', $value, $matches)) {
 387//					$borderThickness = $matches[1];
 388//					break;
 389//				}
 390//			}
 391//		}
 392//		if ($borderThickness > 0) {
 393//			//$this->DebugMessage('Skipping ImageResizeFunction() because BorderThickness="'.$borderThickness.'"', __FILE__, __LINE__);
 394//			$this->thumbnail_image_height /= 2;
 395//		}
 396		$this->ImageResizeFunction(
 397			$this->gdimg_output,
 398			$this->gdimg_source,
 399			$destination_offset_x,
 400			$destination_offset_y,
 401			$this->thumbnailCropX,
 402			$this->thumbnailCropY,
 403			$this->thumbnail_image_width,
 404			$this->thumbnail_image_height,
 405			$this->thumbnailCropW,
 406			$this->thumbnailCropH
 407		);
 408
 409		$this->DebugMessage('memory_get_usage() after copy-resize = '.(function_exists('memory_get_usage') ? @memory_get_usage() : 'n/a'), __FILE__, __LINE__);
 410		ImageDestroy($this->gdimg_source);
 411		$this->DebugMessage('memory_get_usage() after ImageDestroy = '.(function_exists('memory_get_usage') ? @memory_get_usage() : 'n/a'), __FILE__, __LINE__);
 412
 413			$this->phpThumbDebug('8i');
 414		$this->AntiOffsiteLinking();
 415			$this->phpThumbDebug('8j');
 416		$this->ApplyFilters();
 417			$this->phpThumbDebug('8k');
 418		$this->AlphaChannelFlatten();
 419			$this->phpThumbDebug('8l');
 420		$this->MaxFileSize();
 421			$this->phpThumbDebug('8m');
 422
 423		$this->DebugMessage('GenerateThumbnail() completed successfully', __FILE__, __LINE__);
 424		return true;
 425	}
 426
 427
 428	// public:
 429	function RenderOutput() {
 430		if (!$this->useRawIMoutput && !is_resource($this->gdimg_output)) {
 431			$this->DebugMessage('RenderOutput() failed because !is_resource($this->gdimg_output)', __FILE__, __LINE__);
 432			return false;
 433		}
 434		if (!$this->thumbnailFormat) {
 435			$this->DebugMessage('RenderOutput() failed because $this->thumbnailFormat is empty', __FILE__, __LINE__);
 436			return false;
 437		}
 438		if ($this->useRawIMoutput) {
 439			$this->DebugMessage('RenderOutput copying $this->IMresizedData ('.strlen($this->IMresizedData).' bytes) to $this->outputImage', __FILE__, __LINE__);
 440			$this->outputImageData = $this->IMresizedData;
 441			return true;
 442		}
 443
 444		$builtin_formats = array();
 445		if (function_exists('ImageTypes')) {
 446			$imagetypes = ImageTypes();
 447			$builtin_formats['wbmp'] = (bool) ($imagetypes & IMG_WBMP);
 448			$builtin_formats['jpg']  = (bool) ($imagetypes & IMG_JPG);
 449			$builtin_formats['gif']  = (bool) ($imagetypes & IMG_GIF);
 450			$builtin_formats['png']  = (bool) ($imagetypes & IMG_PNG);
 451		}
 452		$this->DebugMessage('RenderOutput() attempting Image'.strtoupper(@$this->thumbnailFormat).'($this->gdimg_output)', __FILE__, __LINE__);
 453		ob_start();
 454		switch ($this->thumbnailFormat) {
 455			case 'wbmp':
 456				if (!@$builtin_formats['wbmp']) {
 457					$this->DebugMessage('GD does not have required built-in support for WBMP output', __FILE__, __LINE__);
 458					ob_end_clean();
 459					return false;
 460				}
 461				ImageJPEG($this->gdimg_output, null, $this->thumbnailQuality);
 462				$this->outputImageData = ob_get_contents();
 463				break;
 464
 465			case 'jpeg':
 466			case 'jpg':  // should be "jpeg" not "jpg" but just in case...
 467				if (!@$builtin_formats['jpg']) {
 468					$this->DebugMessage('GD does not have required built-in support for JPEG output', __FILE__, __LINE__);
 469					ob_end_clean();
 470					return false;
 471				}
 472				ImageJPEG($this->gdimg_output, null, $this->thumbnailQuality);
 473				$this->outputImageData = ob_get_contents();
 474				break;
 475
 476			case 'png':
 477				if (!@$builtin_formats['png']) {
 478					$this->DebugMessage('GD does not have required built-in support for PNG output', __FILE__, __LINE__);
 479					ob_end_clean();
 480					return false;
 481				}
 482				ImagePNG($this->gdimg_output);
 483				$this->outputImageData = ob_get_contents();
 484				break;
 485
 486			case 'gif':
 487				if (!@$builtin_formats['gif']) {
 488					$this->DebugMessage('GD does not have required built-in support for GIF output', __FILE__, __LINE__);
 489					ob_end_clean();
 490					return false;
 491				}
 492				ImageGIF($this->gdimg_output);
 493				$this->outputImageData = ob_get_contents();
 494				break;
 495
 496			case 'bmp':
 497				$ImageOutFunction = '"builtin BMP output"';
 498				if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) {
 499					$this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.bmp.php" which is required for BMP format output', __FILE__, __LINE__);
 500					ob_end_clean();
 501					return false;
 502				}
 503				$phpthumb_bmp = new phpthumb_bmp();
 504				$this->outputImageData = $phpthumb_bmp->GD2BMPstring($this->gdimg_output);
 505				unset($phpthumb_bmp);
 506				break;
 507
 508			case 'ico':
 509				$ImageOutFunction = '"builtin ICO output"';
 510				if (!@include_once(dirname(__FILE__).'/phpthumb.ico.php')) {
 511					$this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.ico.php" which is required for ICO format output', __FILE__, __LINE__);
 512					ob_end_clean();
 513					return false;
 514				}
 515				$phpthumb_ico = new phpthumb_ico();
 516				$arrayOfOutputImages = array($this->gdimg_output);
 517				$this->outputImageData = $phpthumb_ico->GD2ICOstring($arrayOfOutputImages);
 518				unset($phpthumb_ico);
 519				break;
 520
 521			default:
 522				$this->DebugMessage('RenderOutput failed because $this->thumbnailFormat "'.$this->thumbnailFormat.'" is not valid', __FILE__, __LINE__);
 523				ob_end_clean();
 524				return false;
 525		}
 526		ob_end_clean();
 527		if (!$this->outputImageData) {
 528			$this->DebugMessage('RenderOutput() for "'.$this->thumbnailFormat.'" failed', __FILE__, __LINE__);
 529			ob_end_clean();
 530			return false;
 531		}
 532		$this->DebugMessage('RenderOutput() completing with $this->outputImageData = '.strlen($this->outputImageData).' bytes', __FILE__, __LINE__);
 533		return true;
 534	}
 535
 536
 537	// public:
 538	function RenderToFile($filename) {
 539		if (preg_match('#^(f|ht)tps?\://#i', $filename)) {
 540			$this->DebugMessage('RenderToFile() failed because $filename ('.$filename.') is a URL', __FILE__, __LINE__);
 541			return false;
 542		}
 543		// render thumbnail to this file only, do not cache, do not output to browser
 544		//$renderfilename = $this->ResolveFilenameToAbsolute(dirname($filename)).DIRECTORY_SEPARATOR.basename($filename);
 545		$renderfilename = $filename;
 546		if (($filename{0} != '/') && ($filename{0} != '\\') && ($filename{1} != ':')) {
 547			$renderfilename = $this->ResolveFilenameToAbsolute($renderfilename);
 548		}
 549		if (!@is_writable(dirname($renderfilename))) {
 550			$this->DebugMessage('RenderToFile() failed because "'.dirname($renderfilename).'/" is not writable', __FILE__, __LINE__);
 551			return false;
 552		}
 553		if (@is_file($renderfilename) && !@is_writable($renderfilename)) {
 554			$this->DebugMessage('RenderToFile() failed because "'.$renderfilename.'" is not writable', __FILE__, __LINE__);
 555			return false;
 556		}
 557
 558		if ($this->RenderOutput()) {
 559			if (file_put_contents($renderfilename, $this->outputImageData)) {
 560				$this->DebugMessage('RenderToFile('.$renderfilename.') succeeded', __FILE__, __LINE__);
 561				return true;
 562			}
 563			if (!@file_exists($renderfilename)) {
 564				$this->DebugMessage('RenderOutput ['.$this->thumbnailFormat.'('.$renderfilename.')] did not appear to fail, but the output image does not exist either...', __FILE__, __LINE__);
 565			}
 566		} else {
 567			$this->DebugMessage('RenderOutput ['.$this->thumbnailFormat.'('.$renderfilename.')] failed', __FILE__, __LINE__);
 568		}
 569		return false;
 570	}
 571
 572
 573	// public:
 574	function OutputThumbnail() {
 575		$this->purgeTempFiles();
 576
 577		if (!$this->useRawIMoutput && !is_resource($this->gdimg_output)) {
 578			$this->DebugMessage('OutputThumbnail() failed because !is_resource($this->gdimg_output)', __FILE__, __LINE__);
 579			return false;
 580		}
 581		if (headers_sent()) {
 582			return $this->ErrorImage('OutputThumbnail() failed - headers already sent');
 583			exit;
 584		}
 585
 586		$downloadfilename = phpthumb_functions::SanitizeFilename(is_string($this->sia) ? $this->sia : ($this->down ? $this->down : 'phpThumb_generated_thumbnail'.'.'.$this->thumbnailFormat));
 587		$this->DebugMessage('Content-Disposition header filename set to "'.$downloadfilename.'"', __FILE__, __LINE__);
 588		if ($downloadfilename) {
 589			header('Content-Disposition: '.($this->down ? 'attachment' : 'inline').'; filename="'.$downloadfilename.'"');
 590		} else {
 591			$this->DebugMessage('failed to send Content-Disposition header because $downloadfilename is empty', __FILE__, __LINE__);
 592		}
 593
 594		if ($this->useRawIMoutput) {
 595
 596			header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat));
 597			echo $this->IMresizedData;
 598
 599		} else {
 600
 601			$this->DebugMessage('ImageInterlace($this->gdimg_output, '.intval($this->config_output_interlace).')', __FILE__, __LINE__);
 602			ImageInterlace($this->gdimg_output, intval($this->config_output_interlace));
 603			switch ($this->thumbnailFormat) {
 604				case 'jpeg':
 605					header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat));
 606					$ImageOutFunction = 'image'.$this->thumbnailFormat;
 607					@$ImageOutFunction($this->gdimg_output, '', $this->thumbnailQuality);
 608					break;
 609
 610				case 'png':
 611				case 'gif':
 612					header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat));
 613					$ImageOutFunction = 'image'.$this->thumbnailFormat;
 614					@$ImageOutFunction($this->gdimg_output);
 615					break;
 616
 617				case 'bmp':
 618					if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) {
 619						$this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.bmp.php" which is required for BMP format output', __FILE__, __LINE__);
 620						return false;
 621					}
 622					$phpthumb_bmp = new phpthumb_bmp();
 623					if (is_object($phpthumb_bmp)) {
 624						$bmp_data = $phpthumb_bmp->GD2BMPstring($this->gdimg_output);
 625						unset($phpthumb_bmp);
 626						if (!$bmp_data) {
 627							$this->DebugMessage('$phpthumb_bmp->GD2BMPstring() failed', __FILE__, __LINE__);
 628							return false;
 629						}
 630						header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat));
 631						echo $bmp_data;
 632					} else {
 633						$this->DebugMessage('new phpthumb_bmp() failed', __FILE__, __LINE__);
 634						return false;
 635					}
 636					break;
 637
 638				case 'ico':
 639					if (!@include_once(dirname(__FILE__).'/phpthumb.ico.php')) {
 640						$this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.ico.php" which is required for ICO format output', __FILE__, __LINE__);
 641						return false;
 642					}
 643					$phpthumb_ico = new phpthumb_ico();
 644					if (is_object($phpthumb_ico)) {
 645						$arrayOfOutputImages = array($this->gdimg_output);
 646						$ico_data = $phpthumb_ico->GD2ICOstring($arrayOfOutputImages);
 647						unset($phpthumb_ico);
 648						if (!$ico_data) {
 649							$this->DebugMessage('$phpthumb_ico->GD2ICOstring() failed', __FILE__, __LINE__);
 650							return false;
 651						}
 652						header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat));
 653						echo $ico_data;
 654					} else {
 655						$this->DebugMessage('new phpthumb_ico() failed', __FILE__, __LINE__);
 656						return false;
 657					}
 658					break;
 659
 660				default:
 661					$this->DebugMessage('OutputThumbnail failed because $this->thumbnailFormat "'.$this->thumbnailFormat.'" is not valid', __FILE__, __LINE__);
 662					return false;
 663					break;
 664			}
 665
 666		}
 667		return true;
 668	}
 669
 670
 671	// public:
 672	function CleanUpCacheDirectory() {
 673		$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__);
 674
 675		if (!is_writable($this->config_cache_directory)) {
 676			$this->DebugMessage('CleanUpCacheDirectory() skipped because "'.$this->config_cache_directory.'" is not writable', __FILE__, __LINE__);
 677			return true;
 678		}
 679
 680		// cache status of cache directory for 1 hour to avoid hammering the filesystem functions
 681		$phpThumbCacheStats_filename = $this->config_cache_directory.DIRECTORY_SEPARATOR.'phpThumbCacheStats.txt';
 682		if (file_exists($phpThumbCacheStats_filename) && is_readable($phpThumbCacheStats_filename) && (filemtime($phpThumbCacheStats_filename) >= (time() - 3600))) {
 683			$this->DebugMessage('CleanUpCacheDirectory() skipped because "'.$phpThumbCacheStats_filename.'" is recently modified', __FILE__, __LINE__);
 684			return true;
 685		}
 686		touch($phpThumbCacheStats_filename);
 687
 688		$DeletedKeys = array();
 689		$AllFilesInCacheDirectory = array();
 690		if (($this->config_cache_maxage > 0) || ($this->config_cache_maxsize > 0) || ($this->config_cache_maxfiles > 0)) {
 691			$CacheDirOldFilesAge  = array();
 692			$CacheDirOldFilesSize = array();
 693			$AllFilesInCacheDirectory = phpthumb_functions::GetAllFilesInSubfolders($this->config_cache_directory);
 694			foreach ($AllFilesInCacheDirectory as $fullfilename) {
 695				if (preg_match('#^'.preg_quote($this->config_cache_prefix).'#i', $fullfilename) && file_exists($fullfilename)) {
 696					$CacheDirOldFilesAge[$fullfilename] = @fileatime($fullfilename);
 697					if ($CacheDirOldFilesAge[$fullfilename] == 0) {
 698						$CacheDirOldFilesAge[$fullfilename] = @filemtime($fullfilename);
 699					}
 700					$CacheDirOldFilesSize[$fullfilename] = @filesize($fullfilename);
 701				}
 702			}
 703			if (empty($CacheDirOldFilesSize)) {
 704				return true;
 705			}
 706			$DeletedKeys['zerobyte'] = array();
 707			foreach ($CacheDirOldFilesSize as $fullfilename => $filesize) {
 708				// purge all zero-size files more than an hour old (to prevent trying to delete just-created and/or in-use files)
 709				$cutofftime = time() - 3600;
 710				if (($filesize == 0) && ($CacheDirOldFilesAge[$fullfilename] < $cutofftime)) {
 711					$this->DebugMessage('deleting "'.$fullfilename.'"', __FILE__, __LINE__);
 712					if (@unlink($fullfilename)) {
 713						$DeletedKeys['zerobyte'][] = $fullfilename;
 714						unset($CacheDirOldFilesSize[$fullfilename]);
 715						unset($CacheDirOldFilesAge[$fullfilename]);
 716					}
 717				}
 718			}
 719			$this->DebugMessage('CleanUpCacheDirectory() purged '.count($DeletedKeys['zerobyte']).' zero-byte files', __FILE__, __LINE__);
 720			asort($CacheDirOldFilesAge);
 721
 722			if ($this->config_cache_maxfiles > 0) {
 723				$TotalCachedFiles = count($CacheDirOldFilesAge);
 724				$DeletedKeys['maxfiles'] = array();
 725				foreach ($CacheDirOldFilesAge as $fullfilename => $filedate) {
 726					if ($TotalCachedFiles > $this->config_cache_maxfiles) {
 727						$this->DebugMessage('deleting "'.$fullfilename.'"', __FILE__, __LINE__);
 728						if (@unlink($fullfilename)) {
 729							$TotalCachedFiles--;
 730							$DeletedKeys['maxfiles'][] = $fullfilename;
 731						}
 732					} else {
 733						// there are few enough files to keep the rest
 734						break;
 735					}
 736				}
 737				$this->DebugMessage('CleanUpCacheDirectory() purged '.count($DeletedKeys['maxfiles']).' files based on (config_cache_maxfiles='.$this->config_cache_maxfiles.')', __FILE__, __LINE__);
 738				foreach ($DeletedKeys['maxfiles'] as $fullfilename) {
 739					unset($CacheDirOldFilesAge[$fullfilename]);
 740					unset($CacheDirOldFilesSize[$fullfilename]);
 741				}
 742			}
 743
 744			if ($this->config_cache_maxage > 0) {
 745				$mindate = time() - $this->config_cache_maxage;
 746				$DeletedKeys['maxage'] = array();
 747				foreach ($CacheDirOldFilesAge as $fullfilename => $filedate) {
 748					if ($filedate > 0) {
 749						if ($filedate < $mindate) {
 750							$this->DebugMessage('deleting "'.$fullfilename.'"', __FILE__, __LINE__);
 751							if (@unlink($fullfilename)) {
 752								$DeletedKeys['maxage'][] = $fullfilename;
 753							}
 754						} else {
 755							// the rest of the files are new enough to keep
 756							break;
 757						}
 758					}
 759				}
 760				$this->DebugMessage('CleanUpCacheDirectory() purged '.count($DeletedKeys['maxage']).' files based on (config_cache_maxage='.$this->config_cache_maxage.')', __FILE__, __LINE__);
 761				foreach ($DeletedKeys['maxage'] as $fullfilename) {
 762					unset($CacheDirOldFilesAge[$fullfilename]);
 763					unset($CacheDirOldFilesSize[$fullfilename]);
 764				}
 765			}
 766
 767			if ($this->config_cache_maxsize > 0) {
 768				$TotalCachedFileSize = array_sum($CacheDirOldFilesSize);
 769				$DeletedKeys['maxsize'] = array();
 770				foreach ($CacheDirOldFilesAge as $fullfilename => $filedate) {
 771					if ($TotalCachedFileSize > $this->config_cache_maxsize) {
 772						$this->DebugMessage('deleting "'.$fullfilename.'"', __FILE__, __LINE__);
 773						if (@unlink($fullfilename)) {
 774							$TotalCachedFileSize -= $CacheDirOldFilesSize[$fullfilename];
 775							$DeletedKeys['maxsize'][] = $fullfilename;
 776						}
 777					} else {
 778						// the total filesizes are small enough to keep the rest of the files
 779						break;
 780					}
 781				}
 782				$this->DebugMessage('CleanUpCacheDirectory() purged '.count($DeletedKeys['maxsize']).' files based on (config_cache_maxsize='.$this->config_cache_maxsize.')', __FILE__, __LINE__);
 783				foreach ($DeletedKeys['maxsize'] as $fullfilename) {
 784					unset($CacheDirOldFilesAge[$fullfilename]);
 785					unset($CacheDirOldFilesSize[$fullfilename]);
 786				}
 787			}
 788
 789		} else {
 790			$this->DebugMessage('skipping CleanUpCacheDirectory() because config set to not use it', __FILE__, __LINE__);
 791		}
 792		$totalpurged = 0;
 793		foreach ($DeletedKeys as $key => $value) {
 794			$totalpurged += count($value);
 795		}
 796		$this->DebugMessage('CleanUpCacheDirectory() purged '.$totalpurged.' files (from '.count($AllFilesInCacheDirectory).') based on config settings', __FILE__, __LINE__);
 797		if ($totalpurged > 0) {
 798			$empty_dirs = array();
 799			foreach ($AllFilesInCacheDirectory as $fullfilename) {
 800				if (is_dir($fullfilename)) {
 801					$empty_dirs[realpath($fullfilename)] = 1;
 802				} else {
 803					unset($empty_dirs[realpath(dirname($fullfilename))]);
 804				}
 805			}
 806			krsort($empty_dirs);
 807			$totalpurgeddirs = 0;
 808			foreach ($empty_dirs as $empty_dir => $dummy) {
 809				if ($empty_dir == $this->config_cache_directory) {
 810					// shouldn't happen, but just in case, don't let it delete actual cache directory
 811					continue;
 812				} elseif (@rmdir($empty_dir)) {
 813					$totalpurgeddirs++;
 814				} else {
 815					$this->DebugMessage('failed to rmdir('.$empty_dir.')', __FILE__, __LINE__);
 816				}
 817			}
 818			$this->DebugMessage('purged '.$totalpurgeddirs.' empty directories', __FILE__, __LINE__);
 819		}
 820		return true;
 821	}
 822
 823	//////////////////////////////////////////////////////////////////////
 824
 825	// private: re-initializator (call between rendering multiple images with one object)
 826	function resetObject() {
 827		$class_vars = get_class_vars(get_class($this));
 828		foreach ($class_vars as $key => $value) {
 829			// do not clobber debug or config info
 830			if (!preg_match('#^(config_|debug|fatalerror)#i', $key)) {
 831				$this->$key = $value;
 832			}
 833		}
 834		$this->phpThumb(); // re-initialize some class variables
 835		return true;
 836	}
 837
 838	//////////////////////////////////////////////////////////////////////
 839
 840	function ResolveSource() {
 841		if (is_resource($this->gdimg_source)) {
 842			$this->DebugMessage('ResolveSource() exiting because is_resource($this->gdimg_source)', __FILE__, __LINE__);
 843			return true;
 844		}
 845		if ($this->rawImageData) {
 846			$this->sourceFilename = null;
 847			$this->DebugMessage('ResolveSource() exiting because $this->rawImageData is set ('.number_format(strlen($this->rawImageData)).' bytes)', __FILE__, __LINE__);
 848			return true;
 849		}
 850		if ($this->sourceFilename) {
 851			$this->sourceFilename = $this->ResolveFilenameToAbsolute($this->sourceFilename);
 852			$this->DebugMessage('$this->sourceFilename set to "'.$this->sourceFilename.'"', __FILE__, __LINE__);
 853		} elseif ($this->src) {
 854			$this->sourceFilename = $this->ResolveFilenameToAbsolute($this->src);
 855			$this->DebugMessage('$this->sourceFilename set to "'.$this->sourceFilename.'" from $this->src ('.$this->src.')', __FILE__, __LINE__);
 856		} else {
 857			return $this->ErrorImage('$this->sourceFilename and $this->src are both empty');
 858		}
 859		if ($this->iswindows && ((substr($this->sourceFilename, 0, 2) == '//') || (substr($this->sourceFilename, 0, 2) == '\\\\'))) {
 860			// Windows \\share\filename.ext
 861		} elseif (preg_match('#^(f|ht)tps?\://#i', $this->sourceFilename)) {
 862			// URL
 863			if ($this->config_http_user_agent) {
 864				ini_set('user_agent', $this->config_http_user_agent);
 865			}
 866		} elseif (!@file_exists($this->sourceFilename)) {
 867			return $this->ErrorImage('"'.$this->sourceFilename.'" does not exist');
 868		} elseif (!@is_file($this->sourceFilename)) {
 869			return $this->ErrorImage('"'.$this->sourceFilename.'" is not a file');
 870		}
 871		return true;
 872	}
 873
 874	function setOutputFormat() {
 875		static $alreadyCalled = false;
 876		if ($this->thumbnailFormat && $alreadyCalled) {
 877			return true;
 878		}
 879		$alreadyCalled = true;
 880
 881		$AvailableImageOutputFormats = array();
 882		$AvailableImageOutputFormats[] = 'text';
 883		if (@is_readable(dirname(__FILE__).'/phpthumb.ico.php')) {
 884			$AvailableImageOutputFormats[] = 'ico';
 885		}
 886		if (@is_readable(dirname(__FILE__).'/phpthumb.bmp.php')) {
 887			$AvailableImageOutputFormats[] = 'bmp';
 888		}
 889
 890		$this->thumbnailFormat = 'ico';
 891
 892		// Set default output format based on what image types are available
 893		if (function_exists('ImageTypes')) {
 894			$imagetypes = ImageTypes();
 895			if ($imagetypes & IMG_WBMP) {
 896				$this->thumbnailFormat         = 'wbmp';
 897				$AvailableImageOutputFormats[] = 'wbmp';
 898			}
 899			if ($imagetypes & IMG_GIF) {
 900				$this->thumbnailFormat         = 'gif';
 901				$AvailableImageOutputFormats[] = 'gif';
 902			}
 903			if ($imagetypes & IMG_PNG) {
 904				$this->thumbnailFormat         = 'png';
 905				$AvailableImageOutputFormats[] = 'png';
 906			}
 907			if ($imagetypes & IMG_JPG) {
 908				$this->thumbnailFormat         = 'jpeg';
 909				$AvailableImageOutputFormats[] = 'jpeg';
 910			}
 911		} else {
 912			//return $this->ErrorImage('ImageTypes() does not exist - GD support might not be enabled?');
 913			$this->DebugMessage('ImageTypes() does not exist - GD support might not be enabled?',  __FILE__, __LINE__);
 914		}
 915		if ($this->ImageMagickVersion()) {
 916			$IMformats = array('jpeg', 'png', 'gif', 'bmp', 'ico', 'wbmp');
 917			$this->DebugMessage('Addding ImageMagick formats to $AvailableImageOutputFormats ('.implode(';', $AvailableImageOutputFormats).')', __FILE__, __LINE__);
 918			foreach ($IMformats as $key => $format) {
 919				$AvailableImageOutputFormats[] = $format;
 920			}
 921		}
 922		$AvailableImageOutputFormats = array_unique($AvailableImageOutputFormats);
 923		$this->DebugMessage('$AvailableImageOutputFormats = array('.implode(';', $AvailableImageOutputFormats).')', __FILE__, __LINE__);
 924
 925		$this->f = preg_replace('#[^a-z]#', '', strtolower($this->f));
 926		if (strtolower($this->config_output_format) == 'jpg') {
 927			$this->config_output_format = 'jpeg';
 928		}
 929		if (strtolower($this->f) == 'jpg') {
 930			$this->f = 'jpeg';
 931		}
 932		if (phpthumb_functions::CaseInsensitiveInArray($this->config_output_format, $AvailableImageOutputFormats)) {
 933			// set output format to config default if that format is available
 934			$this->DebugMessage('$this->thumbnailFormat set to $this->config_output_format "'.strtolower($this->config_output_format).'"', __FILE__, __LINE__);
 935			$this->thumbnailFormat = strtolower($this->config_output_format);
 936		} elseif ($this->config_output_format) {
 937			$this->DebugMessage('$this->thumbnailFormat staying as "'.$this->thumbnailFormat.'" because $this->config_output_format ('.strtolower($this->config_output_format).') is not in $AvailableImageOutputFormats', __FILE__, __LINE__);
 938		}
 939		if ($this->f && (phpthumb_functions::CaseInsensitiveInArray($this->f, $AvailableImageOutputFormats))) {
 940			// override output format if $this->f is set and that format is available
 941			$this->DebugMessage('$this->thumbnailFormat set to $this->f "'.strtolower($this->f).'"', __FILE__, __LINE__);
 942			$this->thumbnailFormat = strtolower($this->f);
 943		} elseif ($this->f) {
 944			$this->DebugMessage('$this->thumbnailFormat staying as "'.$this->thumbnailFormat.'" because $this->f ('.strtolower($this->f).') is not in $AvailableImageOutputFormats', __FILE__, __LINE__);
 945		}
 946
 947		// for JPEG images, quality 1 (worst) to 99 (best)
 948		// quality < 25 is nasty, with not much size savings - not recommended
 949		// problems with 100 - invalid JPEG?
 950		$this->thumbnailQuality = max(1, min(99, ($this->q ? intval($this->q) : 75)));
 951		$this->DebugMessage('$this->thumbnailQuality set to "'.$this->thumbnailQuality.'"', __FILE__, __LINE__);
 952
 953		return true;
 954	}
 955
 956	function setCacheDirectory() {
 957		// resolve cache directory to absolute pathname
 958		$this->DebugMessage('setCacheDirectory() starting with config_cache_directory = "'.$this->config_cache_directory.'"', __FILE__, __LINE__);
 959		if (substr($this->config_cache_directory, 0, 1) == '.') {
 960			if (preg_match('#^(f|ht)tps?\://#i', $this->src)) {
 961				if (!$this->config_cache_disable_warning) {
 962					$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');
 963				}
 964			} elseif ($this->src) {
 965				// resolve relative cache directory to source image
 966				$this->config_cache_directory = dirname($this->ResolveFilenameToAbsolute($this->src)).DIRECTORY_SEPARATOR.$this->config_cache_directory;
 967			} else {
 968				// $this->new is probably set
 969			}
 970		}
 971		if (substr($this->config_cache_directory, -1) == '/') {
 972			$this->config_cache_directory = substr($this->config_cache_directory, 0, -1);
 973		}
 974		if ($this->iswindows) {
 975			$this->config_cache_directory = str_replace('/', DIRECTORY_SEPARATOR, $this->config_cache_directory);
 976		}
 977		if ($this->config_cache_directory) {
 978			$real_cache_path = realpath($this->config_cache_directory);
 979			if (!$real_cache_path) {
 980				$this->DebugMessage('realpath($this->config_cache_directory) failed for "'.$this->config_cache_directory.'"', __FILE__, __LINE__);
 981				if (!is_dir($this->config_cache_directory)) {
 982					$this->DebugMessage('!is_dir('.$this->config_cache_directory.')', __FILE__, __LINE__);
 983				}
 984			}
 985			if ($real_cache_path) {
 986				$this->DebugMessage('setting config_cache_directory to realpath('.$this->config_cache_directory.') = "'.$real_cache_path.'"', __FILE__, __LINE__);
 987				$this->config_cache_directory = $real_cache_path;
 988			}
 989		}
 990		if (!is_dir($this->config_cache_directory)) {
 991			if (!$this->config_cache_disable_warning) {
 992				$this->ErrorImage('$this->config_cache_directory ('.$this->config_cache_directory.') does not exist. Adjust "cache_directory" or "cache_disable_warning" in phpThumb.config.php');
 993			}
 994			$this->DebugMessage('$this->config_cache_directory ('.$this->config_cache_directory.') is not a directory', __FILE__, __LINE__);
 995			$this->config_cache_directory = null;
 996		} elseif (!@is_writable($this->config_cache_directory)) {
 997			$this->DebugMessage('$this->config_cache_directory is not writable ('.$this->config_cache_directory.')', __FILE__, __LINE__);
 998		}
 999
1000		$this->InitializeTempDirSetting();
1001		if (!@is_dir($this->config_temp_directory) && !@is_writable($this->config_temp_directory) && @is_dir($this->config_cache_directory) && @is_writable($this->config_cache_directory)) {
1002			$this->DebugMessage('setting $this->config_temp_directory = $this->config_cache_directory ('.$this->config_cache_directory.')', __FILE__, __LINE__);
1003			$this->config_temp_directory = $this->config_cache_directory;
1004		}
1005		return true;
1006	}
1007
1008
1009	function ResolveFilenameToAbsolute($filename) {
1010		if (empty($filename)) {
1011			return false;
1012		}
1013
1014		if (preg_match('#^[a-z0-9]+\:/{1,2}#i', $filename)) {
1015			// eg: http://host/path/file.jpg (HTTP URL)
1016			// eg: ftp://host/path/file.jpg  (FTP URL)
1017			// eg: data1:/path/file.jpg      (Netware path)
1018
1019			//$AbsoluteFilename = $filename;
1020			return $filename;
1021
1022		} elseif ($this->iswindows && isset($filename{1}) && ($filename{1} == ':')) {
1023
1024			// absolute pathname (Windows)
1025			$AbsoluteFilename = $filename;
1026
1027		} elseif ($this->iswindows && ((substr($filename, 0, 2) == '//') || (substr($filename, 0, 2) == '\\\\'))) {
1028
1029			// absolute pathname (Windows)
1030			$AbsoluteFilename = $filename;
1031
1032		} elseif ($filename{0} == '/') {
1033
1034			if (@is_readable($filename) && !@is_readable($this->config_document_root.$filename)) {
1035
1036				// absolute filename (*nix)
1037				$AbsoluteFilename = $filename;
1038
1039			} elseif (isset($filename{1}) && ($filename{1} == '~')) {
1040
1041				// /~user/path
1042				if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray($filename)) {
1043					$AbsoluteFilename = $ApacheLookupURIarray['filename'];
1044				} else {
1045					$AbsoluteFilename = realpath($filename);
1046					if (@is_readable($AbsoluteFilename)) {
1047						$this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with realpath($filename)', __FILE__, __LINE__);
1048					} elseif (is_dir(dirname($AbsoluteFilename))) {
1049						$this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname($filename).'", but the correct directory ('.dirname($AbsoluteFilename).') seems to have been resolved with realpath(.)', __FILE__, __LINE__);
1050					} else {
1051						return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'". This has been known to fail on Apache2 - try using the absolute filename for the source image (ex: "/home/user/httpdocs/image.jpg" instead of "/~user/image.jpg")');
1052					}
1053				}
1054
1055			} else {
1056
1057				// relative filename (any OS)
1058				if (preg_match('#^'.preg_quote($this->config_document_root).'#', $filename)) {
1059					$AbsoluteFilename = $filename;
1060					$this->DebugMessage('ResolveFilenameToAbsolute() NOT prepending $this->config_document_root ('.$this->config_document_root.') to $filename ('.$filename.') resulting in ($AbsoluteFilename = "'.$AbsoluteFilename.'")', __FILE__, __LINE__);
1061				} else {
1062					$AbsoluteFilename = $this->config_document_root.$filename;
1063					$this->DebugMessage('ResolveFilenameToAbsolute() prepending $this->config_document_root ('.$this->config_document_root.') to $filename ('.$filename.') resulting in ($AbsoluteFilename = "'.$AbsoluteFilename.'")', __FILE__, __LINE__);
1064				}
1065
1066			}
1067
1068		} else {
1069
1070			// relative to current directory (any OS)
1071			//$AbsoluteFilename = $this->config_document_root.preg_replace('#[/\\\\]#', DIRECTORY_SEPARATOR, dirname(@$_SERVER['PHP_SELF'])).DIRECTORY_SEPARATOR.preg_replace('#[/\\\\]#', DIRECTORY_SEPARATOR, $filename);
1072			$AbsoluteFilename = dirname(__FILE__).DIRECTORY_SEPARATOR.preg_replace('#[/\\\\]#', DIRECTORY_SEPARATOR, $filename);
1073
1074			//if (!@file_exists($AbsoluteFilename) && @file_exists(realpath($this->DotPadRelativeDirectoryPath($filename)))) {
1075			//	$AbsoluteFilename = realpath($this->DotPadRelativeDirectoryPath($filename));
1076			//}
1077
1078			if (substr(dirname(@$_SERVER['PHP_SELF']), 0, 2) == '/~') {
1079				if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray(dirname(@$_SERVER['PHP_SELF']))) {
1080					$AbsoluteFilename = $ApacheLookupURIarray['filename'].DIRECTORY_SEPARATOR.$filename;
1081				} else {
1082					$AbsoluteFilename = realpath('.').DIRECTORY_SEPARATOR.$filename;
1083					if (@is_readable($AbsoluteFilename)) {
1084						$this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with realpath(.)/$filename', __FILE__, __LINE__);
1085					} elseif (is_dir(dirname($AbsoluteFilename))) {
1086						$this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'", but the correct directory ('.dirname($AbsoluteFilename).') seems to have been resolved with realpath(.)', __FILE__, __LINE__);
1087					} else {
1088						return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'". This has been known to fail on Apache2 - try using the absolute filename for the source image');
1089					}
1090				}
1091			}
1092
1093		}
1094		if (is_link($AbsoluteFilename)) {
1095			$this->DebugMessage('is_link()==true, changing "'.$AbsoluteFilename.'" to "'.readlink($AbsoluteFilename).'"', __FILE__, __LINE__);
1096			$AbsoluteFilename = readlink($AbsoluteFilename);
1097		}
1098		if (realpath($AbsoluteFilename)) {
1099			$AbsoluteFilename = realpath($AbsoluteFilename);
1100		}
1101		if ($this->iswindows) {
1102			$AbsoluteFilename = preg_replace('#^'.preg_quote(realpath($this->config_document_root)).'#i', realpath($this->config_document_root), $AbsoluteFilename);
1103			$AbsoluteFilename = str_replace(DIRECTORY_SEPARATOR, '/', $AbsoluteFilename);
1104		}
1105		if (!$this->config_allow_src_above_docroot && !preg_match('#^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', realpath($this->config_document_root))).'#', $AbsoluteFilename)) {
1106			$this->DebugMessage('!$this->config_allow_src_above_docroot therefore setting "'.$AbsoluteFilename.'" (outside "'.realpath($this->config_document_root).'") to null', __FILE__, __LINE__);
1107			return false;
1108		}
1109		if (!$this->config_allow_src_above_phpthumb && !preg_match('#^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', dirname(__FILE__))).'#', $AbsoluteFilename)) {
1110			$this->DebugMessage('!$this->config_allow_src_above_phpthumb therefore setting "'.$AbsoluteFilename.'" (outside "'.dirname(__FILE__).'") to null', __FILE__, __LINE__);
1111			return false;
1112		}
1113		return $AbsoluteFilename;
1114	}
1115
1116	function file_exists_ignoreopenbasedir($filename, $cached=true) {
1117		static $open_basedirs = null;
1118		static $file_exists_cache = array();
1119		if (!$cached || !isset($file_exists_cache[$filename])) {
1120			if (is_null($open_basedirs)) {
1121				$open_basedirs = explode(';', ini_get('open_basedir'));
1122			}
1123			if (empty($open_basedirs) || in_array(dirname($filename), $open_basedirs)) {
1124				$file_exists_cache[$filename] = file_exists($filename);
1125			} elseif ($this->iswindows) {
1126				$ls_filename = trim(phpthumb_functions::SafeExec('dir '.escapeshellarg($filename)));
1127				$file_exists_cache[$filename] = !preg_match('#File Not Found#i', $ls_filename);
1128			} else {
1129				$ls_filename = trim(phpthumb_functions::SafeExec('ls '.escapeshellarg($filename)));
1130				$file_exists_cache[$filename] = ($ls_filename == $filename);
1131			}
1132		}
1133		return $file_exists_cache[$filename];
1134	}
1135
1136	function ImageMagickWhichConvert() {
1137		static $WhichConvert = null;
1138		if (is_null($WhichConvert)) {
1139			if ($this->iswindows) {
1140				$WhichConvert = false;
1141			} else {
1142				$WhichConvert = trim(phpthumb_functions::SafeExec('which convert'));
1143			}
1144		}
1145		return $WhichConvert;
1146	}
1147
1148	function ImageMagickCommandlineBase() {
1149		static $commandline = null;
1150		if (is_null($commandline)) {
1151			if ($this->issafemode) {
1152				$commandline = '';
1153				return $commandline;
1154			}
1155			$commandline = (!is_null($this->config_imagemagick_path) ? $this->config_imagemagick_path : '');
1156
1157			if ($this->config_imagemagick_path && ($this->config_imagemagick_path != realpath($this->config_imagemagick_path))) {
1158				if (@is_executable(realpath($this->config_imagemagick_path))) {
1159					$this->DebugMessage('Changing $this->config_imagemagick_path ('.$this->config_imagemagick_path.') to realpath($this->config_imagemagick_path) ('.realpath($this->config_imagemagick_path).')', __FILE__, __LINE__);
1160					$this->config_imagemagick_path = realpath($this->config_imagemagick_path);
1161				} else {
1162					$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__);
1163				}
1164			}
1165			$this->DebugMessage('                  file_exists('.$this->config_imagemagick_path.') = '.intval(                        @file_exists($this…

Large files files are truncated, but you can click here to view the full file