PageRenderTime 59ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 2ms

/includes/phpthumb/phpthumb.class.php

https://bitbucket.org/dgough/annamaria-daneswood-25102012
PHP | 3969 lines | 3316 code | 428 blank | 225 comment | 738 complexity | 7ceda9e3a161cf78cb9a181219852d64 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1

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

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