{"id":2828,"date":"2011-08-02T09:30:02","date_gmt":"2011-08-02T13:30:02","guid":{"rendered":"http:\/\/teamtutorials.com\/?p=2828"},"modified":"2011-08-02T21:12:35","modified_gmt":"2011-08-03T01:12:35","slug":"fix-the-timthumb-php-wordpress-exploit","status":"publish","type":"post","link":"https:\/\/teamtutorials.com\/web-development-tutorials\/fix-the-timthumb-php-wordpress-exploit","title":{"rendered":"Fix the timthumb.php WordPress exploit"},"content":{"rendered":"
There was a recent exploit found in a common file used to generate thumbnails. I found out about the exploit from Mark Maunder’s site<\/a>. If you have a server running several wordpress blogs, like us, here is a way to fix all the exploits.<\/p>\n If you don’t want to copy and paste skip to the bottom of the post to download the fix.<\/strong><\/p>\n First, upload a fixed version of the tim thumb file names timthumb-fix.php<\/p>\n Then upload our shell script as fix_timthumb.sh:<\/p>\n The all you have to do is execute this command:<\/p>\n The script will find any timthumb.php file and replace it with your fixed file. You will probably need root access to do this.<\/p>\n [tweet2download file=”timthum_fix.zip” tweet=”Replace all timthumb.php files on your server http:\/\/su.pr\/1Libna” follow=”@teamtutorials” \/]<\/p>\n","protected":false},"excerpt":{"rendered":" There was a recent exploit found in a common file used to generate thumbnails. I found out about the exploit from Mark Maunder’s site. If you have a server running several wordpress blogs, like us, here is a way to fix all the exploits. If you don’t want to copy and paste skip to the … Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":2836,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[17,23],"tags":[136,139,140,138,137,108],"yoast_head":"\n\r\n<?php\r\n\/**\r\n * TimThumb script created by Ben Gillbanks, originally created by Tim McDaniels and Darren Hoyt\r\n * http:\/\/code.google.com\/p\/timthumb\/\r\n * \r\n * GNU General Public License, version 2\r\n * http:\/\/www.gnu.org\/licenses\/old-licenses\/gpl-2.0.html\r\n *\r\n * Examples and documentation available on the project homepage\r\n * http:\/\/www.binarymoon.co.uk\/projects\/timthumb\/\r\n *\/\r\n\r\ndefine ('CACHE_SIZE', 1000);\t\t\t\t\/\/ number of files to store before clearing cache\r\ndefine ('CACHE_CLEAR', 20);\t\t\t\t\t\/\/ maximum number of files to delete on each cache clear\r\ndefine ('CACHE_USE', TRUE);\t\t\t\t\t\/\/ use the cache files? (mostly for testing)\r\ndefine ('CACHE_MAX_AGE', 864000);\t\t\t\/\/ time to cache in the browser\r\ndefine ('VERSION', '1.28');\t\t\t\t\t\/\/ version number (to force a cache refresh)\r\ndefine ('DIRECTORY_CACHE', '.\/cache');\t\t\/\/ cache directory\r\ndefine ('MAX_WIDTH', 1500);\t\t\t\t\t\/\/ maximum image width\r\ndefine ('MAX_HEIGHT', 1500);\t\t\t\t\/\/ maximum image height\r\ndefine ('ALLOW_EXTERNAL', FALSE);\t\t\t\/\/ allow external website (override security precaution - not advised!)\r\ndefine ('MEMORY_LIMIT', '30M');\t\t\t\t\/\/ set PHP memory limit\r\ndefine ('MAX_FILE_SIZE', 1500000);\t\t\t\/\/ file size limit to prevent possible DOS attacks (roughly 1.5 megabytes)\r\ndefine ('CURL_TIMEOUT', 10);\t\t\t\t\/\/ timeout duration. Tweak as you require (lower = better)\r\n\r\n\/\/ external domains that are allowed to be displayed on your website\r\n$allowedSites = array ();\r\n\r\n\/\/ STOP MODIFYING HERE!\r\n\/\/ --------------------\r\n\r\n\/\/ sort out image source\r\n$src = get_request ('src', '');\r\nif ($src == '' || strlen ($src) <= 3) {\r\n display_error ('no image specified');\r\n}\r\n\r\n\/\/ clean params before use\r\n$src = clean_source ($src);\r\n\r\n\/\/ get mime type of src\r\n$mime_type = mime_type ($src);\r\n\r\n\/\/ used for external websites only\r\n$external_data_string = '';\r\n\r\n\/\/ generic file handle for reading and writing to files\r\n$fh = '';\r\n\r\n\/\/ check to see if this image is in the cache already\r\n\/\/ if already cached then display the image and die\r\ncheck_cache ($mime_type);\r\n\r\n\/\/ cache doesn't exist and then process everything\r\n\/\/ check to see if GD function exist\r\nif (!function_exists ('imagecreatetruecolor')) {\r\n display_error ('GD Library Error: imagecreatetruecolor does not exist - please contact your webhost and ask them to install the GD library');\r\n}\r\n\r\nif (function_exists ('imagefilter') && defined ('IMG_FILTER_NEGATE')) {\r\n\t$imageFilters = array (\r\n\t\t1 => array (IMG_FILTER_NEGATE, 0),\r\n\t\t2 => array (IMG_FILTER_GRAYSCALE, 0),\r\n\t\t3 => array (IMG_FILTER_BRIGHTNESS, 1),\r\n\t\t4 => array (IMG_FILTER_CONTRAST, 1),\r\n\t\t5 => array (IMG_FILTER_COLORIZE, 4),\r\n\t\t6 => array (IMG_FILTER_EDGEDETECT, 0),\r\n\t\t7 => array (IMG_FILTER_EMBOSS, 0),\r\n\t\t8 => array (IMG_FILTER_GAUSSIAN_BLUR, 0),\r\n\t\t9 => array (IMG_FILTER_SELECTIVE_BLUR, 0),\r\n\t\t10 => array (IMG_FILTER_MEAN_REMOVAL, 0),\r\n\t\t11 => array (IMG_FILTER_SMOOTH, 0),\r\n\t);\r\n}\r\n\r\n\/\/ get standard input properties\r\n$new_width = (int) abs (get_request ('w', 0));\r\n$new_height = (int) abs (get_request ('h', 0));\r\n$zoom_crop = (int) get_request ('zc', 1);\r\n$quality = (int) abs (get_request ('q', 90));\r\n$align = get_request ('a', 'c');\r\n$filters = get_request ('f', '');\r\n$sharpen = (bool) get_request ('s', 0);\r\n\r\n\/\/ set default width and height if neither are set already\r\nif ($new_width == 0 && $new_height == 0) {\r\n $new_width = 100;\r\n $new_height = 100;\r\n}\r\n\r\n\/\/ ensure size limits can not be abused\r\n$new_width = min ($new_width, MAX_WIDTH);\r\n$new_height = min ($new_height, MAX_HEIGHT);\r\n\r\n\/\/ set memory limit to be able to have enough space to resize larger images\r\nini_set ('memory_limit', MEMORY_LIMIT);\r\n\r\nif (file_exists ($src)) {\r\n\r\n \/\/ open the existing image\r\n $image = open_image ($mime_type, $src);\r\n if ($image === false) {\r\n display_error ('Unable to open image : ' . $src);\r\n }\r\n\r\n \/\/ Get original width and height\r\n $width = imagesx ($image);\r\n $height = imagesy ($image);\r\n\t$origin_x = 0;\r\n\t$origin_y = 0;\r\n\r\n \/\/ generate new w\/h if not provided\r\n if ($new_width && !$new_height) {\r\n $new_height = floor ($height * ($new_width \/ $width));\r\n } else if ($new_height && !$new_width) {\r\n $new_width = floor ($width * ($new_height \/ $height));\r\n }\r\n\r\n\t\/\/ scale down and add borders\r\n\tif ($zoom_crop == 3) {\r\n\r\n\t\t$final_height = $height * ($new_width \/ $width);\r\n\r\n\t\tif ($final_height > $new_height) {\r\n\t\t\t$new_width = $width * ($new_height \/ $height);\r\n\t\t} else {\r\n\t\t\t$new_height = $final_height;\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t\/\/ create a new true color image\r\n\t$canvas = imagecreatetruecolor ($new_width, $new_height);\r\n\timagealphablending ($canvas, false);\r\n\r\n\t\/\/ Create a new transparent color for image\r\n\t$color = imagecolorallocatealpha ($canvas, 0, 0, 0, 127);\r\n\r\n\t\/\/ Completely fill the background of the new image with allocated color.\r\n\timagefill ($canvas, 0, 0, $color);\r\n\r\n\t\/\/ scale down and add borders\r\n\tif ($zoom_crop == 2) {\r\n\r\n\t\t$final_height = $height * ($new_width \/ $width);\r\n\t\t\r\n\t\tif ($final_height > $new_height) {\r\n\t\t\t\r\n\t\t\t$origin_x = $new_width \/ 2;\r\n\t\t\t$new_width = $width * ($new_height \/ $height);\r\n\t\t\t$origin_x = round ($origin_x - ($new_width \/ 2));\r\n\r\n\t\t} else {\r\n\r\n\t\t\t$origin_y = $new_height \/ 2;\r\n\t\t\t$new_height = $final_height;\r\n\t\t\t$origin_y = round ($origin_y - ($new_height \/ 2));\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t\/\/ Restore transparency blending\r\n\timagesavealpha ($canvas, true);\r\n\r\n\tif ($zoom_crop > 0) {\r\n\r\n\t\t$src_x = $src_y = 0;\r\n\t\t$src_w = $width;\r\n\t\t$src_h = $height;\r\n\r\n\t\t$cmp_x = $width \/ $new_width;\r\n\t\t$cmp_y = $height \/ $new_height;\r\n\r\n\t\t\/\/ calculate x or y coordinate and width or height of source\r\n\t\tif ($cmp_x > $cmp_y) {\r\n\r\n\t\t\t$src_w = round ($width \/ $cmp_x * $cmp_y);\r\n\t\t\t$src_x = round (($width - ($width \/ $cmp_x * $cmp_y)) \/ 2);\r\n\r\n\t\t} else if ($cmp_y > $cmp_x) {\r\n\r\n\t\t\t$src_h = round ($height \/ $cmp_y * $cmp_x);\r\n\t\t\t$src_y = round (($height - ($height \/ $cmp_y * $cmp_x)) \/ 2);\r\n\r\n\t\t}\r\n\r\n\t\t\/\/ positional cropping!\r\n\t\tif ($align) {\r\n\t\t\tif (strpos ($align, 't') !== false) {\r\n\t\t\t\t$src_y = 0;\r\n\t\t\t}\r\n\t\t\tif (strpos ($align, 'b') !== false) {\r\n\t\t\t\t$src_y = $height - $src_h;\r\n\t\t\t}\r\n\t\t\tif (strpos ($align, 'l') !== false) {\r\n\t\t\t\t$src_x = 0;\r\n\t\t\t}\r\n\t\t\tif (strpos ($align, 'r') !== false) {\r\n\t\t\t\t$src_x = $width - $src_w;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\timagecopyresampled ($canvas, $image, $origin_x, $origin_y, $src_x, $src_y, $new_width, $new_height, $src_w, $src_h);\r\n\r\n } else {\r\n\r\n \/\/ copy and resize part of an image with resampling\r\n imagecopyresampled ($canvas, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);\r\n\r\n }\r\n\r\n if ($filters != '' && function_exists ('imagefilter') && defined ('IMG_FILTER_NEGATE')) {\r\n \/\/ apply filters to image\r\n $filterList = explode ('|', $filters);\r\n foreach ($filterList as $fl) {\r\n\r\n $filterSettings = explode (',', $fl);\r\n if (isset ($imageFilters[$filterSettings[0]])) {\r\n\r\n for ($i = 0; $i < 4; $i ++) {\r\n if (!isset ($filterSettings[$i])) {\r\n\t\t\t\t\t\t$filterSettings[$i] = null;\r\n } else {\r\n\t\t\t\t\t\t$filterSettings[$i] = (int) $filterSettings[$i];\r\n\t\t\t\t\t}\r\n }\r\n\r\n switch ($imageFilters[$filterSettings[0]][1]) {\r\n\r\n case 1:\r\n\r\n imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1]);\r\n break;\r\n\r\n case 2:\r\n\r\n imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2]);\r\n break;\r\n\r\n case 3:\r\n\r\n imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2], $filterSettings[3]);\r\n break;\r\n\r\n case 4:\r\n\r\n imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2], $filterSettings[3], $filterSettings[4]);\r\n break;\r\n\r\n default:\r\n\r\n imagefilter ($canvas, $imageFilters[$filterSettings[0]][0]);\r\n break;\r\n\r\n }\r\n }\r\n }\r\n }\r\n\r\n\t\/\/ sharpen image\r\n\tif ($sharpen && function_exists ('imageconvolution')) {\r\n\r\n\t\t$sharpenMatrix = array (\r\n\t\t\tarray (-1,-1,-1),\r\n\t\t\tarray (-1,16,-1),\r\n\t\t\tarray (-1,-1,-1),\r\n\t\t);\r\n\r\n\t\t$divisor = 8;\r\n\t\t$offset = 0;\r\n\r\n\t\timageconvolution ($canvas, $sharpenMatrix, $divisor, $offset);\r\n\r\n\t}\r\n\r\n \/\/ output image to browser based on mime type\r\n show_image ($mime_type, $canvas);\r\n\r\n \/\/ remove image from memory\r\n imagedestroy ($canvas);\r\n\r\n\t\/\/ if not in cache then clear some space and generate a new file\r\n\tclean_cache ();\r\n\r\n\tdie ();\r\n\r\n} else {\r\n\r\n if (strlen ($src)) {\r\n display_error ('image ' . $src . ' not found');\r\n } else {\r\n display_error ('no source specified');\r\n }\r\n\r\n}\r\n\r\n\r\n\/**\r\n *\r\n * @global <type> $quality\r\n * @param <type> $mime_type\r\n * @param <type> $image_resized \r\n *\/\r\nfunction show_image ($mime_type, $image_resized) {\r\n\r\n global $quality;\r\n\r\n $cache_file = get_cache_file ($mime_type);\r\n\r\n\tswitch ($mime_type) {\r\n\t\tcase 'jpg':\r\n\t\t\timagejpeg ($image_resized, $cache_file, $quality);\r\n\t\t\tbreak;\r\n\r\n\t\tdefault:\r\n\t\tcase 'png':\r\n\t\t\timagepng ($image_resized, $cache_file, floor ($quality * 0.09));\r\n\t\t\tbreak;\r\n\r\n\t}\r\n\r\n\tshow_cache_file ($mime_type);\r\n\r\n}\r\n\r\n\r\n\/**\r\n *\r\n * @param <type> $property\r\n * @param <type> $default\r\n * @return <type> \r\n *\/\r\nfunction get_request ($property, $default = 0) {\r\n\r\n if (isset ($_GET[$property])) {\r\n return $_GET[$property];\r\n } else {\r\n return $default;\r\n }\r\n\r\n}\r\n\r\n\r\n\/**\r\n *\r\n * @param <type> $mime_type\r\n * @param <type> $src\r\n * @return <type>\r\n *\/\r\nfunction open_image ($mime_type, $src) {\r\n\r\n\tswitch ($mime_type) {\r\n\t\tcase 'jpg':\r\n\t\t\t$image = imagecreatefromjpeg ($src);\r\n\t\t\tbreak;\r\n\r\n\t\tcase 'png':\r\n\t\t\t$image = imagecreatefrompng ($src);\r\n\t\t\tbreak;\r\n\r\n\t\tcase 'gif':\r\n\t\t\t$image = imagecreatefromgif ($src);\r\n\t\t\tbreak;\r\n\t}\r\n\r\n return $image;\r\n\r\n}\r\n\r\n\/**\r\n * clean out old files from the cache\r\n * you can change the number of files to store and to delete per loop in the defines at the top of the code\r\n *\r\n * @return <type>\r\n *\/\r\nfunction clean_cache () {\r\n\r\n\t\/\/ add an escape\r\n\t\/\/ Reduces the amount of cache clearing to save some processor speed\r\n\tif (rand (1, 50) > 10) {\r\n\t\treturn true;\r\n\t}\r\n\r\n\tflush ();\r\n\r\n $files = glob (DIRECTORY_CACHE . '\/*', GLOB_BRACE);\r\n\r\n\tif (count ($files) > CACHE_SIZE) {\r\n\t\t\r\n $yesterday = time () - (24 * 60 * 60);\r\n\r\n usort ($files, 'filemtime_compare');\r\n $i = 0;\r\n\r\n\t\tforeach ($files as $file) {\r\n\r\n\t\t\t$i ++;\r\n\r\n\t\t\tif ($i >= CACHE_CLEAR) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tif (@filemtime ($file) > $yesterday) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tif (file_exists ($file)) {\r\n\t\t\t\tunlink ($file);\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n }\r\n\r\n}\r\n\r\n\r\n\/**\r\n * compare the file time of two files\r\n *\r\n * @param <type> $a\r\n * @param <type> $b\r\n * @return <type>\r\n *\/\r\nfunction filemtime_compare ($a, $b) {\r\n\r\n\t$break = explode ('\/', $_SERVER['SCRIPT_FILENAME']);\r\n\t$filename = $break[count ($break) - 1];\r\n\t$filepath = str_replace ($filename, '', $_SERVER['SCRIPT_FILENAME']);\r\n\r\n\t$file_a = realpath ($filepath . $a);\r\n\t$file_b = realpath ($filepath . $b);\r\n\r\n return filemtime ($file_a) - filemtime ($file_b);\r\n\r\n}\r\n\r\n\r\n\/**\r\n * determine the file mime type\r\n *\r\n * @param <type> $file\r\n * @return <type>\r\n *\/\r\nfunction mime_type ($file) {\r\n\r\n\t$file_infos = getimagesize ($file);\r\n\t$mime_type = $file_infos['mime'];\r\n\r\n\t\/\/ no mime type\r\n\tif (empty ($mime_type)) {\r\n\t\tdisplay_error ('no mime type specified');\r\n\t}\r\n\r\n \/\/ use mime_type to determine mime type\r\n if (!preg_match ("\/jpg|jpeg|gif|png\/i", $mime_type)) {\r\n\t\tdisplay_error ('Invalid src mime type: ' . $mime_type);\r\n }\r\n\r\n\t$mime_type = strtolower ($mime_type);\r\n\t$mime_type = str_replace ('image\/', '', $mime_type);\r\n\r\n\tif ($mime_type == 'jpeg') {\r\n\t\t$mime_type = 'jpg';\r\n\t}\r\n\r\n return $mime_type;\r\n\r\n}\r\n\r\n\r\n\/**\r\n *\r\n * @param <type> $mime_type\r\n *\/\r\nfunction check_cache ($mime_type) {\r\n\r\n\tif (CACHE_USE) {\r\n\r\n\t\tif (!show_cache_file ($mime_type)) {\r\n\t\t\t\/\/ make sure cache dir exists\r\n\t\t\tif (!file_exists (DIRECTORY_CACHE)) {\r\n\t\t\t\t\/\/ give 777 permissions so that developer can overwrite\r\n\t\t\t\t\/\/ files created by web server user\r\n\t\t\t\tmkdir (DIRECTORY_CACHE);\r\n\t\t\t\tchmod (DIRECTORY_CACHE, 0777);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t}\r\n\r\n}\r\n\r\n\r\n\/**\r\n *\r\n * @param <type> $mime_type\r\n * @return <type> \r\n *\/\r\nfunction show_cache_file ($mime_type) {\r\n\r\n\t\/\/ use browser cache if available to speed up page load\r\n\tif (!empty ($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {\r\n\t\tif (strtotime ($_SERVER['HTTP_IF_MODIFIED_SINCE']) < strtotime ('now')) {\r\n\t\t\theader ('HTTP\/1.1 304 Not Modified');\r\n\t\t\tdie ();\r\n\t\t}\r\n\t}\r\n\r\n\t$cache_file = get_cache_file ($mime_type);\r\n\r\n\tif (file_exists ($cache_file)) {\r\n\r\n\t\t\/\/ change the modified headers\r\n\t\t$gmdate_expires = gmdate ('D, d M Y H:i:s', strtotime ('now +10 days')) . ' GMT';\r\n\t\t$gmdate_modified = gmdate ('D, d M Y H:i:s') . ' GMT';\r\n\r\n\t\t\/\/ send content headers then display image\r\n\t\theader ('Content-Type: ' . $mime_type);\r\n\t\theader ('Accept-Ranges: bytes');\r\n\t\theader ('Last-Modified: ' . $gmdate_modified);\r\n\t\theader ('Content-Length: ' . filesize ($cache_file));\r\n\t\theader ('Cache-Control: max-age=' . CACHE_MAX_AGE . ', must-revalidate');\r\n\t\theader ('Expires: ' . $gmdate_expires);\r\n\r\n\t\tif (!@readfile ($cache_file)) {\r\n\t\t\t$content = file_get_contents ($cache_file);\r\n\t\t\tif ($content != FALSE) {\r\n\t\t\t\techo $content;\r\n\t\t\t} else {\r\n\t\t\t\tdisplay_error ('cache file could not be loaded');\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tdie ();\r\n\r\n }\r\n\r\n\treturn FALSE;\r\n\r\n}\r\n\r\n\r\n\/**\r\n *\r\n * @staticvar string $cache_file\r\n * @param <type> $mime_type\r\n * @return string\r\n *\/\r\nfunction get_cache_file ($mime_type) {\r\n\r\n static $cache_file;\r\n\tglobal $src;\r\n\r\n\t$file_type = '.png';\r\n\r\n\tif ($mime_type == 'jpg') {\r\n\t\t$file_type = '.jpg';\r\n }\r\n\r\n if (!$cache_file) {\r\n\t\t\/\/ filemtime is used to make sure updated files get recached\r\n $cache_file = DIRECTORY_CACHE . '\/' . md5 ($_SERVER ['QUERY_STRING'] . VERSION . filemtime ($src)) . $file_type;\r\n }\r\n\r\n return $cache_file;\r\n\r\n}\r\n\r\n\r\n\/**\r\n *\r\n * @param <type> $url\r\n * @return <type> \r\n *\/\r\nfunction validate_url ($url) {\r\n\t$pattern = "\/\\b(?:(?:https?):\\\/\\\/|www\\.)[-a-z0-9+&@#\\\/%?=~_|!:,.;]*[-a-z0-9+&@#\\\/%=~_|]\/i";\r\n\treturn preg_match ($pattern, $url);\r\n}\r\n\r\n\r\n\/**\r\n *\r\n * @global array $allowedSites\r\n * @param string $src\r\n * @return string\r\n *\/\r\nfunction check_external ($src) {\r\n\r\n\tglobal $allowedSites;\r\n\r\n\t\/\/ work out file details\r\n\t$fileDetails = pathinfo ($src);\r\n\t$filename = 'external_' . md5 ($src);\r\n\t$local_filepath = DIRECTORY_CACHE . '\/' . $filename . '.' . strtolower ($fileDetails['extension']);\r\n\r\n\t\/\/ only do this stuff the file doesn't already exist\r\n\tif (!file_exists ($local_filepath)) {\r\n\r\n\t\tif (strpos (strtolower ($src), 'http:\/\/') !== false || strpos (strtolower ($src), 'https:\/\/') !== false) {\r\n\r\n\t\t\tif (!validate_url ($src)) {\r\n\t\t\t\tdisplay_error ('invalid url');\r\n\t\t\t}\r\n\r\n\t\t\t$url_info = parse_url ($src);\r\n\r\n\t\t\t\/\/ convert youtube video urls\r\n\t\t\t\/\/ need to tidy up the code\r\n\r\n\t\t\tif ($url_info['host'] == 'www.youtube.com' || $url_info['host'] == 'youtube.com') {\r\n\t\t\t\tparse_str ($url_info['query']);\r\n\r\n\t\t\t\tif (isset ($v)) {\r\n\t\t\t\t\t$src = 'http:\/\/img.youtube.com\/vi\/' . $v . '\/0.jpg';\r\n\t\t\t\t\t$url_info['host'] = 'img.youtube.com';\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t\/\/ check allowed sites (if required)\r\n\t\t\tif (ALLOW_EXTERNAL) {\r\n\r\n\t\t\t\t$isAllowedSite = true;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t$isAllowedSite = false;\r\n\t\t\t\tforeach ($allowedSites as $site) {\r\n\t\t\t\t\tif (strpos (strtolower ($url_info['host']), $site) !== false) {\r\n\t\t\t\t\t\t$isAllowedSite = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t\/\/ if allowed\r\n\t\t\tif ($isAllowedSite) {\r\n\r\n\t\t\t\tif (function_exists ('curl_init')) {\r\n\r\n\t\t\t\t\tglobal $fh;\r\n\r\n\t\t\t\t\t$fh = fopen ($local_filepath, 'w');\r\n\t\t\t\t\t$ch = curl_init ($src);\r\n\r\n\t\t\t\t\tcurl_setopt ($ch, CURLOPT_TIMEOUT, CURL_TIMEOUT);\r\n\t\t\t\t\tcurl_setopt ($ch, CURLOPT_USERAGENT, 'Mozilla\/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko\/20041107 Firefox\/1.0');\r\n\t\t\t\t\tcurl_setopt ($ch, CURLOPT_URL, $src);\r\n\t\t\t\t\tcurl_setopt ($ch, CURLOPT_RETURNTRANSFER, TRUE);\r\n\t\t\t\t\tcurl_setopt ($ch, CURLOPT_HEADER, 0);\r\n\t\t\t\t\tcurl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, FALSE);\r\n\t\t\t\t\tcurl_setopt ($ch, CURLOPT_FILE, $fh);\r\n\t\t\t\t\tcurl_setopt ($ch, CURLOPT_WRITEFUNCTION, 'curl_write');\r\n\r\n\t\t\t\t\t\/\/ error so die\r\n\t\t\t\t\tif (curl_exec ($ch) === FALSE) {\r\n\t\t\t\t\t\tunlink ($local_filepath);\r\n\t\t\t\t\t\ttouch ($local_filepath);\r\n\t\t\t\t\t\tdisplay_error ('error reading file ' . $src . ' from remote host: ' . curl_error ($ch));\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tcurl_close ($ch);\r\n\t\t\t\t\tfclose ($fh);\r\n\r\n } else {\r\n\r\n\t\t\t\t\tif (!$img = file_get_contents ($src)) {\r\n\t\t\t\t\t\tdisplay_error ('remote file for ' . $src . ' can not be accessed. It is likely that the file permissions are restricted');\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif (file_put_contents ($local_filepath, $img) == FALSE) {\r\n\t\t\t\t\t\tdisplay_error ('error writing temporary file');\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (!file_exists ($local_filepath)) {\r\n\t\t\t\t\tdisplay_error ('local file for ' . $src . ' can not be created');\r\n\t\t\t\t}\r\n\r\n\t\t\t\t$src = $local_filepath;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tdisplay_error ('remote host "' . $url_info['host'] . '" not allowed');\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n } else {\r\n\r\n\t\t$src = $local_filepath;\r\n\r\n\t}\r\n\r\n return $src;\r\n\r\n}\r\n\r\n\r\n\/**\r\n * callback for curl command to receive external images\r\n * limit the amount of data downloaded from external servers\r\n * \r\n * @global <type> $data_string\r\n * @param <type> $handle\r\n * @param <type> $data\r\n * @return <type>\r\n *\/\r\nfunction curl_write ($handle, $data) {\r\n\r\n\tglobal $external_data_string, $fh;\r\n\r\n\tfwrite ($fh, $data);\r\n\t$external_data_string .= $data;\r\n\r\n\tif (strlen ($external_data_string) > MAX_FILE_SIZE) {\r\n\t\treturn 0;\r\n\t} else {\r\n\t\treturn strlen ($data);\r\n\t}\r\n\r\n}\r\n\r\n\r\n\/**\r\n * tidy up the image source url\r\n *\r\n * @param <type> $src\r\n * @return string\r\n *\/\r\nfunction clean_source ($src) {\r\n\r\n\t$host = str_replace ('www.', '', $_SERVER['HTTP_HOST']);\r\n\t$regex = "\/^(http(s|):\\\/\\\/)(www\\.|)" . $host . "\\\/\/i";\r\n\r\n\t$src = preg_replace ($regex, '', $src);\r\n\t$src = strip_tags ($src);\r\n $src = check_external ($src);\r\n\r\n \/\/ remove slash from start of string\r\n if (strpos ($src, '\/') === 0) {\r\n $src = substr ($src, -(strlen ($src) - 1));\r\n }\r\n\r\n \/\/ don't allow users the ability to use '..\/'\r\n \/\/ in order to gain access to files below document root\r\n $src = preg_replace ("\/\\.\\.+\\\/\/", "", $src);\r\n\r\n \/\/ get path to image on file system\r\n $src = get_document_root ($src) . '\/' . $src;\r\n\r\n\tif (!is_file ($src)) {\r\n\t\tdisplay_error ('source is not a valid file');\r\n\t}\r\n\r\n\tif (filesize ($src) > MAX_FILE_SIZE) {\r\n\t\tdisplay_error ('source file is too big (filesize > MAX_FILE_SIZE)');\r\n\t}\r\n\r\n\tif (filesize ($src) <= 0) {\r\n\t\tdisplay_error ('source file <= 0 bytes. Possible external file download error (file is too large)');\r\n\t}\r\n\t\r\n return realpath ($src);\r\n\r\n}\r\n\r\n\r\n\/**\r\n *\r\n * @param <type> $src\r\n * @return string\r\n *\/\r\nfunction get_document_root ($src) {\r\n\r\n \/\/ check for unix servers\r\n if (file_exists ($_SERVER['DOCUMENT_ROOT'] . '\/' . $src)) {\r\n return $_SERVER['DOCUMENT_ROOT'];\r\n }\r\n\r\n \/\/ check from script filename (to get all directories to timthumb location)\r\n $parts = array_diff (explode ('\/', $_SERVER['SCRIPT_FILENAME']), explode ('\/', $_SERVER['DOCUMENT_ROOT']));\r\n\r\n\t$path = '.\/';\r\n\t\r\n\tforeach ($parts as $part) {\r\n\t\tif (file_exists ($path . '\/' . $src)) {\r\n\t\t\treturn realpath ($path);\r\n\t\t}\r\n\t\t$path .= '..\/';\r\n\t}\r\n\r\n \/\/ special check for microsoft servers\r\n if (!isset ($_SERVER['DOCUMENT_ROOT'])) {\r\n $path = str_replace ("\/", "\\\\", $_SERVER['ORIG_PATH_INFO']);\r\n $path = str_replace ($path, '', $_SERVER['SCRIPT_FILENAME']);\r\n\r\n if (file_exists ($path . '\/' . $src)) {\r\n return realpath ($path);\r\n }\r\n }\r\n\r\n display_error ('file not found');\r\n\r\n}\r\n\r\n\r\n\/**\r\n * generic error message\r\n *\r\n * @param <type> $errorString\r\n *\/\r\nfunction display_error ($errorString = '') {\r\n\r\n header ('HTTP\/1.1 400 Bad Request');\r\n\techo '<pre>' . htmlentities ($errorString);\r\n\techo '<br \/>Query String : ' . htmlentities ($_SERVER['QUERY_STRING']);\r\n\techo '<br \/>TimThumb version : ' . VERSION . '<\/pre>';\r\n die ();\r\n\r\n}\r\n<\/pre>\n
\r\n#!\/bin\/bash\r\nfind \/home\/ -name 'timthumb.php' -type f -printf '%h\\n' | while read line\r\ndo\r\n#Remove the old thumb\r\nrm -rf $line\/timthumb.php\r\n\r\n#Copy fixed thumb\r\ncp timthumb-fix.php $line\/timthumb.php\r\n\r\necho $line " done";\r\ndone\r\n<\/pre>\n
\r\nsh -x fix_timthumb.sh\r\n<\/pre>\n