Advertisement
Guest User

timthumb.php

a guest
Feb 4th, 2013
197
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.41 KB | None | 0 0
  1. <?php
  2. /*
  3. TimThumb script created by Tim McDaniels and Darren Hoyt with tweaks by Ben Gillbanks
  4. http://code.google.com/p/timthumb/
  5.  
  6. MIT License: http://www.opensource.org/licenses/mit-license.php
  7.  
  8. Paramters
  9. ---------
  10. w: width
  11. h: height
  12. zc: zoom crop (0 or 1)
  13. q: quality (default is 75 and max is 100)
  14.  
  15. HTML example: <img src="/scripts/timthumb.php?src=/images/whatever.jpg&w=150&h=200&zc=1" alt="" />
  16. */
  17.  
  18. /*
  19. $sizeLimits = array(
  20. "100x100",
  21. "150x150",
  22. );
  23. */
  24.  
  25. define ('CACHE_SIZE', 250); // number of files to store before clearing cache
  26. define ('CACHE_CLEAR', 5); // maximum number of files to delete on each cache clear
  27. define ('VERSION', '1.09'); // version number (to force a cache refresh
  28.  
  29. $imageFilters = array(
  30. "1" => array(IMG_FILTER_NEGATE, 0),
  31. "2" => array(IMG_FILTER_GRAYSCALE, 0),
  32. "3" => array(IMG_FILTER_BRIGHTNESS, 1),
  33. "4" => array(IMG_FILTER_CONTRAST, 1),
  34. "5" => array(IMG_FILTER_COLORIZE, 4),
  35. "6" => array(IMG_FILTER_EDGEDETECT, 0),
  36. "7" => array(IMG_FILTER_EMBOSS, 0),
  37. "8" => array(IMG_FILTER_GAUSSIAN_BLUR, 0),
  38. "9" => array(IMG_FILTER_SELECTIVE_BLUR, 0),
  39. "10" => array(IMG_FILTER_MEAN_REMOVAL, 0),
  40. "11" => array(IMG_FILTER_SMOOTH, 0),
  41. );
  42.  
  43. // sort out image source
  44. $src = get_request("src", "");
  45. if($src == "" || strlen($src) <= 3) {
  46. displayError("no image specified");
  47. }
  48.  
  49. // clean params before use
  50. $src = cleanSource($src);
  51. // last modified time (for caching)
  52. $lastModified = filemtime($src);
  53.  
  54. // get properties
  55. $new_width = preg_replace("/[^0-9]+/", "", get_request("w", 0));
  56. $new_height = preg_replace("/[^0-9]+/", "", get_request("h", 0));
  57. $zoom_crop = preg_replace("/[^0-9]+/", "", get_request("zc", 1));
  58. $quality = preg_replace("/[^0-9]+/", "", get_request("q", 80));
  59. $filters = get_request("f", "");
  60.  
  61. if ($new_width == 0 && $new_height == 0) {
  62. $new_width = 100;
  63. $new_height = 100;
  64. }
  65.  
  66. // set path to cache directory (default is ./cache)
  67. // this can be changed to a different location
  68. $cache_dir = './cache';
  69.  
  70. // get mime type of src
  71. $mime_type = mime_type($src);
  72.  
  73. // check to see if this image is in the cache already
  74. check_cache( $cache_dir, $mime_type );
  75.  
  76. // if not in cache then clear some space and generate a new file
  77. cleanCache();
  78.  
  79. ini_set('memory_limit', "30M");
  80.  
  81. // make sure that the src is gif/jpg/png
  82. if(!valid_src_mime_type($mime_type)) {
  83. displayError("Invalid src mime type: " .$mime_type);
  84. }
  85.  
  86. // check to see if GD function exist
  87. if(!function_exists('imagecreatetruecolor')) {
  88. displayError("GD Library Error: imagecreatetruecolor does not exist");
  89. }
  90.  
  91. if(strlen($src) && file_exists($src)) {
  92.  
  93. // open the existing image
  94. $image = open_image($mime_type, $src);
  95. if($image === false) {
  96. displayError('Unable to open image : ' . $src);
  97. }
  98.  
  99. // Get original width and height
  100. $width = imagesx($image);
  101. $height = imagesy($image);
  102.  
  103. // don't allow new width or height to be greater than the original
  104. if( $new_width > $width ) {
  105. $new_width = $width;
  106. }
  107. if( $new_height > $height ) {
  108. $new_height = $height;
  109. }
  110.  
  111. // generate new w/h if not provided
  112. if( $new_width && !$new_height ) {
  113.  
  114. $new_height = $height * ( $new_width / $width );
  115.  
  116. } elseif($new_height && !$new_width) {
  117.  
  118. $new_width = $width * ( $new_height / $height );
  119.  
  120. } elseif(!$new_width && !$new_height) {
  121.  
  122. $new_width = $width;
  123. $new_height = $height;
  124.  
  125. }
  126.  
  127. // create a new true color image
  128. $canvas = imagecreatetruecolor( $new_width, $new_height );
  129. imagealphablending($canvas, false);
  130. // Create a new transparent color for image
  131. $color = imagecolorallocatealpha($canvas, 0, 0, 0, 127);
  132. // Completely fill the background of the new image with allocated color.
  133. imagefill($canvas, 0, 0, $color);
  134. // Restore transparency blending
  135. imagesavealpha($canvas, true);
  136.  
  137. if( $zoom_crop ) {
  138.  
  139. $src_x = $src_y = 0;
  140. $src_w = $width;
  141. $src_h = $height;
  142.  
  143. $cmp_x = $width / $new_width;
  144. $cmp_y = $height / $new_height;
  145.  
  146. // calculate x or y coordinate and width or height of source
  147.  
  148. if ( $cmp_x > $cmp_y ) {
  149.  
  150. $src_w = round( ( $width / $cmp_x * $cmp_y ) );
  151. $src_x = round( ( $width - ( $width / $cmp_x * $cmp_y ) ) / 2 );
  152.  
  153. } elseif ( $cmp_y > $cmp_x ) {
  154.  
  155. $src_h = round( ( $height / $cmp_y * $cmp_x ) );
  156. $src_y = round( ( $height - ( $height / $cmp_y * $cmp_x ) ) / 2 );
  157.  
  158. }
  159.  
  160. imagecopyresampled( $canvas, $image, 0, 0, $src_x, $src_y, $new_width, $new_height, $src_w, $src_h );
  161.  
  162. } else {
  163.  
  164. // copy and resize part of an image with resampling
  165. imagecopyresampled( $canvas, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height );
  166.  
  167. }
  168.  
  169. if ($filters != "") {
  170. // apply filters to image
  171. $filterList = explode("|", $filters);
  172. foreach($filterList as $fl) {
  173. $filterSettings = explode(",", $fl);
  174. if(isset($imageFilters[$filterSettings[0]])) {
  175.  
  176. for($i = 0; $i < 4; $i ++) {
  177. if(!isset($filterSettings[$i])) {
  178. $filterSettings[$i] = null;
  179. }
  180. }
  181.  
  182. switch($imageFilters[$filterSettings[0]][1]) {
  183.  
  184. case 1:
  185.  
  186. imagefilter($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1]);
  187. break;
  188.  
  189. case 2:
  190.  
  191. imagefilter($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2]);
  192. break;
  193.  
  194. case 3:
  195.  
  196. imagefilter($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2], $filterSettings[3]);
  197. break;
  198.  
  199. default:
  200.  
  201. imagefilter($canvas, $imageFilters[$filterSettings[0]][0]);
  202. break;
  203.  
  204. }
  205. }
  206. }
  207. }
  208.  
  209. // output image to browser based on mime type
  210. show_image($mime_type, $canvas, $cache_dir);
  211.  
  212. // remove image from memory
  213. imagedestroy($canvas);
  214.  
  215. } else {
  216.  
  217. if(strlen($src)) {
  218. displayError("image " . $src . " not found");
  219. } else {
  220. displayError("no source specified");
  221. }
  222.  
  223. }
  224.  
  225. /**
  226. *
  227. */
  228. function show_image($mime_type, $image_resized, $cache_dir) {
  229.  
  230. global $quality;
  231.  
  232. // check to see if we can write to the cache directory
  233. $is_writable = 0;
  234. $cache_file_name = $cache_dir . '/' . get_cache_file();
  235.  
  236. if(touch($cache_file_name)) {
  237.  
  238. // give 666 permissions so that the developer
  239. // can overwrite web server user
  240. chmod($cache_file_name, 0666);
  241. $is_writable = 1;
  242.  
  243. } else {
  244.  
  245. $cache_file_name = NULL;
  246. header('Content-type: ' . $mime_type);
  247.  
  248. }
  249.  
  250. $quality = floor($quality * 0.09);
  251.  
  252. imagepng($image_resized, $cache_file_name, $quality);
  253.  
  254. if($is_writable) {
  255. show_cache_file($cache_dir, $mime_type);
  256. }
  257.  
  258. imagedestroy($image_resized);
  259.  
  260. displayError("error showing image");
  261.  
  262. }
  263.  
  264. /**
  265. *
  266. */
  267. function get_request( $property, $default = 0 ) {
  268.  
  269. if( isset($_REQUEST[$property]) ) {
  270.  
  271. return $_REQUEST[$property];
  272.  
  273. } else {
  274.  
  275. return $default;
  276.  
  277. }
  278.  
  279. }
  280.  
  281. /**
  282. *
  283. */
  284. function open_image($mime_type, $src) {
  285.  
  286. if(stristr($mime_type, 'gif')) {
  287.  
  288. $image = imagecreatefromgif($src);
  289.  
  290. } elseif(stristr($mime_type, 'jpeg')) {
  291.  
  292. @ini_set('gd.jpeg_ignore_warning', 1);
  293. $image = imagecreatefromjpeg($src);
  294.  
  295. } elseif( stristr($mime_type, 'png')) {
  296.  
  297. $image = imagecreatefrompng($src);
  298.  
  299. }
  300.  
  301. return $image;
  302.  
  303. }
  304.  
  305. /**
  306. * clean out old files from the cache
  307. * you can change the number of files to store and to delete per loop in the defines at the top of the code
  308. */
  309. function cleanCache() {
  310.  
  311. $files = glob("cache/*", GLOB_BRACE);
  312.  
  313. $yesterday = time() - (24 * 60 * 60);
  314.  
  315. if (count($files) > 0) {
  316.  
  317. usort($files, "filemtime_compare");
  318. $i = 0;
  319.  
  320. if (count($files) > CACHE_SIZE) {
  321.  
  322. foreach ($files as $file) {
  323.  
  324. $i ++;
  325.  
  326. if ($i >= CACHE_CLEAR) {
  327. return;
  328. }
  329.  
  330. if (filemtime($file) > $yesterday) {
  331. return;
  332. }
  333.  
  334. unlink($file);
  335.  
  336. }
  337.  
  338. }
  339.  
  340. }
  341.  
  342. }
  343.  
  344. /**
  345. * compare the file time of two files
  346. */
  347. function filemtime_compare($a, $b) {
  348.  
  349. return filemtime($a) - filemtime($b);
  350.  
  351. }
  352.  
  353. /**
  354. * determine the file mime type
  355. */
  356. function mime_type($file) {
  357.  
  358. if (stristr(PHP_OS, 'WIN')) {
  359. $os = 'WIN';
  360. } else {
  361. $os = PHP_OS;
  362. }
  363.  
  364. $mime_type = '';
  365.  
  366. if (function_exists('mime_content_type')) {
  367. $mime_type = mime_content_type($file);
  368. }
  369.  
  370. // use PECL fileinfo to determine mime type
  371. if (!valid_src_mime_type($mime_type)) {
  372. if (function_exists('finfo_open')) {
  373. $finfo = finfo_open(FILEINFO_MIME);
  374. $mime_type = finfo_file($finfo, $file);
  375. finfo_close($finfo);
  376. }
  377. }
  378.  
  379. // try to determine mime type by using unix file command
  380. // this should not be executed on windows
  381. if (!valid_src_mime_type($mime_type) && $os != "WIN") {
  382. if (preg_match("/FREEBSD|LINUX/", $os)) {
  383. $mime_type = trim(@shell_exec('file -bi "' . $file . '"'));
  384. }
  385. }
  386.  
  387. // use file's extension to determine mime type
  388. if (!valid_src_mime_type($mime_type)) {
  389.  
  390. // set defaults
  391. $mime_type = 'image/png';
  392. // file details
  393. $fileDetails = pathinfo($file);
  394. $ext = strtolower($fileDetails["extension"]);
  395. // mime types
  396. $types = array(
  397. 'jpg' => 'image/jpeg',
  398. 'jpeg' => 'image/jpeg',
  399. 'png' => 'image/png',
  400. 'gif' => 'image/gif'
  401. );
  402.  
  403. if (strlen($ext) && strlen($types[$ext])) {
  404. $mime_type = $types[$ext];
  405. }
  406.  
  407. }
  408.  
  409. return $mime_type;
  410.  
  411. }
  412.  
  413. /**
  414. *
  415. */
  416. function valid_src_mime_type($mime_type) {
  417.  
  418. if (preg_match("/jpg|jpeg|gif|png/i", $mime_type)) {
  419. return true;
  420. }
  421.  
  422. return false;
  423.  
  424. }
  425.  
  426. /**
  427. *
  428. */
  429. function check_cache($cache_dir, $mime_type) {
  430.  
  431. // make sure cache dir exists
  432. if (!file_exists($cache_dir)) {
  433. // give 777 permissions so that developer can overwrite
  434. // files created by web server user
  435. mkdir($cache_dir);
  436. chmod($cache_dir, 0777);
  437. }
  438.  
  439. show_cache_file($cache_dir, $mime_type);
  440.  
  441. }
  442.  
  443. /**
  444. *
  445. */
  446. function show_cache_file($cache_dir) {
  447.  
  448. $cache_file = $cache_dir . '/' . get_cache_file();
  449.  
  450. if (file_exists($cache_file)) {
  451.  
  452. $gmdate_mod = gmdate("D, d M Y H:i:s", filemtime($cache_file));
  453.  
  454. if(! strstr($gmdate_mod, "GMT")) {
  455. $gmdate_mod .= " GMT";
  456. }
  457.  
  458. if (isset($_SERVER["HTTP_IF_MODIFIED_SINCE"])) {
  459.  
  460. // check for updates
  461. $if_modified_since = preg_replace("/;.*$/", "", $_SERVER["HTTP_IF_MODIFIED_SINCE"]);
  462.  
  463. if ($if_modified_since == $gmdate_mod) {
  464. header("HTTP/1.1 304 Not Modified");
  465. exit;
  466. }
  467.  
  468. }
  469.  
  470. $fileSize = filesize($cache_file);
  471.  
  472. // send headers then display image
  473. header("Content-Type: image/png");
  474. header("Accept-Ranges: bytes");
  475. header("Last-Modified: " . $gmdate_mod);
  476. header("Content-Length: " . $fileSize);
  477. header("Cache-Control: max-age=9999, must-revalidate");
  478. header("Expires: " . $gmdate_mod);
  479.  
  480. readfile($cache_file);
  481.  
  482. exit;
  483.  
  484. }
  485.  
  486. }
  487.  
  488. /**
  489. *
  490. */
  491. function get_cache_file() {
  492.  
  493. global $lastModified;
  494. static $cache_file;
  495.  
  496. if(!$cache_file) {
  497. $cachename = $_SERVER['QUERY_STRING'] . VERSION . $lastModified;
  498. $cache_file = md5($cachename) . '.png';
  499. }
  500.  
  501. return $cache_file;
  502.  
  503. }
  504.  
  505. /**
  506. * check to if the url is valid or not
  507. */
  508. function valid_extension ($ext) {
  509.  
  510. if (preg_match("/jpg|jpeg|png|gif/i", $ext)) {
  511. return TRUE;
  512. } else {
  513. return FALSE;
  514. }
  515.  
  516. }
  517.  
  518. /**
  519. * tidy up the image source url
  520. */
  521. function cleanSource($src) {
  522.  
  523. // remove slash from start of string
  524. if(strpos($src, "/") == 0) {
  525. $src = substr($src, -(strlen($src) - 1));
  526. }
  527.  
  528. // remove http/ https/ ftp
  529. $src = preg_replace("/^((ht|f)tp(s|):\/\/)/i", "", $src);
  530. // remove domain name from the source url
  531. $host = $_SERVER["HTTP_HOST"];
  532. $src = str_replace($host, "", $src);
  533. $host = str_replace("www.", "", $host);
  534. $src = str_replace($host, "", $src);
  535.  
  536. // don't allow users the ability to use '../'
  537. // in order to gain access to files below document root
  538.  
  539. // src should be specified relative to document root like:
  540. // src=images/img.jpg or src=/images/img.jpg
  541. // not like:
  542. // src=../images/img.jpg
  543. $src = preg_replace("/\.\.+\//", "", $src);
  544.  
  545. // get path to image on file system
  546. $src = get_document_root($src) . '/' . $src;
  547.  
  548. return $src;
  549.  
  550. }
  551.  
  552. /**
  553. *
  554. */
  555. function get_document_root ($src) {
  556.  
  557. // check for unix servers
  558. if(@file_exists($_SERVER['DOCUMENT_ROOT'] . '/' . $src)) {
  559. return $_SERVER['DOCUMENT_ROOT'];
  560. }
  561.  
  562. // check from script filename (to get all directories to timthumb location)
  563. $parts = array_diff(explode('/', $_SERVER['SCRIPT_FILENAME']), explode('/', $_SERVER['DOCUMENT_ROOT']));
  564. $path = $_SERVER['DOCUMENT_ROOT'] . '/';
  565. foreach ($parts as $part) {
  566. $path .= $part . '/';
  567. if (file_exists($path . $src)) {
  568. return $path;
  569. }
  570. }
  571.  
  572. // the relative paths below are useful if timthumb is moved outside of document root
  573. // specifically if installed in wordpress themes like mimbo pro:
  574. // /wp-content/themes/mimbopro/scripts/timthumb.php
  575. $paths = array(
  576. ".",
  577. "..",
  578. "../..",
  579. "../../..",
  580. "../../../..",
  581. "../../../../.."
  582. );
  583.  
  584. foreach($paths as $path) {
  585. if(@file_exists($path . '/' . $src)) {
  586. return $path;
  587. }
  588. }
  589.  
  590. // special check for microsoft servers
  591. if(!isset($_SERVER['DOCUMENT_ROOT'])) {
  592. $path = str_replace("/", "\\", $_SERVER['ORIG_PATH_INFO']);
  593. $path = str_replace($path, "", $_SERVER['SCRIPT_FILENAME']);
  594.  
  595. if( @file_exists( $path . '/' . $src ) ) {
  596. return $path;
  597. }
  598. }
  599.  
  600. displayError('file not found ' . $src);
  601.  
  602. }
  603.  
  604. /**
  605. * generic error message
  606. */
  607. function displayError($errorString = '') {
  608.  
  609. header('HTTP/1.1 400 Bad Request');
  610. die($errorString);
  611.  
  612. }
  613. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement