3 # Copyright (C) 2007 Jason Woofenden
5 # This file is part of wfpl.
7 # wfpl is free software; you can redistribute it and/or modify it under the
8 # terms of the GNU Lesser General Public License as published by the Free
9 # Software Foundation; either version 2.1 of the License, or (at your option)
12 # wfpl is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
17 # You should have received a copy of the GNU Lesser General Public License
18 # along with wfpl; if not, write to the Free Software Foundation, Inc., 51
19 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 # This file contains functions to accept files being uplodad with the <input
23 # type="file" name="foo"> control.
29 # First, your <form> tag must contain this attribute:
30 # enctype="multipart/form-data"
32 # Second, you should indicate to the browser the maximum file size (in bytes)
33 # allowed for uploads with a hidden input field named MAX_FILE_SIZE. You can
34 # use the function upload_max_filesize() to get the maximum allowed size that
39 # <form action="foo.php" enctype="multipart/form-data" method="post">
40 # <input type="hidden" name="MAX_FILE_SIZE" value="2097152" />
41 # <input type="file" name="photo" />
42 # <input type="submit" name="save" value="Save" />
49 # In the php code you can use either save_uploaded_file('photo',
50 # 'upload/dir/'); or save_uploaded_image('photo', 'upload/dir/'); The only
51 # difference being that save_uploaded_image() will convert gifs to PNGs.
53 # Both functions will generate a reasonable filename based on the filename
54 # passed from the browser (and on the mime-type if there's no extension) unless
55 # you specify a filename. See the comments above the function definitions below
58 # In a future version of save_uploaded_image(), when you specify a filename, it
59 # will check the image type of the uploaded image, and if it's different than
60 # the type you specified, it will convert the image for you.
63 $GLOBALS['mime_to_ext'] = array(
64 'text/plain' => 'txt',
65 'text/html' => 'html',
66 'image/jpeg' => 'jpg',
71 'application/pdf' => 'pdf'
74 $GLOBALS['ext_to_ext'] = array(
81 # return the upload_max_filesize in bytes
82 function upload_max_filesize() {
83 $max = ini_get('upload_max_filesize');
84 $postfix = strtolower(substr($max, -1));
86 return substr($max, 0, -1) * 1073741824;
87 } elseif($postfix == 'm') {
88 return substr($max, 0, -1) * 1048576;
89 } elseif ($postfix == 'k') {
90 return substr($max, 0, -1) * 1024;
97 # pass in the client's path that came from an html <input type="file"/> tag
99 # mime time used to generate extension ONLY IF it doesn't have one already.
100 function generate_filename($path, $mime = 'text/plain') {
102 $filename = strtolower($path);
104 # remove directories (unix, windows and mac paths)
105 $last = strrpos($filename, '/');
106 if($last === false) {
107 $last = strrpos($filename, '\\');
109 if($last === false) {
110 $last = strrpos($filename, ':');
113 $filename = substr($filename, $last + 1);
116 # replace symbols with underscores
117 $filename = ereg_replace('[^a-z0-9_.]', '_', $filename);
119 # remove dots from the beginning (no invisible files)
120 $filename = ereg_replace('^\.*', '', $filename);
123 $last_dot = strrpos($filename, '.');
124 if($last_dot === false) {
126 if(isset($GLOBALS['mime_to_ext'][$mime])) {
127 $filename .= '.' . $GLOBALS['mime_to_ext'][$mime];
130 $basename = substr($filename, 0, $last_dot);
131 $ext = substr($filename, $last_dot + 1);
132 if(isset($GLOBALS['ext_to_ext'][$ext])) {
133 $ext .= $GLOBALS['ext_to_ext'][$ext];
135 $filename = $basename . '.' . $ext;
142 # Move uploaded file, and return the new filename.
144 # Pass in the index into the $_FILES array (the name of the html input tag) and
145 # the path to the folder you'd like it saved to. If path ends with a slash this
146 # function will generate a filename based on the client's name, otherwise it'll
147 # name the file that.
149 # example: save_uploaded_file('pdf', 'uploaded_pdfs/');
150 # example: save_uploaded_file('resume', "/www/example.com/remumes/$user_id.txt");
151 function save_uploaded_file($key, $path) {
152 if(substr($path, -1) == '/') {
153 $filename = $path . generate_filename($_FILES[$key]['name'], $_FILES[$key]['type']);
158 if(!move_uploaded_file($_FILES[$key]['tmp_name'], $filename)) {
165 # this function exists to deal with cases where binaries are installed in very
166 # standard places (like /usr/bin or /usr/local bin) and PHP's PATH environment
167 # variable is not set appropriately.
168 function path_to($prog, $or_die = true) {
169 $prog = ereg_replace('[^a-zA-Z0-9_.-]', '', $prog);
170 $prog = ereg_replace('^[-.]*', '', $prog);
172 die('Invalid argument to path_to()');
175 if(!isset($GLOBALS["path_to_$prog"])) {
176 $ret = _path_to($prog, $or_die);
180 $GLOBALS["path_to_$prog"] = $ret;
183 return $GLOBALS["path_to_$prog"];
186 function _path_to($prog, $or_die) {
187 # relies on PHP's short-circuit mechanism
188 if(file_exists($path = "/usr/local/bin/$prog") ||
189 file_exists($path = "/usr/bin/$prog") ||
190 ($path = `which $prog` != '' && file_exists($path))) {
194 die("Failed to locate '$prog' executable.");
201 # returns new filename with .png extension
202 function gif_to_png($filename, $new_filename = 'just change extension') {
203 if($new_filename == 'just change extension') {
204 $new_filename = $filename;
205 $last_dot = strrpos($new_filename, '.');
206 if($last_dot !== false) {
207 $new_filename = substr($new_filename, 0, $last_dot);
209 $new_filename .= '.png';
212 $convert = path_to('convert');
214 $command = "$convert " . escapeshellarg($filename) . ' ' . escapeshellarg($new_filename);
216 exec($command, $dummy, $ret);
218 die("image conversion failed. convert did exit($ret)");
221 return $new_filename;
224 # make a thumbnail image.
226 # Thumbnail will have the same filename, except "_thumb" will be added right
227 # before the dot preceding the extension. so foo.png yields foo_thumb.png
229 # Thumbnail will retain aspect ratio, and be either $max_width wide or
230 # $max_height tall (or, if the aspect is just right, both)
231 function make_thumbnail($filename, $max_width = '70', $max_height = '70') {
232 $last_dot = strrpos($filename, '.');
233 if($last_dot === false) {
234 die("couldn't make thumbnail because filename has no extension.");
237 $thumb = substr($filename, 0, $last_dot);
239 $thumb .= substr($filename, $last_dot);
241 $convert = path_to('convert');
243 # can't be too careful
244 $max_width = ereg_replace('[^0-9]', '', $max_width);
245 if($max_width == '') {
248 $max_height = ereg_replace('[^0-9]', '', $max_height);
249 if($max_height == '') {
253 $command = "$convert -geometry ${max_width}x$max_height " . escapeshellarg($filename) . ' ' . escapeshellarg($thumb);
255 exec($command, $dummy, $ret);
257 die("Thumbnail creation failed. Convert called exit($ret)");
263 # Argument: path to image file
265 # Return: string in the format WIDTHxHEIGHT, or boolean false
267 # Example: image_dimensions('uploads/foo.png'); ==> "124x58"
268 function image_dimensions($image) {
269 $identify = path_to('identify');
270 $command = "$identify -format '%wx%h' " . escapeshellarg($image);
271 $dimensions = rtrim(`$command`);
272 if($dimensions == '') {
279 # like save_uploaded_file() (above) except it converts gifs to pngs.
281 # FIXME: if a filename is passed in the end of path, we should check if the file type matches, and if not run convert.
282 function save_uploaded_image($key, $path) {
283 if(substr($path, -1) == '/') {
284 $filename = save_uploaded_file($key, $path);
285 if(substr($filename, -4) == '.gif') {
286 $filename = gif_to_png($filename);
290 return save_uploaded_file($key, $path);