Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

various code enhancements #4

Merged
merged 4 commits into from

2 participants

@palepurple
  • Make more stuff configurable
  • Ensure there's no scope for shell injection when executing convert commands
  • Added more docs
  • Added some warnings about using the remote mode / fetching of images.
  • Improved example.php script (pokes you to say you need to make some dirs writeable).
@wes wes merged commit e81a03d into wes:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 30, 2012
  1. @palepurple

    print out helpful message if the default cache directories are not th…

    palepurple authored
    …ere - as this will probably result in the page not rendering
  2. @palepurple

    try and escape the shell arguments with escapeshellarg to make it a b…

    palepurple authored
    …it more secure; add note about retrieval of remote urls and so on
  3. @palepurple
  4. @palepurple

    add in some default parameters, make it more configurable in general …

    palepurple authored
    …(i.e. more can be passed in through $opts)
This page is out of date. Refresh to see the latest.
Showing with 82 additions and 38 deletions.
  1. +10 −1 example.php
  2. +72 −37 function.resize.php
View
11 example.php
@@ -32,6 +32,15 @@
<h1>PHP Image Resizer</h1>
+<?php
+$dirs = array('cache', 'cache/remote');
+foreach($dirs as $dir) {
+ $end_dir = dirname(__FILE__) . DIRECTORY_SEPARATOR . $dir;
+ if(!is_dir($end_dir)) {
+ echo "<p><em>Hint: If this page looks broken, you probably need to 'mkdir -m 777 -p $end_dir</em></p>";
+ }
+}
+?>
<div class='block'>
<?php $settings = array('w'=>300); ?>
<div><img src='<?=resize('images/dog.jpg',$settings)?>' border='0' /></div>
@@ -77,4 +86,4 @@
</div>
</body>
-</html>
+</html>
View
109 function.resize.php
@@ -1,20 +1,42 @@
<?php
-
-/*
-function by Wes Edling .. http://joedesigns.com
-feel free to use this in any project, i just ask for a credit in the source code.
-a link back to my site would be nice too.
-*/
-
+/**
+ * function by Wes Edling .. http://joedesigns.com
+ * feel free to use this in any project, i just ask for a credit in the source code.
+ * a link back to my site would be nice too.
+ *
+ *
+ * Changes:
+ * 2012/01/30 - David Goodwin - call escapeshellarg on parameters going into the shell
+ */
+
+/**
+ * SECURITY:
+ * It's a bad idea to allow user supplied data to become the path for the image you wish to retrieve, as this allows them
+ * to download nearly anything to your server. If you must do this, it's strongly advised that you put a .htaccess file
+ * in the cache directory containing something like the following :
+ * <code>php_flag engine off</code>
+ * to at least stop arbitrary code execution. You can deal with any copyright infringement issues yourself :)
+ */
+
+/**
+ * @param string $imagePath - either a local absolute/relative path, or a remote URL (e.g. http://...flickr.com/.../ ). See SECURITY note above.
+ * @param array $opts (w(pixels), h(pixels), crop(boolean), scale(boolean), thumbnail(boolean), maxOnly(boolean), canvas-color(#abcabc), output-filename(string), cache_http_minutes(int))
+ * @return new URL for resized image.
+ */
function resize($imagePath,$opts=null){
# start configuration
-
$cacheFolder = './cache/'; # path to your cache folder, must be writeable by web server
$remoteFolder = $cacheFolder.'remote/'; # path to the folder you wish to download remote images into
- $quality = 90; # image quality to use for ImageMagick (0 - 100)
-
- $cache_http_minutes = 20; # cache downloaded http images 20 minutes
+
+ $defaults = array('crop' => false, 'scale' => 'false', 'thumbnail' => false, 'maxOnly' => false,
+ 'canvas-color' => 'transparent', 'output-filename' => false,
+ 'cacheFolder' => $cacheFolder, 'remoteFolder' => $remoteFolder, 'quality' => 90, 'cache_http_minutes' => 20);
+
+ $opts = array_merge($defaults, $opts);
+
+ $cacheFolder = $opts['cacheFolder'];
+ $remoteFolder = $opts['remoteFolder'];
$path_to_convert = 'convert'; # this could be something like /usr/bin/convert or /opt/local/share/bin/convert
@@ -31,7 +53,7 @@ function resize($imagePath,$opts=null){
$local_filepath = $remoteFolder.$filename;
$download_image = true;
if(file_exists($local_filepath)):
- if(filemtime($local_filepath) < strtotime('+'.$cache_http_minutes.' minutes')):
+ if(filemtime($local_filepath) < strtotime('+'.$opts['cache_http_minutes'].' minutes')):
$download_image = false;
endif;
endif;
@@ -54,26 +76,31 @@ function resize($imagePath,$opts=null){
$filename = md5_file($imagePath);
- if(!empty($w) and !empty($h)):
- $newPath = $cacheFolder.$filename.'_w'.$w.'_h'.$h.(isset($opts['crop']) && $opts['crop'] == true ? "_cp" : "").(isset($opts['scale']) && $opts['scale'] == true ? "_sc" : "").'.'.$ext;
- elseif(!empty($w)):
- $newPath = $cacheFolder.$filename.'_w'.$w.'.'.$ext;
- elseif(!empty($h)):
- $newPath = $cacheFolder.$filename.'_h'.$h.'.'.$ext;
+ // If the user has requested an explicit output-filename, do not use the cache directory.
+ if(false !== $opts['output-filename']) :
+ $newPath = $opts['output-filename'];
else:
- return false;
+ if(!empty($w) and !empty($h)):
+ $newPath = $cacheFolder.$filename.'_w'.$w.'_h'.$h.(isset($opts['crop']) && $opts['crop'] == true ? "_cp" : "").(isset($opts['scale']) && $opts['scale'] == true ? "_sc" : "").'.'.$ext;
+ elseif(!empty($w)):
+ $newPath = $cacheFolder.$filename.'_w'.$w.'.'.$ext;
+ elseif(!empty($h)):
+ $newPath = $cacheFolder.$filename.'_h'.$h.'.'.$ext;
+ else:
+ return false;
+ endif;
endif;
$create = true;
- if(file_exists($newPath) == true):
- $create = false;
- $origFileTime = date("YmdHis",filemtime($imagePath));
- $newFileTime = date("YmdHis",filemtime($newPath));
- if($newFileTime < $origFileTime):
- $create = true;
- endif;
- endif;
+ if(file_exists($newPath) == true):
+ $create = false;
+ $origFileTime = date("YmdHis",filemtime($imagePath));
+ $newFileTime = date("YmdHis",filemtime($newPath));
+ if($newFileTime < $origFileTime): # Not using $opts['expire-time'] ??
+ $create = true;
+ endif;
+ endif;
if($create == true):
if(!empty($w) and !empty($h)):
@@ -83,33 +110,41 @@ function resize($imagePath,$opts=null){
if($width > $height):
$resize = $w;
- if(isset($opts['crop']) && $opts['crop'] == true):
+ if(true === $opts['crop']):
$resize = "x".$h;
endif;
else:
$resize = "x".$h;
- if(isset($opts['crop']) && $opts['crop'] == true):
+ if(true === $opts['crop']):
$resize = $w;
endif;
endif;
- if(isset($opts['scale']) && $opts['scale'] == true):
- $cmd = $path_to_convert." ".$imagePath." -resize ".$resize." -quality ".$quality." ".$newPath;
+ if(true === $opts['scale']):
+ $cmd = $path_to_convert ." ". escapeshellarg($imagePath) ." -resize ". escapeshellarg($resize) .
+ " -quality ". escapeshellarg($opts['quality']) . " " . escapeshellarg($newPath);
else:
- $cmd = $path_to_convert." ".$imagePath." -resize ".$resize." -size ".$w."x".$h." xc:".(isset($opts['canvas-color'])?$opts['canvas-color']:"transparent")." +swap -gravity center -composite -quality ".$quality." ".$newPath;
+ $cmd = $path_to_convert." ". escapeshellarg($imagePath) ." -resize ". escapeshellarg($resize) .
+ " -size ". escapeshellarg($w ."x". $h) .
+ " xc:". escapeshellarg($opts['canvas-color']) .
+ " +swap -gravity center -composite -quality ". escapeshellarg($opts['quality'])." ".escapeshellarg($newPath);
endif;
else:
- $cmd = $path_to_convert." ".$imagePath." -thumbnail ".(!empty($h) ? 'x':'').$w."".(isset($opts['maxOnly']) && $opts['maxOnly'] == true ? "\>" : "")." -quality ".$quality." ".$newPath;
+ $cmd = $path_to_convert." " . escapeshellarg($imagePath) .
+ " -thumbnail ". (!empty($h) ? 'x':'') . $w ."".
+ (isset($opts['maxOnly']) && $opts['maxOnly'] == true ? "\>" : "") .
+ " -quality ". escapeshellarg($opts['quality']) ." ". escapeshellarg($newPath);
endif;
- $c = exec($cmd);
-
+ $c = exec($cmd, $output, $return_code);
+ if($return_code != 0) {
+ error_log("Tried to execute : $cmd, return code: $return_code, output: " . print_r($output, true));
+ return false;
+ }
endif;
# return cache file path
return str_replace($_SERVER['DOCUMENT_ROOT'],'',$newPath);
}
-
-?>
Something went wrong with that request. Please try again.