Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F800512
in-portal
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, Feb 22, 12:08 AM
Size
19 KB
Mime Type
text/x-diff
Expires
Mon, Feb 24, 12:08 AM (1 h, 35 m)
Engine
blob
Format
Raw Data
Handle
573760
Attached To
rINP In-Portal
in-portal
View Options
Index: branches/5.2.x/core/kernel/utility/formatters/upload_formatter.php
===================================================================
--- branches/5.2.x/core/kernel/utility/formatters/upload_formatter.php (revision 16575)
+++ branches/5.2.x/core/kernel/utility/formatters/upload_formatter.php (revision 16576)
@@ -1,651 +1,653 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2011 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class kUploadFormatter extends kFormatter
{
var $DestinationPath;
var $FullPath;
/**
* File helper reference
*
* @var FileHelper
*/
var $fileHelper = NULL;
/**
* Uploaded files, that are ordered as required (both live & temp images in one list)
*
* @var Array
* @access protected
*/
protected $sorting = Array ();
/**
* Creates formatter instance
*
* @access public
*/
public function __construct()
{
parent::__construct();
$this->fileHelper = $this->Application->recallObject('FileHelper');
if ( $this->DestinationPath ) {
$this->FullPath = FULL_PATH . $this->DestinationPath;
}
}
/**
* Sets field option defaults.
*
* @param string $field_name Field nae.
* @param array $field_options Field options.
* @param kDBBase $object Object.
*
* @return void
*/
public function PrepareOptions($field_name, &$field_options, &$object)
{
if ( !$this->DestinationPath && !isset($field_options['upload_dir']) ) {
$base_path = $this->Application->getUnitOption($object->Prefix, 'BasePath');
$field_options['upload_dir'] = WRITEBALE_BASE . '/' . basename($base_path) . '/';
}
+
+ if ( !isset($field_options['max_size']) ) {
+ $field_options['max_size'] = MAX_UPLOAD_SIZE;
+ }
}
/**
* Processes file uploads from form
*
* @param mixed $value
* @param string $field_name
* @param kDBItem $object
* @return mixed
* @access public
*/
public function Parse($value, $field_name, &$object)
{
$value = $this->Application->HttpQuery->unescapeRequestVariable($value);
$options = $object->GetFieldOptions($field_name);
if ( getArrayValue($options, 'upload_dir') ) {
$this->DestinationPath = $options['upload_dir'];
$this->FullPath = FULL_PATH . $this->DestinationPath;
}
if ( is_array($value) && isset($value['tmp_ids']) ) {
$ret = $this->_processFlashUploader($value, $field_name, $object);
}
else {
$ret = $this->_processRegularUploader($value, $field_name, $object);
}
if ( getArrayValue($options, 'upload_dir') ) {
$this->DestinationPath = null;
$this->FullPath = null;
}
return $ret;
}
/**
* Handles uploaded files, provided by Flash uploader
*
* @param Array|string $value
* @param string $field_name
* @param kDBItem $object
* @return string
* @access protected
*/
protected function _processFlashUploader($value, $field_name, $object)
{
$options = $object->GetFieldOptions($field_name);
$this->sorting = isset($value['order']) ? explode('|', $value['order']) : Array ();
if ( $value['tmp_deleted'] ) {
$n_upload = Array ();
$deleted = explode('|', $value['tmp_deleted']);
$upload = explode('|', $value['upload']);
foreach ($upload as $name) {
if ( in_array($name, $deleted) ) {
continue;
}
$n_upload[] = $name;
}
$value['upload'] = implode('|', $n_upload);
}
if ( !$value['tmp_ids'] ) {
// no pending files -> return already uploaded files
return $this->_sortFiles($value['upload']);
}
$swf_uploaded_ids = explode('|', $value['tmp_ids']);
$swf_uploaded_names = explode('|', $value['tmp_names']);
$existing = $value['upload'] ? explode('|', $value['upload']) : Array ();
$fret = Array ();
$max_files = $this->_getMaxFiles($options);
$pending_actions = $object->getPendingActions();
$files_to_delete = $this->_getFilesToDelete($object);
for ($i = 0; $i < min($max_files, count($swf_uploaded_ids)); $i++) {
// don't delete uploaded file, when it's name matches delete file name
$real_name = $this->_getRealFilename($swf_uploaded_names[$i], $options, $object, $files_to_delete);
$file_name = $this->FullPath . $real_name;
$tmp_file = WRITEABLE . '/tmp/' . $swf_uploaded_ids[$i] . '_' . $swf_uploaded_names[$i];
rename($tmp_file, $file_name);
@chmod($file_name, 0666);
$fret[] = getArrayValue($options, 'upload_dir') ? $real_name : $this->DestinationPath . $real_name;
$pending_actions[] = Array (
'action' => 'make_live', 'id' => $object->GetID(), 'field' => $field_name, 'file' => $file_name
);
$this->_renameFileInSorting($swf_uploaded_names[$i], $real_name);
}
$object->setPendingActions($pending_actions);
return $this->_sortFiles(array_merge($existing, $fret));
}
/**
* Returns files, scheduled for deleting
*
* @param kDBItem $object
* @return Array
* @access protected
*/
protected function _getFilesToDelete($object)
{
$ret = Array ();
foreach ($object->getPendingActions() as $data) {
if ( $data['action'] == 'delete' ) {
$ret[] = $data['file'];
}
}
return $ret;
}
/**
* Handles regular file upload
*
* @param string|Array $value
* @param string $field_name
* @param kDBItem $object
* @return string
* @access protected
*/
protected function _processRegularUploader($value, $field_name, $object)
{
$ret = !is_array($value) ? $value : '';
$options = $object->GetFieldOptions($field_name);
if ( getArrayValue($value, 'upload') && getArrayValue($value, 'error') == UPLOAD_ERR_NO_FILE ) {
// file was not uploaded this time, but was uploaded before, then use previously uploaded file (from db)
return getArrayValue($value, 'upload');
}
if ( is_array($value) && count($value) > 1 && $value['size'] ) {
if ( is_array($value) && (int)$value['error'] === UPLOAD_ERR_OK ) {
- $max_file_size = isset($options['max_size']) ? $options['max_size'] : MAX_UPLOAD_SIZE;
-
// we can get mime type based on file content and don't use one, provided by the client
// $value['type'] = kUtil::mimeContentType($value['tmp_name']);
if ( getArrayValue($options, 'file_types') && !$this->extensionMatch($value['name'], $options['file_types']) ) {
// match by file extensions
$error_params = Array (
'file_name' => $value['name'],
'file_types' => $options['file_types'],
);
$object->SetError($field_name, 'bad_file_format', 'la_error_InvalidFileFormat', $error_params);
}
elseif ( getArrayValue($options, 'allowed_types') && !in_array($value['type'], $options['allowed_types']) ) {
// match by mime type provided by web-browser
$error_params = Array (
'file_type' => $value['type'],
'allowed_types' => $options['allowed_types'],
);
$object->SetError($field_name, 'bad_file_format', 'la_error_InvalidFileFormat', $error_params);
}
- elseif ( $value['size'] > $max_file_size ) {
+ elseif ( $value['size'] > $options['max_size'] ) {
$object->SetError($field_name, 'bad_file_size', 'la_error_FileTooLarge');
}
elseif ( !is_writable($this->FullPath) ) {
$object->SetError($field_name, 'cant_save_file', 'la_error_cant_save_file');
}
else {
$real_name = $this->_getRealFilename($value['name'], $options, $object);
$file_name = $this->FullPath . $real_name;
$storage_format = isset($options['storage_format']) ? $options['storage_format'] : false;
if ( $storage_format ) {
/** @var ImageHelper $image_helper */
$image_helper = $this->Application->recallObject('ImageHelper');
move_uploaded_file($value['tmp_name'], $value['tmp_name'] . '.jpg'); // add extension, so ResizeImage can work
$url = $image_helper->ResizeImage($value['tmp_name'] . '.jpg', $storage_format);
$tmp_name = preg_replace('/^' . preg_quote($this->Application->BaseURL(), '/') . '/', '/', $url);
$moved = rename($tmp_name, $file_name);
}
else {
$moved = move_uploaded_file($value['tmp_name'], $file_name);
}
if ( !$moved ) {
$object->SetError($field_name, 'cant_save_file', 'la_error_cant_save_file');
}
else {
@chmod($file_name, 0666);
if ( getArrayValue($options, 'size_field') ) {
$object->SetDBField($options['size_field'], $value['size']);
}
if ( getArrayValue($options, 'orig_name_field') ) {
$object->SetDBField($options['orig_name_field'], $value['name']);
}
if ( getArrayValue($options, 'content_type_field') ) {
$object->SetDBField($options['content_type_field'], $value['type']);
}
$ret = getArrayValue($options, 'upload_dir') ? $real_name : $this->DestinationPath . $real_name;
// delete previous file, when new file is uploaded under same field
/*$previous_file = isset($value['upload']) ? $value['upload'] : false;
if ( $previous_file && file_exists($this->FullPath . $previous_file) ) {
unlink($this->FullPath . $previous_file);
}*/
}
}
}
else {
$object->SetError($field_name, 'cant_save_file', 'la_error_cant_save_file');
}
}
if ( (count($value) > 1) && $value['error'] && ($value['error'] != UPLOAD_ERR_NO_FILE) ) {
$object->SetError($field_name, 'cant_save_file', 'la_error_cant_save_file', $value);
}
return $ret;
}
/**
* Checks, that given file name has on of provided file extensions
*
* @param string $filename
* @param string $file_types
* @return bool
* @access protected
*/
protected function extensionMatch($filename, $file_types)
{
if ( preg_match_all('/\*\.(.*?)(;|$)/', $file_types, $regs) ) {
$file_extension = mb_strtolower(pathinfo($filename, PATHINFO_EXTENSION));
$file_extensions = array_map('mb_strtolower', $regs[1]);
return in_array($file_extension, $file_extensions);
}
return true;
}
/**
* Resorts uploaded files according to given file order
*
* @param Array|string $files
* @return string
* @access protected
*/
protected function _sortFiles($files)
{
if ( !is_array($files) ) {
$files = explode('|', $files);
}
$sorted_files = array_intersect($this->sorting, $files); // removes deleted files from sorting
$new_files = array_diff($files, $sorted_files); // files, that weren't sorted - add to the end
return implode('|', array_merge($sorted_files, $new_files));
}
/**
* Returns maximal allowed file count per field
*
* @param Array $options
* @return int
* @access protected
*/
protected function _getMaxFiles($options)
{
if ( !isset($options['multiple']) ) {
return 1;
}
return $options['multiple'] == false ? 1 : $options['multiple'];
}
/**
* Returns final filename after applying storage-engine specific naming
*
* @param string $file_name
* @param Array $options
* @param kDBItem $object
* @param Array $files_to_delete
* @return string
* @access protected
*/
protected function _getRealFilename($file_name, $options, $object, $files_to_delete = Array ())
{
$real_name = $this->getStorageEngineFile($file_name, $options, $object->Prefix);
$real_name = $this->getStorageEngineFolder($real_name, $options) . $real_name;
return $this->fileHelper->ensureUniqueFilename($this->FullPath, $real_name, $files_to_delete);
}
/**
* Renames file in sorting list
*
* @param string $old_name
* @param string $new_name
* @return void
* @access protected
*/
protected function _renameFileInSorting($old_name, $new_name)
{
$index = array_search($old_name, $this->sorting);
if ( $index !== false ) {
$this->sorting[$index] = $new_name;
}
}
function getSingleFormat($format)
{
$single_mapping = Array (
'file_raw_urls' => 'raw_url',
'file_display_names' => 'display_name',
'file_urls' => 'full_url',
'file_paths' => 'full_path',
'file_sizes' => 'file_size',
'files_resized' => 'resize',
'img_sizes' => 'img_size',
'wms' => 'wm',
);
return $single_mapping[$format];
}
/**
* Return formatted file url,path or size (or same for multiple files)
*
* @param string $value
* @param string $field_name
* @param kDBItem|kDBList $object
* @param string $format
* @return string
*/
function Format($value, $field_name, &$object, $format = NULL)
{
if ( is_null($value) ) {
return '';
}
$options = $object->GetFieldOptions($field_name);
if ( !isset($format) ) {
$format = isset($options['format']) ? $options['format'] : false;
}
if ( $format && preg_match('/(file_raw_urls|file_display_names|file_urls|file_paths|file_names|file_sizes|img_sizes|files_resized|wms)(.*)/', $format, $regs) ) {
if ( !$value || $format == 'file_names' ) {
// storage format matches display format OR no value
return $value;
}
$ret = Array ();
$files = explode('|', $value);
$format = $this->getSingleFormat($regs[1]) . $regs[2];
foreach ($files as $a_file) {
$ret[] = $this->GetFormatted($a_file, $field_name, $object, $format);
}
return implode('|', $ret);
}
$tc_value = $this->TypeCast($value, $options);
if ( ($tc_value === false) || ($tc_value != $value) ) {
// for leaving badly formatted date on the form
return $value;
}
return $this->GetFormatted($tc_value, $field_name, $object, $format);
}
/**
* Return formatted file url,path or size
*
* @param string $value
* @param string $field_name
* @param kDBItem $object
* @param string $format
* @return string
*/
function GetFormatted($value, $field_name, &$object, $format = NULL)
{
if ( !$format ) {
return $value;
}
$options = $object->GetFieldOptions($field_name);
$upload_dir = isset($options['include_path']) && $options['include_path'] ? '' : $this->getUploadDir($options);
$file_path = strlen($value) ? FULL_PATH . str_replace('/', DIRECTORY_SEPARATOR, $upload_dir) . $value : '';
if ( preg_match('/resize:([\d]*)x([\d]*)/', $format, $regs) ) {
/** @var ImageHelper $image_helper */
$image_helper = $this->Application->recallObject('ImageHelper');
try {
return $image_helper->ResizeImage($file_path, $format);
}
catch ( RuntimeException $e ) {
// error, during image resize -> return empty string
return '';
}
}
elseif ( !strlen($file_path) || !file_exists($file_path) ) {
// file doesn't exist OR not uploaded
return '';
}
switch ($format) {
case 'display_name':
return kUtil::removeTempExtension($value);
break;
case 'raw_url':
return $this->fileHelper->pathToUrl($file_path);
break;
case 'full_url':
$direct_links = isset($options['direct_links']) ? $options['direct_links'] : true;
if ( $direct_links ) {
return $this->fileHelper->pathToUrl($file_path);
}
else {
$url_params = Array (
'pass' => 'm,'.$object->Prefix,
$object->Prefix . '_event' => 'OnViewFile',
'file' => $value, 'field' => $field_name
);
return $this->Application->HREF('', '', $url_params);
}
break;
case 'full_path':
return $file_path;
break;
case 'file_size':
return filesize($file_path);
break;
case 'img_size':
/** @var ImageHelper $image_helper */
$image_helper = $this->Application->recallObject('ImageHelper');
$image_info = $image_helper->getImageInfo($file_path);
return $image_info ? $image_info[3] : '';
break;
}
return sprintf($format, $value);
}
/**
* Creates & returns folder, based on storage engine specified in field options
*
* @param string $file_name
* @param array $options
* @return string
* @access protected
* @throws Exception
*/
protected function getStorageEngineFolder($file_name, $options)
{
$storage_engine = (string)getArrayValue($options, 'storage_engine');
if ( !$storage_engine ) {
return '';
}
switch ($storage_engine) {
case StorageEngine::HASH:
$folder_path = kUtil::getHashPathForLevel($file_name);
break;
case StorageEngine::TIMESTAMP:
$folder_path = adodb_date('Y-m/d/');
break;
default:
throw new Exception('Unknown storage engine "<strong>' . $storage_engine . '</strong>".');
break;
}
return $folder_path;
}
/**
* Applies prefix & suffix to uploaded filename, based on storage engine in field options
*
* @param string $name
* @param array $options
* @param string $unit_prefix
* @return string
* @access protected
*/
protected function getStorageEngineFile($name, $options, $unit_prefix)
{
$prefix = $this->getStorageEngineFilePart(getArrayValue($options, 'filename_prefix'), $unit_prefix);
$suffix = $this->getStorageEngineFilePart(getArrayValue($options, 'filename_suffix'), $unit_prefix);
$parts = pathinfo($name);
return ($prefix ? $prefix . '_' : '') . $parts['filename'] . ($suffix ? '_' . $suffix : '') . '.' . $parts['extension'];
}
/**
* Creates prefix/suffix to join with uploaded file
*
* Added "u" before user_id to keep this value after FileHelper::ensureUniqueFilename method call
*
* @param string $option
* @param string $unit_prefix
* @return string
* @access protected
*/
protected function getStorageEngineFilePart($option, $unit_prefix)
{
$replace_from = Array (
StorageEngine::PS_DATE_TIME, StorageEngine::PS_PREFIX, StorageEngine::PS_USER
);
$replace_to = Array (
adodb_date('Ymd-His'), $unit_prefix, 'u' . $this->Application->RecallVar('user_id')
);
return str_replace($replace_from, $replace_to, $option);
}
public function getUploadDir($options)
{
return isset($options['upload_dir']) ? $options['upload_dir'] : $this->DestinationPath;
}
}
class kPictureFormatter extends kUploadFormatter
{
public function __construct()
{
$this->NakeLookupPath = IMAGES_PATH; // used ?
$this->DestinationPath = kUtil::constOn('ADMIN') ? IMAGES_PENDING_PATH : IMAGES_PATH;
parent::__construct();
}
/**
* Return formatted file url,path or size
*
* @param string $value
* @param string $field_name
* @param kDBItem $object
* @param string $format
* @return string
*/
function GetFormatted($value, $field_name, &$object, $format = NULL)
{
if ( $format == 'img_size' ) {
$options = $object->GetFieldOptions($field_name);
$img_path = FULL_PATH . '/' . $this->getUploadDir($options) . $value;
$image_info = getimagesize($img_path);
return ' ' . $image_info[3];
}
return parent::GetFormatted($value, $field_name, $object, $format);
}
}
Event Timeline
Log In to Comment