Fix a warning generated in return_bytes function and refactor it

It was multiplying a string containing a letter.

Moved function to Utils.php and display a human readable limit size
This commit is contained in:
ArthurHoaro 2017-03-10 20:06:01 +01:00
parent d9d49b687a
commit 84315a3bad
4 changed files with 172 additions and 31 deletions

View file

@ -345,3 +345,92 @@ function format_date($date, $time = true, $intl = true)
return $formatter->format($date);
}
/**
* Check if the input is an integer, no matter its real type.
*
* PHP is a bit messy regarding this:
* - is_int returns false if the input is a string
* - ctype_digit returns false if the input is an integer or negative
*
* @param mixed $input value
*
* @return bool true if the input is an integer, false otherwise
*/
function is_integer_mixed($input)
{
if (is_array($input) || is_bool($input) || is_object($input)) {
return false;
}
$input = strval($input);
return ctype_digit($input) || (startsWith($input, '-') && ctype_digit(substr($input, 1)));
}
/**
* Convert post_max_size/upload_max_filesize (e.g. '16M') parameters to bytes.
*
* @param string $val Size expressed in string.
*
* @return int Size expressed in bytes.
*/
function return_bytes($val)
{
if (is_integer_mixed($val) || $val === '0' || empty($val)) {
return $val;
}
$val = trim($val);
$last = strtolower($val[strlen($val)-1]);
$val = intval(substr($val, 0, -1));
switch($last) {
case 'g': $val *= 1024;
case 'm': $val *= 1024;
case 'k': $val *= 1024;
}
return $val;
}
/**
* Return a human readable size from bytes.
*
* @param int $bytes value
*
* @return string Human readable size
*/
function human_bytes($bytes)
{
if ($bytes === '') {
return t('Setting not set');
}
if (! is_integer_mixed($bytes)) {
return $bytes;
}
$bytes = intval($bytes);
if ($bytes === 0) {
return t('Unlimited');
}
$units = [t('B'), t('kiB'), t('MiB'), t('GiB')];
for ($i = 0; $i < count($units) && $bytes >= 1024; ++$i) {
$bytes /= 1024;
}
return $bytes . $units[$i];
}
/**
* Try to determine max file size for uploads (POST).
* Returns an integer (in bytes)
*
* @param mixed $limitPost post_max_size PHP setting
* @param mixed $limitUpload upload_max_filesize PHP setting
*
* @return int max upload file size in bytes.
*/
function get_max_upload_size($limitPost, $limitUpload)
{
$size1 = return_bytes($limitPost);
$size2 = return_bytes($limitUpload);
// Return the smaller of two:
$maxsize = min($size1, $size2);
return human_bytes($maxsize);
}

View file

@ -472,34 +472,6 @@ if (isset($_POST['login']))
}
}
// ------------------------------------------------------------------------------------------
// Misc utility functions:
// Convert post_max_size/upload_max_filesize (e.g. '16M') parameters to bytes.
function return_bytes($val)
{
$val = trim($val); $last=strtolower($val[strlen($val)-1]);
switch($last)
{
case 'g': $val *= 1024;
case 'm': $val *= 1024;
case 'k': $val *= 1024;
}
return $val;
}
// Try to determine max file size for uploads (POST).
// Returns an integer (in bytes)
function getMaxFileSize()
{
$size1 = return_bytes(ini_get('post_max_size'));
$size2 = return_bytes(ini_get('upload_max_filesize'));
// Return the smaller of two:
$maxsize = min($size1,$size2);
// FIXME: Then convert back to readable notations ? (e.g. 2M instead of 2000000)
return $maxsize;
}
// ------------------------------------------------------------------------------------------
// Token management for XSRF protection
// Token should be used in any form which acts on data (create,update,delete,import...).
@ -1517,7 +1489,7 @@ function renderPage($conf, $pluginManager, $LINKSDB)
if (! isset($_POST['token']) || ! isset($_FILES['filetoupload'])) {
// Show import dialog
$PAGE->assign('maxfilesize', getMaxFileSize());
$PAGE->assign('maxfilesize', get_max_upload_size(ini_get('post_max_size'), ini_get('upload_max_filesize')));
$PAGE->renderPage('import');
exit;
}
@ -1527,7 +1499,7 @@ function renderPage($conf, $pluginManager, $LINKSDB)
// The file is too big or some form field may be missing.
echo '<script>alert("The file you are trying to upload is probably'
.' bigger than what this webserver can accept ('
.getMaxFileSize().' bytes).'
.get_max_upload_size(ini_get('post_max_size'), ini_get('upload_max_filesize')).').'
.' Please upload in smaller chunks.");document.location=\'?do='
.Router::$PAGE_IMPORT .'\';</script>';
exit;

View file

@ -4,6 +4,7 @@
*/
require_once 'application/Utils.php';
require_once 'application/Languages.php';
require_once 'tests/utils/ReferenceSessionIdHashes.php';
// Initialize reference data before PHPUnit starts a session
@ -326,4 +327,83 @@ class UtilsTest extends PHPUnit_Framework_TestCase
$this->assertFalse(format_date([]));
$this->assertFalse(format_date(null));
}
/**
* Test is_integer_mixed with valid values
*/
public function testIsIntegerMixedValid()
{
$this->assertTrue(is_integer_mixed(12));
$this->assertTrue(is_integer_mixed('12'));
$this->assertTrue(is_integer_mixed(-12));
$this->assertTrue(is_integer_mixed('-12'));
$this->assertTrue(is_integer_mixed(0));
$this->assertTrue(is_integer_mixed('0'));
$this->assertTrue(is_integer_mixed(0x0a));
}
/**
* Test is_integer_mixed with invalid values
*/
public function testIsIntegerMixedInvalid()
{
$this->assertFalse(is_integer_mixed(true));
$this->assertFalse(is_integer_mixed(false));
$this->assertFalse(is_integer_mixed([]));
$this->assertFalse(is_integer_mixed(['test']));
$this->assertFalse(is_integer_mixed([12]));
$this->assertFalse(is_integer_mixed(new DateTime()));
$this->assertFalse(is_integer_mixed('0x0a'));
$this->assertFalse(is_integer_mixed('12k'));
$this->assertFalse(is_integer_mixed('k12'));
$this->assertFalse(is_integer_mixed(''));
}
/**
* Test return_bytes
*/
public function testReturnBytes()
{
$this->assertEquals(2 * 1024, return_bytes('2k'));
$this->assertEquals(2 * 1024, return_bytes('2K'));
$this->assertEquals(2 * (1024 ** 2), return_bytes('2m'));
$this->assertEquals(2 * (1024 ** 2), return_bytes('2M'));
$this->assertEquals(2 * (1024 ** 3), return_bytes('2g'));
$this->assertEquals(2 * (1024 ** 3), return_bytes('2G'));
$this->assertEquals(374, return_bytes('374'));
$this->assertEquals(374, return_bytes(374));
$this->assertEquals(0, return_bytes('0'));
$this->assertEquals(0, return_bytes(0));
$this->assertEquals(-1, return_bytes('-1'));
$this->assertEquals(-1, return_bytes(-1));
$this->assertEquals('', return_bytes(''));
}
/**
* Test human_bytes
*/
public function testHumanBytes()
{
$this->assertEquals('2kiB', human_bytes(2 * 1024));
$this->assertEquals('2kiB', human_bytes(strval(2 * 1024)));
$this->assertEquals('2MiB', human_bytes(2 * (1024 ** 2)));
$this->assertEquals('2MiB', human_bytes(strval(2 * (1024 ** 2))));
$this->assertEquals('2GiB', human_bytes(2 * (1024 ** 3)));
$this->assertEquals('2GiB', human_bytes(strval(2 * (1024 ** 3))));
$this->assertEquals('374B', human_bytes(374));
$this->assertEquals('374B', human_bytes('374'));
$this->assertEquals('Unlimited', human_bytes('0'));
$this->assertEquals('Unlimited', human_bytes(0));
$this->assertEquals('Setting not set', human_bytes(''));
}
/**
* Test get_max_upload_size
*/
public function testGetMaxUploadSize()
{
$this->assertEquals('1MiB', get_max_upload_size(2097152, '1024k'));
$this->assertEquals('1MiB', get_max_upload_size('1m', '2m'));
$this->assertEquals('100B', get_max_upload_size(100, 100));
}
}

View file

@ -5,7 +5,7 @@
<div id="pageheader">
{include="page.header"}
<div id="uploaddiv">
Import Netscape HTML bookmarks (as exported from Firefox/Chrome/Opera/Delicious/Diigo...) (Max: {$maxfilesize} bytes).
Import Netscape HTML bookmarks (as exported from Firefox/Chrome/Opera/Delicious/Diigo...) (Max: {$maxfilesize}).
<form method="POST" action="?do=import" enctype="multipart/form-data"
name="uploadform" id="uploadform">
<input type="hidden" name="token" value="{$token}">