From 000f9306b841492d5df66d5f004e2ba62dc7171b Mon Sep 17 00:00:00 2001 From: = Date: Wed, 12 Sep 2012 23:04:14 -0400 Subject: [PATCH 1/4] Ensure file system storage directory is writable Fixes #8 --- src/Upload/Storage/FileSystem.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Upload/Storage/FileSystem.php b/src/Upload/Storage/FileSystem.php index eca5ed7..64be408 100644 --- a/src/Upload/Storage/FileSystem.php +++ b/src/Upload/Storage/FileSystem.php @@ -58,12 +58,16 @@ class FileSystem extends \Upload\Storage\Base * @param string $directory Relative or absolute path to upload directory * @param bool $overwrite Should this overwrite existing files? * @throws \InvalidArgumentException If directory does not exist + * @throws \InvalidArgumentException If directory is not writable */ public function __construct($directory, $overwrite = false) { if (!is_dir($directory)) { throw new \InvalidArgumentException('Directory does not exist'); } + if (!is_writable($directory)) { + throw new \InvalidArgumentException('Directory is not writable'); + } $this->directory = rtrim($directory, '/') . DIRECTORY_SEPARATOR; $this->overwrite = $overwrite; } From 940c9e0939e98c97c09c5feeeac1342f33ef1dbe Mon Sep 17 00:00:00 2001 From: Alex Kucherenko Date: Mon, 29 Oct 2012 13:07:07 +0200 Subject: [PATCH 2/4] Add Extension validator --- src/Upload/Validation/Extensions.php | 95 ++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/Upload/Validation/Extensions.php diff --git a/src/Upload/Validation/Extensions.php b/src/Upload/Validation/Extensions.php new file mode 100644 index 0000000..d864888 --- /dev/null +++ b/src/Upload/Validation/Extensions.php @@ -0,0 +1,95 @@ + + * @copyright 2012 Josh Lockhart + * @link http://www.joshlockhart.com + * @version 1.0.0 + * + * MIT LICENSE + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +namespace Upload\Validation; + +/** + * Validate File Extensions + * + * This class validates an uploads file extension. It takes file extension with out dot + * or array of extensions. For example: 'png' or array('jpg', 'png', 'gif'). + * + * WARING! Validation only by file extension not very secure. + * + * @author Alex Kucherenko + * @package Upload + */ +class Extensions extends \Upload\Validation\Base +{ + + /** + * Acceptable file extensions, always array + * + * @var array + */ + protected $allowedExtensions; + + /** + * Error message + * @var string + */ + protected $message = 'Invalid file extension allowed only %s'; + + /** + * Constructor + * + * @param string|array $allowedExtensions - Allowed file extensions + * @example new Extensions(array('png','jpg','gif')) or if one: new Extensions('png') + */ + public function __construct($allowedExtensions) + { + + if(is_string($allowedExtensions)){ $allowedExtensions = array($allowedExtensions); } + + array_filter($allowedExtensions, function($val){ + return strtolower($val); + }); + + $this->allowedExtensions = $allowedExtensions; + } + + /** + * Validate + * @param \Upload\File $file + * @return bool + */ + public function validate(\Upload\File $file) + { + $fileExtension = strtolower($file->getExtension()); + $isValid = true; + + if (!in_array($fileExtension, $this->allowedExtensions)) { + $this->setMessage(sprintf($this->message, implode(', ', $this->allowedExtensions))); + $isValid = false; + } + + return $isValid; + } +} From 5de6511da8e297290b2bceaedaa1eb3938c0892a Mon Sep 17 00:00:00 2001 From: = Date: Mon, 5 Nov 2012 19:37:57 -0500 Subject: [PATCH 3/4] Tidy up Extension validator code --- .../{Extensions.php => Extension.php} | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) rename src/Upload/Validation/{Extensions.php => Extension.php} (66%) diff --git a/src/Upload/Validation/Extensions.php b/src/Upload/Validation/Extension.php similarity index 66% rename from src/Upload/Validation/Extensions.php rename to src/Upload/Validation/Extension.php index d864888..1a9d8fb 100644 --- a/src/Upload/Validation/Extensions.php +++ b/src/Upload/Validation/Extension.php @@ -31,7 +31,7 @@ namespace Upload\Validation; /** - * Validate File Extensions + * Validate File Extension * * This class validates an uploads file extension. It takes file extension with out dot * or array of extensions. For example: 'png' or array('jpg', 'png', 'gif'). @@ -41,12 +41,10 @@ * @author Alex Kucherenko * @package Upload */ -class Extensions extends \Upload\Validation\Base +class Extension extends \Upload\Validation\Base { - /** - * Acceptable file extensions, always array - * + * Array of cceptable file extensions without leading dots * @var array */ protected $allowedExtensions; @@ -55,24 +53,26 @@ class Extensions extends \Upload\Validation\Base * Error message * @var string */ - protected $message = 'Invalid file extension allowed only %s'; + protected $message = 'Invalid file extension. Must be one of: %s'; - /** - * Constructor - * - * @param string|array $allowedExtensions - Allowed file extensions - * @example new Extensions(array('png','jpg','gif')) or if one: new Extensions('png') - */ + /** + * Constructor + * + * @param string|array $allowedExtensions Allowed file extensions + * @example new \Upload\Validation\Extension(array('png','jpg','gif')) + * @example new \Upload\Validation\Extension('png') + */ public function __construct($allowedExtensions) { + if (is_string($allowedExtensions)) { + $allowedExtensions = array($allowedExtensions); + } - if(is_string($allowedExtensions)){ $allowedExtensions = array($allowedExtensions); } - - array_filter($allowedExtensions, function($val){ - return strtolower($val); - }); + array_filter($allowedExtensions, function ($val) { + return strtolower($val); + }); - $this->allowedExtensions = $allowedExtensions; + $this->allowedExtensions = $allowedExtensions; } /** @@ -82,14 +82,14 @@ public function __construct($allowedExtensions) */ public function validate(\Upload\File $file) { - $fileExtension = strtolower($file->getExtension()); - $isValid = true; + $fileExtension = strtolower($file->getExtension()); + $isValid = true; - if (!in_array($fileExtension, $this->allowedExtensions)) { - $this->setMessage(sprintf($this->message, implode(', ', $this->allowedExtensions))); - $isValid = false; - } + if (!in_array($fileExtension, $this->allowedExtensions)) { + $this->setMessage(sprintf($this->message, implode(', ', $this->allowedExtensions))); + $isValid = false; + } - return $isValid; + return $isValid; } } From 9aec42825f5bd53f1164e791c0f1fb58385c4cb8 Mon Sep 17 00:00:00 2001 From: = Date: Mon, 5 Nov 2012 19:38:07 -0500 Subject: [PATCH 4/4] Add tests for Extension validator --- tests/Validation/ExtensionTest.php | 43 ++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tests/Validation/ExtensionTest.php diff --git a/tests/Validation/ExtensionTest.php b/tests/Validation/ExtensionTest.php new file mode 100644 index 0000000..617bb4e --- /dev/null +++ b/tests/Validation/ExtensionTest.php @@ -0,0 +1,43 @@ +assetsDirectory = dirname(__DIR__) . '/assets'; + + // Create stubbed storage instance + $this->storage = $this->getMock( + '\Upload\Storage\FileSystem', + array('upload'), + array($this->assetsDirectory) + ); + $this->storage->expects($this->any()) + ->method('upload') + ->will($this->returnValue(true)); + + // Reset $_FILES superglobal + $_FILES['foo'] = array( + 'name' => 'foo.txt', + 'tmp_name' => $this->assetsDirectory . '/foo.txt', + 'error' => 0 + ); + } + + public function testValidExtension() + { + $file = new \Upload\File('foo', $this->storage); + $validation = new \Upload\Validation\Extension('txt'); + $this->assertTrue($validation->validate($file)); + } + + public function testInvalidExtension() + { + $file = new \Upload\File('foo', $this->storage); + $validation = new \Upload\Validation\Extension('csv'); + $this->assertFalse($validation->validate($file)); + } +}