// Example #2: // Example #3: // // NOTE: $cache_dir must be readable + writable by PHP! //======================================================================================================== error_reporting(E_WARNING); //======================================================================================================== // Set variables, if they are not registered globally; needs PHP 4.1.0 or higher //======================================================================================================== //security patch for LightNEasy: if(isset($_REQUEST['image'])) $image = sanitize($_REQUEST['image']); if(isset($_REQUEST['width'])) { if(!is_intval($_REQUEST['width'])) die ("Aha! Clever!"); else $width = $_REQUEST['width']; } if(isset($_REQUEST['height'])) { if(!is_intval($_REQUEST['height'])) die ("Aha! Clever!"); else $height = $_REQUEST['height']; } $cache_dir = "../data"; // not used by LightNEasy /* if(isset($_REQUEST['cache_dir'])) $cache_dir = $_REQUEST['cache_dir']; if(isset($_REQUEST['database'])) $database = $_REQUEST['database']; if(isset($_REQUEST['table'])) $table = $_REQUEST['table']; if(isset($_REQUEST['field'])) $field = $_REQUEST['field']; if(isset($_REQUEST['key'])) $key = $_REQUEST['key']; if(isset($_REQUEST['id'])) $id = $_REQUEST['id']; */ //======================================================================================================== // Configuration //======================================================================================================== if(!$width) $width = 100; // max. thumbnail width if(!$height) $height = 100; // max. thumbnail height if(!$cache_dir) $cache_dir = "cache"; // path to cache $autodelete = 7; // delete files from cache after .. days (0 = never delete) $IM_path = ""; // path to ImageMagick's convert function, e.g. "/usr/bin" // (leave empty to use the GD library instead) // only needed if used with MySQL: $db_host = "localhost"; // MySQL server $db_user = "root"; // user name $db_pass = ""; // password //======================================================================================================== // Functions //======================================================================================================== // sanitizes a input. It's probably an overkill in this case function sanitize($text) { // Convert problematic ascii characters to their true values $search = array("40","41","58","65","66","67","68","69","70", "71","72","73","74","75","76","77","78","79","80","81", "82","83","84","85","86","87","88","89","90","97","98", "99","100","101","102","103","104","105","106","107", "108","109","110","111","112","113","114","115","116", "117","118","119","120","121","122" ); $replace = array("(",")",":","a","b","c","d","e","f","g","h", "i","j","k","l","m","n","o","p","q","r","s","t","u", "v","w","x","y","z","a","b","c","d","e","f","g","h", "i","j","k","l","m","n","o","p","q","r","s","t","u", "v","w","x","y","z" ); $entities = count($search); for ($i=0;$i < $entities;$i++) $text = preg_replace("#(&\#)(0*".$search[$i]."+);*#si", $replace[$i], $text); // the following is based on code from bitflux (http://blog.bitflux.ch/wiki/) // Kill hexadecimal characters completely $text = preg_replace('#(&\#x)([0-9A-F]+);*#si', "", $text); // remove any attribute starting with "on" or xmlns $text = preg_replace('#(<[^>]+[\\"\'\s])(onmouseover|onmousedown|onmouseup|onmouseout|onmousemove|onclick|ondblclick|onload|xmlns)[^>]*>#iU', ">", $text); do { $oldtext = $text; preg_replace('#]*>#i', "", $text); // remove javascript: and vbscript: protocol } while ($oldtext != $text); $text = preg_replace('#([a-z]*)=([\`\'\"]*)script:#iU', '$1=$2nojscript...', $text); $text = preg_replace('#([a-z]*)=([\`\'\"]*)javascript:#iU', '$1=$2nojavascript...', $text); $text = preg_replace('#([a-z]*)=([\'\"]*)vbscript:#iU', '$1=$2novbscript...', $text); $text = preg_replace('#(<[^>]+)style=([\`\'\"]*).*expression\([^>]*>#iU', "$1>", $text); $text = preg_replace('#(<[^>]+)style=([\`\'\"]*).*behaviour\([^>]*>#iU', "$1>", $text); return $text; } //returns true only if the string is composed only of digits or "+-" function is_intval($value) { return 1 === preg_match('/^[+-]?[0-9]+$/', $value); } //-------------------------------------------------------------------------------------------------------- // Delete files older than .. days from cache //-------------------------------------------------------------------------------------------------------- // Arguments: path to cache, number of days //-------------------------------------------------------------------------------------------------------- function clearCache($cache_dir, $days) { if($dp = @opendir($cache_dir)) { while($file = readdir($dp)) { if(preg_match('/^img_/', $file)) { $mtime = @filemtime("$cache_dir/$file"); if($mtime < time() - 3600 * 24 * $days) @unlink("$cache_dir/$file"); } } closedir($dp); } } //-------------------------------------------------------------------------------------------------------- // If gd_info() doesn't exist it must be simulated //-------------------------------------------------------------------------------------------------------- function gdInfo() { $gd = array('GD Version' => '', 'FreeType Support' => 0, 'FreeType Linkage' => '', 'T1Lib Support' => 0, 'GIF Read Support' => 0, 'GIF Create Support' => 0, 'GIF Support' => 0, 'JPG Support' => 0, 'PNG Support' => 0, 'WBMP Support' => 0, 'XBM Support' => 0); if(function_exists('ob_start')) { ob_start(); phpinfo(); $info = explode("\n", ob_get_contents()); ob_end_clean(); for($i = 0; $i < count($info); $i++) { while(list($str, $v) = each($gd)) { if(strstr($info[$i], $str)) { $val = trim(str_replace($str, '', strip_tags($info[$i]))); $gd[$str] = ($val == 'enabled') ? 1 : $val; } } reset($gd); } if($gd['GIF Support']) $gd['GIF Read Support'] = $gd['GIF Create Support'] = 1; else if($gd['GIF Read Support'] && $gd['GIF Create Support']) $gd['GIF Support'] = 1; } return $gd; } //-------------------------------------------------------------------------------------------------------- // If getImageSize() doesn't return proper values //-------------------------------------------------------------------------------------------------------- // Arguments: image data (binary) // Returns: image type (gif, jpeg, png, swf) //-------------------------------------------------------------------------------------------------------- function getImgType($data) { $header = substr($data, 0, 20); if(strstr($header, 'GIF')) $type = 'gif'; else if(strstr($header, 'JFIF') || strstr($header, 'Exif')) $type = 'jpeg'; else if(strstr($header, 'PNG')) $type = 'png'; else if(strstr($header, 'FWS') || strstr($header, 'CWS')) $type = 'swf'; else $type = ''; return $type; } //-------------------------------------------------------------------------------------------------------- // Calculate thumbnail size //-------------------------------------------------------------------------------------------------------- // Arguments: source width, source height // Globals: max. thumbnail width, max. thumbnail height // Returns: dest. width, dest. height //-------------------------------------------------------------------------------------------------------- function getNewSize($src_w, $src_h) { global $width, $height; $perc_w = $width * 100 / $src_w; $perc_h = $height * 100 / $src_h; $div = ($perc_w < $perc_h) ? 100 / $perc_w : 100 / $perc_h; $dst_w = round($src_w / $div); $dst_h = round($src_h / $div); return array($dst_w, $dst_h); } //-------------------------------------------------------------------------------------------------------- // View image with headers //-------------------------------------------------------------------------------------------------------- // Arguments: filename, image type //-------------------------------------------------------------------------------------------------------- function viewImage($file, $type) { $last_modified = gmdate('D, d M Y H:i:s', filemtime($file)) . ' GMT'; $now = gmdate('D, d M Y H:i:s', time()) . ' GMT'; header("Content-Type: image/$type"); header("Last-Modified: $last_modified"); header('Cache-control: private, no-cache, must-revalidate'); header('Expires: Sat, 01 Jan 2000 00:00:00 GMT'); header("Date: $now"); header('Pragma: no-cache'); readfile($file); exit; } //-------------------------------------------------------------------------------------------------------- // Read thumbnail from cache //-------------------------------------------------------------------------------------------------------- // Arguments: original name, thumbnail name, [ view image (true or false) ] //-------------------------------------------------------------------------------------------------------- function readCachedThumb($original, $thumbname, $view = true) { if(file_exists($original)) { if(file_exists("$thumbname.gif")) $type = 'gif'; else if(file_exists("$thumbname.jpeg")) $type = 'jpeg'; else if(file_exists("$thumbname.png")) $type = 'png'; else $type = ''; if($type) { $thumbnail = "$thumbname.$type"; clearstatcache(); $last_modified = gmdate('D, d M Y H:i:s', filemtime($thumbnail)) . ' GMT'; if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { $if_modified_since = preg_replace('/;.*$/', '', $_SERVER['HTTP_IF_MODIFIED_SINCE']); if($if_modified_since == $last_modified) { if($view) { header('HTTP/1.0 304 Not Modified'); exit; } else return true; } } if($view) viewImage($thumbnail, $type); else return true; } } return false; } //-------------------------------------------------------------------------------------------------------- // Copy palette and set transparency //-------------------------------------------------------------------------------------------------------- // Arguments: destination image, source image, color index //-------------------------------------------------------------------------------------------------------- function setTransparency($dst_img, $src_img, $trans_col) { if(function_exists('ImagePaletteCopy')) ImagePaletteCopy($dst_img, $src_img); if($trans_col == -1) $trans_col = 0; ImageFill($dst_img, 0, 0, $trans_col); ImageColorTransparent($dst_img, $trans_col); } //-------------------------------------------------------------------------------------------------------- // Create thumbnail with ImageMagick //-------------------------------------------------------------------------------------------------------- // Arguments: original name, thumbnail name, type (jpeg/gif/png), [ view image (true or false) ] // Globals: path to ImageMagick's convert function //-------------------------------------------------------------------------------------------------------- function createThumbIM($original, $thumbname, $type, $view = true) { global $IM_path; if($IM_path) { $imgsize = @getImageSize($original); list($dst_w, $dst_h) = getNewSize($imgsize[0], $imgsize[1]); $format = $dst_w . 'x' . $dst_h; $type2 = ($type == 'gif') ? 'png' : $type; $thumbnail = $thumbname . '.' . $type2; @exec("$IM_path/convert -sample $format $type:$original $type2:$thumbnail"); if(file_exists("$thumbnail.0")) { @rename("$thumbnail.0", $thumbnail); for($cnt = 1; file_exists("$thumbnail.$cnt"); $cnt++) @unlink("$thumbnail.$cnt"); } if(file_exists($thumbnail)) { if(filesize($thumbnail) == 0) @unlink($thumbnail); else if($view) viewImage($thumbnail, $type2); else return true; } } return false; } //-------------------------------------------------------------------------------------------------------- // Create thumbnail with GD //-------------------------------------------------------------------------------------------------------- // Arguments: path to original, thumbnail name, type (jpeg/gif/png), [ view image (true or false) ] //-------------------------------------------------------------------------------------------------------- function createThumbGD($original, $thumbname, $type, $view = true) { $error = ''; $gd = function_exists('gd_info') ? gd_info() : gdInfo(); $gd_ver = ereg_replace('[^0-9.]+', '', $gd['GD Version']); switch($type) { case 'gif': if(!$gd['GIF Read Support'] && !$gd['GIF Support']) $error = "GD $gd_ver: No GIF support"; break; case 'png': if(!$gd['PNG Support']) $error = "GD $gd_ver: No PNG support"; break; case 'jpeg': if(!$gd['JPG Support']) $error = "GD $gd_ver: No JPG support"; break; default: $error = 'No ' . strtoupper($type) . ' support'; break; } if(!$error) { if($fp = @fopen($original, 'rb')) { $data = fread($fp, filesize($original)); fclose($fp); if($data) { if(function_exists('ImageCreateFromString')) { $src_img = @ImageCreateFromString($data); } if(!$src_img) { $php_ver = phpversion(); if($type == 'jpeg') { if(function_exists('ImageCreateFromJPEG')) { $src_img = @ImageCreateFromJPEG($original); } if(!$src_img) $error = "PHP $php_ver: No JPG support"; } else if($type == 'gif') { if(function_exists('ImageCreateFromGIF')) { $src_img = @ImageCreateFromGIF($original); } if(!$src_img) $error = "PHP $php_ver: No GIF support"; } else if($type == 'png') { if(function_exists('ImageCreateFromPNG')) { $src_img = @ImageCreateFromPNG($original); } if(!$src_img) $error = "PHP $php_ver: No PNG support"; } else $error = 'Unknown type'; } if(!$error) { $src_w = ImageSX($src_img); $src_h = ImageSY($src_img); list($dst_w, $dst_h) = getNewSize($src_w, $src_h); if($type == 'gif' || $type == 'png') $trans_col = ImageColorTransparent($src_img); else $trans_col = -1; if($type == 'png' && $trans_col == -1) if(ImageColorsTotal($src_img) <= 256) $trans_col = 0; if($gd_ver >= 2.0) { if($trans_col == -1 && function_exists('ImageCreateTrueColor')) $dst_img = ImageCreateTrueColor($dst_w, $dst_h); else { $dst_img = ImageCreate($dst_w, $dst_h); setTransparency($dst_img, $src_img, $trans_col); } if(function_exists('ImageCopyResampled')) ImageCopyResampled($dst_img, $src_img, 0, 0, 0, 0, $dst_w, $dst_h, $src_w, $src_h); else ImageCopyResized($dst_img, $src_img, 0, 0, 0, 0, $dst_w, $dst_h, $src_w, $src_h); } else { $dst_img = ImageCreate($dst_w, $dst_h); if($trans_col != -1) setTransparency($dst_img, $src_img, $trans_col); ImageCopyResized($dst_img, $src_img, 0, 0, 0, 0, $dst_w, $dst_h, $src_w, $src_h); } if($type == 'jpeg') { if(function_exists('ImageJPEG')) @ImageJPEG($dst_img, "$thumbname.$type"); else $error = "PHP $php_ver: No JPG preview"; } else if($type == 'gif') { if(function_exists('ImageGIF')) @ImageGIF($dst_img, "$thumbname.$type"); else if(function_exists('ImagePNG')) @ImagePNG($dst_img, "$thumbname.png"); else $error = "PHP $php_ver: No GIF preview"; } else if($type == 'png') { if(function_exists('ImagePNG')) @ImagePNG($dst_img, "$thumbname.$type"); else $error = "PHP $php_ver: No PNG preview"; } ImageDestroy($src_img); ImageDestroy($dst_img); if($view) readCachedThumb($original, $thumbname); } } else $error = 'No data'; } else $error = 'Could not open'; } return $error; } //-------------------------------------------------------------------------------------------------------- // View message as image with GD //-------------------------------------------------------------------------------------------------------- // Arguments: text, width, height, [ font (1 - 5) ] //-------------------------------------------------------------------------------------------------------- function showMessage($text, $width, $height, $font = 2) { if($img = @ImageCreate($width, $height)) { $red = ImageColorAllocate($img, 255, 0, 0); $white = ImageColorAllocate($img, 255, 255, 255); ImageFill($img, 0, 0, $white); ImageColorTransparent($img, $white); $hcenter = $width / 2; $vcenter = $height / 2; $x = round($hcenter - ImageFontWidth($font) * strlen($text) / 2); $y = round($vcenter - ImageFontHeight($font) / 2); ImageString($img, $font, $x, $y, $text, $red); if(function_exists('ImagePNG')) { header('Content-Type: image/png'); @ImagePNG($img); } else if(function_exists('ImageGIF')) { header('Content-Type: image/gif'); @ImageGIF($img); } else if(function_exists('ImageJPEG')) { header('Content-Type: image/jpeg'); @ImageJPEG($img); } ImageDestroy($img); } } //======================================================================================================== // Main //======================================================================================================== $blankImg = 'R0lGODlhCgAKAIAAAMDAwAAAACH5BAEAAAAALAAAAAAKAAoAAAIIhI+py+0PYysAOw=='; $error = ''; if($autodelete) clearCache($cache_dir, $autodelete); if(($table && $field && $key && $id) || $image) { $data = ''; if(strstr($table, '.')) { $arr = explode('.', $table); $database = $arr[0]; $table = $arr[1]; } if($image) { if($fp = @fopen($image, 'rb')) { while(!feof($fp)) $data .= fread($fp, 4096); fclose($fp); } else $error = 'Could not open'; } else if($database) { if(@mysql_connect($db_host, $db_user, $db_pass)) { $sql = "SELECT $field FROM $database.$table WHERE $key='$id'"; if($result = mysql_query($sql)) { if(mysql_num_rows($result)) $data = mysql_result($result, $field); else $error = 'Not found'; } else $error = 'Bad SQL query'; mysql_close(); } else $error = 'No connection'; } else $error = 'Database?'; if(!$error) { if(!$data) { header("Content-Type: image/gif"); echo base64_decode($blankImg); exit; } else { $original = "$cache_dir/img_" . md5($data); $thumbname = $original . '_' . $width . 'x' . $height; $cached = readCachedThumb($original, $thumbname); if(!$cached) { @unlink("$thumbname.gif"); @unlink("$thumbname.jpeg"); @unlink("$thumbname.png"); if(!file_exists($original)) { if($fp = @fopen($original, 'wb')) { fwrite($fp, $data, strlen($data)); fclose($fp); } else $error = 'Could not save'; } if(!$error) { $imgsize = @getImageSize($original); switch($imgsize[2]) { case 1: $type = 'gif'; break; case 2: $type = 'jpeg'; break; case 3: $type = 'png'; break; case 4: $type = 'swf'; break; default: $type = getImgType($data); } if($type == 'swf') $error = 'No SWF preview'; else if($type) { if($imgsize[0] <= $width && $imgsize[1] <= $height) { viewImage($original, $type); } else { if($imgsize[0] < $width) $width = $imgsize[0]; if($imgsize[1] < $height) $height = $imgsize[1]; if(!createThumbIM($original, $thumbname, $type)) { $error = createThumbGD($original, $thumbname, $type); } } } else $error = 'Unknown type'; } } } } } else $error = 'Arguments?'; if($error) showMessage($error, ($width < 200) ? 200 : $width, $height); ?>