From 423f31ad0add74bbb6066d3c9f760ad0a5580cda Mon Sep 17 00:00:00 2001 From: Jason Woofenden Date: Thu, 28 May 2009 06:25:22 -0400 Subject: [PATCH] revamped uploaded image handling, added thumbnailing support to metaform --- encode.php | 29 +++++++- format.php | 34 ++++++++- metaform.php | 30 +++++--- metaform/template.html | 6 +- metaform/template.php | 12 ++- upload.php | 194 ++++++++++++++++++++++++++++++++++++++---------- 6 files changed, 248 insertions(+), 57 deletions(-) diff --git a/encode.php b/encode.php index 273d026..9aa09a6 100644 --- a/encode.php +++ b/encode.php @@ -342,4 +342,31 @@ function enc_evenodd($values, $name) { } } -?> +function enc_image_src($str) { + list($src, $width, $height, $a, $b, $c) = explode(' ', $str); + return $src; +} + +function enc_image_width($str) { + list($src, $width, $height, $a, $b, $c) = explode(' ', $str); + return $width; +} + +function enc_image_height($str) { + list($src, $width, $height, $a, $b, $c) = explode(' ', $str); + return $height; +} + +function enc_thumb_src($str) { + list($a, $b, $c, $src, $width, $height) = explode(' ', $str); + return $src; +} + +function enc_thumb_width($str) { + list($a, $b, $c, $src, $width, $height) = explode(' ', $str); + return $width; +} +function enc_thumb_height($str) { + list($a, $b, $c, $src, $width, $height) = explode(' ', $str); + return $height; +} diff --git a/format.php b/format.php index f90fc1f..f931cdd 100644 --- a/format.php +++ b/format.php @@ -112,24 +112,50 @@ function format_filename($str, $allow_uppercase = false) { return ereg_replace('^[.-]', '_', $str); } +function format_path($str, $allow_uppercase = false) { + if(!$allow_uppercase) { + $str = strtolower($str); + } + $str = ereg_replace('[^a-zA-Z0-9_./-]', '_', $str); + return ereg_replace('^[.-]', '_', $str); +} + function client_path_to_filename($path) { $filename = ereg_replace(".*[:/\\]", '', $path); return format_filename($filename, true); } -function format_h_w_image($str) { +function format_image_w_h($str) { $fields = explode(' ', $str); if(count($fields) != 3) { return ''; } - list($width, $height, $filename) = $fields; + list($filename, $width, $height) = $fields; + $filename = format_path($filename); + $width = format_int_0($width); + $height = format_int_0($height); + + return "$filename $width $height"; +} + +function format_image_w_h_thumb_w_h($str) { + $fields = explode(' ', $str); + if(count($fields) != 6) { + die('count: ' . count($fields)); + return ''; + } + + list($filename, $width, $height, $thumb_filename, $thumb_width, $thumb_height) = $fields; + $filename = format_path($filename); $width = format_int_0($width); $height = format_int_0($height); - $filename = format_filename($filename); + $thumb_filename = format_path($thumb_filename); + $thumb_width = format_int_0($thumb_width); + $thumb_height = format_int_0($thumb_height); - return "$width $height $filename"; + return "$filename $width $height $thumb_filename $thumb_width $thumb_height"; } function format_varname($str) { diff --git a/metaform.php b/metaform.php index b2d3c21..04e786a 100644 --- a/metaform.php +++ b/metaform.php @@ -51,7 +51,8 @@ $GLOBALS['types'] = array( 'rightyesno' => array('checkbox', 'yesno', 'varchar(3)'), 'yesno' => array('leftcheck', 'yesno', 'varchar(3)'), 'delete' => array('checkbox', 'yesno', 'n/a'), - 'image' => array('image', 'oneline', 'varchar(200)'), + 'image' => array('image', 'oneline', 'varchar(120)'), + 'thumb' => array('image', 'oneline', 'varchar(240)'), 'submit' => array('submit', 'oneline', 'n/a') ); @@ -244,6 +245,9 @@ function make_html($whole_file = true) { if($GLOBALS['opt_display'] == 'Yes') { switch($input) { + case 'image': + $tem->show('display_image'); + break; case 'checkbox': case 'leftcheck': $tem->show('display_yesno'); @@ -270,10 +274,15 @@ function make_html($whole_file = true) { if(show_in_listing($type, $input, $format, $sql)) { if($format == 'bool' || $format == 'yesno') { $tem->set('listing_enc', 'yesno'); + $tem->show('listing_value_enc'); } elseif($input == 'date') { $tem->set('listing_enc', 'mmddyyyy'); + $tem->show('listing_value_enc'); + } elseif($type == 'thumb') { + $tem->show('listing_value_thumb'); } else { $tem->set('listing_enc', 'html'); + $tem->show('listing_value_enc'); } $tem->show('listing_head_col'); $tem->show('listing_row_col'); @@ -333,11 +342,13 @@ function show_in_listing($type, $input, $format, $sql) { case 'textarea': case 'html': return false; - default: - return true; } -} + if($type == 'image') { + return false; + } + return true; +} function make_php() { $tem = new tem(); @@ -364,8 +375,13 @@ function make_php() { $php_fields .= '$' . $name; } if($input == 'image') { + if($type == 'thumb') { + $tem->show('thumb_settings'); + $tem->show('thumb_upload_params'); + $tem->show('thumb_w_h'); + } + $tem->show('image_settings'); $tem->show('image_upload'); - $tem->show('image_db'); if(!$image_included_yet) { $tem->show('image_include'); $tem->show('upload_max'); @@ -438,7 +454,6 @@ function view_php() { echo make_php(); } - function make_email() { $tem = new tem(); $tem->load('code/wfpl/metaform/template.email.txt'); @@ -474,7 +489,6 @@ function view_email() { echo make_email(); } - function preview() { tem_load('code/wfpl/metaform/preview.html'); tem_set('file_name', $GLOBALS['file_name']); @@ -523,5 +537,3 @@ function download_tar() { metaform(); exit(); - -?> diff --git a/metaform/template.html b/metaform/template.html index 68dac08..0c5c774 100644 --- a/metaform/template.html +++ b/metaform/template.html @@ -49,7 +49,9 @@

~singular.cap~ details

- + + + @@ -87,7 +89,7 @@
~caption.html~:
~caption.html~:~~~name~.yesno~~
~caption.html~:~~~name~.mmddyyyy~~
- + diff --git a/metaform/template.php b/metaform/template.php index bdd7da1..1822ff3 100644 --- a/metaform/template.php +++ b/metaform/template.php @@ -25,7 +25,13 @@ define('~file_name.upper~_DB_FIELDS', '~db_fields~'); # Set this to the path to your uploads directory. It can be relative to the # location of this script. IT MUST END WITH A SLASH $GLOBALS['upload_directory'] = 'uploads/'; - + +$GLOBALS['~name~_max_width'] = '400'; +$GLOBALS['~name~_max_height'] = '400'; +$GLOBALS['~name~_thumb_max_width'] = '70'; +$GLOBALS['~name~_thumb_max_height'] = '70'; +$GLOBALS['~name~_file_name'] = uniqid() . getmypid() . '.jpg'; # comment this out to use uploader's filename + # Define the username and password required to view this form: define('AUTH_REALM', '~file_name~ administration area'); define('AUTH_USER', 'fixme'); @@ -42,12 +48,12 @@ require_once('code/wfpl/upload.php'); function ~file_name~_get_fields() { $~name~ = format_~format~($_REQUEST['~name~'], '~name~'); if($_FILES['~name~'] && $_FILES['~name~']['error'] == 0) { - $~name~ = substr(save_uploaded_image('~name~', $GLOBALS['upload_directory']), strlen($GLOBALS['upload_directory'])); + $~name~ = convert_uploaded_image('~name~', $GLOBALS['upload_directory'] . $GLOBALS['~name~_file_name'], $GLOBALS['~name~_max_width'], $GLOBALS['~name~_max_height'], $GLOBALS['~name~_thumb_max_width'], $GLOBALS['~name~_thumb_max_height']); } else { if($_REQUEST['delete_~name~'] == 'Yes') { $~name~ = ''; } else { - $~name~ = format_filename($_REQUEST['old_~name~']); + $~name~ = format_image_w_h_thumb_w_h($_REQUEST['old_~name~']); } } diff --git a/upload.php b/upload.php index 1bca71a..f52f0cf 100644 --- a/upload.php +++ b/upload.php @@ -116,12 +116,18 @@ function generate_filename($path, $mime = 'text/plain') { # remove dots from the beginning (no invisible files) $filename = ereg_replace('^\.*', '', $filename); + if(strlen($filename > 80)) { + $filename = substr($filename, -80); + } + # fix extension $last_dot = strrpos($filename, '.'); if($last_dot === false) { #no extension if(isset($GLOBALS['mime_to_ext'][$mime])) { $filename .= '.' . $GLOBALS['mime_to_ext'][$mime]; + } else { + $filename .= '.bin'; } } else { $basename = substr($filename, 0, $last_dot); @@ -138,15 +144,27 @@ function generate_filename($path, $mime = 'text/plain') { # Move uploaded file, and return the new filename. # -# Pass in the index into the $_FILES array (the name of the html input tag) and -# the path to the folder you'd like it saved to. If path ends with a slash this -# function will generate a filename based on the client's name, otherwise it'll -# name the file that. +# $key: Pass in the index into the $_FILES array (the name of the html input tag) and +# the path to the folder you'd like it saved to. # -# example: save_uploaded_file('pdf', 'uploaded_pdfs/'); -# example: save_uploaded_file('resume', "/www/example.com/remumes/$user_id.txt"); +# $path: If path ends with a slash this function will generate a filename based +# on the client's name. If it ends with a period, the dot will be removed and +# the client's name appended. Otherwise $path will be used as the filename +# exactly as is, even if extensions differ between the client's name and $path. +# +# where user uploads "c:\foo\Bar baz.PDF" at +# save_uploaded_file('in', 'uploaded_pdfs/'); yeilds: +# "uploaded_pdfs/bar_baz.pdf" +# save_uploaded_file('in', 'uploaded_pdfs/prefix.'); yeilds: +# "uploaded_pdfs/prefixbar_baz.pdf" +# save_uploaded_file('in', 'uploaded_pdfs/qux.pdf'); yeilds: +# "uploaded_pdfs/qux.pdf" function save_uploaded_file($key, $path) { - if(substr($path, -1) == '/') { + $end = substr($path, -1); + if($end == '.' || $end == '/') { + if($end == '.') { + $path = substr($path, 0, -1); + } $filename = $path . generate_filename($_FILES[$key]['name'], $_FILES[$key]['type']); } else { $filename = $path; @@ -206,14 +224,8 @@ function gif_to_png($filename, $new_filename = 'just change extension') { $new_filename .= '.png'; } - $convert = path_to('convert'); - - $command = "$convert " . escapeshellarg($filename) . ' ' . escapeshellarg($new_filename); + imagemagick_convert($filename, $new_filename, "$convert -colorspace RGB", 'GIF to PNG conversion'); - exec($command, $dummy, $ret); - if($ret != 0) { - die("image conversion failed. convert did exit($ret)"); - } unlink($filename); return $new_filename; } @@ -235,26 +247,56 @@ function make_thumbnail($filename, $max_width = '70', $max_height = '70') { $thumb .= '_thumb'; $thumb .= substr($filename, $last_dot); - $convert = path_to('convert'); + $max_width = format_int_70($max_width); + $height_width = format_int_70($height_width); - # can't be too careful - $max_width = ereg_replace('[^0-9]', '', $max_width); - if($max_width == '') { - $max_width = '70'; - } - $max_height = ereg_replace('[^0-9]', '', $max_height); - if($max_height == '') { - $max_height = '70'; - } + imagemagick_convert($filename, $thumb, "-geometry ${max_width}x$max_height", 'Thumbnail creation'); - $command = "$convert -geometry ${max_width}x$max_height " . escapeshellarg($filename) . ' ' . escapeshellarg($thumb); + return $thumb; +} +function exec_or_die($command, $doing_what) { exec($command, $dummy, $ret); if($ret != 0) { - die("Thumbnail creation failed. Convert called exit($ret)"); + $base = basename(ereg_replace(' .*', '', $command)); + die("$doing_what failed. $base called exit($ret)"); } +} - return $thumb; +# exec convert from imagemagick. +function imagemagick_convert($in_filename, $out_filename, $args, $doing_what = "Image conversion") { + $in = escapeshellarg($in_filename); + $out = escapeshellarg($out_filename); + $command = path_to('convert') . " $in $args $out"; + + exec_or_die($command, $doing_what); +} + +# exec mogrify from imagemagick. +function imagemagick_mogrify($in_filename, $args, $doing_what = "Image conversion") { + $command = path_to('mogrify') . " $args " . escapeshellarg($in_filename); + + exec_or_die($command, $doing_what); +} + +function format_int_70($str) { + $str = ereg_replace('[^0-9]', '', $str); + if($str == '') { + $str = '70'; + } + return $str; +} + + +# Resize image. +# +# The image will retain aspect ratio, and be either $max_width wide or +# $max_height tall (or, if the aspect is just right, both) +function resize_image($filename, $max_width = '70', $max_height = '70') { + $max_width = format_int_70($max_width); + $height_width = format_int_70($height_width); + + imagimagick_mogrify($filename, "-geometry ${max_width}x$max_height"); } # Argument: path to image file @@ -273,19 +315,95 @@ function image_dimensions($image) { } } -# like save_uploaded_file() (above) except it converts gifs to pngs. +# return an array of the width and height of the image passed. +# calls die() if this can't be done for any reason. +function image_w_h_or_die($filename) { + $wxh = image_dimensions($filename); + if($wxh == false) { + die("couldn't git image dimensions of $filename"); + } + $wh = explode('x', $wxh); + if(count($wh) != 2) { + die("image $filename seems to have " . count($wh) . ' dimensions'); + } + return $wh; +} + + +# Like save_uploaded_file() (above) except that it converts all images to PNG +# or JPEG, converts to RGB colorspace, and optionally scales and/or creates a +# thumbnail. And, if $path ends with a period, the correct extension will be +# appended. # -# FIXME: if a filename is passed in the end of path, we should check if the file type matches, and if not run convert. -function save_uploaded_image($key, $path) { - if(substr($path, -1) == '/') { - $filename = save_uploaded_file($key, $path); - if(substr($filename, -4) == '.gif') { - $filename = gif_to_png($filename); - } - return $filename; +# You are encouraged to use convert_uploaded_image() instead of this function, +# because it has a more useful return value. +# +# If the image_width and image_height parameters are above zero, then the image +# will be scaled (see below). +# +# If the thumb_width and thumb_height parameters are above zero, then a 2nd +# image will be created and scaled (see below) with the same name, except +# having "_thumb" added before the extension. +# +# Scaling: images are scaled (maintaining the aspect ratio) so they are as big +# as possible without either dimension being larger than what you specify. +# +# This function just returns the name of the main image. To get the dimensions +# and names, call convert_uploaded_image(). +function save_uploaded_image($key, $path, $image_width = 0, $image_height = 0, $thumbnail_width = 0, $thumbnail_height = 0) { + $image_w_h_thumb_w_h = convert_uploaded_image($key, $path, $image_width, $image_height, $thumbnail_width, $thumbnail_height); + return ereg_replace(' .*', '', $image_w_h_thumb_w_h); +} + +function ext_to_web_image_ext($in) { + if($in == 'png' || $in == 'gif') { + return 'png'; } else { - return save_uploaded_file($key, $path); + return 'jpg'; } } -?> +# this function is just like save_uploaded_image() above except that the return +# value is a string like "filename width height" or (if you specified both +# thumbnail dimensions) "image_filename image_width image_height thumb_filename +# thumb_width thumb_height" +# +# +# examples: +# convert_uploaded_image('image', 'uploads/', 500, 500); +# might return: "uploads/foo.jpg 500 400" +# convert_uploaded_image('image', 'uploads/', 500, 500, 70, 70); +# might return: "uploads/foo.jpg 500 400 uploads/foo_thumb.jpg 70 56" +function convert_uploaded_image($key, $path, $image_width = 0, $image_height = 0, $thumb_width = 0, $thumb_height = 0) { + $ret = ''; + $tmp_filename = save_uploaded_file($key, $path . '__.'); + $ext_rpos = strrpos($tmp_filename, '.'); + if($ext_rpos === false) { + die('save_uploaded_file() gave us a filename with no extension.'); + } + $tmp_base = substr($tmp_filename, 0, $ext_rpos); + $tmp_ext = substr($tmp_filename, $ext_rpos + 1); + if(substr($path, -1) == '/') { + $filename = $path . substr($tmp_base, strlen($path) + 2); + $filename .= '.' . ext_to_web_image_ext($tmp_ext); + } elseif(substr($path, -1) == '.') { + $filename = $path . ext_to_web_image_ext($tmp_ext); + } else { + $filename = $path; + } + + $convert_params = '-colorspace RGB'; + if($image_width > 0 && $image_height > 0) { + $convert_params .= " -geometry ${image_width}x$image_height"; + } + imagemagick_convert($tmp_filename, $filename, $convert_params); + unlink($tmp_filename); + list($w, $h) = image_w_h_or_die($filename); + $ret = "$filename $w $h"; + if($thumb_width > 0 && $thumb_height > 0) { + $thumb_name = make_thumbnail($filename, $thumb_width, $thumb_height); + list($w, $h) = image_w_h_or_die($thumb_name); + $ret .= " $thumb_name $w $h"; + } + return $ret; +} -- 1.7.10.4
~caption~ 
~~~name~.~listing_enc~~~~~~name~.~listing_enc~~~ [delete this ~singular~]