Version 4.1.19

This commit is contained in:
Neo committed 2025-12-19 05:38:56 -08:00
1 parent 28bd025b35
commit 2bd5025018
2674 files changed
+233518 -77766

No files matched your search

+79 -52
View File
@@ -2,9 +2,9 @@
/**
* @brief Upload class for Form Builder
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @package IPS Community Suite
* @since 18 Feb 2013
* @version SVN_VERSION_NUMBER
*/
@@ -34,6 +34,7 @@ class _Upload extends FormAbstract
'allowedFileTypes' => array( 'pdf', 'txt' ), // Allowed file extensions. NULL allows any. Default is NULL.
'maxFileSize' => 100, // Maximum file size in megabytes. NULL is no limit. Default is NULL. Note that there *may* be server limitations regardless of this value which are calculated automatically.
'totalMaxSize' => 100, // If this is a "multiple" upload field, the maximum storage space allowed in total in megabytes.
'maxFiles' => NULL, // Maximum number of files that can be uploaded
'postKey' => 'abc', // If provided, uploads will be treated as post attachments using the given post key
'temporary' => TRUE, // If TRUE, the image will not be moved and the filename returned, rather than an \IPS\File object. This should ONLY be used for files which are genuinely
temporary (e.g. importing skins, languages) as the file will be deleted after the script finished executing. Default is FALSE.
@@ -51,6 +52,7 @@ class _Upload extends FormAbstract
'allowedFileTypes' => NULL,
'maxFileSize' => NULL,
'totalMaxSize' => NULL,
'maxFiles' => NULL,
'postKey' => NULL,
'storageExtension' => NULL,
'storageContainer' => NULL,
@@ -79,65 +81,72 @@ class _Upload extends FormAbstract
*
* @see \IPS\Helpers\Form\Abstract::__construct
* @param string $name Name
* @param mixed $defaultValue Default value
* @param bool $required Required?
* @param array $options Type-specific options
* @param callback $customValidationCode Custom validation code
* @param string $prefix HTML to show before input field
* @param string $suffix HTML to show after input field
* @param string $id The ID to add to the row
* @return void
*/
public function __construct( $name )
public function __construct( $name, $defaultValue=NULL, $required=FALSE, $options=array(), $customValidationCode=NULL, $prefix=NULL, $suffix=NULL, $id=NULL )
{
/* What's PHP's upload limit */
$potentialValues = array();
if( (float) ini_get('upload_max_filesize') > 0 )
{
$potentialValues[] = \IPS\File::returnBytes( ini_get('upload_max_filesize') );
}
if( (float) ini_get('post_max_size') > 0 )
{
$potentialValues[] = \IPS\File::returnBytes( ini_get('post_max_size') ) - 1048576;
}
if( (float) ini_get('memory_limit') > 0 )
{
$potentialValues[] = \IPS\File::returnBytes( ini_get('memory_limit') );
}
/* We want the value in MB */
$this->maxChunkSize = min( $potentialValues ) / 1048576;
/* Call parent constructor */
call_user_func_array( 'parent::__construct', func_get_args() );
/* Work out storage extension */
if ( $this->options['postKey'] and !$this->options['storageExtension'] )
if ( isset( $options['postKey'] ) and $options['postKey'] and ( !isset( $options['storageExtension'] ) or !$options['storageExtension'] ) )
{
$this->options['storageExtension'] = 'core_Attachment';
$options['storageExtension'] = 'core_Attachment';
}
if ( !$this->options['storageExtension'] and !$this->options['temporary'] )
if ( ( !isset( $options['storageExtension'] ) or !$options['storageExtension'] ) and ( !isset( $options['temporary'] ) or !$options['temporary'] ) )
{
throw new \InvalidArgumentException;
}
/* Does the storage extension support chunking? */
if ( $this->options['storageExtension'] )
if ( isset( $options['storageExtension'] ) and $options['storageExtension'] )
{
$storageClass = \IPS\File::getClass( $this->options['storageExtension'] );
if( !$storageClass::$supportsChunking and ( $this->options['maxFileSize'] === NULL or $this->maxChunkSize < $this->options['maxFileSize'] ) )
$storageClass = \IPS\File::getClass( $options['storageExtension'] );
if( !$storageClass::$supportsChunking and ( !isset( $options['maxFileSize'] ) or $this->maxChunkSize < $options['maxFileSize'] ) )
{
$this->options['maxFileSize'] = $this->maxChunkSize;
$options['maxFileSize'] = $this->maxChunkSize;
}
}
if( $this->options['maxFileSize'] !== NULL AND $this->options['maxFileSize'] <= 0 )
if( isset( $options['maxFileSize'] ) AND $options['maxFileSize'] <= 0 )
{
throw new \InvalidArgumentException;
}
if( isset( $options['maxFiles'] ) AND $options['maxFiles'] <= 0 )
{
throw new \InvalidArgumentException;
}
/* If this has to be an image, set the allowed file types */
if ( $this->options['image'] !== NULL and !isset( $this->options['image']['optional'] ) and $this->options['allowedFileTypes'] === NULL )
if ( isset( $options['image'] ) and !isset( $options['image']['optional'] ) and !isset( $options['allowedFileTypes'] ) )
{
$this->options['allowedFileTypes'] = \IPS\Image::$imageExtensions;
$options['allowedFileTypes'] = \IPS\Image::$imageExtensions;
}
/* Call parent constructor */
parent::__construct( $name, $defaultValue, $required, $options, $customValidationCode, $prefix, $suffix, $id );
/* Add JS */
if ( \IPS\IN_DEV )
{
@@ -171,7 +180,7 @@ class _Upload extends FormAbstract
}
/* Are we processing an AJAX upload? */
if( isset( $_SERVER['HTTP_X_PLUPLOAD'] ) AND ( $_SERVER['HTTP_X_PLUPLOAD'] == md5( $this->name . session_id() ) ) )
if( isset( $_SERVER['HTTP_X_PLUPLOAD'] ) AND \IPS\Login::compareHashes( $_SERVER['HTTP_X_PLUPLOAD'], md5( $this->name . session_id() ) ) )
{
try
{
@@ -211,6 +220,12 @@ class _Upload extends FormAbstract
try
{
$image = \IPS\Image::create( $fileObj->contents() );
if( $image::exifSupported() )
{
$image->setExifData( $fileObj->contents() );
}
$image->resizeToMax( $options['image']['maxWidth'] ?: NULL, $options['image']['maxHeight'] ?: NULL );
$fileObj->replace( (string) $image );
@@ -219,11 +234,12 @@ class _Upload extends FormAbstract
}
$insertId = \IPS\Db::i()->insert( 'core_files_temp', array(
'upload_key' => md5( $this->name . session_id() ),
'filename' => $fileObj->originalFilename,
'mime' => \IPS\File::getMimeType( $fileObj->originalFilename ),
'contents' => (string) $fileObj,
'time' => time()
'upload_key' => md5( $this->name . session_id() ),
'filename' => $fileObj->originalFilename,
'mime' => \IPS\File::getMimeType( $fileObj->originalFilename ),
'contents' => (string) $fileObj,
'time' => time(),
'storage_extension' => $this->options['storageExtension']
) );
if ( $this->options['callback'] )
@@ -271,7 +287,11 @@ class _Upload extends FormAbstract
{
$message = \IPS\Member::loggedIn()->language()->addToStack("uploaderr_{$e->getMessage()}");
}
else
{
$message = \IPS\Member::loggedIn()->language()->addToStack("uploaderr_unspecified");
}
\IPS\Output::i()->json( array(
'error' => $message,
'extra' => $e->getCode()
@@ -373,7 +393,7 @@ class _Upload extends FormAbstract
$maxFileSize = $this->options['maxFileSize'] ? number_format( $this->options['maxFileSize'], 4, '.', '' ) : $this->options['maxFileSize'];
/* The html() method is called more than once, however $this->value is wiped out so if it was an attachments array all of the array properties are lost */
$this->builtHtml = call_user_func( $this->template, $this->name, $this->value, $this->options['minimize'], $maxFileSize, $this->maxChunkSize, $this->options['totalMaxSize'], $this->options['allowedFileTypes'], $uploadKey, $this->options['multiple'], $this->options['postKey'], $this->options['temporary'] or ( isset( \IPS\Request::i()->cookie['vle_editor'] ) and \IPS\Request::i()->cookie['vle_editor'] ), $this->options['template'], $existing, $this->options['default'] );
$this->builtHtml = call_user_func( $this->template, $this->name, $this->value, $this->options['minimize'], $maxFileSize, $this->options['maxFiles'], $this->maxChunkSize, $this->options['totalMaxSize'], $this->options['allowedFileTypes'], $uploadKey, $this->options['multiple'], $this->options['postKey'], $this->options['temporary'] or ( isset( \IPS\Request::i()->cookie['vle_editor'] ) and \IPS\Request::i()->cookie['vle_editor'] ), $this->options['template'], $existing, $this->options['default'] );
return $this->builtHtml;
}
@@ -444,9 +464,9 @@ class _Upload extends FormAbstract
{
/* Don't delete file if new file upload has same name */
$okToDelete = TRUE;
foreach( $tempFiles as $tid => $path )
foreach( $tempFiles as $tid => $tmpFile )
{
if ( (string) $this->defaultValue[ $id ] == $path )
if ( (string) $this->defaultValue[ $id ] == $tmpFile['contents'] )
{
$okToDelete = FALSE;
}
@@ -471,12 +491,12 @@ class _Upload extends FormAbstract
if ( is_array( $this->defaultValue ) )
{
foreach( $this->defaultValue as $file )
{
{
/* Don't delete file if new file upload has same name */
$okToDelete = TRUE;
foreach( $tempFiles as $id => $path )
foreach( $tempFiles as $id => $tmpFile )
{
if ( (string) $file == $path )
if ( (string) $file == $tmpFile['contents'] )
{
$okToDelete = FALSE;
}
@@ -492,9 +512,9 @@ class _Upload extends FormAbstract
{
/* Don't delete file if new file upload has same name */
$okToDelete = TRUE;
foreach( $tempFiles as $id => $path )
foreach( $tempFiles as $id => $tmpFile )
{
if ( (string) $this->defaultValue == $path )
if ( (string) $this->defaultValue == $tmpFile['contents'] )
{
$okToDelete = FALSE;
}
@@ -594,7 +614,7 @@ class _Upload extends FormAbstract
{
\IPS\File::validateUpload( $file, $this->options['allowedFileTypes'], $this->options['maxFileSize'] );
$ext = mb_substr( $file['name'], ( mb_strrpos( $file['name'], '.' ) + 1 ) );
$ext = mb_strtolower( mb_substr( $file['name'], ( mb_strrpos( $file['name'], '.' ) + 1 ) ) );
/* Don't allow "XSS" in images */
if( in_array( $ext, \IPS\File::$safeFileExtensions ) AND in_array( $ext, \IPS\Image::$imageExtensions ) )
@@ -616,16 +636,22 @@ class _Upload extends FormAbstract
if ( is_array( $this->options['image'] ) )
{
$options = $this->options;
$fileObjects = \IPS\File::createFromUploads( $this->options['storageExtension'], $fieldName, $this->options['allowedFileTypes'], $this->options['maxFileSize'], $this->options['totalMaxSize'], 0, function( $contents ) use ( $options )
{
try
$fileObjects = \IPS\File::createFromUploads( $this->options['storageExtension'], $fieldName, $this->options['allowedFileTypes'], $this->options['maxFileSize'], $this->options['totalMaxSize'], 0, function( $contents, $filename ) use ( $options )
{
$ext = mb_strtolower( mb_substr( $filename, mb_strrpos( $filename, '.' ) + 1 ) );
/* Resize images */
if ( in_array( $ext, \IPS\Image::$imageExtensions ) )
{
$image = \IPS\Image::create( $contents );
$image->resizeToMax( $options['image']['maxWidth'] ?: NULL, $options['image']['maxHeight'] ?: NULL );
return (string) $image;
try
{
$image = \IPS\Image::create( $contents );
$image->resizeToMax( $options['image']['maxWidth'] ?: NULL, $options['image']['maxHeight'] ?: NULL );
return (string) $image;
}
catch ( \Exception $e ) {}
}
catch ( \Exception $e ) {}
return $contents;
}, $this->options['storageContainer'], $this->options['obscure'] );
@@ -634,15 +660,16 @@ class _Upload extends FormAbstract
{
$fileObjects = \IPS\File::createFromUploads( $this->options['storageExtension'], $fieldName, $this->options['allowedFileTypes'], $this->options['maxFileSize'], $this->options['totalMaxSize'], 0, NULL, $this->options['storageContainer'], $this->options['obscure'] );
}
foreach ( $fileObjects as $fileObj )
{
$insertId = \IPS\Db::i()->insert( 'core_files_temp', array(
'upload_key' => md5( $this->name . session_id() ),
'filename' => $fileObj->originalFilename,
'mime' => \IPS\File::getMimeType( $fileObj->originalFilename ),
'contents' => (string) $fileObj,
'time' => time()
'upload_key' => md5( $this->name . session_id() ),
'filename' => $fileObj->originalFilename,
'mime' => \IPS\File::getMimeType( $fileObj->originalFilename ),
'contents' => (string) $fileObj,
'time' => time(),
'storage_extension' => $this->options['storageExtension']
) );
if ( $this->options['callback'] )