/**
  * Validates a $_FILES array against the upload configuration
  * 
  * @param array $file_array  The $_FILES array for a single file
  * @return string  The validation error message
  */
 private function validateField($file_array)
 {
     if (empty($file_array['name'])) {
         if ($this->required) {
             return self::compose('Please upload a file');
         }
         return NULL;
     }
     if ($file_array['error'] == UPLOAD_ERR_FORM_SIZE || $file_array['error'] == UPLOAD_ERR_INI_SIZE) {
         $max_size = !empty($_POST['MAX_FILE_SIZE']) ? $_POST['MAX_FILE_SIZE'] : ini_get('upload_max_filesize');
         $max_size = !is_numeric($max_size) ? fFilesystem::convertToBytes($max_size) : $max_size;
         return self::compose('The file uploaded is over the limit of %s', fFilesystem::formatFilesize($max_size));
     }
     if ($this->max_size && $file_array['size'] > $this->max_size) {
         return self::compose('The file uploaded is over the limit of %s', fFilesystem::formatFilesize($this->max_size));
     }
     if (empty($file_array['tmp_name']) || empty($file_array['size'])) {
         if ($this->required) {
             return self::compose('Please upload a file');
         }
         return NULL;
     }
     if (!empty($this->mime_types) && file_exists($file_array['tmp_name'])) {
         $contents = file_get_contents($file_array['tmp_name'], FALSE, NULL, 0, 4096);
         if (!in_array(fFile::determineMimeType($file_array['name'], $contents), $this->mime_types)) {
             return self::compose($this->mime_type_message);
         }
     }
     if (!$this->allow_php) {
         $file_info = fFilesystem::getPathInfo($file_array['name']);
         if (in_array(strtolower($file_info['extension']), array('php', 'php4', 'php5'))) {
             return self::compose('The file uploaded is a PHP file, but those are not permitted');
         }
     }
     if (!$this->allow_dot_files) {
         if (substr($file_array['name'], 0, 1) == '.') {
             return self::compose('The name of the uploaded file may not being with a .');
         }
     }
     if ($this->image_dimensions && file_exists($file_array['tmp_name'])) {
         if (fImage::isImageCompatible($file_array['tmp_name'])) {
             list($width, $height, $other) = getimagesize($file_array['tmp_name']);
             if ($this->image_dimensions['min_width'] && $width < $this->image_dimensions['min_width']) {
                 return self::compose('The uploaded image is narrower than the minimum width of %spx', $this->image_dimensions['min_width']);
             }
             if ($this->image_dimensions['min_height'] && $height < $this->image_dimensions['min_height']) {
                 return self::compose('The uploaded image is shorter than the minimum height of %spx', $this->image_dimensions['min_height']);
             }
             if ($this->image_dimensions['max_width'] && $width > $this->image_dimensions['max_width']) {
                 return self::compose('The uploaded image is wider than the maximum width of %spx', $this->image_dimensions['max_width']);
             }
             if ($this->image_dimensions['max_height'] && $height > $this->image_dimensions['max_height']) {
                 return self::compose('The uploaded image is taller than the maximum height of %spx', $this->image_dimensions['max_height']);
             }
         }
     }
     if ($this->image_ratio && file_exists($file_array['tmp_name'])) {
         if (fImage::isImageCompatible($file_array['tmp_name'])) {
             list($width, $height, $other) = getimagesize($file_array['tmp_name']);
             if ($this->image_ratio['allow_excess_dimension'] == 'width' && $width / $height < $this->image_ratio['width'] / $this->image_ratio['height']) {
                 return self::compose('The uploaded image is too narrow for its height. The required ratio is %1$sx%2$s or wider.', $this->image_ratio['width'], $this->image_ratio['height']);
             }
             if ($this->image_ratio['allow_excess_dimension'] == 'height' && $width / $height > $this->image_ratio['width'] / $this->image_ratio['height']) {
                 return self::compose('The uploaded image is too short for its width. The required ratio is %1$sx%2$s or taller.', $this->image_ratio['width'], $this->image_ratio['height']);
             }
         }
     }
 }
 /**
  * @dataProvider convertToBytesProvider
  */
 public function testConvertToBytes($input, $output)
 {
     $this->assertEquals($output, fFilesystem::convertToBytes($input));
 }
Example #3
0
 /**
  * Validates a $_FILES array against the upload configuration
  * 
  * @param array $file_array  The $_FILES array for a single file
  * @return string  The validation error message
  */
 private function validateField($file_array)
 {
     if (empty($file_array['name'])) {
         if ($this->required) {
             return self::compose('Please upload a file');
         }
         return NULL;
     }
     if ($file_array['error'] == UPLOAD_ERR_FORM_SIZE || $file_array['error'] == UPLOAD_ERR_INI_SIZE) {
         $max_size = !empty($_POST['MAX_FILE_SIZE']) ? $_POST['MAX_FILE_SIZE'] : ini_get('upload_max_filesize');
         $max_size = !is_numeric($max_size) ? fFilesystem::convertToBytes($max_size) : $max_size;
         return self::compose('The file uploaded is over the limit of %s', fFilesystem::formatFilesize($max_size));
     }
     if ($this->max_size && $file_array['size'] > $this->max_size) {
         return self::compose('The file uploaded is over the limit of %s', fFilesystem::formatFilesize($this->max_size));
     }
     if (empty($file_array['tmp_name']) || empty($file_array['size'])) {
         if ($this->required) {
             return self::compose('Please upload a file');
         }
         return NULL;
     }
     if (!empty($this->mime_types) && file_exists($file_array['tmp_name'])) {
         $contents = file_get_contents($file_array['tmp_name'], FALSE, NULL, 0, 4096);
         if (!in_array(fFile::determineMimeType($file_array['name'], $contents), $this->mime_types)) {
             return self::compose($this->mime_type_message);
         }
     }
     if (!$this->allow_php) {
         $file_info = fFilesystem::getPathInfo($file_array['name']);
         if (in_array(strtolower($file_info['extension']), array('php', 'php4', 'php5'))) {
             return self::compose('The file uploaded is a PHP file, but those are not permitted');
         }
     }
     if (!$this->allow_dot_files) {
         if (substr($file_array['name'], 0, 1) == '.') {
             return self::compose('The name of the uploaded file may not being with a .');
         }
     }
 }
Example #4
0
 /**
  * Validates the uploaded file, ensuring a file was actually uploaded and that is matched the restrictions put in place
  * 
  * @throws fValidationException  When no file is uploaded or the uploaded file violates the options set for this object
  * 
  * @param  string  $field  The field the file was uploaded through
  * @param  integer $index  If the field was an array of file uploads, this specifies which one to validate
  * @return void
  */
 public function validate($field, $index = NULL)
 {
     if (!self::check($field)) {
         throw new fProgrammerException('The field specified, %s, does not appear to be a file upload field', $field);
     }
     $file_array = $this->extractFileUploadArray($field, $index);
     // Do some validation of the file provided
     if (empty($file_array['name'])) {
         throw new fValidationException('Please upload a file');
     }
     if ($file_array['error'] == UPLOAD_ERR_FORM_SIZE || $file_array['error'] == UPLOAD_ERR_INI_SIZE) {
         $max_size = !empty($_POST['MAX_FILE_SIZE']) ? $_POST['MAX_FILE_SIZE'] : ini_get('upload_max_filesize');
         $max_size = !is_numeric($max_size) ? fFilesystem::convertToBytes($max_size) : $max_size;
         $msg = $this->max_message != "" ? $this->max_message : 'The file uploaded is over the limit of %s';
         throw new fValidationException($msg, fFilesystem::formatFilesize($max_size));
     }
     if ($this->max_file_size && $file_array['size'] > $this->max_file_size) {
         $msg = $this->max_message != "" ? $this->max_message : 'The file uploaded is over the limit of %s';
         throw new fValidationException($msg, fFilesystem::formatFilesize($this->max_file_size));
     }
     if (empty($file_array['tmp_name']) || empty($file_array['size'])) {
         throw new fValidationException('Please upload a file');
     }
     if (!empty($this->mime_types) && file_exists($file_array['tmp_name']) && !in_array(fFile::determineMimeType($file_array['tmp_name']), $this->mime_types)) {
         throw new fValidationException($this->mime_type_message);
     }
     if (!$this->allow_php) {
         $file_info = fFilesystem::getPathInfo($file_array['name']);
         if (in_array(strtolower($file_info['extension']), array('php', 'php4', 'php5'))) {
             throw new fValidationException('The file uploaded is a PHP file, but those are not permitted');
         }
     }
     return $file_array;
 }
Example #5
0
 /**
  * Processes the current image using GD
  *
  * @param  string  $output_file   The file to save the image to
  * @param  integer $jpeg_quality  The JPEG quality to use
  * @return void
  */
 private function processWithGD($output_file, $jpeg_quality)
 {
     $type = self::getImageType($this->file);
     $save_alpha = FALSE;
     $path_info = fFilesystem::getPathInfo($output_file);
     $new_type = $path_info['extension'];
     $new_type = $type == 'jpeg' ? 'jpg' : $type;
     if (!in_array($new_type, array('gif', 'jpg', 'png'))) {
         $new_type = $type;
     }
     if (ini_get('memory_limit') != '-1') {
         // We will estimate memory usage at 3MB if we can't actually check it
         $beginning_memory_usage = 3145728;
         if (function_exists('memory_get_usage')) {
             $beginning_memory_usage = memory_get_usage();
         }
         $memory_limit_bytes = fFilesystem::convertToBytes(ini_get('memory_limit'));
         // Estimate the memory usage and throw an exception if we will run out
         $load_byte_usage = $this->pending_modifications[0]['old_width'] * $this->pending_modifications[0]['old_height'] * 4;
         if ($load_byte_usage + $beginning_memory_usage > $memory_limit_bytes) {
             throw new fEnvironmentException('The predicted memory usage to complete the image modifications using the GD extension, %1$s, will most likely exceed the memory limit of %2$s', $load_byte_usage + $beginning_memory_usage, $memory_limit_bytes);
         }
     }
     switch ($type) {
         case 'gif':
             $gd_res = imagecreatefromgif($this->file);
             $save_alpha = TRUE;
             break;
         case 'jpg':
             $gd_res = imagecreatefromjpeg($this->file);
             break;
         case 'png':
             $gd_res = imagecreatefrompng($this->file);
             $save_alpha = TRUE;
             break;
     }
     foreach ($this->pending_modifications as $num => $mod) {
         if (ini_get('memory_limit') != '-1') {
             $old_byte_usage = $this->pending_modifications[0]['old_width'] * $this->pending_modifications[0]['old_height'] * 4;
             $new_byte_usage = $this->pending_modifications[0]['width'] * $this->pending_modifications[0]['height'] * 4;
             if ($old_byte_usage + $new_byte_usage + $beginning_memory_usage > $memory_limit_bytes) {
                 throw new fEnvironmentException('The predicted memory usage to complete the image modifications using the GD extension, %1$s, will most likely exceed the memory limit of %2$s', $old_byte_usage + $new_byte_usage + $beginning_memory_usage, $memory_limit_bytes);
             }
         }
         $new_gd_res = imagecreatetruecolor($mod['width'], $mod['height']);
         if ($save_alpha) {
             imagealphablending($new_gd_res, FALSE);
             imagesavealpha($new_gd_res, TRUE);
             if ($new_type == 'gif') {
                 $transparent = imagecolorallocatealpha($new_gd_res, 255, 255, 255, 127);
                 imagefilledrectangle($new_gd_res, 0, 0, $mod['width'], $mod['height'], $transparent);
                 imagecolortransparent($new_gd_res, $transparent);
             }
         }
         // Perform the resize operation
         if ($mod['operation'] == 'resize') {
             imagecopyresampled($new_gd_res, $gd_res, 0, 0, 0, 0, $mod['width'], $mod['height'], $mod['old_width'], $mod['old_height']);
             // Perform the crop operation
         } elseif ($mod['operation'] == 'crop') {
             imagecopyresampled($new_gd_res, $gd_res, 0, 0, $mod['start_x'], $mod['start_y'], $mod['width'], $mod['height'], $mod['width'], $mod['height']);
             // Perform the desaturate operation
         } elseif ($mod['operation'] == 'desaturate') {
             // Create a palette of grays
             $grays = array();
             for ($i = 0; $i < 256; $i++) {
                 $grays[$i] = imagecolorallocate($new_gd_res, $i, $i, $i);
             }
             $transparent = imagecolorallocatealpha($new_gd_res, 255, 255, 255, 127);
             // Loop through every pixel and convert the rgb values to grays
             for ($x = 0; $x < $mod['width']; $x++) {
                 for ($y = 0; $y < $mod['height']; $y++) {
                     $color = imagecolorat($gd_res, $x, $y);
                     if ($type != 'gif') {
                         $red = $color >> 16 & 0xff;
                         $green = $color >> 8 & 0xff;
                         $blue = $color & 0xff;
                         if ($save_alpha) {
                             $alpha = $color >> 24 & 0x7f;
                         }
                     } else {
                         $color_info = imagecolorsforindex($gd_res, $color);
                         $red = $color_info['red'];
                         $green = $color_info['green'];
                         $blue = $color_info['blue'];
                         $alpha = $color_info['alpha'];
                     }
                     if (!$save_alpha || $alpha != 127) {
                         // Get the appropriate gray (http://en.wikipedia.org/wiki/YIQ)
                         $yiq = round($red * 0.299 + $green * 0.587 + $blue * 0.114);
                         if (!$save_alpha || $alpha == 0) {
                             $new_color = $grays[$yiq];
                         } else {
                             $new_color = imagecolorallocatealpha($new_gd_res, $yiq, $yiq, $yiq, $alpha);
                         }
                     } else {
                         $new_color = $transparent;
                     }
                     imagesetpixel($new_gd_res, $x, $y, $new_color);
                 }
             }
             // Perform the rotate operation
         } elseif ($mod['operation'] == 'rotate') {
             // The imagerotate() function is only available if the PHP-bundled
             // version of GD is used, which is not always the case (e.g. debian/ubuntu)
             if (function_exists('imagerotate')) {
                 // For some reason imagerotate() seem to rotate counter-clockwise
                 if ($mod['degrees'] == 90) {
                     $mod['degrees'] = 270;
                 } elseif ($mod['degrees'] == 270) {
                     $mod['degrees'] = 90;
                 }
                 // If the source image is not true color, we need to convert
                 // to a true color image first, otherwise imagerotate() fails
                 // and returns false, causing no image to be saved
                 if (imagecolorstotal($gd_res)) {
                     imagecopy($new_gd_res, $gd_res, 0, 0, 0, 0, $mod['width'], $mod['height']);
                     imagedestroy($gd_res);
                     $gd_res = $new_gd_res;
                     unset($new_gd_res);
                 }
                 $new_gd_res = imagerotate($gd_res, $mod['degrees'], -1);
                 // If you don't set the alpha mode for PNG, images that
                 // contain transparency and are rotated will be distored
                 // in odd ways
                 if ($new_type == 'png') {
                     imagealphablending($new_gd_res, false);
                     imagesavealpha($new_gd_res, true);
                 }
             } else {
                 switch ($mod['degrees']) {
                     case 90:
                         for ($x = 0; $x < $mod['width']; $x++) {
                             for ($y = 0; $y < $mod['height']; $y++) {
                                 imagecopy($new_gd_res, $gd_res, $mod['height'] - $y - 1, $x, $x, $y, 1, 1);
                             }
                         }
                         break;
                     case 180:
                         // Rather than copying one pixel at a time, like with 90
                         // and 270 degrees, for 180 degrees we can copy one rpw
                         // at a time for better performance
                         for ($x = 0; $x < $mod['width']; $x++) {
                             imagecopy($new_gd_res, $gd_res, $mod['width'] - $x - 1, 0, $x, 0, 1, $mod['height']);
                         }
                         $row = imagecreatetruecolor($mod['width'], 1);
                         for ($y = 0; $y < $mod['height'] / 2; $y++) {
                             imagecopy($row, $new_gd_res, 0, 0, 0, $mod['height'] - $y - 1, $mod['width'], 1);
                             imagecopy($new_gd_res, $new_gd_res, 0, $mod['height'] - $y - 1, 0, $y, $mod['width'], 1);
                             imagecopy($new_gd_res, $row, 0, $y, 0, 0, $mod['width'], 1);
                         }
                         imagedestroy($row);
                         break;
                     case 270:
                         for ($x = 0; $x < $mod['width']; $x++) {
                             for ($y = 0; $y < $mod['height']; $y++) {
                                 imagecopy($new_gd_res, $gd_res, $y, $mod['width'] - $x - 1, $x, $y, 1, 1);
                             }
                         }
                         break;
                 }
             }
         }
         imagedestroy($gd_res);
         $gd_res = $new_gd_res;
     }
     // Save the file
     switch ($new_type) {
         case 'gif':
             imagetruecolortopalette($gd_res, TRUE, 256);
             imagegif($gd_res, $output_file);
             break;
         case 'jpg':
             imagejpeg($gd_res, $output_file, $jpeg_quality);
             break;
         case 'png':
             imagepng($gd_res, $output_file);
             break;
     }
     imagedestroy($gd_res);
 }