# HG changeset patch # User Dan # Date 1194113714 14400 # Node ID 3daa715e0f699012372dd6cc04189edfde89620c # Parent 6a4573507ff875f148c75da4fd9aadef8fd54108 Alternate scaling using GD is implemented now; images will be scaled with ImageMagick if enabled and working; else, GD will be used. No UI changes to speak of, but a check in the installer will be added in a later commit diff -r 6a4573507ff8 -r 3daa715e0f69 includes/functions.php --- a/includes/functions.php Fri Nov 02 15:38:20 2007 -0400 +++ b/includes/functions.php Sat Nov 03 14:15:14 2007 -0400 @@ -3182,6 +3182,169 @@ $cron_tasks[$hour_interval][] = $func; } +/** + * Scales an image to the specified width and height, and writes the output to the specified + * file. Will use ImageMagick if present, but if not will attempt to scale with GD. This will + * always scale images proportionally. + * @param string Path to image file + * @param string Path to output file + * @param int Image width, in pixels + * @param int Image height, in pixels + * @param bool If true, the output file will be deleted if it exists before it is written + * @return bool True on success, false on failure + */ + +function scale_image($in_file, $out_file, $width = 225, $height = 225, $unlink = false) +{ + global $db, $session, $paths, $template, $plugins; // Common objects + + if ( !is_int($width) || !is_int($height) ) + return false; + + if ( !file_exists($in_file) ) + return false; + + if ( preg_match('/["\'\/\\]/', $in_file) || preg_match('/["\'\/\\]/', $out_file) ) + die('SECURITY: scale_image(): infile or outfile path is screwy'); + + if ( file_exists($out_file) && !$unlink ) + return false; + else if ( file_exists($out_file) && $unlink ) + @unlink($out_file); + if ( file_exists($out_file) ) + // couldn't unlink (delete) the output file + return false; + + $file_ext = substr($in_file, ( strrpos($in_file, '.') + 1)); + switch($file_ext) + { + case 'png': + $func = 'imagecreatefrompng'; + break; + case 'jpg': + case 'jpeg': + $func = 'imagecreatefromjpeg'; + break; + case 'gif': + $func = 'imagecreatefromgif'; + break; + case 'xpm': + $func = 'imagecreatefromxpm'; + break; + default: + return false; + } + + $magick_path = getConfig('imagemagick_path'); + $can_use_magick = ( + getConfig('enable_imagemagick') == '1' && + file_exists($magick_path) && + is_executable($magick_path) + ); + $can_use_gd = ( + function_exists('getimagesize') && + function_exists('imagecreatetruecolor') && + function_exists('imagecopyresampled') && + function_exists($func) + ); + if ( $can_use_magick ) + { + if ( !preg_match('/^([\/A-z0-9_-]+)$/', $magick_path) ) + { + die('SECURITY: ImageMagick path is screwy'); + } + $cmdline = "$magick_path \"$in_file\" -resize \"{$width}x{$height}>\" \"$out_file\""; + system($cmdline, $return); + if ( !file_exists($out_file) ) + return false; + return true; + } + else if ( $can_use_gd ) + { + @list($width_orig, $height_orig) = @getimagesize($in_file); + if ( !$width_orig || !$height_orig ) + return false; + // calculate new width and height + + $ratio = $width_orig / $height_orig; + if ( $ratio > 1 ) + { + // orig. width is greater that height + $new_width = $width; + $new_height = round( $width / $ratio ); + } + else if ( $ratio < 1 ) + { + // orig. height is greater than width + $new_width = round( $height / $ratio ); + $new_height = $height; + } + else if ( $ratio == 1 ) + { + $new_width = $width; + $new_height = $width; + } + if ( $new_width > $width_orig || $new_height > $height_orig ) + { + // Too big for our britches here; set it to only convert the file + $new_width = $width_orig; + $new_height = $height_orig; + } + + $newimage = @imagecreatetruecolor($new_width, $new_height); + if ( !$newimage ) + return false; + $oldimage = @$func($in_file); + if ( !$oldimage ) + return false; + + // Perform scaling + imagecopyresampled($newimage, $oldimage, 0, 0, 0, 0, $new_width, $new_height, $width_orig, $height_orig); + + // Get output format + $out_ext = substr($out_file, ( strrpos($out_file, '.') + 1)); + switch($out_ext) + { + case 'png': + $outfunc = 'imagepng'; + break; + case 'jpg': + case 'jpeg': + $outfunc = 'imagejpeg'; + break; + case 'gif': + $outfunc = 'imagegif'; + break; + case 'xpm': + $outfunc = 'imagexpm'; + break; + default: + imagedestroy($newimage); + imagedestroy($oldimage); + return false; + } + + // Write output + $outfunc($newimage, $out_file); + + // clean up + imagedestroy($newimage); + imagedestroy($oldimage); + + // done! + return true; + } + // Neither scaling method worked; we'll let plugins try to scale it, and then if the file still doesn't exist, die + $code = $plugins->setHook('scale_image_failure'); + foreach ( $code as $cmd ) + { + eval($cmd); + } + if ( file_exists($out_file) ) + return true; + return false; +} + //die('
Original:  01010101010100101010100101010101011010'."\nProcessed: ".uncompress_bitfield(compress_bitfield('01010101010100101010100101010101011010')).'
'); ?> diff -r 6a4573507ff8 -r 3daa715e0f69 includes/template.php --- a/includes/template.php Fri Nov 02 15:38:20 2007 -0400 +++ b/includes/template.php Sat Nov 03 14:15:14 2007 -0400 @@ -1413,7 +1413,9 @@ // $message = preg_replace('#\[(http|ftp|irc):\/\/([a-z0-9\/:_\.\?&%\#@_\\\\-]+?) ([^\]]+)\\]#', '\\3
', $message); // $message = preg_replace('#\[(http|ftp|irc):\/\/([a-z0-9\/:_\.\?&%\#@_\\\\-]+?)\\]#', '\\1://\\2
', $message); - preg_match_all('/\[((https?|ftp|irc):\/\/([^@\]"\':]+)?((([a-z0-9-]+\.)*)[a-z0-9-]+)(\/[A-z0-9_%\|~`!\!@#\$\^&\*\(\):;\.,\/-]*(\?(([a-z0-9_-]+)(=[A-z0-9_%\|~`\!@#\$\^&\*\(\):;\.,\/-\[\]]+)?((&([a-z0-9_-]+)(=[A-z0-9_%\|~`!\!@#\$\^&\*\(\):;\.,\/-]+)?)*))?)?)?) ([^\]]+)\]/is', $message, $ext_link); + preg_match_all('/\[((https?|ftp|irc):\/\/([^@\s\]"\':]+)?((([a-z0-9-]+\.)*)[a-z0-9-]+)(\/[A-z0-9_%\|~`!\!@#\$\^&\*\(\):;\.,\/-]*(\?(([a-z0-9_-]+)(=[A-z0-9_%\|~`\!@#\$\^&\*\(\):;\.,\/-\[\]]+)?((&([a-z0-9_-]+)(=[A-z0-9_%\|~`!\!@#\$\^&\*\(\):;\.,\/-]+)?)*))?)?)?) ([^\]]+)\]/is', $message, $ext_link); + + // die('
' . htmlspecialchars( print_r($ext_link, true) ) . '
'); for ( $i = 0; $i < count($ext_link[0]); $i++ ) { @@ -1425,7 +1427,7 @@ $message = str_replace($ext_link[0][$i], $text_parser->run(), $message); } - preg_match_all('/\[((https?|ftp|irc):\/\/([^@\]"\':]+)?((([a-z0-9-]+\.)*)[a-z0-9-]+)(\/[A-z0-9_%\|~`!\!@#\$\^&\*\(\):;\.,\/-]*(\?(([a-z0-9_-]+)(=[A-z0-9_%\|~`\!@#\$\^&\*\(\):;\.,\/-\[\]]+)?((&([a-z0-9_-]+)(=[A-z0-9_%\|~`!\!@#\$\^&\*\(\):;\.,\/-]+)?)*))?)?)?)\]/is', $message, $ext_link); + preg_match_all('/\[((https?|ftp|irc):\/\/([^@\s\]"\':]+)?((([a-z0-9-]+\.)*)[a-z0-9-]+)(\/[A-z0-9_%\|~`!\!@#\$\^&\*\(\):;\.,\/-]*(\?(([a-z0-9_-]+)(=[A-z0-9_%\|~`\!@#\$\^&\*\(\):;\.,\/-\[\]]+)?((&([a-z0-9_-]+)(=[A-z0-9_%\|~`!\!@#\$\^&\*\(\):;\.,\/-]+)?)*))?)?)?)\]/is', $message, $ext_link); for ( $i = 0; $i < count($ext_link[0]); $i++ ) { diff -r 6a4573507ff8 -r 3daa715e0f69 install.php --- a/install.php Fri Nov 02 15:38:20 2007 -0400 +++ b/install.php Sat Nov 03 14:15:14 2007 -0400 @@ -665,7 +665,7 @@ break; case "website": if(!isset($_POST['_cont'])) { - echo 'No POST data signature found. Please restart the installation.'; + echo 'No POST data signature found. Please restart the installation.'; $template->footer(); exit; } @@ -736,7 +736,7 @@ break; case "login": if(!isset($_POST['_cont'])) { - echo 'No POST data signature found. Please restart the installation.'; + echo 'No POST data signature found. Please restart the installation.'; $template->footer(); exit; } @@ -766,7 +766,9 @@ { var frm = document.forms.login; ret = true; - if ( frm.admin_user.value.match(/^([A-z0-9 \-\.]+)$/g) && !frm.admin_user.value.match(/^(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/) && frm.admin_user.value.toLowerCase() != 'anonymous' ) + var ip_regexp = new RegExp('^(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$', ''); + var valid_username = new RegExp('^([A-z0-9 \-\.]+)$', ''); + if ( frm.admin_user.value.match(valid_username) && !frm.admin_user.value.match(ip_regexp) && frm.admin_user.value.toLowerCase() != 'anonymous' ) { document.getElementById('s_user').src = 'images/good.gif'; } @@ -784,7 +786,8 @@ document.getElementById('s_password').src = 'images/bad.gif'; ret = false; } - if(frm.admin_email.value.match(/^(?:[\w\d]+\.?)+@(?:(?:[\w\d]\-?)+\.)+\w{2,4}$/)) + var valid_email = new RegExp('^(?:[\w\d]+\.?)+@(?:(?:[\w\d]\-?)+\.)+\w{2,4}$', ''); + if(frm.admin_email.value.match(valid_email)) { document.getElementById('s_email').src = 'images/good.gif'; } @@ -920,7 +923,7 @@ break; case "confirm": if(!isset($_POST['_cont'])) { - echo 'No POST data signature found. Please restart the installation.'; + echo 'No POST data signature found. Please restart the installation.'; $template->footer(); exit; } @@ -970,7 +973,7 @@ !isset($_POST['urlscheme']) ) { - echo 'The installer has detected that one or more required form values is not set. Please restart the installation.'; + echo 'The installer has detected that one or more required form values is not set. Please restart the installation.'; $template->footer(); exit; } @@ -989,6 +992,9 @@ } function err($t) { global $template; echo $t; $template->footer(); exit; } + if ( !preg_match('/^[a-z0-9_]*$/', $_POST['table_prefix']) ) + err('Hacking attempt was detected in table_prefix.'); + echo 'Connecting to MySQL...'; if($_POST['db_root_user'] != '') { @@ -1138,12 +1144,13 @@ $dbname = \''.addslashes($_POST['db_name']).'\'; $dbuser = \''.addslashes($_POST['db_user']).'\'; $dbpasswd = \''.addslashes($_POST['db_pass']).'\'; -if(!defined(\'ENANO_CONSTANTS\')) { -define(\'ENANO_CONSTANTS\', \'\'); -define(\'table_prefix\', \''.$_POST['table_prefix'].'\'); -define(\'scriptPath\', \''.scriptPath.'\'); -define(\'contentPath\', \''.$cp.'\'); -define(\'ENANO_INSTALLED\', \'true\'); +if ( !defined(\'ENANO_CONSTANTS\') ) +{ + define(\'ENANO_CONSTANTS\', \'\'); + define(\'table_prefix\', \''.addslashes($_POST['table_prefix']).'\'); + define(\'scriptPath\', \''.scriptPath.'\'); + define(\'contentPath\', \''.$cp.'\'); + define(\'ENANO_INSTALLED\', \'true\'); } $crypto_key = \''.$privkey.'\'; ?>'; diff -r 6a4573507ff8 -r 3daa715e0f69 plugins/SpecialUpdownload.php --- a/plugins/SpecialUpdownload.php Fri Nov 02 15:38:20 2007 -0400 +++ b/plugins/SpecialUpdownload.php Sat Nov 03 14:15:14 2007 -0400 @@ -235,45 +235,73 @@ } $fname = ENANO_ROOT . '/files/' . $row['file_key'] . '_' . $row['time_id'] . $row['file_extension']; - $data = file_get_contents($fname); - if(isset($_GET['preview']) && getConfig('enable_imagemagick')=='1' && file_exists(getConfig('imagemagick_path')) && substr($row['mimetype'], 0, 6) == 'image/') + + if ( isset($_GET['preview']) && substr($row['mimetype'], 0, 6) == 'image/' ) { - $nam = tempnam('/tmp', $filename); - $h = @fopen($nam, 'w'); - if(!$h) die('Error opening '.$nam.' for writing'); - fwrite($h, $data); - fclose($h); - /* Make sure the request doesn't contain commandline injection - yow! */ - if(!isset($_GET['width' ]) || (isset($_GET['width'] ) && !preg_match('#^([0-9]+)$#', $_GET['width'] ))) $width = '320'; else $width = $_GET['width' ]; - if(!isset($_GET['height']) || (isset($_GET['height']) && !preg_match('#^([0-9]+)$#', $_GET['height'] ))) $height = '240'; else $height = $_GET['height']; - $cache_filename=ENANO_ROOT.'/cache/'.$filename.'-'.$row['time_id'].'-'.$width.'x'.$height.$row['file_extension']; - if(getConfig('cache_thumbs')=='1' && file_exists($cache_filename) && is_writable(ENANO_ROOT.'/cache')) { - $data = file_get_contents($cache_filename); - } elseif(getConfig('enable_imagemagick')=='1' && file_exists(getConfig('imagemagick_path'))) { - // Use ImageMagick to convert the image - //unlink($nam); - error_reporting(E_ALL); - $cmd = ''.getConfig('imagemagick_path').' "'.$nam.'" -resize "'.$width.'x'.$height.'>" "'.$nam.'.scaled'.$row['file_extension'].'"'; - system($cmd, $stat); - if(!file_exists($nam.'.scaled'.$row['file_extension'])) die('Failed to call ImageMagick (return value '.$stat.'), command line was:
'.$cmd); - $data = file_get_contents($nam.'.scaled'.$row['file_extension']); - // Be stingy about it - better to re-generate the image hundreds of times than to fail completely - if(getConfig('cache_thumbs')=='1' && !file_exists($cache_filename)) { - // Write the generated thumbnail to the cache directory - $h = @fopen($cache_filename, 'w'); - if(!$h) die('Error opening cache file "'.$cache_filename.'" for writing.'); - fwrite($h, $data); - fclose($h); + // Determine appropriate width and height + $width = ( isset($_GET['width']) ) ? intval($_GET['width'] ) : 320; + $height = ( isset($_GET['height']) ) ? intval($_GET['height']) : 320; + $cache_filename = ENANO_ROOT . "/cache/{$filename}-{$row['time_id']}-{$width}x{$height}{$row['file_extension']}"; + if ( file_exists($cache_filename) ) + { + $fname = $cache_filename; + } + else + { + $allow_scale = false; + $orig_fname = $fname; + // is caching enabled? + if ( getConfig('cache_thumbs') == '1' ) + { + $fname = $cache_filename; + if ( is_writeable(dirname($fname)) ) + { + $allow_scale = true; + } + } + else + { + // Get a temporary file + // In this case, the file will not be cached and will be scaled each time it's requested + $temp_dir = ( is_dir('/tmp') ) ? '/tmp' : ( isset($_ENV['TEMP']) ) ? $_ENV['TEMP'] : 'SOME RANDOM NAME'; + // if tempnam() cannot use the specified directory name, it will fall back on the system default + $tempname = tempnam($temp_dir, $filename); + if ( $tempname && is_writeable($tempname) ) + { + $allow_scale = true; + } + } + if ( $allow_scale ) + { + $result = scale_image($orig_fname, $fname, $width, $height); + if ( !$result ) + $fname = $orig_fname; + } + else + { + $fname = $orig_fname; } } - unlink($nam); } - $len = strlen($data); + $handle = @fopen($fname, 'r'); + if ( !$handle ) + die('Can\'t open output file for reading'); + + $len = filesize($fname); header('Content-type: '.$row['mimetype']); - if(isset($_GET['download'])) header('Content-disposition: attachment, filename="'.$filename.'";'); + if ( isset($_GET['download']) ) + { + header('Content-disposition: attachment, filename="' . $filename . '";'); + } header('Content-length: '.$len); header('Last-Modified: '.date('r', $row['time_id'])); - echo($data); + + // using this method limits RAM consumption + while ( !feof($handle) ) + { + echo fread($handle, 512000); + } + fclose($handle); gzip_output();