1
0
mirror of https://github.com/phpbb/phpbb.git synced 2025-05-05 07:07:51 +02:00

Merge pull request #3727 from marc1706/ticket/13904

[ticket/13904] Refactor attachments functions into service

* marc1706/ticket/13904: (66 commits)
  [ticket/13904] Use filespec's get_filesize instead of calling filesize()
  [ticket/13904] Set properties to protected where possible in filespec
  [ticket/13904] Fix tests after changes to factory
  [ticket/13904] Minor coding style fixes
  [ticket/13904] Add language entries for error messages in upload class
  [ticket/13904] Modify files for updated fast-image-size library
  [ticket/13904] Update composer.lock
  [ticket/13904] Improve code coverage
  [ticket/13904] Add unit tests for local upload type
  [ticket/13904] Minor coding style fixes
  [ticket/13904] Improve test coverage of base upload type class
  [ticket/13904] Improve test coverage of remote upload type
  [ticket/13904] Improve test coverage of form upload type
  [ticket/13904] Improve test coverage of filespec class
  [ticket/13904] Add back tests for retrieving floats
  [ticket/13904] Use ini_get() wrapper in file upload types
  [ticket/13904] Modify files for changes in ini wrapper
  [ticket/13904] Add bantu/ini-get-wrapper to composer.json
  [ticket/13904] Switch around constructor arguments
  [ticket/13904] Use \phpbb\php\ini class for ini_get()
  ...
This commit is contained in:
Tristan Darricau 2015-09-16 11:55:13 +02:00
commit a562fea230
39 changed files with 2986 additions and 1270 deletions

View File

@ -25,6 +25,7 @@
"phpbb/phpbb-core": "self.version"
},
"require": {
"bantu/ini-get-wrapper": "1.0.*",
"lusitanian/oauth": "0.2.*",
"marc1706/fast-image-size": "1.1.*",
"patchwork/utf8": "1.1.*",

32
phpBB/composer.lock generated
View File

@ -4,8 +4,38 @@
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "da690ad4ab4884661792b4b9d648934a",
"hash": "983770c26a0dcd7399ebd488846ade9a",
"packages": [
{
"name": "bantu/ini-get-wrapper",
"version": "v1.0.1",
"source": {
"type": "git",
"url": "https://github.com/bantuXorg/php-ini-get-wrapper.git",
"reference": "4770c7feab370c62e23db4f31c112b7c6d90aee2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bantuXorg/php-ini-get-wrapper/zipball/4770c7feab370c62e23db4f31c112b7c6d90aee2",
"reference": "4770c7feab370c62e23db4f31c112b7c6d90aee2",
"shasum": ""
},
"require-dev": {
"phpunit/phpunit": "3.7.*"
},
"type": "library",
"autoload": {
"psr-4": {
"bantu\\IniGetWrapper\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Convenience wrapper around ini_get()",
"time": "2014-09-15 13:12:35"
},
{
"name": "lusitanian/oauth",
"version": "v0.2.1",

View File

@ -63,8 +63,8 @@ services:
- %core.php_ext%
- @filesystem
- @path_helper
- @mimetype.guesser
- @dispatcher
- @files.factory
- @cache.driver
calls:
- [set_name, [avatar.driver.upload]]

View File

@ -1,3 +1,60 @@
services:
filesystem:
class: phpbb\filesystem\filesystem
files.factory:
class: phpbb\files\factory
arguments:
- @service_container
files.filespec:
class: phpbb\files\filespec
scope: prototype
arguments:
- @filesystem
- @language
- @php_ini
- @upload_imagesize
- %core.root_path%
- @mimetype.guesser
- @plupload
files.upload:
class: phpbb\files\upload
scope: prototype
arguments:
- @filesystem
- @files.factory
- @language
- @php_ini
- @request
- %core.root_path%
files.types.form:
class: phpbb\files\types\form
scope: prototype
arguments:
- @files.factory
- @language
- @php_ini
- @plupload
- @request
files.types.local:
class: phpbb\files\types\form
scope: prototype
arguments:
- @files.factory
- @language
- @php_ini
- @request
files.types.remote:
class: phpbb\files\types\remote
scope: prototype
arguments:
- @files.factory
- @language
- @php_ini
- @request
- %core.root_path%

View File

@ -1,3 +1,3 @@
services:
php_ini:
class: phpbb\php\ini
class: bantu\IniGetWrapper\IniGetWrapper

View File

@ -405,14 +405,13 @@ function posting_gen_topic_types($forum_id, $cur_topic_type = POST_NORMAL)
function upload_attachment($form_name, $forum_id, $local = false, $local_storage = '', $is_message = false, $local_filedata = false, \phpbb\mimetype\guesser $mimetype_guesser = null, \phpbb\plupload\plupload $plupload = null)
{
global $auth, $user, $config, $db, $cache;
global $phpbb_root_path, $phpEx, $phpbb_dispatcher, $phpbb_filesystem;
global $phpbb_root_path, $phpEx, $phpbb_dispatcher, $phpbb_container;
$filedata = array(
'error' => array()
);
include_once($phpbb_root_path . 'includes/functions_upload.' . $phpEx);
$upload = new fileupload($phpbb_filesystem);
$upload = $phpbb_container->get('files.upload');
if ($config['check_attachment_content'] && isset($config['mime_triggers']))
{
@ -434,9 +433,10 @@ function upload_attachment($form_name, $forum_id, $local = false, $local_storage
$extensions = $cache->obtain_attach_extensions((($is_message) ? false : (int) $forum_id));
$upload->set_allowed_extensions(array_keys($extensions['_allowed_']));
$file = ($local) ? $upload->local_upload($local_storage, $local_filedata, $mimetype_guesser) : $upload->form_upload($form_name, $mimetype_guesser, $plupload);
/** @var \phpbb\files\filespec $file */
$file = ($local) ? $upload->handle_upload('files.types.local', $local_storage, $local_filedata) : $upload->handle_upload('files.types.form', $form_name);
if ($file->init_error)
if ($file->init_error())
{
$filedata['post_attach'] = false;
return $filedata;

File diff suppressed because it is too large Load Diff

View File

@ -205,8 +205,8 @@ $migrator->set_migrations($migrations);
// What is a safe limit of execution time? Half the max execution time should be safe.
// No more than 15 seconds so the user isn't sitting and waiting for a very long time
$phpbb_ini = new \phpbb\php\ini();
$safe_time_limit = min(15, ($phpbb_ini->get_int('max_execution_time') / 2));
$phpbb_ini = new \bantu\IniGetWrapper\IniGetWrapper();
$safe_time_limit = min(15, ($phpbb_ini->getNumeric('max_execution_time') / 2));
// While we're going to try limit this to half the max execution time,
// we want to try and take additional measures to prevent hitting the

View File

@ -105,11 +105,13 @@ $lang = array_merge($lang, array(
'AVATAR_EMPTY_FILEUPLOAD' => 'The uploaded avatar file is empty.',
'AVATAR_INVALID_FILENAME' => '%s is an invalid filename.',
'AVATAR_NOT_UPLOADED' => 'Avatar could not be uploaded.',
'AVATAR_NO_TEMP_DIR' => 'Temporary folder could not be found or is not writable.',
'AVATAR_NO_SIZE' => 'The width or height of the linked avatar could not be determined. Please enter them manually.',
'AVATAR_PARTIAL_UPLOAD' => 'The specified file was only partially uploaded.',
'AVATAR_PHP_SIZE_NA' => 'The avatars filesize is too large.<br />The maximum allowed filesize set in php.ini could not be determined.',
'AVATAR_PHP_SIZE_OVERRUN' => 'The avatars filesize is too large. The maximum allowed upload size is %1$d %2$s.<br />Please note this is set in php.ini and cannot be overridden.',
'AVATAR_REMOTE_UPLOAD_TIMEOUT' => 'The specified avatar could not be uploaded because the request timed out.',
'AVATAR_PHP_UPLOAD_STOPPED' => 'A PHP extension has stopped the file upload.',
'AVATAR_URL_INVALID' => 'The URL you specified is invalid.',
'AVATAR_URL_NOT_FOUND' => 'The file specified could not be found.',
'AVATAR_WRONG_FILESIZE' => 'The avatars filesize must be between 0 and %1$d %2$s.',

View File

@ -176,8 +176,10 @@ $lang = array_merge($lang, array(
'NO_POLL_TITLE' => 'You have to enter a poll title.',
'NO_POST' => 'The requested post does not exist.',
'NO_POST_MODE' => 'No post mode specified.',
'NO_TEMP_DIR' => 'Temporary folder could not be found or is not writable.',
'PARTIAL_UPLOAD' => 'The uploaded file was only partially uploaded.',
'PHP_UPLOAD_STOPPED' => 'A PHP extension has stopped the file upload.',
'PHP_SIZE_NA' => 'The attachments file size is too large.<br />Could not determine the maximum size defined by PHP in php.ini.',
'PHP_SIZE_OVERRUN' => 'The attachments file size is too large, the maximum upload size is %1$d %2$s.<br />Please note this is set in php.ini and cannot be overridden.',
'PLACE_INLINE' => 'Place inline',

View File

@ -114,13 +114,8 @@ class remote extends \phpbb\avatar\driver\driver
return false;
}
if (!class_exists('fileupload'))
{
include($this->phpbb_root_path . 'includes/functions_upload.' . $this->php_ext);
}
$types = \fileupload::image_types();
$extension = strtolower(\filespec::get_extension($url));
$types = \phpbb\files\upload::image_types();
$extension = strtolower(\phpbb\files\filespec::get_extension($url));
// Check if this is actually an image
if ($file_stream = @fopen($url, 'r'))

View File

@ -23,37 +23,37 @@ class upload extends \phpbb\avatar\driver\driver
*/
protected $filesystem;
/**
* @var \phpbb\mimetype\guesser
*/
protected $mimetype_guesser;
/**
* @var \phpbb\event\dispatcher_interface
*/
protected $dispatcher;
/**
* @var \phpbb\files\factory
*/
protected $files_factory;
/**
* Construct a driver object
*
* @param \phpbb\config\config $config phpBB configuration
* @param string $phpbb_root_path Path to the phpBB root
* @param string $php_ext PHP file extension
* @param \phpbb\filesystem\filesystem_interface phpBB filesystem helper
* @param \phpbb\filesystem\filesystem_interface $filesystem phpBB filesystem helper
* @param \phpbb\path_helper $path_helper phpBB path helper
* @param \phpbb\mimetype\guesser $mimetype_guesser Mimetype guesser
* @param \phpbb\event\dispatcher_interface $dispatcher phpBB Event dispatcher object
* @param \phpbb\files\factory $files_factory File classes factory
* @param \phpbb\cache\driver\driver_interface $cache Cache driver
*/
public function __construct(\phpbb\config\config $config, $phpbb_root_path, $php_ext, \phpbb\filesystem\filesystem_interface $filesystem, \phpbb\path_helper $path_helper, \phpbb\mimetype\guesser $mimetype_guesser, \phpbb\event\dispatcher_interface $dispatcher, \phpbb\cache\driver\driver_interface $cache = null)
public function __construct(\phpbb\config\config $config, $phpbb_root_path, $php_ext, \phpbb\filesystem\filesystem_interface $filesystem, \phpbb\path_helper $path_helper, \phpbb\event\dispatcher_interface $dispatcher, \phpbb\files\factory $files_factory, \phpbb\cache\driver\driver_interface $cache = null)
{
$this->config = $config;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
$this->filesystem = $filesystem;
$this->path_helper = $path_helper;
$this->mimetype_guesser = $mimetype_guesser;
$this->dispatcher = $dispatcher;
$this->files_factory = $files_factory;
$this->cache = $cache;
}
@ -99,19 +99,24 @@ class upload extends \phpbb\avatar\driver\driver
return false;
}
if (!class_exists('fileupload'))
{
include($this->phpbb_root_path . 'includes/functions_upload.' . $this->php_ext);
}
$upload = new \fileupload($this->filesystem, 'AVATAR_', $this->allowed_extensions, $this->config['avatar_filesize'], $this->config['avatar_min_width'], $this->config['avatar_min_height'], $this->config['avatar_max_width'], $this->config['avatar_max_height'], (isset($this->config['mime_triggers']) ? explode('|', $this->config['mime_triggers']) : false));
/** @var \phpbb\files\upload $upload */
$upload = $this->files_factory->get('upload')
->set_error_prefix('AVATAR_')
->set_allowed_extensions($this->allowed_extensions)
->set_max_filesize($this->config['avatar_filesize'])
->set_allowed_dimensions(
$this->config['avatar_min_width'],
$this->config['avatar_min_height'],
$this->config['avatar_max_width'],
$this->config['avatar_max_height'])
->set_disallowed_content((isset($this->config['mime_triggers']) ? explode('|', $this->config['mime_triggers']) : false));
$url = $request->variable('avatar_upload_url', '');
$upload_file = $request->file('avatar_upload_file');
if (!empty($upload_file['name']))
{
$file = $upload->form_upload('avatar_upload_file', $this->mimetype_guesser);
$file = $upload->handle_upload('files.types.form', 'avatar_upload_file');
}
else if (!empty($this->config['allow_avatar_remote_upload']) && !empty($url))
{
@ -141,7 +146,7 @@ class upload extends \phpbb\avatar\driver\driver
return false;
}
$file = $upload->remote_upload($url, $this->mimetype_guesser);
$file = $upload->handle_upload('files.types.remote', $url);
}
else
{

View File

@ -0,0 +1,58 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\files;
class factory
{
/**
* @var \Symfony\Component\DependencyInjection\ContainerInterface
*/
private $container;
/**
* Constructor
*
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
*/
public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container)
{
$this->container = $container;
}
/**
* Get files service
*
* @param string $name Service name
*
* @return object|bool Requested service or false if service could not be
* found by the container
*/
public function get($name)
{
$service = false;
$name = (strpos($name, '.') === false) ? 'files.' . $name : $name;
try
{
$service = $this->container->get($name);
}
catch (\Exception $e)
{
// do nothing
}
return $service;
}
}

View File

@ -0,0 +1,584 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\files;
use phpbb\language\language;
/**
* Responsible for holding all file relevant information, as well as doing file-specific operations.
* The {@link fileupload fileupload class} can be used to upload several files, each of them being this object to operate further on.
*/
class filespec
{
/** @var string File name */
protected $filename = '';
/** @var string Real name of file */
protected $realname = '';
/** @var string Upload name of file */
protected $uploadname = '';
/** @var string Mimetype of file */
protected $mimetype = '';
/** @var string File extension */
protected $extension = '';
/** @var int File size */
protected $filesize = 0;
/** @var int Width of file */
protected $width = 0;
/** @var int Height of file */
protected $height = 0;
/** @var array Image info including type and size */
protected $image_info = array();
/** @var string Destination file name */
protected $destination_file = '';
/** @var string Destination file path */
protected $destination_path = '';
/** @var bool Whether file was moved */
protected $file_moved = false;
/** @var bool Whether file is local */
protected $local = false;
/** @var bool Class initialization flag */
protected $class_initialized = false;
/** @var array Error array */
public $error = array();
/** @var upload Instance of upload class */
public $upload;
/** @var \phpbb\filesystem\filesystem_interface */
protected $filesystem;
/** @var \bantu\IniGetWrapper\IniGetWrapper ini_get() wrapper class */
protected $php_ini;
/** @var \FastImageSize\FastImageSize */
protected $imagesize;
/** @var language Language class */
protected $language;
/** @var string phpBB root path */
protected $phpbb_root_path;
/** @var \phpbb\plupload\plupload The plupload object */
protected $plupload;
/** @var \phpbb\mimetype\guesser phpBB Mimetype guesser */
protected $mimetype_guesser;
/**
* File upload class
*
* @param \phpbb\filesystem\filesystem_interface $phpbb_filesystem Filesystem
* @param language $language Language
* @param \bantu\IniGetWrapper\IniGetWrapper $php_ini ini_get() wrapper
* @param \FastImageSize\FastImageSize $imagesize Imagesize class
* @param string $phpbb_root_path phpBB root path
* @param \phpbb\mimetype\guesser $mimetype_guesser Mime type guesser
* @param \phpbb\plupload\plupload $plupload Plupload
*/
public function __construct(\phpbb\filesystem\filesystem_interface $phpbb_filesystem, language $language, \bantu\IniGetWrapper\IniGetWrapper $php_ini, \FastImageSize\FastImageSize $imagesize, $phpbb_root_path, \phpbb\mimetype\guesser $mimetype_guesser = null, \phpbb\plupload\plupload $plupload = null)
{
$this->filesystem = $phpbb_filesystem;
$this->language = $language;
$this->php_ini = $php_ini;
$this->imagesize = $imagesize;
$this->phpbb_root_path = $phpbb_root_path;
$this->plupload = $plupload;
$this->mimetype_guesser = $mimetype_guesser;
}
/**
* Set upload ary
*
* @param array $upload_ary Upload ary
*
* @return filespec This instance of the filespec class
*/
public function set_upload_ary($upload_ary)
{
if (!isset($upload_ary) || !sizeof($upload_ary))
{
return $this;
}
$this->class_initialized = true;
$this->filename = $upload_ary['tmp_name'];
$this->filesize = $upload_ary['size'];
$name = (STRIP) ? stripslashes($upload_ary['name']) : $upload_ary['name'];
$name = trim(utf8_basename($name));
$this->realname = $this->uploadname = $name;
$this->mimetype = $upload_ary['type'];
// Opera adds the name to the mime type
$this->mimetype = (strpos($this->mimetype, '; name') !== false) ? str_replace(strstr($this->mimetype, '; name'), '', $this->mimetype) : $this->mimetype;
if (!$this->mimetype)
{
$this->mimetype = 'application/octet-stream';
}
$this->extension = strtolower(self::get_extension($this->realname));
// Try to get real filesize from temporary folder (not always working) ;)
$this->filesize = ($this->get_filesize($this->filename)) ?: $this->filesize;
$this->width = $this->height = 0;
$this->file_moved = false;
$this->local = (isset($upload_ary['local_mode'])) ? true : false;
return $this;
}
/**
* Set the upload namespace
*
* @param upload $namespace Instance of upload class
*
* @return filespec This instance of the filespec class
*/
public function set_upload_namespace($namespace)
{
$this->upload = $namespace;
return $this;
}
/**
* Check if class members were not properly initialised yet
*
* @return bool True if there was an init error, false if not
*/
public function init_error()
{
return !$this->class_initialized;
}
/**
* Set error in error array
*
* @param mixed $error Content for error array
*
* @return \phpbb\files\filespec This instance of the filespec class
*/
public function set_error($error)
{
$this->error[] = $error;
return $this;
}
/**
* Cleans destination filename
*
* @param string $mode Either real, unique, or unique_ext. Real creates a
* realname, filtering some characters, lowering every
* character. Unique creates a unique filename.
* @param string $prefix Prefix applied to filename
* @param string $user_id The user_id is only needed for when cleaning a user's avatar
*/
public function clean_filename($mode = 'unique', $prefix = '', $user_id = '')
{
if ($this->init_error())
{
return;
}
switch ($mode)
{
case 'real':
// Remove every extension from filename (to not let the mime bug being exposed)
if (strpos($this->realname, '.') !== false)
{
$this->realname = substr($this->realname, 0, strpos($this->realname, '.'));
}
// Replace any chars which may cause us problems with _
$bad_chars = array("'", "\\", ' ', '/', ':', '*', '?', '"', '<', '>', '|');
$this->realname = rawurlencode(str_replace($bad_chars, '_', strtolower($this->realname)));
$this->realname = preg_replace("/%(\w{2})/", '_', $this->realname);
$this->realname = $prefix . $this->realname . '.' . $this->extension;
break;
case 'unique':
$this->realname = $prefix . md5(unique_id());
break;
case 'avatar':
$this->extension = strtolower($this->extension);
$this->realname = $prefix . $user_id . '.' . $this->extension;
break;
case 'unique_ext':
default:
$this->realname = $prefix . md5(unique_id()) . '.' . $this->extension;
}
}
/**
* Get property from file object
*
* @param string $property Name of property
*
* @return mixed Content of property
*/
public function get($property)
{
if ($this->init_error() || !isset($this->$property))
{
return false;
}
return $this->$property;
}
/**
* Check if file is an image (mime type)
*
* @return bool true if it is an image, false if not
*/
public function is_image()
{
return (strpos($this->mimetype, 'image/') === 0);
}
/**
* Check if the file got correctly uploaded
*
* @return bool true if it is a valid upload, false if not
*/
public function is_uploaded()
{
$is_plupload = $this->plupload && $this->plupload->is_active();
if (!$this->local && !$is_plupload && !is_uploaded_file($this->filename))
{
return false;
}
if (($this->local || $is_plupload) && !file_exists($this->filename))
{
return false;
}
return true;
}
/**
* Remove file
*/
public function remove()
{
if ($this->file_moved)
{
@unlink($this->destination_file);
}
}
/**
* Get file extension
*
* @param string $filename Filename that needs to be checked
*
* @return string Extension of the supplied filename
*/
static public function get_extension($filename)
{
$filename = utf8_basename($filename);
if (strpos($filename, '.') === false)
{
return '';
}
$filename = explode('.', $filename);
return array_pop($filename);
}
/**
* Get mime type
*
* @param string $filename Filename that needs to be checked
* @return string Mime type of supplied filename
*/
public function get_mimetype($filename)
{
if ($this->mimetype_guesser !== null)
{
$mimetype = $this->mimetype_guesser->guess($filename, $this->uploadname);
if ($mimetype !== 'application/octet-stream')
{
$this->mimetype = $mimetype;
}
}
return $this->mimetype;
}
/**
* Get file size
*
* @param string $filename File name of file to check
*
* @return int File size
*/
public function get_filesize($filename)
{
return @filesize($filename);
}
/**
* Check the first 256 bytes for forbidden content
*
* @param array $disallowed_content Array containg disallowed content
*
* @return bool False if disallowed content found, true if not
*/
public function check_content($disallowed_content)
{
if (empty($disallowed_content))
{
return true;
}
$fp = @fopen($this->filename, 'rb');
if ($fp !== false)
{
$ie_mime_relevant = fread($fp, 256);
fclose($fp);
foreach ($disallowed_content as $forbidden)
{
if (stripos($ie_mime_relevant, '<' . $forbidden) !== false)
{
return false;
}
}
}
return true;
}
/**
* Move file to destination folder
* The phpbb_root_path variable will be applied to the destination path
*
* @param string $destination Destination path, for example $config['avatar_path']
* @param bool $overwrite If set to true, an already existing file will be overwritten
* @param bool $skip_image_check If set to true, the check for the file to be a valid image is skipped
* @param string|bool $chmod Permission mask for chmodding the file after a successful move.
* The mode entered here reflects the mode defined by {@link phpbb_chmod()}
*
* @return bool True if file was moved, false if not
* @access public
*/
public function move_file($destination, $overwrite = false, $skip_image_check = false, $chmod = false)
{
if (sizeof($this->error))
{
return false;
}
$chmod = ($chmod === false) ? CHMOD_READ | CHMOD_WRITE : $chmod;
// We need to trust the admin in specifying valid upload directories and an attacker not being able to overwrite it...
$this->destination_path = $this->phpbb_root_path . $destination;
// Check if the destination path exist...
if (!file_exists($this->destination_path))
{
@unlink($this->filename);
return false;
}
$upload_mode = ($this->php_ini->getBool('open_basedir') || $this->php_ini->getBool('safe_mode')) ? 'move' : 'copy';
$upload_mode = ($this->local) ? 'local' : $upload_mode;
$this->destination_file = $this->destination_path . '/' . utf8_basename($this->realname);
// Check if the file already exist, else there is something wrong...
if (file_exists($this->destination_file) && !$overwrite)
{
@unlink($this->filename);
$this->error[] = $this->language->lang($this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR', $this->destination_file);
$this->file_moved = false;
return false;
}
else
{
if (file_exists($this->destination_file))
{
@unlink($this->destination_file);
}
switch ($upload_mode)
{
case 'copy':
if (!@copy($this->filename, $this->destination_file))
{
if (!@move_uploaded_file($this->filename, $this->destination_file))
{
$this->error[] = $this->language->lang($this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR', $this->destination_file);
}
}
break;
case 'move':
if (!@move_uploaded_file($this->filename, $this->destination_file))
{
if (!@copy($this->filename, $this->destination_file))
{
$this->error[] = $this->language->lang($this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR', $this->destination_file);
}
}
break;
case 'local':
if (!@copy($this->filename, $this->destination_file))
{
$this->error[] = $this->language->lang($this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR', $this->destination_file);
}
break;
}
// Remove temporary filename
@unlink($this->filename);
if (sizeof($this->error))
{
return false;
}
try
{
$this->filesystem->phpbb_chmod($this->destination_file, $chmod);
}
catch (\phpbb\filesystem\exception\filesystem_exception $e)
{
// Do nothing
}
}
// Try to get real filesize from destination folder
$this->filesize = ($this->get_filesize($this->destination_file)) ?: $this->filesize;
// Get mimetype of supplied file
$this->mimetype = $this->get_mimetype($this->destination_file);
if ($this->is_image() && !$skip_image_check)
{
$this->width = $this->height = 0;
$this->image_info = $this->imagesize->getImageSize($this->destination_file, $this->mimetype);
if ($this->image_info !== false)
{
$this->width = $this->image_info['width'];
$this->height = $this->image_info['height'];
// Check image type
$types = upload::image_types();
if (!isset($types[$this->image_info['type']]) || !in_array($this->extension, $types[$this->image_info['type']]))
{
if (!isset($types[$this->image_info['type']]))
{
$this->error[] = $this->language->lang('IMAGE_FILETYPE_INVALID', $this->image_info['type'], $this->mimetype);
}
else
{
$this->error[] = $this->language->lang('IMAGE_FILETYPE_MISMATCH', $types[$this->image_info['type']][0], $this->extension);
}
}
// Make sure the dimensions match a valid image
if (empty($this->width) || empty($this->height))
{
$this->error[] = $this->language->lang('ATTACHED_IMAGE_NOT_IMAGE');
}
}
else
{
$this->error[] = $this->language->lang('UNABLE_GET_IMAGE_SIZE');
}
}
$this->file_moved = true;
$this->additional_checks();
unset($this->upload);
return true;
}
/**
* Performing additional checks
*
* @return bool False if issue was found, true if not
*/
public function additional_checks()
{
if (!$this->file_moved)
{
return false;
}
// Filesize is too big or it's 0 if it was larger than the maxsize in the upload form
if ($this->upload->max_filesize && ($this->get('filesize') > $this->upload->max_filesize || $this->filesize == 0))
{
$max_filesize = get_formatted_filesize($this->upload->max_filesize, false);
$this->error[] = $this->language->lang($this->upload->error_prefix . 'WRONG_FILESIZE', $max_filesize['value'], $max_filesize['unit']);
return false;
}
if (!$this->upload->valid_dimensions($this))
{
$this->error[] = $this->language->lang($this->upload->error_prefix . 'WRONG_SIZE',
$this->language->lang('PIXELS', (int) $this->upload->min_width),
$this->language->lang('PIXELS', (int) $this->upload->min_height),
$this->language->lang('PIXELS', (int) $this->upload->max_width),
$this->language->lang('PIXELS', (int) $this->upload->max_height),
$this->language->lang('PIXELS', (int) $this->width),
$this->language->lang('PIXELS', (int) $this->height));
return false;
}
return true;
}
}

View File

@ -0,0 +1,65 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\files\types;
abstract class base implements type_interface
{
/** @var \phpbb\language\language */
protected $language;
/** @var \bantu\IniGetWrapper\IniGetWrapper */
protected $php_ini;
/** @var \phpbb\files\upload */
protected $upload;
/**
* Check if upload exceeds maximum file size
*
* @param \phpbb\files\filespec $file Filespec object
*
* @return \phpbb\files\filespec Returns same filespec instance
*/
public function check_upload_size($file)
{
// PHP Upload filesize exceeded
if ($file->get('filename') == 'none')
{
$max_filesize = $this->php_ini->getString('upload_max_filesize');
$unit = 'MB';
if (!empty($max_filesize))
{
$unit = strtolower(substr($max_filesize, -1, 1));
$max_filesize = (int) $max_filesize;
$unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB');
}
$file->error[] = (empty($max_filesize)) ? $this->language->lang($this->upload->error_prefix . 'PHP_SIZE_NA') : $this->language->lang($this->upload->error_prefix . 'PHP_SIZE_OVERRUN', $max_filesize, $this->language->lang($unit));
}
return $file;
}
/**
* {@inheritdoc}
*/
public function set_upload(\phpbb\files\upload $upload)
{
$this->upload = $upload;
return $this;
}
}

View File

@ -0,0 +1,138 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\files\types;
use bantu\IniGetWrapper\IniGetWrapper;
use phpbb\files\factory;
use phpbb\files\filespec;
use phpbb\language\language;
use phpbb\plupload\plupload;
use phpbb\request\request_interface;
class form extends base
{
/** @var factory Files factory */
protected $factory;
/** @var language */
protected $language;
/** @var IniGetWrapper */
protected $php_ini;
/** @var plupload */
protected $plupload;
/** @var request_interface */
protected $request;
/** @var \phpbb\files\upload */
protected $upload;
/**
* Construct a form upload type
*
* @param factory $factory Files factory
* @param language $language Language class
* @param IniGetWrapper $php_ini ini_get() wrapper
* @param plupload $plupload Plupload
* @param request_interface $request Request object
*/
public function __construct(factory $factory, language $language, IniGetWrapper $php_ini, plupload $plupload, request_interface $request)
{
$this->factory = $factory;
$this->language = $language;
$this->php_ini = $php_ini;
$this->plupload = $plupload;
$this->request = $request;
}
/**
* {@inheritdoc}
*/
public function upload()
{
$args = func_get_args();
return $this->form_upload($args[0]);
}
/**
* Form upload method
* Upload file from users harddisk
*
* @param string $form_name Form name assigned to the file input field (if it is an array, the key has to be specified)
*
* @return filespec $file Object "filespec" is returned, all further operations can be done with this object
* @access public
*/
protected function form_upload($form_name)
{
$upload = $this->request->file($form_name);
unset($upload['local_mode']);
$result = $this->plupload->handle_upload($form_name);
if (is_array($result))
{
$upload = array_merge($upload, $result);
}
/** @var filespec $file */
$file = $this->factory->get('filespec')
->set_upload_ary($upload)
->set_upload_namespace($this->upload);
if ($file->init_error())
{
$file->error[] = '';
return $file;
}
// Error array filled?
if (isset($upload['error']))
{
$error = $this->upload->assign_internal_error($upload['error']);
if ($error !== false)
{
$file->error[] = $error;
return $file;
}
}
// Check if empty file got uploaded (not catched by is_uploaded_file)
if (isset($upload['size']) && $upload['size'] == 0)
{
$file->error[] = $this->language->lang($this->upload->error_prefix . 'EMPTY_FILEUPLOAD');
return $file;
}
// PHP Upload file size check
$file = $this->check_upload_size($file);
if (sizeof($file->error))
{
return $file;
}
// Not correctly uploaded
if (!$file->is_uploaded())
{
$file->error[] = $this->language->lang($this->upload->error_prefix . 'NOT_UPLOADED');
return $file;
}
$this->upload->common_checks($file);
return $file;
}
}

View File

@ -0,0 +1,136 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\files\types;
use bantu\IniGetWrapper\IniGetWrapper;
use phpbb\files\factory;
use phpbb\files\filespec;
use phpbb\language\language;
use phpbb\request\request_interface;
class local extends base
{
/** @var factory Files factory */
protected $factory;
/** @var language */
protected $language;
/** @var IniGetWrapper */
protected $php_ini;
/** @var request_interface */
protected $request;
/** @var \phpbb\files\upload */
protected $upload;
/**
* Construct a form upload type
*
* @param factory $factory Files factory
* @param language $language Language class
* @param IniGetWrapper $php_ini ini_get() wrapper
* @param request_interface $request Request object
*/
public function __construct(factory $factory, language $language, IniGetWrapper $php_ini, request_interface $request)
{
$this->factory = $factory;
$this->language = $language;
$this->php_ini = $php_ini;
$this->request = $request;
}
/**
* {@inheritdoc}
*/
public function upload()
{
$args = func_get_args();
return $this->local_upload($args[0], isset($args[1]) ? $args[1] : false);
}
/**
* Move file from another location to phpBB
*
* @param string $source_file Filename of source file
* @param array|bool $filedata Array with filedata or false
*
* @return filespec Object "filespec" is returned, all further operations can be done with this object
*/
protected function local_upload($source_file, $filedata = false)
{
$upload = $this->get_upload_ary($source_file, $filedata);
/** @var filespec $file */
$file = $this->factory->get('filespec')
->set_upload_ary($upload)
->set_upload_namespace($this->upload);
if ($file->init_error())
{
$file->error[] = '';
return $file;
}
// PHP Upload file size check
$file = $this->check_upload_size($file);
if (sizeof($file->error))
{
return $file;
}
// Not correctly uploaded
if (!$file->is_uploaded())
{
$file->error[] = $this->language->lang($this->upload->error_prefix . 'NOT_UPLOADED');
return $file;
}
$this->upload->common_checks($file);
$this->request->overwrite('local', $upload, request_interface::FILES);
return $file;
}
/**
* Retrieve upload array
*
* @param string $source_file Source file name
* @param array $filedata File data array
*
* @return array Upload array
*/
protected function get_upload_ary($source_file, $filedata)
{
$upload = array();
$upload['local_mode'] = true;
$upload['tmp_name'] = $source_file;
if ($filedata === false)
{
$upload['name'] = utf8_basename($source_file);
$upload['size'] = 0;
}
else
{
$upload['name'] = $filedata['realname'];
$upload['size'] = $filedata['size'];
$upload['type'] = $filedata['type'];
}
return $upload;
}
}

View File

@ -0,0 +1,260 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\files\types;
use bantu\IniGetWrapper\IniGetWrapper;
use phpbb\files\factory;
use phpbb\files\filespec;
use phpbb\language\language;
use phpbb\request\request_interface;
class remote extends base
{
/** @var factory Files factory */
protected $factory;
/** @var language */
protected $language;
/** @var IniGetWrapper */
protected $php_ini;
/** @var request_interface */
protected $request;
/** @var \phpbb\files\upload */
protected $upload;
/** @var string phpBB root path */
protected $phpbb_root_path;
/**
* Construct a form upload type
*
* @param factory $factory Files factory
* @param language $language Language class
* @param IniGetWrapper $php_ini ini_get() wrapper
* @param request_interface $request Request object
* @param string $phpbb_root_path phpBB root path
*/
public function __construct(factory $factory, language $language, IniGetWrapper $php_ini, request_interface $request, $phpbb_root_path)
{
$this->factory = $factory;
$this->language = $language;
$this->php_ini = $php_ini;
$this->request = $request;
$this->phpbb_root_path = $phpbb_root_path;
}
/**
* {@inheritdoc}
*/
public function upload()
{
$args = func_get_args();
return $this->remote_upload($args[0]);
}
/**
* Remote upload method
* Uploads file from given url
*
* @param string $upload_url URL pointing to file to upload, for example http://www.foobar.com/example.gif
* @return filespec $file Object "filespec" is returned, all further operations can be done with this object
* @access public
*/
protected function remote_upload($upload_url)
{
$upload_ary = array();
$upload_ary['local_mode'] = true;
if (!preg_match('#^(https?://).*?\.(' . implode('|', $this->upload->allowed_extensions) . ')$#i', $upload_url, $match))
{
return $this->factory->get('filespec')->set_error($this->language->lang($this->upload->error_prefix . 'URL_INVALID'));
}
$url = parse_url($upload_url);
$host = $url['host'];
$path = $url['path'];
$port = (!empty($url['port'])) ? (int) $url['port'] : 80;
$upload_ary['type'] = 'application/octet-stream';
$url['path'] = explode('.', $url['path']);
$ext = array_pop($url['path']);
$url['path'] = implode('', $url['path']);
$upload_ary['name'] = utf8_basename($url['path']) . (($ext) ? '.' . $ext : '');
$filename = $url['path'];
$filesize = 0;
$remote_max_filesize = $this->get_max_file_size();
$errno = 0;
$errstr = '';
if (!($fsock = @fsockopen($host, $port, $errno, $errstr)))
{
return $this->factory->get('filespec')->set_error($this->language->lang($this->upload->error_prefix . 'NOT_UPLOADED'));
}
// Make sure $path not beginning with /
if (strpos($path, '/') === 0)
{
$path = substr($path, 1);
}
fputs($fsock, 'GET /' . $path . " HTTP/1.1\r\n");
fputs($fsock, "HOST: " . $host . "\r\n");
fputs($fsock, "Connection: close\r\n\r\n");
// Set a proper timeout for the socket
socket_set_timeout($fsock, $this->upload->upload_timeout);
$get_info = false;
$data = '';
$length = false;
$timer_stop = time() + $this->upload->upload_timeout;
while ((!$length || $filesize < $length) && !@feof($fsock))
{
if ($get_info)
{
if ($length)
{
// Don't attempt to read past end of file if server indicated length
$block = @fread($fsock, min($length - $filesize, 1024));
}
else
{
$block = @fread($fsock, 1024);
}
$filesize += strlen($block);
if ($remote_max_filesize && $filesize > $remote_max_filesize)
{
$max_filesize = get_formatted_filesize($remote_max_filesize, false);
return $this->factory->get('filespec')->set_error($this->language->lang($this->upload->error_prefix . 'WRONG_FILESIZE', $max_filesize['value'], $max_filesize['unit']));
}
$data .= $block;
}
else
{
$line = @fgets($fsock, 1024);
if ($line == "\r\n")
{
$get_info = true;
}
else
{
if (stripos($line, 'content-type: ') !== false)
{
$upload_ary['type'] = rtrim(str_replace('content-type: ', '', strtolower($line)));
}
else if ($this->upload->max_filesize && stripos($line, 'content-length: ') !== false)
{
$length = (int) str_replace('content-length: ', '', strtolower($line));
if ($remote_max_filesize && $length && $length > $remote_max_filesize)
{
$max_filesize = get_formatted_filesize($remote_max_filesize, false);
return $this->factory->get('filespec')->set_error($this->language->lang($this->upload->error_prefix . 'WRONG_FILESIZE', $max_filesize['value'], $max_filesize['unit']));
}
}
else if (stripos($line, '404 not found') !== false)
{
return $this->factory->get('filespec')->set_error($this->upload->error_prefix . 'URL_NOT_FOUND');
}
}
}
$stream_meta_data = stream_get_meta_data($fsock);
// Cancel upload if we exceed timeout
if (!empty($stream_meta_data['timed_out']) || time() >= $timer_stop)
{
return $this->factory->get('filespec')->set_error($this->upload->error_prefix . 'REMOTE_UPLOAD_TIMEOUT');
}
}
@fclose($fsock);
if (empty($data))
{
return $this->factory->get('filespec')->set_error($this->upload->error_prefix . 'EMPTY_REMOTE_DATA');
}
$tmp_path = (!$this->php_ini->getBool('safe_mode')) ? false : $this->phpbb_root_path . 'cache';
$filename = tempnam($tmp_path, unique_id() . '-');
if (!($fp = @fopen($filename, 'wb')))
{
return $this->factory->get('filespec')->set_error($this->upload->error_prefix . 'NOT_UPLOADED');
}
$upload_ary['size'] = fwrite($fp, $data);
fclose($fp);
unset($data);
$upload_ary['tmp_name'] = $filename;
/** @var filespec $file */
$file = $this->factory->get('filespec')
->set_upload_ary($upload_ary)
->set_upload_namespace($this->upload);
$this->upload->common_checks($file);
return $file;
}
/**
* Get maximum file size for remote uploads
*
* @return int Maximum file size
*/
protected function get_max_file_size()
{
$max_file_size = $this->upload->max_filesize;
if (!$max_file_size)
{
$max_file_size = $this->php_ini->getString('upload_max_filesize');
if (!empty($max_file_size))
{
$unit = strtolower(substr($max_file_size, -1, 1));
$max_file_size = (int) $max_file_size;
switch ($unit)
{
case 'g':
$max_file_size *= 1024;
// no break
case 'm':
$max_file_size *= 1024;
// no break
case 'k':
$max_file_size *= 1024;
// no break
}
}
}
return $max_file_size;
}
}

View File

@ -0,0 +1,38 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\files\types;
use phpbb\files\upload;
interface type_interface
{
/**
* Handle upload for upload types. Arguments passed to this method will be
* handled by the upload type classes themselves.
*
* @return \phpbb\files\filespec|bool Filespec instance if upload is
* successful or false if not
*/
public function upload();
/**
* Set upload instance
* Needs to be executed before every upload.
*
* @param upload $upload Upload instance
*
* @return type_interface Returns itself
*/
public function set_upload(upload $upload);
}

View File

@ -0,0 +1,395 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\files;
use phpbb\filesystem\filesystem_interface;
use phpbb\language\language;
use phpbb\request\request_interface;
/**
* File upload class
* Init class (all parameters optional and able to be set/overwritten separately) - scope is global and valid for all uploads
*/
class upload
{
/** @var array Allowed file extensions */
public $allowed_extensions = array();
/** @var array Disallowed content */
protected $disallowed_content = array('body', 'head', 'html', 'img', 'plaintext', 'a href', 'pre', 'script', 'table', 'title');
/** @var int Maximum filesize */
public $max_filesize = 0;
/** @var int Minimum width of images */
public $min_width = 0;
/** @var int Minimum height of images */
public $min_height = 0;
/** @var int Maximum width of images */
public $max_width = 0;
/** @var int Maximum height of images */
public $max_height = 0;
/** @var string Prefix for language variables of errors */
public $error_prefix = '';
/** @var int Timeout for remote upload */
public $upload_timeout = 6;
/** @var filesystem_interface */
protected $filesystem;
/** @var \phpbb\files\factory Files factory */
protected $factory;
/** @var \bantu\IniGetWrapper\IniGetWrapper ini_get() wrapper */
protected $php_ini;
/** @var \phpbb\language\language Language class */
protected $language;
/** @var request_interface Request class */
protected $request;
/** @var string phpBB root path */
protected $phpbb_root_path;
/**
* Init file upload class.
*
* @param filesystem_interface $filesystem
* @param factory $factory Files factory
* @param language $language Language class
* @param \bantu\IniGetWrapper\IniGetWrapper $php_ini ini_get() wrapper
* @param request_interface $request Request class
* @param string $phpbb_root_path phpBB root path
*/
public function __construct(filesystem_interface $filesystem, factory $factory, language $language, \bantu\IniGetWrapper\IniGetWrapper $php_ini, request_interface $request, $phpbb_root_path)
{
$this->filesystem = $filesystem;
$this->factory = $factory;
$this->language = $language;
$this->php_ini = $php_ini;
$this->request = $request;
$this->phpbb_root_path = $phpbb_root_path;
}
/**
* Reset vars
*/
public function reset_vars()
{
$this->max_filesize = 0;
$this->min_width = $this->min_height = $this->max_width = $this->max_height = 0;
$this->error_prefix = '';
$this->allowed_extensions = array();
$this->disallowed_content = array();
}
/**
* Set allowed extensions
*
* @param array $allowed_extensions Allowed file extensions
*
* @return \phpbb\files\upload This instance of upload
*/
public function set_allowed_extensions($allowed_extensions)
{
if ($allowed_extensions !== false && is_array($allowed_extensions))
{
$this->allowed_extensions = $allowed_extensions;
}
return $this;
}
/**
* Set allowed dimensions
*
* @param int $min_width Minimum image width
* @param int $min_height Minimum image height
* @param int $max_width Maximum image width
* @param int $max_height Maximum image height
*
* @return \phpbb\files\upload This instance of upload
*/
public function set_allowed_dimensions($min_width, $min_height, $max_width, $max_height)
{
$this->min_width = (int) $min_width;
$this->min_height = (int) $min_height;
$this->max_width = (int) $max_width;
$this->max_height = (int) $max_height;
return $this;
}
/**
* Set maximum allowed file size
*
* @param int $max_filesize Maximum file size
*
* @return \phpbb\files\upload This instance of upload
*/
public function set_max_filesize($max_filesize)
{
if ($max_filesize !== false && (int) $max_filesize)
{
$this->max_filesize = (int) $max_filesize;
}
return $this;
}
/**
* Set disallowed strings
*
* @param array $disallowed_content Disallowed content
*
* @return \phpbb\files\upload This instance of upload
*/
public function set_disallowed_content($disallowed_content)
{
if ($disallowed_content !== false && is_array($disallowed_content))
{
$this->disallowed_content = array_diff($disallowed_content, array(''));
}
return $this;
}
/**
* Set error prefix
*
* @param string $error_prefix Prefix for language variables of errors
*
* @return \phpbb\files\upload This instance of upload
*/
public function set_error_prefix($error_prefix)
{
$this->error_prefix = $error_prefix;
return $this;
}
/**
* Handle upload based on type
*
* @param string $type Upload type
*
* @return \phpbb\files\filespec|bool A filespec instance if upload was
* successful, false if there were issues or the type is not supported
*/
public function handle_upload($type)
{
$args = func_get_args();
array_shift($args);
$type_class = $this->factory->get($type)
->set_upload($this);
return (is_object($type_class)) ? call_user_func_array(array($type_class, 'upload'), $args) : false;
}
/**
* Assign internal error
*
* @param string $errorcode Error code to assign
*
* @return string Error string
* @access public
*/
public function assign_internal_error($errorcode)
{
switch ($errorcode)
{
case UPLOAD_ERR_INI_SIZE:
$max_filesize = $this->php_ini->getString('upload_max_filesize');
$unit = 'MB';
if (!empty($max_filesize))
{
$unit = strtolower(substr($max_filesize, -1, 1));
$max_filesize = (int) $max_filesize;
$unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB');
}
$error = (empty($max_filesize)) ? $this->language->lang($this->error_prefix . 'PHP_SIZE_NA') : $this->language->lang($this->error_prefix . 'PHP_SIZE_OVERRUN', $max_filesize, $this->language->lang($unit));
break;
case UPLOAD_ERR_FORM_SIZE:
$max_filesize = get_formatted_filesize($this->max_filesize, false);
$error = $this->language->lang($this->error_prefix . 'WRONG_FILESIZE', $max_filesize['value'], $max_filesize['unit']);
break;
case UPLOAD_ERR_PARTIAL:
$error = $this->language->lang($this->error_prefix . 'PARTIAL_UPLOAD');
break;
case UPLOAD_ERR_NO_FILE:
$error = $this->language->lang($this->error_prefix . 'NOT_UPLOADED');
break;
case UPLOAD_ERR_NO_TMP_DIR:
case UPLOAD_ERR_CANT_WRITE:
$error = $this->language->lang($this->error_prefix . 'NO_TEMP_DIR');
break;
case UPLOAD_ERR_EXTENSION:
$error = $this->language->lang($this->error_prefix . 'PHP_UPLOAD_STOPPED');
break;
default:
$error = false;
break;
}
return $error;
}
/**
* Perform common file checks
*
* @param filespec $file Instance of filespec class
*/
public function common_checks(&$file)
{
// Filesize is too big or it's 0 if it was larger than the maxsize in the upload form
if ($this->max_filesize && ($file->get('filesize') > $this->max_filesize || $file->get('filesize') == 0))
{
$max_filesize = get_formatted_filesize($this->max_filesize, false);
$file->error[] = $this->language->lang($this->error_prefix . 'WRONG_FILESIZE', $max_filesize['value'], $max_filesize['unit']);
}
// check Filename
if (preg_match("#[\\/:*?\"<>|]#i", $file->get('realname')))
{
$file->error[] = $this->language->lang($this->error_prefix . 'INVALID_FILENAME', $file->get('realname'));
}
// Invalid Extension
if (!$this->valid_extension($file))
{
$file->error[] = $this->language->lang($this->error_prefix . 'DISALLOWED_EXTENSION', $file->get('extension'));
}
// MIME Sniffing
if (!$this->valid_content($file))
{
$file->error[] = $this->language->lang($this->error_prefix . 'DISALLOWED_CONTENT');
}
}
/**
* Check for allowed extension
*
* @param filespec $file Instance of filespec class
*
* @return bool True if extension is allowed, false if not
*/
public function valid_extension(&$file)
{
return (in_array($file->get('extension'), $this->allowed_extensions)) ? true : false;
}
/**
* Check for allowed dimension
*
* @param filespec $file Instance of filespec class
*
* @return bool True if dimensions are valid or no constraints set, false
* if not
*/
public function valid_dimensions(&$file)
{
if (!$this->max_width && !$this->max_height && !$this->min_width && !$this->min_height)
{
return true;
}
if (($file->get('width') > $this->max_width && $this->max_width) ||
($file->get('height') > $this->max_height && $this->max_height) ||
($file->get('width') < $this->min_width && $this->min_width) ||
($file->get('height') < $this->min_height && $this->min_height))
{
return false;
}
return true;
}
/**
* Check if form upload is valid
*
* @param string $form_name Name of form
*
* @return bool True if form upload is valid, false if not
*/
public function is_valid($form_name)
{
$upload = $this->request->file($form_name);
return (!empty($upload) && $upload['name'] !== 'none');
}
/**
* Check for bad content (IE mime-sniffing)
*
* @param filespec $file Instance of filespec class
*
* @return bool True if content is valid, false if not
*/
public function valid_content(&$file)
{
return ($file->check_content($this->disallowed_content));
}
/**
* Get image type/extension mapping
*
* @return array Array containing the image types and their extensions
*/
static public function image_types()
{
$result = array(
IMAGETYPE_GIF => array('gif'),
IMAGETYPE_JPEG => array('jpg', 'jpeg'),
IMAGETYPE_PNG => array('png'),
IMAGETYPE_SWF => array('swf'),
IMAGETYPE_PSD => array('psd'),
IMAGETYPE_BMP => array('bmp'),
IMAGETYPE_TIFF_II => array('tif', 'tiff'),
IMAGETYPE_TIFF_MM => array('tif', 'tiff'),
IMAGETYPE_JPC => array('jpg', 'jpeg'),
IMAGETYPE_JP2 => array('jpg', 'jpeg'),
IMAGETYPE_JPX => array('jpg', 'jpeg'),
IMAGETYPE_JB2 => array('jpg', 'jpeg'),
IMAGETYPE_IFF => array('iff'),
IMAGETYPE_WBMP => array('wbmp'),
IMAGETYPE_XBM => array('xbm'),
);
if (defined('IMAGETYPE_SWC'))
{
$result[IMAGETYPE_SWC] = array('swc');
}
return $result;
}
}

View File

@ -41,7 +41,7 @@ class config
protected $install_config_file;
/**
* @var \phpbb\php\ini
* @var \bantu\IniGetWrapper\IniGetWrapper
*/
protected $php_ini;
@ -83,7 +83,7 @@ class config
/**
* Constructor
*/
public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, \phpbb\php\ini $php_ini, $phpbb_root_path)
public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, \bantu\IniGetWrapper\IniGetWrapper $php_ini, $phpbb_root_path)
{
$this->filesystem = $filesystem;
$this->php_ini = $php_ini;
@ -373,7 +373,7 @@ class config
protected function setup_system_data()
{
// Query maximum runtime from php.ini
$execution_time = $this->php_ini->get_int('max_execution_time');
$execution_time = $this->php_ini->getNumeric('max_execution_time');
$execution_time = min(15, $execution_time / 2);
$this->system_data['max_execution_time'] = $execution_time;
@ -381,6 +381,6 @@ class config
$this->system_data['start_time'] = time();
// Get memory limit
$this->system_data['memory_limit'] = $this->php_ini->get_bytes('memory_limit');
$this->system_data['memory_limit'] = $this->php_ini->getBytes('memory_limit');
}
}

View File

@ -39,7 +39,7 @@ class plupload
protected $user;
/**
* @var \phpbb\php\ini
* @var \bantu\IniGetWrapper\IniGetWrapper
*/
protected $php_ini;
@ -67,10 +67,10 @@ class plupload
* @param \phpbb\config\config $config
* @param \phpbb\request\request_interface $request
* @param \phpbb\user $user
* @param \phpbb\php\ini $php_ini
* @param \bantu\IniGetWrapper\IniGetWrapper $php_ini
* @param \phpbb\mimetype\guesser $mimetype_guesser
*/
public function __construct($phpbb_root_path, \phpbb\config\config $config, \phpbb\request\request_interface $request, \phpbb\user $user, \phpbb\php\ini $php_ini, \phpbb\mimetype\guesser $mimetype_guesser)
public function __construct($phpbb_root_path, \phpbb\config\config $config, \phpbb\request\request_interface $request, \phpbb\user $user, \bantu\IniGetWrapper\IniGetWrapper $php_ini, \phpbb\mimetype\guesser $mimetype_guesser)
{
$this->phpbb_root_path = $phpbb_root_path;
$this->config = $config;
@ -284,9 +284,9 @@ class plupload
public function get_chunk_size()
{
$max = min(
$this->php_ini->get_bytes('upload_max_filesize'),
$this->php_ini->get_bytes('post_max_size'),
max(1, $this->php_ini->get_bytes('memory_limit')),
$this->php_ini->getBytes('upload_max_filesize'),
$this->php_ini->getBytes('post_max_size'),
max(1, $this->php_ini->getBytes('memory_limit')),
$this->config['max_filesize']
);
@ -303,7 +303,7 @@ class plupload
$this->temporary_directory,
$this->config['plupload_salt'],
md5($file_name),
\filespec::get_extension($file_name)
\phpbb\files\filespec::get_extension($file_name)
);
}

View File

@ -73,6 +73,8 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case
->will($this->returnValue('avatar.driver.barfoo'));
$avatar_drivers = array($this->avatar_foobar, $this->avatar_barfoo);
$files_factory = new \phpbb\files\factory($phpbb_container);
foreach ($this->avatar_drivers() as $driver)
{
if ($driver !== 'upload')
@ -81,7 +83,7 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case
}
else
{
$cur_avatar = $this->getMock('\phpbb\avatar\driver\\' . $driver, array('get_name'), array($this->config, $phpbb_root_path, $phpEx, $filesystem, $path_helper, $guesser, $dispatcher, $cache));
$cur_avatar = $this->getMock('\phpbb\avatar\driver\\' . $driver, array('get_name'), array($this->config, $phpbb_root_path, $phpEx, $filesystem, $path_helper, $dispatcher, $files_factory, $cache));
}
$cur_avatar->expects($this->any())
->method('get_name')

View File

@ -34,14 +34,14 @@ class phpbb_cache_apc_driver_test extends phpbb_cache_common_test_case
self::markTestSkipped('APC extension is not loaded');
}
$php_ini = new \phpbb\php\ini;
$php_ini = new \bantu\IniGetWrapper\IniGetWrapper;
if (!$php_ini->get_bool('apc.enabled'))
if (!$php_ini->getBool('apc.enabled'))
{
self::markTestSkipped('APC is not enabled. Make sure apc.enabled=1 in php.ini');
}
if (PHP_SAPI == 'cli' && !$php_ini->get_bool('apc.enable_cli'))
if (PHP_SAPI == 'cli' && !$php_ini->getBool('apc.enable_cli'))
{
self::markTestSkipped('APC is not enabled for CLI. Set apc.enable_cli=1 in php.ini');
}

31
tests/files/type_foo.php Normal file
View File

@ -0,0 +1,31 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\files\types;
class foo extends \phpbb\files\types\remote
{
static public $tempnam_path;
}
function tempnam($one, $two)
{
if (empty(foo::$tempnam_path))
{
return \tempnam($one, $two);
}
else
{
return foo::$tempnam_path;
}
}

View File

@ -0,0 +1,93 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
class phpbb_files_types_base_test extends phpbb_test_case
{
private $path;
private $filesystem;
/** @var \Symfony\Component\DependencyInjection\ContainerInterface */
protected $container;
/** @var \phpbb\files\factory */
protected $factory;
/** @var \bantu\IniGetWrapper\IniGetWrapper */
protected $php_ini;
/** @var \phpbb\language\language */
protected $language;
/** @var \phpbb\request\request_interface */
protected $request;
/** @var string phpBB root path */
protected $phpbb_root_path;
protected function setUp()
{
global $phpbb_root_path, $phpEx;
$this->request = $this->getMock('\phpbb\request\request');
$this->filesystem = new \phpbb\filesystem\filesystem();
$this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
$this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper;
$this->container = new phpbb_mock_container_builder($phpbb_root_path, $phpEx);
$this->container->set('files.filespec', new \phpbb\files\filespec(
$this->filesystem,
$this->language,
$this->php_ini,
new \FastImageSize\FastImageSize(),
$phpbb_root_path,
new \phpbb\mimetype\guesser(array(
'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(),
))));
$this->factory = new \phpbb\files\factory($this->container);
$this->path = __DIR__ . '/fixture/';
$this->phpbb_root_path = $phpbb_root_path;
}
public function data_check_upload_size()
{
return array(
array('foo', '500KB', array()),
array('none', '500KB', array('PHP_SIZE_OVERRUN')),
array('none', '', array('PHP_SIZE_NA')),
);
}
/**
* @dataProvider data_check_upload_size
*/
public function test_check_upload_size($filename, $max_filesize, $expected)
{
$php_ini = $this->getMock('\bantu\IniGetWrapper\IniGetWrapper');
$php_ini->expects($this->any())
->method('getString')
->willReturn($max_filesize);
$type_form = new \phpbb\files\types\local($this->factory, $this->language, $php_ini, $this->request);
$file = $this->getMockBuilder('\phpbb\files\filespec')
->disableOriginalConstructor()
->getMock();
$file->expects($this->any())
->method('get')
->willReturn($filename);
$type_form->check_upload_size($file);
$this->assertSame($expected, $file->error);
}
}

View File

@ -0,0 +1,174 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
class phpbb_files_types_form_test extends phpbb_test_case
{
private $path;
private $filesystem;
/** @var \Symfony\Component\DependencyInjection\ContainerInterface */
protected $container;
/** @var \phpbb\files\factory */
protected $factory;
/** @var \bantu\IniGetWrapper\IniGetWrapper */
protected $php_ini;
/** @var \phpbb\language\language */
protected $language;
/** @var \phpbb\request\request_interface */
protected $request;
/** @var \phpbb\plupload\plupload */
protected $plupload;
/** @var string phpBB root path */
protected $phpbb_root_path;
protected function setUp()
{
global $phpbb_root_path, $phpEx;
$this->request = $this->getMock('\phpbb\request\request');
$this->request->expects($this->any())
->method('file')
->willReturn(array());
$this->filesystem = new \phpbb\filesystem\filesystem();
$this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
$this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper;
$this->container = new phpbb_mock_container_builder($phpbb_root_path, $phpEx);
$this->container->set('files.filespec', new \phpbb\files\filespec(
$this->filesystem,
$this->language,
$this->php_ini,
new \FastImageSize\FastImageSize(),
$phpbb_root_path,
new \phpbb\mimetype\guesser(array(
'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(),
))));
$this->factory = new \phpbb\files\factory($this->container);
$this->plupload = $this->getMockBuilder('\phpbb\plupload\plupload')
->disableOriginalConstructor()
->getMock();
$this->plupload->expects($this->any())
->method('handle_upload')
->willReturn(array());
$this->path = __DIR__ . '/fixture/';
$this->phpbb_root_path = $phpbb_root_path;
}
public function data_upload_form()
{
return array(
array(
array(),
array(''),
),
array(
array(
'tmp_name' => 'foo',
'name' => 'foo',
'size' => 500,
'type' => 'image/png',
'error' => UPLOAD_ERR_PARTIAL,
),
array('PARTIAL_UPLOAD'),
),
array(
array(
'tmp_name' => 'foo',
'name' => 'foo',
'size' => 500,
'type' => 'image/png',
'error' => -9,
),
array('NOT_UPLOADED'),
),
array(
array(
'tmp_name' => 'foo',
'name' => 'foo',
'size' => 0,
'type' => 'image/png',
),
array('EMPTY_FILEUPLOAD'),
),
array(
array(
'tmp_name' => 'none',
'name' => 'none',
'size' => 50,
'type' => 'image/png',
),
array('PHP_SIZE_OVERRUN'),
),
array(
array(
'tmp_name' => 'tests/upload/fixture/png',
'name' => 'foo.png',
'size' => 500,
'type' => 'image/png',
'local_mode' => true,
),
array(),
array('local_mode' => true),
),
);
}
/**
* @dataProvider data_upload_form
*/
public function test_upload_form($upload, $expected, $plupload = array())
{
$this->request = $this->getMock('\phpbb\request\request');
$this->request->expects($this->any())
->method('file')
->willReturn($upload);
$filespec = new \phpbb\files\filespec(
$this->filesystem,
$this->language,
$this->php_ini,
new \FastImageSize\FastImageSize(),
$this->phpbb_root_path,
new \phpbb\mimetype\guesser(array(
'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(),
)));
$this->container->set('files.filespec', $filespec);
$this->factory = new \phpbb\files\factory($this->container);
$this->plupload = $this->getMockBuilder('\phpbb\plupload\plupload')
->disableOriginalConstructor()
->getMock();
$this->plupload->expects($this->any())
->method('handle_upload')
->willReturn($plupload);
$type_form = new \phpbb\files\types\form($this->factory, $this->language, $this->php_ini, $this->plupload, $this->request);
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload->set_allowed_extensions(array('png'));
$type_form->set_upload($upload);
$file = $type_form->upload('foobar');
$this->assertSame($expected, $file->error);
$this->assertInstanceOf('\phpbb\files\filespec', $file);
}
}

View File

@ -0,0 +1,163 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
class phpbb_files_types_local_test extends phpbb_test_case
{
private $path;
private $filesystem;
/** @var \Symfony\Component\DependencyInjection\ContainerInterface */
protected $container;
/** @var \phpbb\files\factory */
protected $factory;
/** @var \bantu\IniGetWrapper\IniGetWrapper */
protected $php_ini;
/** @var \phpbb\language\language */
protected $language;
/** @var \phpbb\request\request_interface */
protected $request;
/** @var \phpbb\plupload\plupload */
protected $plupload;
/** @var string phpBB root path */
protected $phpbb_root_path;
protected function setUp()
{
global $phpbb_root_path, $phpEx;
$this->request = $this->getMock('\phpbb\request\request');
$this->request->expects($this->any())
->method('file')
->willReturn(array());
$this->filesystem = new \phpbb\filesystem\filesystem();
$this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
$this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper;
$this->container = new phpbb_mock_container_builder($phpbb_root_path, $phpEx);
$this->container->set('files.filespec', new \phpbb\files\filespec(
$this->filesystem,
$this->language,
$this->php_ini,
new \FastImageSize\FastImageSize(),
$phpbb_root_path,
new \phpbb\mimetype\guesser(array(
'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(),
))));
$this->factory = new \phpbb\files\factory($this->container);
$this->plupload = $this->getMockBuilder('\phpbb\plupload\plupload')
->disableOriginalConstructor()
->getMock();
$this->plupload->expects($this->any())
->method('handle_upload')
->willReturn(array());
$this->path = __DIR__ . '/fixture/';
$this->phpbb_root_path = $phpbb_root_path;
}
public function test_upload_init_error()
{
$filespec = $this->getMockBuilder('\phpbb\files\filespec')
->disableOriginalConstructor()
->getMock();
$filespec->expects($this->any())
->method('init_error')
->willReturn(true);
$filespec->expects($this->any())
->method('set_upload_ary')
->willReturnSelf();
$filespec->expects($this->any())
->method('set_upload_namespace')
->willReturnSelf();
$this->container->set('files.filespec', $filespec);
$this->factory = new \phpbb\files\factory($this->container);
$type_local = new \phpbb\files\types\local($this->factory, $this->language, $this->php_ini, $this->request);
$file = $type_local->upload('foo', false);
$this->assertSame(array(''), $file->error);
$this->assertInstanceOf('\phpbb\files\filespec', $file);
}
public function data_upload_form()
{
return array(
array(
'foo',
array(
'tmp_name' => 'foo',
'size' => 500,
'type' => 'image/png',
),
array('NOT_UPLOADED'),
),
array(
'none',
false,
array('PHP_SIZE_OVERRUN'),
),
array(
'tests/upload/fixture/png',
array(
'realname' => 'foo.png',
'size' => 500,
'type' => 'image/png',
'local_mode' => true,
),
array(),
),
);
}
/**
* @dataProvider data_upload_form
*/
public function test_upload_form($filename, $upload_ary, $expected)
{
$filespec = new \phpbb\files\filespec(
$this->filesystem,
$this->language,
$this->php_ini,
new \FastImageSize\FastImageSize(),
$this->phpbb_root_path,
new \phpbb\mimetype\guesser(array(
'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(),
)));
$filespec_local = new ReflectionProperty($filespec, 'local');
$filespec_local->setAccessible(true);
$filespec_local->setValue($filespec, true);
$this->container->set('files.filespec', $filespec);
$this->factory = new \phpbb\files\factory($this->container);
$type_local = new \phpbb\files\types\local($this->factory, $this->language, $this->php_ini, $this->request);
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload->set_allowed_extensions(array('png'));
$type_local->set_upload($upload);
$file = $type_local->upload($filename, $upload_ary);
$this->assertSame($expected, $file->error);
$this->assertInstanceOf('\phpbb\files\filespec', $file);
}
}

View File

@ -0,0 +1,141 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
require_once dirname(__FILE__) . '/type_foo.php';
class phpbb_files_types_remote_test extends phpbb_test_case
{
private $path;
private $filesystem;
/** @var \Symfony\Component\DependencyInjection\ContainerInterface */
protected $container;
/** @var \phpbb\files\factory */
protected $factory;
/** @var \bantu\IniGetWrapper\IniGetWrapper */
protected $php_ini;
/** @var \phpbb\language\language */
protected $language;
/** @var \phpbb\request\request_interface */
protected $request;
/** @var string phpBB root path */
protected $phpbb_root_path;
protected function setUp()
{
global $config, $phpbb_root_path, $phpEx;
$config = new \phpbb\config\config(array());
$this->request = $this->getMock('\phpbb\request\request');
$this->filesystem = new \phpbb\filesystem\filesystem();
$this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
$this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper;
$this->container = new phpbb_mock_container_builder($phpbb_root_path, $phpEx);
$this->container->set('files.filespec', new \phpbb\files\filespec(
$this->filesystem,
$this->language,
$this->php_ini,
new \FastImageSize\FastImageSize(),
$phpbb_root_path,
new \phpbb\mimetype\guesser(array(
'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(),
))));
$this->factory = new \phpbb\files\factory($this->container);
$this->path = __DIR__ . '/fixture/';
$this->phpbb_root_path = $phpbb_root_path;
}
public function test_upload_fsock_fail()
{
$type_remote = new \phpbb\files\types\remote($this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload->set_allowed_extensions(array('png'));
$type_remote->set_upload($upload);
$file = $type_remote->upload('https://bärföö.com/foo.png');
$this->assertSame(array('NOT_UPLOADED'), $file->error);
}
public function data_get_max_file_size()
{
return array(
array('', 'http://example.com/foo/bar.png'),
array('2k', 'http://example.com/foo/bar.png'),
array('500k', 'http://example.com/foo/bar.png'),
array('500M', 'http://example.com/foo/bar.png'),
array('500m', 'http://example.com/foo/bar.png'),
array('500k', 'http://google.com/.png', 'DISALLOWED_CONTENT'),
array('1', 'http://google.com/.png', 'WRONG_FILESIZE'),
array('500g', 'http://example.com/foo/bar.png'),
array('foobar', 'http://example.com/foo/bar.png'),
array('-5k', 'http://example.com/foo/bar.png'),
);
}
/**
* @dataProvider data_get_max_file_size
*/
public function test_get_max_file_size($max_file_size, $link, $expected = 'URL_NOT_FOUND')
{
$php_ini = $this->getMock('\bantu\IniGetWrapper\IniGetWrapper', array('getString'));
$php_ini->expects($this->any())
->method('getString')
->willReturn($max_file_size);
$type_remote = new \phpbb\files\types\remote($this->factory, $this->language, $php_ini, $this->request, $this->phpbb_root_path);
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload->set_allowed_extensions(array('png'));
$type_remote->set_upload($upload);
$file = $type_remote->upload($link);
$this->assertSame(array($expected), $file->error);
}
public function test_upload_timeout()
{
$type_remote = new \phpbb\files\types\remote($this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload->set_allowed_extensions(array('png'));
$type_remote->set_upload($upload);
$upload->upload_timeout = -5;
$file = $type_remote->upload('http://google.com/.png');
$this->assertSame(array('REMOTE_UPLOAD_TIMEOUT'), $file->error);
}
public function test_upload_wrong_path()
{
$type_remote = new \phpbb\files\types\foo($this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload->set_allowed_extensions(array('png'));
$type_remote->set_upload($upload);
$type_remote::$tempnam_path = $this->phpbb_root_path . 'cache/wrong/path';
$file = $type_remote->upload('http://google.com/.png');
$this->assertSame(array('NOT_UPLOADED'), $file->error);
$type_remote::$tempnam_path = '';
}
}

128
tests/files/upload_test.php Normal file
View File

@ -0,0 +1,128 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
class phpbb_files_upload_test extends phpbb_test_case
{
private $path;
private $filesystem;
/** @var \Symfony\Component\DependencyInjection\ContainerInterface */
protected $container;
/** @var \phpbb\files\factory */
protected $factory;
/** @var \bantu\IniGetWrapper\IniGetWrapper */
protected $php_ini;
/** @var \phpbb\language\language */
protected $language;
/** @var \phpbb\request\request_interface */
protected $request;
/** @var string phpBB root path */
protected $phpbb_root_path;
protected function setUp()
{
// Global $config required by unique_id
global $config, $phpbb_root_path, $phpEx;
if (!is_array($config))
{
$config = array();
}
$config['rand_seed'] = '';
$config['rand_seed_last_update'] = time() + 600;
$this->request = $this->getMock('\phpbb\request\request');
$this->filesystem = new \phpbb\filesystem\filesystem();
$this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
$this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper;
$this->container = new phpbb_mock_container_builder($phpbb_root_path, $phpEx);
$this->container->set('files.filespec', new \phpbb\files\filespec(
$this->filesystem,
$this->language,
$this->php_ini,
new \FastImageSize\FastImageSize(),
$phpbb_root_path,
new \phpbb\mimetype\guesser(array(
'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(),
))));
$this->factory = new \phpbb\files\factory($this->container);
$this->path = __DIR__ . '/fixture/';
$this->phpbb_root_path = $phpbb_root_path;
}
public function test_reset_vars()
{
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload->set_max_filesize(500);
$this->assertEquals(500, $upload->max_filesize);
$upload->reset_vars();
$this->assertEquals(0, $upload->max_filesize);
}
public function test_set_disallowed_content()
{
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$disallowed_content = new ReflectionProperty($upload, 'disallowed_content');
$disallowed_content->setAccessible(true);
$upload->set_disallowed_content(array('foo'));
$this->assertEquals(array('foo'), $disallowed_content->getValue($upload));
$upload->set_disallowed_content(array('foo', 'bar', 'meh'));
$this->assertEquals(array('foo', 'bar', 'meh'), $disallowed_content->getValue($upload));
$upload->set_disallowed_content('');
$this->assertEquals(array('foo', 'bar', 'meh'), $disallowed_content->getValue($upload));
$this->assertINstanceOf('\phpbb\files\upload', $upload->set_disallowed_content(array()));
$this->assertEquals(array(), $disallowed_content->getValue($upload));
$upload->reset_vars();
$this->assertEquals(array(), $disallowed_content->getValue($upload));
}
public function test_is_valid()
{
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$this->assertFalse($upload->is_valid('foobar'));
}
public function data_internal_error()
{
return array(
array(UPLOAD_ERR_INI_SIZE, 'PHP_SIZE_OVERRUN'),
array(UPLOAD_ERR_FORM_SIZE, 'WRONG_FILESIZE'),
array(UPLOAD_ERR_PARTIAL, 'PARTIAL_UPLOAD'),
array(UPLOAD_ERR_NO_FILE, 'NOT_UPLOADED'),
array(UPLOAD_ERR_NO_TMP_DIR, 'NO_TEMP_DIR'),
array(UPLOAD_ERR_CANT_WRITE, 'NO_TEMP_DIR'),
array(UPLOAD_ERR_EXTENSION, 'PHP_UPLOAD_STOPPED'),
array(9, false),
);
}
/**
* @dataProvider data_internal_error
*/
public function test_assign_internal_error($error_code, $expected)
{
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$this->assertSame($expected, $upload->assign_internal_error($error_code));
}
}

View File

@ -11,15 +11,29 @@
*
*/
require_once __DIR__ . '/../../phpBB/includes/functions_upload.php';
/**
* @group functional
*/
class phpbb_functional_fileupload_remote_test extends phpbb_functional_test_case
{
/** @var \phpbb\filesystem\filesystem_interface */
protected $filesystem;
/** @var \phpbb\files\factory */
protected $factory;
/** @var \bantu\IniGetWrapper\IniGetWrapper */
protected $php_ini;
/** @var \phpbb\language\language */
protected $language;
/** @var \phpbb\request\request_interface */
protected $request;
/** @var string phpBB root path */
protected $phpbb_root_path;
public function setUp()
{
parent::setUp();
@ -27,8 +41,7 @@ class phpbb_functional_fileupload_remote_test extends phpbb_functional_test_case
// URL
// Global $config required by unique_id
// Global $user required by fileupload::remote_upload
global $config, $user;
global $config, $phpbb_root_path, $phpEx;
if (!is_array($config))
{
@ -38,9 +51,17 @@ class phpbb_functional_fileupload_remote_test extends phpbb_functional_test_case
$config['rand_seed'] = '';
$config['rand_seed_last_update'] = time() + 600;
$user = new phpbb_mock_user();
$user->lang = new phpbb_mock_lang();
$this->filesystem = new \phpbb\filesystem\filesystem();
$this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
$this->request = $this->getMock('\phpbb\request\request');
$this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper;
$container = new phpbb_mock_container_builder();
$container->set('files.filespec', new \phpbb\files\filespec($this->filesystem, $this->language, $this->php_ini, new \FastImageSize\FastImageSize(), $this->phpbb_root_path));
$this->factory = new \phpbb\files\factory($container);
$container->set('files.factory', $this->factory);
$container->set('files.types.remote', new \phpbb\files\types\remote($this->factory, $this->language, $this->php_ini, $this->request, $phpbb_root_path));
$this->phpbb_root_path = $phpbb_root_path;
}
public function tearDown()
@ -52,30 +73,47 @@ class phpbb_functional_fileupload_remote_test extends phpbb_functional_test_case
public function test_invalid_extension()
{
$upload = new fileupload($this->filesystem, '', array('jpg'), 100);
$file = $upload->remote_upload(self::$root_url . 'develop/blank.gif');
/** @var \phpbb\files\upload $upload */
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload->set_error_prefix('')
->set_allowed_extensions(array('jpg'))
->set_max_filesize(100);
$file = $upload->handle_upload('files.types.remote', self::$root_url . 'develop/blank.gif');
$this->assertEquals('URL_INVALID', $file->error[0]);
}
public function test_empty_file()
{
$upload = new fileupload($this->filesystem, '', array('jpg'), 100);
$file = $upload->remote_upload(self::$root_url . 'develop/blank.jpg');
/** @var \phpbb\files\upload $upload */
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload->set_error_prefix('')
->set_allowed_extensions(array('jpg'))
->set_max_filesize(100);
$file = $upload->handle_upload('files.types.remote', self::$root_url . 'develop/blank.jpg');
$this->assertEquals('EMPTY_REMOTE_DATA', $file->error[0]);
}
public function test_successful_upload()
{
$upload = new fileupload($this->filesystem, '', array('gif'), 1000);
$file = $upload->remote_upload(self::$root_url . 'styles/prosilver/theme/images/forum_read.gif');
/** @var \phpbb\files\upload $upload */
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload->set_error_prefix('')
->set_allowed_extensions(array('gif'))
->set_max_filesize(1000);
$file = $upload->handle_upload('files.types.remote', self::$root_url . 'styles/prosilver/theme/images/forum_read.gif');
$this->assertEquals(0, sizeof($file->error));
$this->assertTrue(file_exists($file->filename));
$this->assertTrue(file_exists($file->get('filename')));
$this->assertTrue($file->is_uploaded());
}
public function test_too_large()
{
$upload = new fileupload($this->filesystem, '', array('gif'), 100);
$file = $upload->remote_upload(self::$root_url . 'styles/prosilver/theme/images/forum_read.gif');
/** @var \phpbb\files\upload $upload */
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload->set_error_prefix('')
->set_allowed_extensions(array('gif'))
->set_max_filesize(100);
$file = $upload->handle_upload('files.types.remote', self::$root_url . 'styles/prosilver/theme/images/forum_read.gif');
$this->assertEquals(1, sizeof($file->error));
$this->assertEquals('WRONG_FILESIZE', $file->error[0]);
}

View File

@ -24,11 +24,11 @@ class phpbb_installer_config_test extends phpbb_test_case
{
$phpbb_root_path = __DIR__ . './../../phpBB/';
$filesystem = $this->getMock('\phpbb\filesystem\filesystem');
$php_ini = $this->getMockBuilder('\phpbb\php\ini')
$php_ini = $this->getMockBuilder('\bantu\IniGetWrapper\IniGetWrapper')
->getMock();
$php_ini->method('get_int')
$php_ini->method('getInt')
->willReturn(-1);
$php_ini->method('get_bytes')
$php_ini->method('getBytes')
->willReturn(-1);
$this->config = new config($filesystem, $php_ini, $phpbb_root_path);

View File

@ -43,7 +43,7 @@ class module_base_test extends phpbb_test_case
$this->module = new test_installer_module($module_collection, true, false);
$iohandler = $this->getMock('\phpbb\install\helper\iohandler\iohandler_interface');
$config = new \phpbb\install\helper\config(new \phpbb\filesystem\filesystem(), new \phpbb\php\ini(), '', 'php');
$config = new \phpbb\install\helper\config(new \phpbb\filesystem\filesystem(), new \bantu\IniGetWrapper\IniGetWrapper(), '', 'php');
$this->module->setup($config, $iohandler);
}

View File

@ -19,9 +19,10 @@ class phpbb_mock_fileupload
{
public $max_filesize = 100;
public $error_prefix = '';
public $valid_dimensions = true;
public function valid_dimensions($filespec)
{
return true;
return $this->valid_dimensions;
}
}

View File

@ -48,7 +48,7 @@ class phpbb_plupload_test extends phpbb_test_case
$config,
new phpbb_mock_request,
new \phpbb\user($lang, '\phpbb\datetime'),
new \phpbb\php\ini,
new \bantu\IniGetWrapper\IniGetWrapper,
new \phpbb\mimetype\guesser(array(new \phpbb\mimetype\extension_guesser))
);

View File

@ -13,7 +13,6 @@
require_once __DIR__ . '/../../phpBB/includes/functions.php';
require_once __DIR__ . '/../../phpBB/includes/utf/utf_tools.php';
require_once __DIR__ . '/../../phpBB/includes/functions_upload.php';
class phpbb_filespec_test extends phpbb_test_case
{
@ -26,12 +25,16 @@ class phpbb_filespec_test extends phpbb_test_case
private $filesystem;
public $path;
/** @var \phpbb\language\language */
protected $language;
/** @var string phpBB root path */
protected $phpbb_root_path;
protected function setUp()
{
// Global $config required by unique_id
// Global $user required by filespec::additional_checks and
// filespec::move_file
global $config, $user, $phpbb_filesystem;
global $config, $phpbb_root_path, $phpEx;
if (!is_array($config))
{
@ -45,9 +48,6 @@ class phpbb_filespec_test extends phpbb_test_case
// See: phpBB/install/schemas/schema_data.sql
$config['mime_triggers'] = 'body|head|html|img|plaintext|a href|pre|script|table|title';
$user = new phpbb_mock_user();
$user->lang = new phpbb_mock_lang();
$this->config = &$config;
$this->path = __DIR__ . '/fixture/';
@ -76,8 +76,17 @@ class phpbb_filespec_test extends phpbb_test_case
$guessers[2]->set_priority(-2);
$guessers[3]->set_priority(-2);
$this->mimetype_guesser = new \phpbb\mimetype\guesser($guessers);
$this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
$this->filesystem = $phpbb_filesystem = new \phpbb\filesystem\filesystem();
$this->filesystem = new \phpbb\filesystem\filesystem();
$this->phpbb_root_path = $phpbb_root_path;
}
private function set_reflection_property(&$class, $property_name, $value)
{
$property = new ReflectionProperty($class, $property_name);
$property->setAccessible(true);
$property->setValue($class, $value);
}
private function get_filespec($override = array())
@ -91,14 +100,13 @@ class phpbb_filespec_test extends phpbb_test_case
'error' => '',
);
return new filespec(array_merge($upload_ary, $override), null, $this->filesystem, $this->mimetype_guesser);
$filespec = new \phpbb\files\filespec($this->filesystem, $this->language, new \bantu\IniGetWrapper\IniGetWrapper, new \FastImageSize\FastImageSize(), $this->phpbb_root_path, $this->mimetype_guesser);
return $filespec->set_upload_ary(array_merge($upload_ary, $override));
}
protected function tearDown()
{
global $user;
$this->config = array();
$user = null;
$iterator = new DirectoryIterator($this->path . 'copies');
foreach ($iterator as $fileinfo)
@ -111,6 +119,13 @@ class phpbb_filespec_test extends phpbb_test_case
}
}
public function test_empty_upload_ary()
{
$filespec = new \phpbb\files\filespec($this->filesystem, $this->language, new \bantu\IniGetWrapper\IniGetWrapper, new \FastImageSize\FastImageSize(), $this->phpbb_root_path, $this->mimetype_guesser);
$this->assertInstanceOf('\phpbb\files\filespec', $filespec->set_upload_ary(array()));
$this->assertTrue($filespec->init_error());
}
public function additional_checks_variables()
{
// False here just indicates the file is too large and fails the
@ -132,13 +147,26 @@ class phpbb_filespec_test extends phpbb_test_case
{
$upload = new phpbb_mock_fileupload();
$filespec = $this->get_filespec();
$filespec->upload = $upload;
$filespec->file_moved = true;
$filespec->filesize = $filespec->get_filesize($this->path . $filename);
$filespec->set_upload_namespace($upload);
$this->set_reflection_property($filespec, 'file_moved', true);
$this->set_reflection_property($filespec, 'filesize', $filespec->get_filesize($this->path . $filename));
$this->assertEquals($expected, $filespec->additional_checks());
}
public function test_additional_checks_dimensions()
{
$upload = new phpbb_mock_fileupload();
$filespec = $this->get_filespec();
$filespec->set_upload_namespace($upload);
$upload->valid_dimensions = false;
$this->set_reflection_property($filespec, 'file_moved', true);
$upload->max_filesize = 0;
$this->assertEquals(false, $filespec->additional_checks());
$this->assertSame(array('WRONG_SIZE'), $filespec->error);
}
public function check_content_variables()
{
// False here indicates that a file is non-binary and contains
@ -173,6 +201,7 @@ class phpbb_filespec_test extends phpbb_test_case
array($chunks[2] . $chunks[9]),
array($chunks[3] . $chunks[4]),
array($chunks[5] . $chunks[6]),
array('foobar.png'),
);
}
@ -184,7 +213,7 @@ class phpbb_filespec_test extends phpbb_test_case
$bad_chars = array("'", "\\", ' ', '/', ':', '*', '?', '"', '<', '>', '|');
$filespec = $this->get_filespec(array('name' => $filename));
$filespec->clean_filename('real', self::PREFIX);
$name = $filespec->realname;
$name = $filespec->get('realname');
$this->assertEquals(0, preg_match('/%(\w{2})/', $name));
foreach ($bad_chars as $char)
@ -200,7 +229,7 @@ class phpbb_filespec_test extends phpbb_test_case
{
$filespec = $this->get_filespec();
$filespec->clean_filename('unique', self::PREFIX);
$name = $filespec->realname;
$name = $filespec->get('realname');
$this->assertEquals(strlen($name), 32 + strlen(self::PREFIX));
$this->assertRegExp('#^[A-Za-z0-9]+$#', substr($name, strlen(self::PREFIX)));
@ -209,6 +238,55 @@ class phpbb_filespec_test extends phpbb_test_case
}
}
public function test_clean_filename_unique_ext()
{
$filenames = array();
for ($tests = 0; $tests < self::TEST_COUNT; $tests++)
{
$filespec = $this->get_filespec(array('name' => 'foobar.jpg'));
$filespec->clean_filename('unique_ext', self::PREFIX);
$name = $filespec->get('realname');
$this->assertEquals(strlen($name), 32 + strlen(self::PREFIX) + strlen('.jpg'));
$this->assertRegExp('#^[A-Za-z0-9]+\.jpg$#', substr($name, strlen(self::PREFIX)));
$this->assertFalse(isset($filenames[$name]));
$filenames[$name] = true;
}
}
public function data_clean_filename_avatar()
{
return array(
array(false, false, ''),
array('foobar.png', 'u5.png', 'avatar', 'u', 5),
array('foobar.png', 'g9.png', 'avatar', 'g', 9),
);
}
/**
* @dataProvider data_clean_filename_avatar
*/
public function test_clean_filename_avatar($filename, $expected, $mode, $prefix = '', $user_id = '')
{
$filespec = new \phpbb\files\filespec($this->filesystem, $this->language, new \bantu\IniGetWrapper\IniGetWrapper, new \FastImageSize\FastImageSize(), $this->phpbb_root_path, $this->mimetype_guesser);
if ($filename)
{
$upload_ary = array(
'name' => $filename,
'type' => '',
'size' => '',
'tmp_name' => '',
'error' => '',
);
$filespec->set_upload_ary($upload_ary);
}
$filespec->clean_filename($mode, $prefix, $user_id);
$this->assertSame($expected, $filespec->get('realname'));
}
public function get_extension_variables()
{
return array(
@ -226,7 +304,7 @@ class phpbb_filespec_test extends phpbb_test_case
*/
public function test_get_extension($filename, $expected)
{
$this->assertEquals($expected, filespec::get_extension($filename));
$this->assertEquals($expected, \phpbb\files\filespec::get_extension($filename));
}
public function is_image_variables()
@ -289,7 +367,7 @@ class phpbb_filespec_test extends phpbb_test_case
array('txt_copy', 'txt_as_img', 'image/jpg', 'txt', false, true),
array('txt_copy_2', 'txt_moved', 'text/plain', 'txt', false, true),
array('jpg_copy', 'jpg_moved', 'image/png', 'jpg', false, true),
array('png_copy', 'png_moved', 'image/png', 'jpg', 'IMAGE_FILETYPE_MISMATCH png jpg', true),
array('png_copy', 'png_moved', 'image/png', 'jpg', 'Image file type mismatch: expected extension png but extension jpg given.', true),
);
}
@ -300,8 +378,7 @@ class phpbb_filespec_test extends phpbb_test_case
{
// Global $phpbb_root_path and $phpEx are required by phpbb_chmod
global $phpbb_root_path, $phpEx;
$phpbb_root_path = '';
$phpEx = 'php';
$this->phpbb_root_path = '';
$upload = new phpbb_mock_fileupload();
$upload->max_filesize = self::UPLOAD_MAX_FILESIZE;
@ -311,18 +388,137 @@ class phpbb_filespec_test extends phpbb_test_case
'name' => $realname,
'type' => $mime_type,
));
$filespec->extension = $extension;
$filespec->upload = $upload;
$filespec->local = true;
$this->set_reflection_property($filespec, 'extension', $extension);
$filespec->set_upload_namespace($upload);
$this->set_reflection_property($filespec, 'local', true);
$this->assertEquals($expected, $filespec->move_file($this->path . 'copies'));
$this->assertEquals($filespec->file_moved, file_exists($this->path . 'copies/' . $realname));
$this->assertEquals($filespec->get('file_moved'), file_exists($this->path . 'copies/' . $realname));
if ($error)
{
$this->assertEquals($error, $filespec->error[0]);
}
$phpEx = '';
$this->phpbb_root_path = $phpbb_root_path;
}
public function test_move_file_error()
{
$filespec = $this->get_filespec();
$this->assertFalse($filespec->move_file('foobar'));
$filespec->error[] = 'foo';
$this->assertFalse($filespec->move_file('foo'));
}
public function data_move_file_copy()
{
return array(
array('gif_copy', true, false, array()),
array('gif_copy', true, true, array()),
array('foo_bar', false, false, array('GENERAL_UPLOAD_ERROR')),
array('foo_bar', false, true, array('GENERAL_UPLOAD_ERROR')),
);
}
/**
* @dataProvider data_move_file_copy
*/
public function test_move_file_copy($tmp_name, $move_success, $safe_mode_on, $expected_error)
{
// Initialise a blank filespec object for use with trivial methods
$upload_ary = array(
'name' => 'gif_moved',
'type' => 'image/gif',
'size' => '',
'tmp_name' => $this->path . 'copies/' . $tmp_name,
'error' => '',
);
$php_ini = $this->getMockBuilder('\bantu\IniGetWrapper\IniGetWrapper')
->getMock();
$php_ini->expects($this->any())
->method('getBool')
->with($this->anything())
->willReturn($safe_mode_on);
$upload = new phpbb_mock_fileupload();
$upload->max_filesize = self::UPLOAD_MAX_FILESIZE;
$filespec = new \phpbb\files\filespec($this->filesystem, $this->language, $php_ini, new \FastImageSize\FastImagesize, '', $this->mimetype_guesser);
$filespec->set_upload_ary($upload_ary);
$this->set_reflection_property($filespec, 'local', false);
$this->set_reflection_property($filespec, 'extension', 'gif');
$filespec->set_upload_namespace($upload);
$this->assertEquals($move_success, $filespec->move_file($this->path . 'copies'));
$this->assertEquals($filespec->get('file_moved'), file_exists($this->path . 'copies/gif_moved'));
$this->assertSame($expected_error, $filespec->error);
}
public function data_move_file_imagesize()
{
return array(
array(
array(
'width' => 2,
'height' => 2,
'type' => IMAGETYPE_GIF,
),
array()
),
array(
array(
'width' => 2,
'height' => 2,
'type' => -1,
),
array('Image file type -1 for mimetype image/gif not supported.')
),
array(
array(
'width' => 0,
'height' => 0,
'type' => IMAGETYPE_GIF,
),
array('The image file you tried to attach is invalid.')
),
array(
false,
array('It was not possible to determine the dimensions of the image. Please verify that the URL you entered is correct.')
)
);
}
/**
* @dataProvider data_move_file_imagesize
*/
public function test_move_file_imagesize($imagesize_return, $expected_error)
{
// Initialise a blank filespec object for use with trivial methods
$upload_ary = array(
'name' => 'gif_moved',
'type' => 'image/gif',
'size' => '',
'tmp_name' => $this->path . 'copies/gif_copy',
'error' => '',
);
$imagesize = $this->getMockBuilder('\FastImageSize\FastImageSize')
->getMock();
$imagesize->expects($this->any())
->method('getImageSize')
->with($this->anything())
->willReturn($imagesize_return);
$upload = new phpbb_mock_fileupload();
$upload->max_filesize = self::UPLOAD_MAX_FILESIZE;
$filespec = new \phpbb\files\filespec($this->filesystem, $this->language, new \bantu\IniGetWrapper\IniGetWrapper, $imagesize, '', $this->mimetype_guesser);
$filespec->set_upload_ary($upload_ary);
$this->set_reflection_property($filespec, 'local', false);
$this->set_reflection_property($filespec, 'extension', 'gif');
$filespec->set_upload_namespace($upload);
$this->assertEquals(true, $filespec->move_file($this->path . 'copies'));
$this->assertEquals($filespec->get('file_moved'), file_exists($this->path . 'copies/gif_moved'));
$this->assertSame($expected_error, $filespec->error);
}
/**
@ -336,6 +532,29 @@ class phpbb_filespec_test extends phpbb_test_case
$type_cast_helper->set_var($upload_name, $filename, 'string', true, true);
$filespec = $this->get_filespec(array('name'=> $upload_name));
$this->assertSame(trim(utf8_basename(htmlspecialchars($filename))), $filespec->uploadname);
$this->assertSame(trim(utf8_basename(htmlspecialchars($filename))), $filespec->get('uploadname'));
}
public function test_is_uploaded()
{
$filespec = new \phpbb\files\filespec($this->filesystem, $this->language, new \bantu\IniGetWrapper\IniGetWrapper, new \FastImageSize\FastImageSize(), $this->phpbb_root_path, null);
$reflection_filespec = new ReflectionClass($filespec);
$plupload_property = $reflection_filespec->getProperty('plupload');
$plupload_property->setAccessible(true);
$plupload_mock = $this->getMockBuilder('\phpbb\plupload\plupload')
->disableOriginalConstructor()
->getMock();
$plupload_mock->expects($this->any())
->method('is_active')
->will($this->returnValue(true));
$plupload_property->setValue($filespec, $plupload_mock);
$is_uploaded = $reflection_filespec->getMethod('is_uploaded');
// Plupload is active and file does not exist
$this->assertFalse($is_uploaded->invoke($filespec));
// Plupload is not active and file was not uploaded
$plupload_property->setValue($filespec, null);
$this->assertFalse($is_uploaded->invoke($filespec));
}
}

View File

@ -13,7 +13,6 @@
require_once __DIR__ . '/../../phpBB/includes/functions.php';
require_once __DIR__ . '/../../phpBB/includes/utf/utf_tools.php';
require_once __DIR__ . '/../../phpBB/includes/functions_upload.php';
require_once __DIR__ . '/../mock/filespec.php';
class phpbb_fileupload_test extends phpbb_test_case
@ -22,29 +21,80 @@ class phpbb_fileupload_test extends phpbb_test_case
private $filesystem;
/** @var \Symfony\Component\DependencyInjection\ContainerInterface */
protected $container;
/** @var \phpbb\files\factory */
protected $factory;
/** @var \bantu\IniGetWrapper\IniGetWrapper */
protected $php_ini;
/** @var \phpbb\language\language */
protected $language;
/** @var \phpbb\request\request_interface */
protected $request;
/** @var string phpBB root path */
protected $phpbb_root_path;
protected function setUp()
{
// Global $config required by unique_id
// Global $user required by several functions dealing with translations
// Global $request required by form_upload, local_upload and is_valid
global $config, $user, $request, $phpbb_filesystem;
global $config, $phpbb_root_path, $phpEx;
if (!is_array($config))
{
$config = array();
$config = new \phpbb\config\config(array());
}
$config['rand_seed'] = '';
$config['rand_seed_last_update'] = time() + 600;
$user = new phpbb_mock_user();
$user->lang = new phpbb_mock_lang();
$this->request = $this->getMock('\phpbb\request\request');
$this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper;
$request = new phpbb_mock_request();
$this->filesystem = new \phpbb\filesystem\filesystem();
$this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
$guessers = array(
new \Symfony\Component\HttpFoundation\File\MimeType\FileinfoMimeTypeGuesser(),
new \Symfony\Component\HttpFoundation\File\MimeType\FileBinaryMimeTypeGuesser(),
new \phpbb\mimetype\content_guesser(),
new \phpbb\mimetype\extension_guesser(),
);
$guessers[2]->set_priority(-2);
$guessers[3]->set_priority(-2);
$this->mimetype_guesser = new \phpbb\mimetype\guesser($guessers);
$this->filesystem = $phpbb_filesystem = new \phpbb\filesystem\filesystem();
$this->container = new phpbb_mock_container_builder($phpbb_root_path, $phpEx);
$this->container->set('files.filespec', new \phpbb\files\filespec(
$this->filesystem,
$this->language,
$this->php_ini,
new \FastImageSize\FastImageSize(),
$phpbb_root_path,
new \phpbb\mimetype\guesser(array(
'mimetype.extension_guesser' => new \phpbb\mimetype\extension_guesser(),
))));
$this->factory = new \phpbb\files\factory($this->container);
$plupload = new \phpbb\plupload\plupload($phpbb_root_path, $config, $this->request, new \phpbb\user($this->language, '\phpbb\datetime'), $this->php_ini, $this->mimetype_guesser);
$this->container->set('files.types.form', new \phpbb\files\types\form(
$this->factory,
$this->language,
$this->php_ini,
$plupload,
$this->request
), phpbb_mock_container_builder::SCOPE_PROTOTYPE);
$this->container->set('files.types.local', new \phpbb\files\types\local(
$this->factory,
$this->language,
$this->php_ini,
$this->request
), phpbb_mock_container_builder::SCOPE_PROTOTYPE);
$this->path = __DIR__ . '/fixture/';
$this->phpbb_root_path = $phpbb_root_path;
}
private function gen_valid_filespec()
@ -69,15 +119,38 @@ class phpbb_fileupload_test extends phpbb_test_case
public function test_common_checks_invalid_extension()
{
$upload = new fileupload($this->filesystem, '', array('png'), 100);
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload->set_allowed_extensions(array('png'))
->set_max_filesize(100);
$file = $this->gen_valid_filespec();
$upload->common_checks($file);
$this->assertEquals('DISALLOWED_EXTENSION', $file->error[0]);
}
public function test_common_checks_disallowed_content()
{
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload->set_allowed_extensions(array('jpg'))
->set_max_filesize(1000);
$file = new \phpbb\files\filespec($this->filesystem, $this->language, $this->php_ini, new \FastImageSize\FastImageSize(), $this->phpbb_root_path);
$file->set_upload_ary(array(
'size' => 50,
'tmp_name' => dirname(__FILE__) . '/fixture/disallowed',
'name' => 'disallowed.jpg',
'type' => 'image/jpg'
))
->set_upload_namespace($upload);
file_put_contents(dirname(__FILE__) . '/fixture/disallowed', '<body>' . file_get_contents(dirname(__FILE__) . '/fixture/jpg'));
$upload->common_checks($file);
$this->assertEquals('DISALLOWED_CONTENT', $file->error[0]);
unlink(dirname(__FILE__) . '/fixture/disallowed');
}
public function test_common_checks_invalid_filename()
{
$upload = new fileupload($this->filesystem, '', array('jpg'), 100);
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload->set_allowed_extensions(array('jpg'))
->set_max_filesize(100);
$file = $this->gen_valid_filespec();
$file->realname = 'invalid?';
$upload->common_checks($file);
@ -86,7 +159,9 @@ class phpbb_fileupload_test extends phpbb_test_case
public function test_common_checks_too_large()
{
$upload = new fileupload($this->filesystem, '', array('jpg'), 100);
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload->set_allowed_extensions(array('jpg'))
->set_max_filesize(100);
$file = $this->gen_valid_filespec();
$file->filesize = 1000;
$upload->common_checks($file);
@ -95,7 +170,9 @@ class phpbb_fileupload_test extends phpbb_test_case
public function test_common_checks_valid_file()
{
$upload = new fileupload($this->filesystem, '', array('jpg'), 1000);
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload->set_allowed_extensions(array('jpg'))
->set_max_filesize(1000);
$file = $this->gen_valid_filespec();
$upload->common_checks($file);
$this->assertEquals(0, sizeof($file->error));
@ -103,33 +180,41 @@ class phpbb_fileupload_test extends phpbb_test_case
public function test_local_upload()
{
$upload = new fileupload($this->filesystem, '', array('jpg'), 1000);
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload->set_allowed_extensions(array('jpg'))
->set_max_filesize(1000);
copy($this->path . 'jpg', $this->path . 'jpg.jpg');
$file = $upload->local_upload($this->path . 'jpg.jpg');
$file = $upload->handle_upload('files.types.local', $this->path . 'jpg.jpg');
$this->assertEquals(0, sizeof($file->error));
unlink($this->path . 'jpg.jpg');
$this->assertFalse($file->additional_checks());
$this->assertTrue($file->move_file('../tests/upload/fixture/copies', true));
$file->remove();
}
public function test_move_existent_file()
{
$upload = new fileupload($this->filesystem, '', array('jpg'), 1000);
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload->set_allowed_extensions(array('jpg'))
->set_max_filesize(1000);
copy($this->path . 'jpg', $this->path . 'jpg.jpg');
$file = $upload->local_upload($this->path . 'jpg.jpg');
$file = $upload->handle_upload('files.types.local', $this->path . 'jpg.jpg');
$this->assertEquals(0, sizeof($file->error));
$this->assertFalse($file->move_file('../tests/upload/fixture'));
$this->assertFalse($file->file_moved);
$this->assertFalse($file->get('file_moved'));
$this->assertEquals(1, sizeof($file->error));
}
public function test_move_existent_file_overwrite()
{
$upload = new fileupload($this->filesystem, '', array('jpg'), 1000);
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload->set_allowed_extensions(array('jpg'))
->set_max_filesize(1000);
copy($this->path . 'jpg', $this->path . 'jpg.jpg');
copy($this->path . 'jpg', $this->path . 'copies/jpg.jpg');
$file = $upload->local_upload($this->path . 'jpg.jpg');
$file = $upload->handle_upload('files.types.local', $this->path . 'jpg.jpg');
$this->assertEquals(0, sizeof($file->error));
$file->move_file('../tests/upload/fixture/copies', true);
$this->assertEquals(0, sizeof($file->error));
@ -138,7 +223,10 @@ class phpbb_fileupload_test extends phpbb_test_case
public function test_valid_dimensions()
{
$upload = new fileupload($this->filesystem, '', false, false, 1, 1, 100, 100);
$upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path);
$upload->set_allowed_extensions(false)
->set_max_filesize(false)
->set_allowed_dimensions(1, 1, 100, 100);
$file1 = $this->gen_valid_filespec();
$file2 = $this->gen_valid_filespec();

View File

@ -11,7 +11,7 @@
*
*/
class phpbb_php_ini_fake extends \phpbb\php\ini
class phpbb_php_ini_fake extends \bantu\IniGetWrapper\IniGetWrapper
{
function get($varname)
{

View File

@ -16,6 +16,7 @@ require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
class phpbb_wrapper_phpbb_php_ini_test extends phpbb_test_case
{
/** @var \phpbb_php_ini_fake php_ini */
protected $php_ini;
public function setUp()
@ -25,44 +26,44 @@ class phpbb_wrapper_phpbb_php_ini_test extends phpbb_test_case
public function test_get_string()
{
$this->assertSame(false, $this->php_ini->get_string(false));
$this->assertSame('phpbb', $this->php_ini->get_string(' phpbb '));
$this->assertSame('', $this->php_ini->getString(false));
$this->assertSame('phpbb', $this->php_ini->getString(' phpbb '));
}
public function test_get_bool()
{
$this->assertSame(true, $this->php_ini->get_bool('ON'));
$this->assertSame(true, $this->php_ini->get_bool('on'));
$this->assertSame(true, $this->php_ini->get_bool('1'));
$this->assertSame(true, $this->php_ini->getBool('ON'));
$this->assertSame(true, $this->php_ini->getBool('on'));
$this->assertSame(true, $this->php_ini->getBool('1'));
$this->assertSame(false, $this->php_ini->get_bool('OFF'));
$this->assertSame(false, $this->php_ini->get_bool('off'));
$this->assertSame(false, $this->php_ini->get_bool('0'));
$this->assertSame(false, $this->php_ini->get_bool(''));
$this->assertSame(false, $this->php_ini->getBool('OFF'));
$this->assertSame(false, $this->php_ini->getBool('off'));
$this->assertSame(false, $this->php_ini->getBool('0'));
$this->assertSame(false, $this->php_ini->getBool(''));
}
public function test_get_int()
{
$this->assertSame(1234, $this->php_ini->get_int('1234'));
$this->assertSame(-12345, $this->php_ini->get_int('-12345'));
$this->assertSame(false, $this->php_ini->get_int('phpBB'));
$this->assertSame(1234, $this->php_ini->getNumeric('1234'));
$this->assertSame(-12345, $this->php_ini->getNumeric('-12345'));
$this->assertSame(null, $this->php_ini->getNumeric('phpBB'));
}
public function test_get_float()
{
$this->assertSame(1234.0, $this->php_ini->get_float('1234'));
$this->assertSame(-12345.0, $this->php_ini->get_float('-12345'));
$this->assertSame(false, $this->php_ini->get_float('phpBB'));
$this->assertSame(1234.0, $this->php_ini->getNumeric('1234.0'));
$this->assertSame(-12345.0, $this->php_ini->getNumeric('-12345.0'));
$this->assertSame(null, $this->php_ini->getNumeric('phpBB'));
}
public function test_get_bytes_invalid()
{
$this->assertSame(false, $this->php_ini->get_bytes(false));
$this->assertSame(false, $this->php_ini->get_bytes('phpBB'));
$this->assertSame(false, $this->php_ini->get_bytes('k'));
$this->assertSame(false, $this->php_ini->get_bytes('-k'));
$this->assertSame(false, $this->php_ini->get_bytes('M'));
$this->assertSame(false, $this->php_ini->get_bytes('-M'));
$this->assertSame(null, $this->php_ini->getBytes(false));
$this->assertSame(null, $this->php_ini->getBytes('phpBB'));
$this->assertSame(null, $this->php_ini->getBytes('k'));
$this->assertSame(null, $this->php_ini->getBytes('-k'));
$this->assertSame(null, $this->php_ini->getBytes('M'));
$this->assertSame(null, $this->php_ini->getBytes('-M'));
}
/**
@ -70,7 +71,7 @@ class phpbb_wrapper_phpbb_php_ini_test extends phpbb_test_case
*/
public function test_get_bytes($expected, $value)
{
$actual = $this->php_ini->get_bytes($value);
$actual = $this->php_ini->getBytes($value);
$this->assertTrue(is_float($actual) || is_int($actual));
$this->assertEquals($expected, $actual);