public function testAppendRollback()
 {
     fFilesystem::begin();
     $file = new fFile('output/fFile/one.txt');
     $file->append('+one=two');
     $this->assertEquals('one+one=two', file_get_contents('output/fFile/one.txt'));
     fFilesystem::rollback();
     $this->assertEquals('one', file_get_contents('output/fFile/one.txt'));
 }
 /**
  * Generates a new filename in an attempt to create a unique name
  * 
  * @param  string $filename  The filename to generate another name for
  * @return string  The newly generated filename
  */
 private function generateNewFilename($filename)
 {
     $filename_info = fFilesystem::getPathInfo($filename);
     if (preg_match('#_copy(\\d+)($|\\.)#D', $filename_info['filename'], $match)) {
         $i = $match[1] + 1;
     } else {
         $i = 1;
     }
     $extension = $filename_info['extension'] ? '.' . $filename_info['extension'] : '';
     return preg_replace('#_copy\\d+$#D', '', $filename_info['filename']) . '_copy' . $i . $extension;
 }
 /**
  * @dataProvider convertToBytesProvider
  */
 public function testConvertToBytes($input, $output)
 {
     $this->assertEquals($output, fFilesystem::convertToBytes($input));
 }
Example #4
0
 /**
  * Rolls back a filesystem transaction, it is safe to rollback when no transaction is in progress
  * 
  * @return void
  */
 public static function rollback()
 {
     if (self::$rollback_operations === NULL) {
         return;
     }
     self::$rollback_operations = array_reverse(self::$rollback_operations);
     foreach (self::$rollback_operations as $operation) {
         switch ($operation['action']) {
             case 'append':
                 $current_length = filesize($operation['filename']);
                 $handle = fopen($operation['filename'], 'r+');
                 ftruncate($handle, $current_length - $operation['length']);
                 fclose($handle);
                 break;
             case 'delete':
                 self::updateDeletedMap($operation['filename'], debug_backtrace());
                 unlink($operation['filename']);
                 fFilesystem::updateFilenameMap($operation['filename'], '*DELETED at ' . time() . ' with token ' . uniqid('', TRUE) . '* ' . $operation['filename']);
                 break;
             case 'write':
                 file_put_contents($operation['filename'], $operation['old_data']);
                 break;
             case 'rename':
                 fFilesystem::updateFilenameMap($operation['new_name'], $operation['old_name']);
                 rename($operation['new_name'], $operation['old_name']);
                 break;
         }
     }
     // All files to be deleted should have their backtraces erased
     foreach (self::$commit_operations as $operation) {
         if (isset($operation['object'])) {
             self::updateDeletedMap($operation['object']->getPath(), NULL);
             fFilesystem::updateFilenameMap($operation['object']->getPath(), preg_replace('#*DELETED at \\d+ with token [\\w.]+* #', '', $operation['filename']));
         }
     }
     self::$commit_operations = NULL;
     self::$rollback_operations = NULL;
 }
<?php

define('MY_ROOT', realpath(dirname(__FILE__) . '/../'));
include MY_ROOT . '/inc/init.php';
//header('Content-type: application/json; charset=utf-8');
///////////////// PACHUBE ///////////////////
// create a new cURL resource
$ch = curl_init();
// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, "http://radiation.crowdmap.com/feed/");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
// grab URL and pass it to the browser
$output = curl_exec($ch);
try {
    $file = new fFile(DOC_ROOT . '/feeds/crowdmapStatic.xml');
} catch (fExpectedException $e) {
    $file = fFilesystem::createObject(DOC_ROOT . '/feeds/crowdmapStatic.xml');
}
$file->write($output);
// close cURL resource, and free up system resources
curl_close($ch);
echo $output;
?>


 /**
  * Performs a [http://php.net/scandir scandir()] on a directory, removing the `.` and `..` entries
  * 
  * If the `$filter` looks like a valid PCRE pattern - matching delimeters
  * (a delimeter can be any non-alphanumeric, non-backslash, non-whitespace
  * character) followed by zero or more of the flags `i`, `m`, `s`, `x`,
  * `e`, `A`, `D`,  `S`, `U`, `X`, `J`, `u` - then
  * [http://php.net/preg_match `preg_match()`] will be used.
  * 
  * Otherwise the `$filter` will do a case-sensitive match with `*` matching
  * zero or more characters and `?` matching a single character.
  * 
  * On all OSes (even Windows), directories will be separated by `/`s when
  * comparing with the `$filter`.
  * 
  * @param  string $filter  A PCRE or glob pattern to filter files/directories by path - directories can be detected by checking for a trailing / (even on Windows)
  * @return array  The fFile (or fImage) and fDirectory objects for the files/directories in this directory
  */
 public function scan($filter = NULL)
 {
     $this->tossIfDeleted();
     $files = array_diff(scandir($this->directory), array('.', '..'));
     $objects = array();
     if ($filter && !preg_match('#^([^a-zA-Z0-9\\\\\\s]).*\\1[imsxeADSUXJu]*$#D', $filter)) {
         $filter = '#^' . strtr(preg_quote($filter, '#'), array('\\*' => '.*', '\\?' => '.')) . '$#D';
     }
     natcasesort($files);
     foreach ($files as $file) {
         if ($filter) {
             $test_path = is_dir($this->directory . $file) ? $file . '/' : $file;
             if (!preg_match($filter, $test_path)) {
                 continue;
             }
         }
         $objects[] = fFilesystem::createObject($this->directory . $file);
     }
     return $objects;
 }
Example #7
0
 /**
  * Performs a [http://php.net/scandir scandir()] on a directory, removing the `.` and `..` entries
  * 
  * @param  string $regex_filter  A PCRE to filter files/directories by path, directories can be detected by checking for a trailing / (even on Windows)
  * @return array  The fFile (or fImage) and fDirectory objects for the files/directories in this directory
  */
 public function scan($regex_filter = NULL)
 {
     $this->tossIfException();
     $files = array_diff(scandir($this->directory), array('.', '..'));
     $objects = array();
     foreach ($files as $file) {
         $file = $this->directory . $file;
         if ($regex_filter) {
             $test_path = is_dir($file) ? $file . '/' : $file;
             if (!preg_match($regex_filter, $test_path)) {
                 continue;
             }
         }
         $objects[] = fFilesystem::createObject($file);
     }
     return $objects;
 }
Example #8
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 #9
0
 /**
  * Writes the provided data to the file
  * 
  * Requires all previous data to be stored in memory if inside a
  * transaction, use with caution on large files!
  * 
  * If a filesystem transaction is in progress and is rolled back, the
  * previous data will be restored.
  * 
  * @param  mixed $data  The data to write to the file
  * @return fFile  The file object, to allow for method chaining
  */
 public function write($data)
 {
     $this->tossIfDeleted();
     if (!$this->isWritable()) {
         throw new fEnvironmentException('This file, %s, can not be written to because it is not writable', $this->file);
     }
     // Allow filesystem transactions
     if (fFilesystem::isInsideTransaction()) {
         fFilesystem::recordWrite($this);
     }
     file_put_contents($this->file, $data);
     return $this;
 }
Example #10
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 #11
0
 /**
  * Adds an attachment to the email
  * 
  * If a duplicate filename is detected, it will be changed to be unique.
  * 
  * @param  string $filename   The name of the file to attach
  * @param  string $mime_type  The mime type of the file
  * @param  string $contents   The contents of the file
  * @return void
  */
 public function addAttachment($filename, $mime_type, $contents)
 {
     if (!self::stringlike($filename)) {
         throw new fProgrammerException('The filename specified, %s, does not appear to be a valid filename', $filename);
     }
     $filename = (string) $filename;
     $i = 1;
     while (isset($this->attachments[$filename])) {
         $filename_info = fFilesystem::getPathInfo($filename);
         $extension = $filename_info['extension'] ? '.' . $filename_info['extension'] : '';
         $filename = preg_replace('#_copy\\d+$#D', '', $filename_info['filename']) . '_copy' . $i . $extension;
         $i++;
     }
     $this->attachments[$filename] = array('mime-type' => $mime_type, 'contents' => $contents);
 }
Example #12
0
 /**
  * Rolls back a filesystem transaction, it is safe to rollback when no transaction is in progress
  * 
  * @return void
  */
 public static function rollback()
 {
     self::$rollback_operations = array_reverse(self::$rollback_operations);
     foreach (self::$rollback_operations as $operation) {
         switch ($operation['action']) {
             case 'delete':
                 self::updateExceptionMap($operation['filename'], new fProgrammerException('The action requested can not be performed because the file has been deleted'));
                 unlink($operation['filename']);
                 break;
             case 'write':
                 file_put_contents($operation['filename'], $operation['old_data']);
                 break;
             case 'rename':
                 fFilesystem::updateFilenameMap($operation['new_name'], $operation['old_name']);
                 rename($operation['new_name'], $operation['old_name']);
                 break;
         }
     }
     // All files to be deleted should have their exceptions erased
     foreach (self::$commit_operations as $operation) {
         if (isset($operation['object'])) {
             self::updateExceptionMap($operation['object']->getPath(), NULL);
         }
     }
     self::$commit_operations = NULL;
     self::$rollback_operations = NULL;
 }
Example #13
0
 /**
  * Sends a message via the SMTP server
  * 
  * @internal
  * 
  * @throws fValidationException  When the message is too large for the server
  * 
  * @param string $from     The email address being sent from - this will be used as the `Return-Path` header
  * @param array  $to       All of the To, Cc and Bcc email addresses to send the message to - this does not affect the message headers in any way
  * @param string $headers  The message headers - the Bcc header will be removed if present
  * @param string $body     The mail body
  * @return void
  */
 public function send($from, $to, $headers, $body)
 {
     $this->connect();
     // Lines starting with . need to start with two .s because the leading
     // . will be stripped
     $body = preg_replace('#^\\.#m', '..', $body);
     // Removed the Bcc header incase the SMTP server doesn't
     $headers = preg_replace('#^Bcc:(.*?)\\r\\n([^ ])#mi', '\\2', $headers);
     // Add the Date header
     $headers = "Date: " . date('D, j M Y H:i:s O') . "\r\n" . $headers;
     $data = $headers . "\r\n\r\n" . $body;
     if ($this->max_size && strlen($data) > $this->max_size) {
         throw new fValidationException('The email provided is %1$s, which is larger than the maximum size of %2$s that the server supports', fFilesystem::formatFilesize(strlen($data)), fFilesystem::formatFilesize($this->max_size));
     }
     $mail_from = "MAIL FROM:<" . $from . ">";
     if ($this->pipelining) {
         $expect = 2;
         $rcpt_to = '';
         foreach ($to as $email) {
             $rcpt_to .= "RCPT TO:<" . $email . ">\r\n";
             $expect++;
         }
         $rcpt_to = trim($rcpt_to);
         $this->write($mail_from . "\r\n" . $rcpt_to . "\r\nDATA\r\n", $expect);
     } else {
         $this->write($mail_from, 1);
         foreach ($to as $email) {
             $this->write("RCPT TO:<" . $email . ">", 1);
         }
         $this->write('DATA', 1);
     }
     $this->write($data . "\r\n.\r\n", 1);
     $this->write('RSET', 1);
 }
Example #14
0
foreach ($flickrFeeds as $feed) {
    $ch = curl_init();
    // set URL and other appropriate options
    curl_setopt($ch, CURLOPT_URL, $feed);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    $data = curl_exec($ch);
    // execute curl session
    $data = str_replace('jsonFlickrApi(', '', $data);
    $data = substr($data, 0, strlen($data) - 1);
    //strip out last paren
    $object = json_decode($data);
    // stdClass object
    $items = $object->photos->photo;
    foreach ($items as $item) {
        $newFeed .= '{"title": "' . $item->title . '","title_jp": "","description": "' . $item->tags . '","creator": "probe","feed": "http://api.flickr.com/services/rest","location": {"lon":' . $item->longitude . ', "lat":' . $item->latitude . ', "name": ""},"id":"' . $item->owner . '","datastreams": [{"at": "' . $item->datetaken . '","max_value": "0","min_value": "0","current_value": "' . $item->url_m . '","id": "1","unit": {"type": "photo","label": "photo","symbol": "photo"}}]},';
    }
    curl_close($ch);
    $total += count($items);
}
$newFeed = substr($newFeed, 0, strlen($newFeed) - 1);
//strip out last comma
$newFeed .= '], "itemsPerPage": ' . $total . ', "startIndex": 0, "totalResults": ' . $total . '}';
try {
    $file = new fFile(DOC_ROOT . '/feeds/probe002.json');
} catch (fExpectedException $e) {
    $file = fFilesystem::createObject(DOC_ROOT . '/feeds/probe002.json');
}
$file->write($newFeed);
// close cURL resource, and free up system resources
print_r($newFeed);
Example #15
0
 /**
  * Uploads a file
  * 
  * @internal
  * 
  * @param  fActiveRecord $object            The fActiveRecord instance
  * @param  array         &$values           The current values
  * @param  array         &$old_values       The old values
  * @param  array         &$related_records  Any records related to this record
  * @param  array         &$cache            The cache array for the record
  * @param  string        $method_name       The method that was called
  * @param  array         $parameters        The parameters passed to the method
  * @return fFile  The uploaded file
  */
 public static function upload($object, &$values, &$old_values, &$related_records, &$cache, $method_name, $parameters)
 {
     $class = get_class($object);
     list($action, $column) = fORM::parseMethod($method_name);
     $existing_temp_file = FALSE;
     // Try to upload the file putting it in the temp dir incase there is a validation problem with the record
     try {
         $upload_dir = self::$file_upload_columns[$class][$column];
         $temp_dir = self::prepareTempDir($upload_dir);
         if (!fUpload::check($column)) {
             throw new fExpectedException('Please upload a file');
         }
         $uploader = self::setUpFUpload($class, $column);
         $file = $uploader->move($temp_dir, $column);
         // If there was an eror, check to see if we have an existing file
     } catch (fExpectedException $e) {
         // If there is an existing file and none was uploaded, substitute the existing file
         $existing_file = fRequest::get('existing-' . $column);
         $delete_file = fRequest::get('delete-' . $column, 'boolean');
         $no_upload = $e->getMessage() == self::compose('Please upload a file');
         if ($existing_file && $delete_file && $no_upload) {
             $file = NULL;
         } elseif ($existing_file) {
             $file_path = $upload_dir->getPath() . $existing_file;
             $file = fFilesystem::createObject($file_path);
             $current_file = $values[$column];
             // If the existing file is the same as the current file, we can just exit now
             if ($current_file && $file->getPath() == $current_file->getPath()) {
                 return;
             }
             $existing_temp_file = TRUE;
         } else {
             $file = NULL;
         }
     }
     // Assign the file
     fActiveRecord::assign($values, $old_values, $column, $file);
     // Perform the file upload inheritance
     if (!empty(self::$column_inheritence[$class][$column])) {
         foreach (self::$column_inheritence[$class][$column] as $other_column) {
             if ($file) {
                 // Image columns will only inherit if it is an fImage object
                 if (!$file instanceof fImage && isset(self::$image_upload_columns[$class][$other_column])) {
                     continue;
                 }
                 $other_upload_dir = self::$file_upload_columns[$class][$other_column];
                 $other_temp_dir = self::prepareTempDir($other_upload_dir);
                 if ($existing_temp_file) {
                     $other_file = fFilesystem::createObject($other_temp_dir->getPath() . $file->getName());
                 } else {
                     $other_file = $file->duplicate($other_temp_dir, FALSE);
                 }
             } else {
                 $other_file = $file;
             }
             fActiveRecord::assign($values, $old_values, $other_column, $other_file);
             if (!$existing_temp_file && $other_file) {
                 self::processImage($class, $other_column, $other_file);
             }
         }
     }
     // Process the file
     if (!$existing_temp_file && $file) {
         self::processImage($class, $column, $file);
     }
     return $file;
 }
Example #16
0
 /**
  * Combines an array of CSS or JS files and places them as a single file
  *
  * @param string $type     The type of compilation, 'css' or 'js'
  * @param string $element  The element name
  * @param array  $values   An array of file paths
  * @return void
  */
 protected function handleMinified($type, $element, $values)
 {
     $paths = array();
     $media = NULL;
     foreach ($values as $value) {
         if (is_array($value)) {
             $paths[] = $this->minification_prefix . $value['path'];
             if ($type == 'css') {
                 $media = !empty($value['media']) ? $value['media'] : NULL;
             }
         } else {
             $paths[] = $this->minification_prefix . $value;
         }
     }
     $hash = sha1(join('|', $paths));
     $cache_file = $this->minification_directory . $hash . '.' . $type;
     $regenerate = FALSE;
     $checked_paths = FALSE;
     if (!file_exists($cache_file)) {
         $regenerate = TRUE;
     } elseif ($this->minification_mode == 'development') {
         $cache_mtime = filemtime($cache_file);
         $checked_paths = TRUE;
         foreach ($paths as $path) {
             if (!file_exists($path)) {
                 throw new fEnvironmentException('The file specified, %s, does not exist under the $path_prefix specified', preg_replace('#^' . preg_quote($this->minification_prefix, '#') . '#', '', $path));
             }
             if (filemtime($path) > $cache_mtime) {
                 $regenerate = TRUE;
                 break;
             }
         }
     }
     if ($regenerate) {
         $minified = '';
         foreach ($paths as $path) {
             $path_cache_file = $this->minification_directory . sha1($path) . '.' . $type;
             if ($checked_paths && !file_exists($path)) {
                 throw new fEnvironmentException('The file specified, %s, does not exist under the $path_prefix specified', preg_replace('#^' . preg_quote($this->minification_prefix, '#') . '#', '', $path));
             }
             // Checks if this path has been cached
             if (file_exists($path_cache_file) && filemtime($path_cache_file) >= filemtime($path)) {
                 $minified_path = file_get_contents($path_cache_file);
             } else {
                 $minified_path = trim($this->minify(file_get_contents($path), $type));
                 file_put_contents($path_cache_file, $minified_path);
             }
             $minified .= "\n" . $minified_path;
         }
         file_put_contents($cache_file, substr($minified, 1));
     }
     $version = filemtime($cache_file);
     $compiled_value = fFilesystem::translateToWebPath($cache_file) . '?v=' . $version;
     if ($type == 'css' && $media) {
         $compiled_value = array('path' => $compiled_value, 'media' => $media);
     }
     $method = 'place' . strtoupper($type);
     $this->{$method}($compiled_value);
 }
Example #17
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 .');
         }
     }
     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']);
             }
         }
     }
 }
Example #18
0
 /**
  * Saves any changes to the image
  * 
  * If the file type is different than the current one, removes the current
  * file once the new one is created.
  * 
  * This operation will be reverted by a filesystem transaction being rolled
  * back. If a transaction is in progress and the new image type causes a
  * new file to be created, the old file will not be deleted until the
  * transaction is committed.
  * 
  * @param  string  $new_image_type  The new file format for the image: 'NULL` (no change), `'jpg'`, `'gif'`, `'png'`
  * @param  integer $jpeg_quality    The quality setting to use for JPEG images - this may be ommitted
  * @param  boolean $overwrite       If an existing file with the same name and extension should be overwritten
  * @param  string  :$new_image_type
  * @param  boolean :$overwrite
  * @return fImage  The image object, to allow for method chaining
  */
 public function saveChanges($new_image_type = NULL, $jpeg_quality = 90, $overwrite = FALSE)
 {
     // This allows ommitting the $jpeg_quality parameter, which is very useful for non-jpegs
     $args = func_get_args();
     if (count($args) == 2 && is_bool($args[1])) {
         $overwrite = $args[1];
         $jpeg_quality = 90;
     }
     $this->tossIfDeleted();
     self::determineProcessor();
     if (self::$processor == 'none') {
         throw new fEnvironmentException("The changes to the image can't be saved because neither the GD extension or ImageMagick appears to be installed on the server");
     }
     $type = self::getImageType($this->file);
     if ($type == 'tif' && self::$processor == 'gd') {
         throw new fEnvironmentException('The image specified, %s, is a TIFF file and the GD extension can not handle TIFF files. Please install ImageMagick if you wish to manipulate TIFF files.', $this->file);
     }
     $valid_image_types = array('jpg', 'gif', 'png');
     if ($new_image_type !== NULL && !in_array($new_image_type, $valid_image_types)) {
         throw new fProgrammerException('The new image type specified, %1$s, is invalid. Must be one of: %2$s.', $new_image_type, join(', ', $valid_image_types));
     }
     if (is_numeric($jpeg_quality)) {
         $jpeg_quality = (int) round($jpeg_quality);
     }
     if (!is_integer($jpeg_quality) || $jpeg_quality < 1 || $jpeg_quality > 100) {
         throw new fProgrammerException('The JPEG quality specified, %1$s, is either not an integer, less than %2$s or greater than %3$s.', $jpeg_quality, 1, 100);
     }
     if ($new_image_type && fFilesystem::getPathInfo($this->file, 'extension') != $new_image_type) {
         if ($overwrite) {
             $path_info = fFilesystem::getPathInfo($this->file);
             $output_file = $path_info['dirname'] . $path_info['filename'] . '.' . $new_image_type;
         } else {
             $output_file = fFilesystem::makeUniqueName($this->file, $new_image_type);
         }
         if (file_exists($output_file)) {
             if (!is_writable($output_file)) {
                 throw new fEnvironmentException('Changes to the image can not be saved because the file, %s, is not writable', $output_file);
             }
         } else {
             $output_dir = dirname($output_file);
             if (!is_writable($output_dir)) {
                 throw new fEnvironmentException('Changes to the image can not be saved because the directory to save the new file, %s, is not writable', $output_dir);
             }
         }
     } else {
         $output_file = $this->file;
         if (!is_writable($output_file)) {
             throw new fEnvironmentException('Changes to the image can not be saved because the file, %s, is not writable', $output_file);
         }
     }
     // If we don't have any changes and no name change, just exit
     if (!$this->pending_modifications && $output_file == $this->file) {
         return $this;
     }
     // Wrap changes to the image into the filesystem transaction
     if ($output_file == $this->file && fFilesystem::isInsideTransaction()) {
         fFilesystem::recordWrite($this);
     }
     if (self::$processor == 'gd') {
         $this->processWithGD($output_file, $jpeg_quality);
     } elseif (self::$processor == 'imagemagick') {
         $this->processWithImageMagick($output_file, $jpeg_quality);
     }
     $old_file = $this->file;
     fFilesystem::updateFilenameMap($this->file, $output_file);
     // If we created a new image, delete the old one
     if ($output_file != $old_file) {
         $old_image = new fImage($old_file);
         $old_image->delete();
     }
     $this->pending_modifications = array();
     return $this;
 }