X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=upload.php;h=b1b33230e92a780de0d56b41e6d833f572b8d5cf;hb=1445d4dad7bde149b738f36564bceb65c8eae1a2;hp=46f8b3cbd53e7386917bb6c7d697b4b750b1eeff;hpb=dabdfec87e89ad579cf543608ad118f30981a1c5;p=wfpl.git
diff --git a/upload.php b/upload.php
index 46f8b3c..b1b3323 100644
--- a/upload.php
+++ b/upload.php
@@ -2,21 +2,18 @@
# Copyright (C) 2007 Jason Woofenden
#
-# This file is part of wfpl.
-#
-# wfpl is free software; you can redistribute it and/or modify it under the
-# terms of the GNU Lesser General Public License as published by the Free
-# Software Foundation; either version 2.1 of the License, or (at your option)
-# any later version.
-#
-# wfpl is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
-# more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with wfpl; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
# This file contains functions to accept files being uplodad with the
-#
-#
-#
+#
+#
+#
#
#
# #######
@@ -119,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);
@@ -141,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;
@@ -162,25 +177,41 @@ function save_uploaded_file($key, $path) {
return $filename;
}
-function path_to_convert() {
- if(!isset($GLOBALS['path_to_convert'])) {
- $convert = '/usr/local/bin/convert';
- if(!file_exists($convert)) {
- $convert = '/usr/bin/convert';
- }
- if(!file_exists($convert)) {
- $convert = `which convert`;
- }
- if($convert == '' || !file_exists($convert)) {
- die("can't find imagemagick's 'convert' program");
- }
+# this function exists to deal with cases where binaries are installed in very
+# standard places (like /usr/bin or /usr/local bin) and PHP's PATH environment
+# variable is not set appropriately.
+function path_to($prog, $or_die = true) {
+ $prog = ereg_replace('[^a-zA-Z0-9_.-]', '', $prog);
+ $prog = ereg_replace('^[-.]*', '', $prog);
+ if($prog == '') {
+ die('Invalid argument to path_to()');
+ }
- $GLOBALS['path_to_convert'] = $convert;
+ if(!isset($GLOBALS["path_to_$prog"])) {
+ $ret = _path_to($prog, $or_die);
+ if($ret == false) {
+ return false;
+ }
+ $GLOBALS["path_to_$prog"] = $ret;
}
- return $GLOBALS['path_to_convert'];
+ return $GLOBALS["path_to_$prog"];
+}
+
+function _path_to($prog, $or_die) {
+ # relies on PHP's short-circuit mechanism
+ if(file_exists($path = "/usr/local/bin/$prog") ||
+ file_exists($path = "/usr/bin/$prog") ||
+ ($path = `which $prog` != '' && file_exists($path))) {
+ return $path;
+ } else {
+ if($or_die) {
+ die("Failed to locate '$prog' executable.");
+ }
+ return false;
+ }
}
-
+
# returns new filename with .png extension
function gif_to_png($filename, $new_filename = 'just change extension') {
@@ -193,14 +224,8 @@ function gif_to_png($filename, $new_filename = 'just change extension') {
$new_filename .= '.png';
}
- $convert = path_to_convert();
+ imagemagick_convert($filename, $new_filename, "$convert -colorspace RGB", 'GIF to PNG conversion');
- $command = "$convert " . escapeshellarg($filename) . ' ' . escapeshellarg($new_filename);
-
- exec($command, $dummy, $ret);
- if($ret != 0) {
- die("image conversion failed. convert did exit($ret)");
- }
unlink($filename);
return $new_filename;
}
@@ -213,46 +238,172 @@ function gif_to_png($filename, $new_filename = 'just change extension') {
# Thumbnail will retain aspect ratio, and be either $max_width wide or
# $max_height tall (or, if the aspect is just right, both)
function make_thumbnail($filename, $max_width = '70', $max_height = '70') {
- $thumb = ereg_replace('[.]([a-z]+)$', "_thumb.\\1", $filename);
- if($thumb == $filename) {
+ $last_dot = strrpos($filename, '.');
+ if($last_dot === false) {
die("couldn't make thumbnail because filename has no extension.");
}
- $convert = path_to_convert();
+ $thumb = substr($filename, 0, $last_dot);
+ $thumb .= '_thumb';
+ $thumb .= substr($filename, $last_dot);
- # 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';
- }
+ $max_width = format_int_70($max_width);
+ $height_width = format_int_70($height_width);
+
+ 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 creatin failed. convert did 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);
}
-# like save_uploaded_file() (above) except it converts gifs to pngs.
+# 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.
#
-# 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;
+# 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
+#
+# Return: string in the format WIDTHxHEIGHT, or boolean false
+#
+# Example: image_dimensions('uploads/foo.png'); ==> "124x58"
+function image_dimensions($image) {
+ $identify = path_to('identify');
+ $command = "$identify -format '%wx%h' " . escapeshellarg($image);
+ $dimensions = rtrim(`$command`);
+ if($dimensions == '') {
+ return false;
+ } else {
+ return $dimensions;
+ }
+}
+
+# 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.
+#
+# 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 -auto-orient';
+ 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;
+}