Guest User

timthumb.php - v1.34 - Secure

a guest
Sep 12th, 2011
307
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <?php
  2. /**
  3.  * TimThumb script created by Ben Gillbanks, originally created by Tim McDaniels and Darren Hoyt
  4.  * http://code.google.com/p/timthumb/
  5.  *
  6.  * GNU General Public License, version 2
  7.  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  8.  *
  9.  * Examples and documentation available on the project homepage
  10.  * http://www.binarymoon.co.uk/projects/timthumb/
  11.  */
  12.  
  13. define ('CACHE_SIZE', 1000);                // number of files to store before clearing cache
  14. define ('CACHE_CLEAR', 20);                 // maximum number of files to delete on each cache clear
  15. define ('CACHE_USE', TRUE);                 // use the cache files? (mostly for testing)
  16. define ('CACHE_MAX_AGE', 864000);           // time to cache in the browser
  17. define ('VERSION', '1.34');                 // version number (to force a cache refresh)
  18. define ('DIRECTORY_CACHE', './cache');      // cache directory
  19. define ('MAX_WIDTH', 1500);                 // maximum image width
  20. define ('MAX_HEIGHT', 1500);                // maximum image height
  21. define ('ALLOW_EXTERNAL', FALSE);           // allow external website (override security precaution - not advised!)
  22. define ('MEMORY_LIMIT', '30M');             // set PHP memory limit
  23. define ('MAX_FILE_SIZE', 1500000);          // file size limit to prevent possible DOS attacks (roughly 1.5 megabytes)
  24. define ('CURL_TIMEOUT', 10);                // timeout duration. Tweak as you require (lower = better)
  25.  
  26. // external domains that are allowed to be displayed on your website
  27. $allowedSites = array ();
  28.  
  29. // STOP MODIFYING HERE!
  30. // --------------------
  31.  
  32. // sort out image source
  33. $src = get_request ('src', '');
  34. if ($src == '' || strlen ($src) <= 3) {
  35.     display_error ('no image specified');
  36. }
  37.  
  38. // clean params before use
  39. $src = clean_source ($src);
  40.  
  41. // get mime type of src
  42. $mime_type = mime_type ($src);
  43.  
  44. // used for external websites only
  45. $external_data_string = '';
  46.  
  47. // generic file handle for reading and writing to files
  48. $fh = '';
  49.  
  50. // check to see if this image is in the cache already
  51. // if already cached then display the image and die
  52. check_cache ($mime_type);
  53.  
  54. // cache doesn't exist and then process everything
  55. // check to see if GD function exist
  56. if (!function_exists ('imagecreatetruecolor')) {
  57.     display_error ('GD Library Error: imagecreatetruecolor does not exist - please contact your webhost and ask them to install the GD library');
  58. }
  59.  
  60. if (function_exists ('imagefilter') && defined ('IMG_FILTER_NEGATE')) {
  61.     $imageFilters = array (
  62.         1 => array (IMG_FILTER_NEGATE, 0),
  63.         2 => array (IMG_FILTER_GRAYSCALE, 0),
  64.         3 => array (IMG_FILTER_BRIGHTNESS, 1),
  65.         4 => array (IMG_FILTER_CONTRAST, 1),
  66.         5 => array (IMG_FILTER_COLORIZE, 4),
  67.         6 => array (IMG_FILTER_EDGEDETECT, 0),
  68.         7 => array (IMG_FILTER_EMBOSS, 0),
  69.         8 => array (IMG_FILTER_GAUSSIAN_BLUR, 0),
  70.         9 => array (IMG_FILTER_SELECTIVE_BLUR, 0),
  71.         10 => array (IMG_FILTER_MEAN_REMOVAL, 0),
  72.         11 => array (IMG_FILTER_SMOOTH, 0),
  73.     );
  74. }
  75.  
  76. // get standard input properties
  77. $new_width =  (int) abs (get_request ('w', 0));
  78. $new_height = (int) abs (get_request ('h', 0));
  79. $zoom_crop = (int) get_request ('zc', 1);
  80. $quality = (int) abs (get_request ('q', 90));
  81. $align = get_request ('a', 'c');
  82. $filters = get_request ('f', '');
  83. $sharpen = (bool) get_request ('s', 0);
  84. $canvas_color = get_request ('cc', 'ffffff');
  85.  
  86. // set default width and height if neither are set already
  87. if ($new_width == 0 && $new_height == 0) {
  88.     $new_width = 100;
  89.     $new_height = 100;
  90. }
  91.  
  92. // ensure size limits can not be abused
  93. $new_width = min ($new_width, MAX_WIDTH);
  94. $new_height = min ($new_height, MAX_HEIGHT);
  95.  
  96. // set memory limit to be able to have enough space to resize larger images
  97. ini_set ('memory_limit', MEMORY_LIMIT);
  98.  
  99. if (file_exists ($src)) {
  100.  
  101.     // open the existing image
  102.     $image = open_image ($mime_type, $src);
  103.     if ($image === false) {
  104.         display_error ('Unable to open image : ' . $src);
  105.     }
  106.  
  107.     // Get original width and height
  108.     $width = imagesx ($image);
  109.     $height = imagesy ($image);
  110.     $origin_x = 0;
  111.     $origin_y = 0;
  112.  
  113.     // generate new w/h if not provided
  114.     if ($new_width && !$new_height) {
  115.         $new_height = floor ($height * ($new_width / $width));
  116.     } else if ($new_height && !$new_width) {
  117.         $new_width = floor ($width * ($new_height / $height));
  118.     }
  119.  
  120.     // scale down and add borders
  121.     if ($zoom_crop == 3) {
  122.  
  123.         $final_height = $height * ($new_width / $width);
  124.  
  125.         if ($final_height > $new_height) {
  126.             $new_width = $width * ($new_height / $height);
  127.         } else {
  128.             $new_height = $final_height;
  129.         }
  130.  
  131.     }
  132.  
  133.     // create a new true color image
  134.     $canvas = imagecreatetruecolor ($new_width, $new_height);
  135.     imagealphablending ($canvas, false);
  136.  
  137.     if (strlen ($canvas_color) < 6) {
  138.         $canvas_color = 'ffffff';
  139.     }
  140.  
  141.     $canvas_color_R = hexdec (substr ($canvas_color, 0, 2));
  142.     $canvas_color_G = hexdec (substr ($canvas_color, 2, 2));
  143.     $canvas_color_B = hexdec (substr ($canvas_color, 2, 2));
  144.  
  145.     // Create a new transparent color for image
  146.     $color = imagecolorallocatealpha ($canvas, $canvas_color_R, $canvas_color_G, $canvas_color_B, 127);
  147.  
  148.     // Completely fill the background of the new image with allocated color.
  149.     imagefill ($canvas, 0, 0, $color);
  150.  
  151.     // scale down and add borders
  152.     if ($zoom_crop == 2) {
  153.  
  154.         $final_height = $height * ($new_width / $width);
  155.        
  156.         if ($final_height > $new_height) {
  157.            
  158.             $origin_x = $new_width / 2;
  159.             $new_width = $width * ($new_height / $height);
  160.             $origin_x = round ($origin_x - ($new_width / 2));
  161.  
  162.         } else {
  163.  
  164.             $origin_y = $new_height / 2;
  165.             $new_height = $final_height;
  166.             $origin_y = round ($origin_y - ($new_height / 2));
  167.  
  168.         }
  169.  
  170.     }
  171.  
  172.     // Restore transparency blending
  173.     imagesavealpha ($canvas, true);
  174.  
  175.     if ($zoom_crop > 0) {
  176.  
  177.         $src_x = $src_y = 0;
  178.         $src_w = $width;
  179.         $src_h = $height;
  180.  
  181.         $cmp_x = $width / $new_width;
  182.         $cmp_y = $height / $new_height;
  183.  
  184.         // calculate x or y coordinate and width or height of source
  185.         if ($cmp_x > $cmp_y) {
  186.  
  187.             $src_w = round ($width / $cmp_x * $cmp_y);
  188.             $src_x = round (($width - ($width / $cmp_x * $cmp_y)) / 2);
  189.  
  190.         } else if ($cmp_y > $cmp_x) {
  191.  
  192.             $src_h = round ($height / $cmp_y * $cmp_x);
  193.             $src_y = round (($height - ($height / $cmp_y * $cmp_x)) / 2);
  194.  
  195.         }
  196.  
  197.         // positional cropping!
  198.         if ($align) {
  199.             if (strpos ($align, 't') !== false) {
  200.                 $src_y = 0;
  201.             }
  202.             if (strpos ($align, 'b') !== false) {
  203.                 $src_y = $height - $src_h;
  204.             }
  205.             if (strpos ($align, 'l') !== false) {
  206.                 $src_x = 0;
  207.             }
  208.             if (strpos ($align, 'r') !== false) {
  209.                 $src_x = $width - $src_w;
  210.             }
  211.         }
  212.  
  213.         imagecopyresampled ($canvas, $image, $origin_x, $origin_y, $src_x, $src_y, $new_width, $new_height, $src_w, $src_h);
  214.  
  215.     } else {
  216.  
  217.         // copy and resize part of an image with resampling
  218.         imagecopyresampled ($canvas, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
  219.  
  220.     }
  221.  
  222.     if ($filters != '' && function_exists ('imagefilter') && defined ('IMG_FILTER_NEGATE')) {
  223.         // apply filters to image
  224.         $filterList = explode ('|', $filters);
  225.         foreach ($filterList as $fl) {
  226.  
  227.             $filterSettings = explode (',', $fl);
  228.             if (isset ($imageFilters[$filterSettings[0]])) {
  229.  
  230.                 for ($i = 0; $i < 4; $i ++) {
  231.                     if (!isset ($filterSettings[$i])) {
  232.                         $filterSettings[$i] = null;
  233.                     } else {
  234.                         $filterSettings[$i] = (int) $filterSettings[$i];
  235.                     }
  236.                 }
  237.  
  238.                 switch ($imageFilters[$filterSettings[0]][1]) {
  239.  
  240.                     case 1:
  241.  
  242.                         imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1]);
  243.                         break;
  244.  
  245.                     case 2:
  246.  
  247.                         imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2]);
  248.                         break;
  249.  
  250.                     case 3:
  251.  
  252.                         imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2], $filterSettings[3]);
  253.                         break;
  254.  
  255.                     case 4:
  256.  
  257.                         imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2], $filterSettings[3], $filterSettings[4]);
  258.                         break;
  259.  
  260.                     default:
  261.  
  262.                         imagefilter ($canvas, $imageFilters[$filterSettings[0]][0]);
  263.                         break;
  264.  
  265.                 }
  266.             }
  267.         }
  268.     }
  269.  
  270.     // sharpen image
  271.     if ($sharpen && function_exists ('imageconvolution')) {
  272.  
  273.         $sharpenMatrix = array (
  274.             array (-1,-1,-1),
  275.             array (-1,16,-1),
  276.             array (-1,-1,-1),
  277.         );
  278.  
  279.         $divisor = 8;
  280.         $offset = 0;
  281.  
  282.         imageconvolution ($canvas, $sharpenMatrix, $divisor, $offset);
  283.  
  284.     }
  285.  
  286.     // output image to browser based on mime type
  287.     show_image ($mime_type, $canvas);
  288.  
  289.     // remove image from memory
  290.     imagedestroy ($canvas);
  291.  
  292.     // if not in cache then clear some space and generate a new file
  293.     clean_cache ();
  294.  
  295.     die ();
  296.  
  297. } else {
  298.  
  299.     if (strlen ($src)) {
  300.         display_error ('image ' . $src . ' not found');
  301.     } else {
  302.         display_error ('no source specified');
  303.     }
  304.  
  305. }
  306.  
  307.  
  308. /**
  309.  *
  310.  * @global <type> $quality
  311.  * @param <type> $mime_type
  312.  * @param <type> $image_resized
  313.  */
  314. function show_image ($mime_type, $image_resized) {
  315.  
  316.     global $quality;
  317.  
  318.     $cache_file = get_cache_file ($mime_type);
  319.  
  320.     switch ($mime_type) {
  321.         case 'jpg':
  322.             imagejpeg ($image_resized, $cache_file, $quality);
  323.             break;
  324.  
  325.         default:
  326.         case 'png':
  327.             imagepng ($image_resized, $cache_file, floor ($quality * 0.09));
  328.             break;
  329.  
  330.     }
  331.  
  332.     show_cache_file ($mime_type);
  333.  
  334. }
  335.  
  336.  
  337. /**
  338.  *
  339.  * @param <type> $property
  340.  * @param <type> $default
  341.  * @return <type>
  342.  */
  343. function get_request ($property, $default = 0) {
  344.  
  345.     if (isset ($_GET[$property])) {
  346.         return $_GET[$property];
  347.     } else {
  348.         return $default;
  349.     }
  350.  
  351. }
  352.  
  353.  
  354. /**
  355.  *
  356.  * @param <type> $mime_type
  357.  * @param <type> $src
  358.  * @return <type>
  359.  */
  360. function open_image ($mime_type, $src) {
  361.  
  362.     switch ($mime_type) {
  363.         case 'jpg':
  364.             $image = imagecreatefromjpeg ($src);
  365.             break;
  366.  
  367.         case 'png':
  368.             $image = imagecreatefrompng ($src);
  369.             break;
  370.  
  371.         case 'gif':
  372.             $image = imagecreatefromgif ($src);
  373.             break;
  374.     }
  375.  
  376.     return $image;
  377.  
  378. }
  379.  
  380. /**
  381.  * clean out old files from the cache
  382.  * you can change the number of files to store and to delete per loop in the defines at the top of the code
  383.  *
  384.  * @return <type>
  385.  */
  386. function clean_cache () {
  387.  
  388.     // add an escape
  389.     // Reduces the amount of cache clearing to save some processor speed
  390.     if (rand (1, 50) > 10) {
  391.         return true;
  392.     }
  393.  
  394.     flush ();
  395.  
  396.     $files = glob (DIRECTORY_CACHE . '/*', GLOB_BRACE);
  397.  
  398.     if (count ($files) > CACHE_SIZE) {
  399.        
  400.         $yesterday = time () - (24 * 60 * 60);
  401.  
  402.         usort ($files, 'filemtime_compare');
  403.         $i = 0;
  404.  
  405.         foreach ($files as $file) {
  406.  
  407.             $i ++;
  408.  
  409.             if ($i >= CACHE_CLEAR) {
  410.                 return;
  411.             }
  412.  
  413.             if (@filemtime ($file) > $yesterday) {
  414.                 return;
  415.             }
  416.  
  417.             if (file_exists ($file)) {
  418.                 unlink ($file);
  419.             }
  420.  
  421.         }
  422.  
  423.     }
  424.  
  425. }
  426.  
  427.  
  428. /**
  429.  * compare the file time of two files
  430.  *
  431.  * @param <type> $a
  432.  * @param <type> $b
  433.  * @return <type>
  434.  */
  435. function filemtime_compare ($a, $b) {
  436.  
  437.     $break = explode ('/', $_SERVER['SCRIPT_FILENAME']);
  438.     $filename = $break[count ($break) - 1];
  439.     $filepath = str_replace ($filename, '', $_SERVER['SCRIPT_FILENAME']);
  440.  
  441.     $file_a = realpath ($filepath . $a);
  442.     $file_b = realpath ($filepath . $b);
  443.  
  444.     return filemtime ($file_a) - filemtime ($file_b);
  445.  
  446. }
  447.  
  448.  
  449. /**
  450.  * determine the file mime type
  451.  *
  452.  * @param <type> $file
  453.  * @return <type>
  454.  */
  455. function mime_type ($file) {
  456.  
  457.     $file_infos = getimagesize ($file);
  458.    
  459.     // no mime type
  460.     if (empty ($file_infos['mime'])) {
  461.         display_error ('no mime type specified in image');
  462.     }
  463.  
  464.     $mime_type = $file_infos['mime'];
  465.  
  466.     // use mime_type to determine mime type
  467.     if (!preg_match ("/jpg|jpeg|gif|png/i", $mime_type)) {
  468.         display_error ('Invalid src mime type: ' . $mime_type);
  469.     }
  470.  
  471.     $mime_type = strtolower ($mime_type);
  472.     $mime_type = str_replace ('image/', '', $mime_type);
  473.  
  474.     if ($mime_type == 'jpeg') {
  475.         $mime_type = 'jpg';
  476.     }
  477.  
  478.     return $mime_type;
  479.  
  480. }
  481.  
  482.  
  483. /**
  484.  *
  485.  * @param <type> $mime_type
  486.  */
  487. function check_cache ($mime_type) {
  488.  
  489.     if (CACHE_USE) {
  490.  
  491.         if (!show_cache_file ($mime_type)) {
  492.             // make sure cache dir exists
  493.             if (!file_exists (DIRECTORY_CACHE)) {
  494.                 // give 777 permissions so that developer can overwrite
  495.                 // files created by web server user
  496.                 mkdir (DIRECTORY_CACHE);
  497.                 chmod (DIRECTORY_CACHE, 0777);
  498.             }
  499.         }
  500.  
  501.     }
  502.  
  503. }
  504.  
  505.  
  506. /**
  507.  *
  508.  * @param <type> $mime_type
  509.  * @return <type>
  510.  */
  511. function show_cache_file ($mime_type) {
  512.  
  513.     // use browser cache if available to speed up page load
  514.     if (!empty ($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
  515.         if (strtotime ($_SERVER['HTTP_IF_MODIFIED_SINCE']) < strtotime ('now')) {
  516.             header ('HTTP/1.1 304 Not Modified');
  517.             die ();
  518.         }
  519.     }
  520.  
  521.     $cache_file = get_cache_file ($mime_type);
  522.  
  523.     if (file_exists ($cache_file)) {
  524.  
  525.         // change the modified headers
  526.         $gmdate_expires = gmdate ('D, d M Y H:i:s', strtotime ('now +10 days')) . ' GMT';
  527.         $gmdate_modified = gmdate ('D, d M Y H:i:s') . ' GMT';
  528.  
  529.         // send content headers then display image
  530.         header ('Content-Type: image/' . get_file_type ($mime_type));
  531.         header ('Accept-Ranges: bytes');
  532.         header ('Last-Modified: ' . $gmdate_modified);
  533.         header ('Content-Length: ' . filesize ($cache_file));
  534.         header ('Cache-Control: max-age=' . CACHE_MAX_AGE . ', must-revalidate');
  535.         header ('Expires: ' . $gmdate_expires);
  536.  
  537.         if (!@readfile ($cache_file)) {
  538.             $content = file_get_contents ($cache_file);
  539.             if ($content != FALSE) {
  540.                 echo $content;
  541.             } else {
  542.                 display_error ('cache file could not be loaded');
  543.             }
  544.         }
  545.  
  546.         die ();
  547.  
  548.     }
  549.  
  550.     return FALSE;
  551.  
  552. }
  553.  
  554.  
  555. /**
  556.  *
  557.  * @param type $extension
  558.  * @return type
  559.  */
  560. function get_file_type ($extension) {
  561.    
  562.     switch ($extension) {
  563.         case 'png':
  564.         case 'gif':
  565.             return 'png';
  566.            
  567.         case 'jpg':
  568.         case 'jpeg':
  569.             return 'jpeg';
  570.            
  571.         default:
  572.             display_error ('file type not found : ' . $extension);
  573.     }
  574.    
  575. }
  576.  
  577.  
  578. /**
  579.  *
  580.  * @staticvar string $cache_file
  581.  * @param <type> $mime_type
  582.  * @return string
  583.  */
  584. function get_cache_file ($mime_type) {
  585.  
  586.     static $cache_file;
  587.     global $src;
  588.  
  589.     if (!$cache_file) {
  590.         // filemtime is used to make sure updated files get recached
  591.         $cache_file = DIRECTORY_CACHE . '/' . md5 ($_SERVER ['QUERY_STRING'] . VERSION . filemtime ($src)) . '.' . $mime_type;
  592.     }
  593.  
  594.     return $cache_file;
  595.  
  596. }
  597.  
  598.  
  599. /**
  600.  *
  601.  * @param <type> $url
  602.  * @return <type>
  603.  */
  604. function validate_url ($url) {
  605.     $pattern = "/\b(?:(?:https?):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i";
  606.     return preg_match ($pattern, $url);
  607. }
  608.  
  609.  
  610. /**
  611.  *
  612.  * @global array $allowedSites
  613.  * @param string $src
  614.  * @return string
  615.  */
  616. function check_external ($src) {
  617.  
  618.     global $allowedSites;
  619.  
  620.     // work out file details
  621.     $filename = 'external_' . md5 ($src);
  622.     $local_filepath = DIRECTORY_CACHE . '/' . $filename;
  623.    
  624.     // only do this stuff the file doesn't already exist
  625.     if (!file_exists ($local_filepath)) {
  626.  
  627.         if (strpos (strtolower ($src), 'http://') !== false || strpos (strtolower ($src), 'https://') !== false) {
  628.  
  629.             if (!validate_url ($src)) {
  630.                 display_error ('invalid url');
  631.             }
  632.  
  633.             $url_info = parse_url ($src);
  634.  
  635.             if (count (explode ('.', $url_info['path'])) > 2) {
  636.                 display_error ('source filename invalid');
  637.             }          
  638.  
  639.             if (($url_info['host'] == 'www.youtube.com' || $url_info['host'] == 'youtube.com') && preg_match ('/v=([^&]+)/i', $url_info['query'], $matches)) {
  640.                 $v = $matches[1];
  641.                 $src = 'http://img.youtube.com/vi/' . $v . '/0.jpg';
  642.                 $url_info['host'] = 'img.youtube.com';
  643.             }
  644.            
  645.             $isAllowedSite = false;
  646.  
  647.             // check allowed sites (if required)
  648.             if (ALLOW_EXTERNAL) {
  649.  
  650.                 $isAllowedSite = true;
  651.  
  652.             } else {
  653.  
  654.                 foreach ($allowedSites as $site) {
  655.                     if (preg_match ('/(?:^|\.)' . $site . '$/i', $url_info['host'])) {
  656.                         $isAllowedSite = true;
  657.                     }
  658.                 }
  659.  
  660.             }
  661.  
  662.             // if allowed
  663.             if ($isAllowedSite) {
  664.  
  665.                 if (function_exists ('curl_init')) {
  666.  
  667.                     global $fh;
  668.  
  669.                     $fh = fopen ($local_filepath, 'w');
  670.                     $ch = curl_init ($src);
  671.  
  672.                     curl_setopt ($ch, CURLOPT_TIMEOUT, CURL_TIMEOUT);
  673.                     curl_setopt ($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0');
  674.                     curl_setopt ($ch, CURLOPT_URL, $src);
  675.                     curl_setopt ($ch, CURLOPT_RETURNTRANSFER, TRUE);
  676.                     curl_setopt ($ch, CURLOPT_HEADER, 0);
  677.                     curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  678.                     curl_setopt ($ch, CURLOPT_FILE, $fh);
  679.                     curl_setopt ($ch, CURLOPT_WRITEFUNCTION, 'curl_write');
  680.  
  681.                     // error so die
  682.                     if (curl_exec ($ch) === FALSE) {
  683.                         unlink ($local_filepath);
  684.                         touch ($local_filepath);
  685.                         display_error ('error reading file ' . $src . ' from remote host: ' . curl_error ($ch));
  686.                     }
  687.  
  688.                     curl_close ($ch);
  689.                     fclose ($fh);
  690.                    
  691.                     // check it's actually an image
  692.                     $file_infos = getimagesize ($local_filepath);
  693.  
  694.                     // no mime type or invalid mime type
  695.                     if (empty ($file_infos['mime']) || !preg_match ("/jpg|jpeg|gif|png/i", $file_infos['mime'])) {
  696.                         unlink ($local_filepath);
  697.                         touch ($local_filepath);
  698.                         display_error ('remote file not a valid image');
  699.                     }                  
  700.  
  701.                 } else {
  702.  
  703.                     if (!$img = file_get_contents ($src)) {
  704.                         display_error ('remote file for ' . $src . ' can not be accessed. It is likely that the file permissions are restricted');
  705.                     }
  706.  
  707.                     if (file_put_contents ($local_filepath, $img) == FALSE) {
  708.                         display_error ('error writing temporary file');
  709.                     }
  710.  
  711.                 }
  712.  
  713.                 if (!file_exists ($local_filepath)) {
  714.                     display_error ('local file for ' . $src . ' can not be created');
  715.                 }
  716.  
  717.                 $src = $local_filepath;
  718.  
  719.             } else {
  720.  
  721.                 display_error ('remote host "' . $url_info['host'] . '" not allowed');
  722.  
  723.             }
  724.  
  725.         }
  726.  
  727.     } else {
  728.  
  729.         $src = $local_filepath;
  730.  
  731.     }
  732.  
  733.     return $src;
  734.  
  735. }
  736.  
  737.  
  738. /**
  739.  * callback for curl command to receive external images
  740.  * limit the amount of data downloaded from external servers
  741.  *
  742.  * @global <type> $data_string
  743.  * @param <type> $handle
  744.  * @param <type> $data
  745.  * @return <type>
  746.  */
  747. function curl_write ($handle, $data) {
  748.  
  749.     global $external_data_string, $fh;
  750.  
  751.     fwrite ($fh, $data);
  752.     $external_data_string .= $data;
  753.  
  754.     if (strlen ($external_data_string) > MAX_FILE_SIZE) {
  755.         return 0;
  756.     } else {
  757.         return strlen ($data);
  758.     }
  759.  
  760. }
  761.  
  762.  
  763. /**
  764.  * tidy up the image source url
  765.  *
  766.  * @param <type> $src
  767.  * @return string
  768.  */
  769. function clean_source ($src) {
  770.  
  771.     $host = str_replace ('www.', '', $_SERVER['HTTP_HOST']);
  772.     $regex = "/^(http(s|):\/\/)(www\.|)" . $host . "\//i";
  773.  
  774.     $src = preg_replace ($regex, '', $src);
  775.     $src = strip_tags ($src);
  776.     $src = check_external ($src);
  777.  
  778.     // remove slash from start of string
  779.     if (strpos ($src, '/') === 0) {
  780.         $src = substr ($src, -(strlen ($src) - 1));
  781.     }
  782.  
  783.     // don't allow users the ability to use '../'
  784.     // in order to gain access to files below document root
  785.     $src = preg_replace ("/\.\.+\//", "", $src);
  786.    
  787.     // get path to image on file system
  788.     $src = get_document_root ($src) . '/' . $src;
  789.  
  790.     if (!is_file ($src)) {
  791.         display_error ('source is not a valid file');
  792.     }
  793.  
  794.     if (filesize ($src) > MAX_FILE_SIZE) {
  795.         display_error ('source file is too big (filesize > MAX_FILE_SIZE)');
  796.     }
  797.  
  798.     if (filesize ($src) <= 0) {
  799.         display_error ('source file <= 0 bytes. Possible external file download error (file is too large)');
  800.     }
  801.  
  802.     return realpath ($src);
  803.  
  804. }
  805.  
  806.  
  807. /**
  808.  *
  809.  * @param <type> $src
  810.  * @return string
  811.  */
  812. function get_document_root ($src) {
  813.  
  814.     // check for unix servers
  815.     if (file_exists ($_SERVER['DOCUMENT_ROOT'] . '/' . $src)) {
  816.         return $_SERVER['DOCUMENT_ROOT'];
  817.     }
  818.  
  819.     // check from script filename (to get all directories to timthumb location)
  820.     $parts = array_diff (explode ('/', $_SERVER['SCRIPT_FILENAME']), explode ('/', $_SERVER['DOCUMENT_ROOT']));
  821.  
  822.     $path = './';
  823.    
  824.     foreach ($parts as $part) {
  825.         if (file_exists ($path . '/' . $src)) {
  826.             return realpath ($path);
  827.         }
  828.         $path .= '../';
  829.     }
  830.  
  831.     // special check for microsoft servers
  832.     if (!isset ($_SERVER['DOCUMENT_ROOT'])) {
  833.         $path = str_replace ("/", "\\", $_SERVER['ORIG_PATH_INFO']);
  834.         $path = str_replace ($path, '', $_SERVER['SCRIPT_FILENAME']);
  835.  
  836.         if (file_exists ($path . '/' . $src)) {
  837.             return realpath ($path);
  838.         }
  839.     }
  840.  
  841.     display_error ('file not found');
  842.  
  843. }
  844.  
  845.  
  846. /**
  847.  * generic error message
  848.  *
  849.  * @param <type> $errorString
  850.  */
  851. function display_error ($errorString = '') {
  852.  
  853.     header ('HTTP/1.1 400 Bad Request');
  854.     echo '<pre>' . htmlentities ($errorString);
  855.     echo '<br />Query String : ' . htmlentities ($_SERVER['QUERY_STRING']);
  856.     echo '<br />TimThumb version : ' . VERSION . '</pre>';
  857.     die ();
  858.  
  859. }
  860. ?>
RAW Paste Data