29
0
mirror of https://github.com/joomla/joomla-cms.git synced 2024-06-24 22:39:31 +00:00

Merge commit 'd17dde8' into 4.0-dev

This commit is contained in:
wilsonge 2021-04-05 19:27:39 +01:00
commit 321def11e9
No known key found for this signature in database
GPG Key ID: EF81319318FC9D04
20 changed files with 399 additions and 267 deletions

View File

@ -460,4 +460,31 @@ class BannerModel extends AdminModel
{
return Factory::getUser()->authorise('core.create', 'com_banners');
}
/**
* Method to validate the form data.
*
* @param JForm $form The form to validate against.
* @param array $data The data to validate.
* @param string $group The name of the field group to validate.
*
* @return array|boolean Array of filtered data if valid, false otherwise.
*
* @see JFormRule
* @see JFilterInput
* @since 3.9.26
*/
public function validate($form, $data, $group = null)
{
// Don't allow to change the users if not allowed to access com_users.
if (!JFactory::getUser()->authorise('core.manage', 'com_users'))
{
if (isset($data['created_by']))
{
unset($data['created_by']);
}
}
return parent::validate($form, $data, $group);
}
}

View File

@ -382,7 +382,7 @@ class CategoryModel extends AdminModel
/**
* Method to validate the form data.
*
* @param JForm $form The form to validate against.
* @param Form $form The form to validate against.
* @param array $data The data to validate.
* @param string $group The name of the field group to validate.
*
@ -394,6 +394,15 @@ class CategoryModel extends AdminModel
*/
public function validate($form, $data, $group = null)
{
// Don't allow to change the users if not allowed to access com_users.
if (!Factory::getUser()->authorise('core.manage', 'com_users'))
{
if (isset($data['created_user_id']))
{
unset($data['created_user_id']);
}
}
if (!Factory::getUser()->authorise('core.admin', $data['extension']))
{
if (isset($data['rules']))

View File

@ -543,4 +543,31 @@ class ContactModel extends AdminModel
{
return Factory::getUser()->authorise('core.create', 'com_contact');
}
/**
* Method to validate the form data.
*
* @param JForm $form The form to validate against.
* @param array $data The data to validate.
* @param string $group The name of the field group to validate.
*
* @return array|boolean Array of filtered data if valid, false otherwise.
*
* @see JFormRule
* @see JFilterInput
* @since 3.9.26
*/
public function validate($form, $data, $group = null)
{
// Don't allow to change the users if not allowed to access com_users.
if (!JFactory::getUser()->authorise('core.manage', 'com_users'))
{
if (isset($data['created_by']))
{
unset($data['created_by']);
}
}
return parent::validate($form, $data, $group);
}
}

View File

@ -498,7 +498,7 @@ class ArticleModel extends AdminModel implements WorkflowModelInterface
$record = new \stdClass;
// Get ID of the article from input, for frontend, we use a_id while backend uses id
$articleIdFromInput = $app->input->getInt('a_id') ?: $app->input->getInt('id', 0);
$articleIdFromInput = (int) $app->input->getInt('a_id') ?: $app->input->getInt('id', 0);
// On edit article, we get ID of article from article.id state, but on save, we use data from input
$id = (int) $this->getState('article.id', $articleIdFromInput);
@ -634,17 +634,12 @@ class ArticleModel extends AdminModel implements WorkflowModelInterface
public function validate($form, $data, $group = null)
{
// Don't allow to change the users if not allowed to access com_users.
if (Factory::getApplication()->isClient('administrator') && !Factory::getUser()->authorise('core.manage', 'com_users'))
if (!Factory::getUser()->authorise('core.manage', 'com_users'))
{
if (isset($data['created_by']))
{
unset($data['created_by']);
}
if (isset($data['modified_by']))
{
unset($data['modified_by']);
}
}
if (!Factory::getUser()->authorise('core.admin', 'com_content'))

View File

@ -936,6 +936,15 @@ class FieldModel extends AdminModel
*/
public function validate($form, $data, $group = null)
{
// Don't allow to change the users if not allowed to access com_users.
if (!Factory::getUser()->authorise('core.manage', 'com_users'))
{
if (isset($data['created_user_id']))
{
unset($data['created_user_id']);
}
}
if (!Factory::getUser()->authorise('core.admin', 'com_fields'))
{
if (isset($data['rules']))

View File

@ -280,6 +280,15 @@ class GroupModel extends AdminModel
*/
public function validate($form, $data, $group = null)
{
// Don't allow to change the users if not allowed to access com_users.
if (!Factory::getUser()->authorise('core.manage', 'com_users'))
{
if (isset($data['created_by']))
{
unset($data['created_by']);
}
}
if (!Factory::getUser()->authorise('core.admin', 'com_fields'))
{
if (isset($data['rules']))

View File

@ -30,6 +30,7 @@
size="50"
default="images"
validate="filePath"
exclude="administrator|api|bin|cache|cli|components|includes|language|layouts|libraries|media|modules|plugins|templates|tmp"
/>
<field
@ -40,6 +41,7 @@
size="50"
default="images"
validate="filePath"
exclude="administrator|api|bin|cache|cli|components|includes|language|layouts|libraries|modules|plugins|templates|tmp"
/>
<field

View File

@ -448,4 +448,31 @@ class NewsfeedModel extends AdminModel
{
return Factory::getUser()->authorise('core.create', 'com_newsfeeds');
}
/**
* Method to validate the form data.
*
* @param JForm $form The form to validate against.
* @param array $data The data to validate.
* @param string $group The name of the field group to validate.
*
* @return array|boolean Array of filtered data if valid, false otherwise.
*
* @see JFormRule
* @see JFilterInput
* @since 3.9.26
*/
public function validate($form, $data, $group = null)
{
// Don't allow to change the users if not allowed to access com_users.
if (!JFactory::getUser()->authorise('core.manage', 'com_users'))
{
if (isset($data['created_by']))
{
unset($data['created_by']);
}
}
return parent::validate($form, $data, $group);
}
}

View File

@ -14,6 +14,7 @@ namespace Joomla\Component\Templates\Administrator\Controller;
use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\Client\ClientHelper;
use Joomla\CMS\Filesystem\Path;
use Joomla\CMS\Filter\InputFilter;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\Controller\BaseController;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
@ -74,7 +75,7 @@ class TemplateController extends BaseController
public function close()
{
$file = base64_encode('home');
$id = $this->input->get('id');
$id = (int) $this->input->get('id', 0, 'int');
$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
$this->setRedirect(Route::_($url, false));
}
@ -150,10 +151,10 @@ class TemplateController extends BaseController
$app = $this->app;
$this->input->set('installtype', 'folder');
$newName = $this->input->get('new_name');
$newNameRaw = $this->input->get('new_name', null, 'string');
$templateID = $this->input->getInt('id', 0);
$file = $this->input->get('file');
$newName = (string) $this->input->get('new_name', null, 'cmd');
$newNameRaw = (string) $this->input->get('new_name', null, 'string');
$templateID = (int) $this->input->getInt('id', 0);
$file = (string) $this->input->get('file', '', 'cmd');
// Access check.
if (!$this->allowEdit())
@ -288,7 +289,7 @@ class TemplateController extends BaseController
/** @var \Joomla\Component\Templates\Administrator\Model\TemplateModel $model */
$model = $this->getModel();
$fileName = $this->input->get('file');
$fileName = (string) $this->input->getCmd('file', '');
$explodeArray = explode(':', base64_decode($fileName));
// Access check.
@ -382,7 +383,7 @@ class TemplateController extends BaseController
default:
// Redirect to the list screen.
$file = base64_encode('home');
$id = $this->input->get('id');
$id = (int) $this->input->get('id', 0, 'int');
$url = 'index.php?option=com_templates&view=template&id=' . $id . '&file=' . $file;
$this->setRedirect(Route::_($url, false));
break;
@ -403,9 +404,15 @@ class TemplateController extends BaseController
/* @var \Joomla\Component\Templates\Administrator\Model\TemplateModel $model */
$model = $this->getModel();
$file = $this->input->get('file');
$override = base64_decode($this->input->get('folder'));
$id = $this->input->get('id');
$file = (string) $this->input->getCmd('file', '');
$override = (string) InputFilter::getInstance(
[],
[],
InputFilter::ONLY_BLOCK_DEFINED_TAGS,
InputFilter::ONLY_BLOCK_DEFINED_ATTRIBUTES
)
->clean(base64_decode($this->input->getBase64('folder', '')), 'path');
$id = (int) $this->input->get('id', 0, 'int');
// Access check.
if (!$this->allowEdit())
@ -436,8 +443,8 @@ class TemplateController extends BaseController
/* @var \Joomla\Component\Templates\Administrator\Model\TemplateModel $model */
$model = $this->getModel();
$id = $this->input->get('id');
$file = $this->input->get('file');
$id = (int) $this->input->get('id', 0, 'int');
$file = (string) $this->input->getCmd('file', '');
// Access check.
if (!$this->allowEdit())
@ -488,11 +495,17 @@ class TemplateController extends BaseController
/* @var \Joomla\Component\Templates\Administrator\Model\TemplateModel $model */
$model = $this->getModel();
$id = $this->input->get('id');
$file = $this->input->get('file');
$name = $this->input->get('name');
$location = base64_decode($this->input->get('address'));
$type = $this->input->get('type');
$id = (int) $this->input->get('id', 0, 'int');
$file = (string) $this->input->get('file', '', 'cmd');
$name = (string) $this->input->get('name', '', 'cmd');
$location = (string) InputFilter::getinstance(
[],
[],
InputFilter::ONLY_BLOCK_DEFINED_TAGS,
InputFilter::ONLY_BLOCK_DEFINED_ATTRIBUTES
)
->clean(base64_decode($this->input->getBase64('address', '')), 'path');
$type = (string) $this->input->get('type', '', 'cmd');
// Access check.
if (!$this->allowEdit())
@ -543,10 +556,16 @@ class TemplateController extends BaseController
/* @var \Joomla\Component\Templates\Administrator\Model\TemplateModel $model */
$model = $this->getModel();
$id = $this->input->get('id');
$file = $this->input->get('file');
$id = (int) $this->input->get('id', 0, 'int');
$file = (string) $this->input->getCmd('file', '');
$upload = $this->input->files->get('files');
$location = base64_decode($this->input->get('address'));
$location = (string) InputFilter::getinstance(
[],
[],
InputFilter::ONLY_BLOCK_DEFINED_TAGS,
InputFilter::ONLY_BLOCK_DEFINED_ATTRIBUTES
)
->clean(base64_decode($this->input->getBase64('address', '')), 'path');
// Access check.
if (!$this->allowEdit())
@ -585,10 +604,16 @@ class TemplateController extends BaseController
/** @var \Joomla\Component\Templates\Administrator\Model\TemplateModel $model */
$model = $this->getModel();
$id = $this->input->get('id');
$file = $this->input->get('file');
$id = (int) $this->input->get('id', 0, 'int');
$file = (string) $this->input->getCmd('file', '');
$name = $this->input->get('name');
$location = base64_decode($this->input->get('address'));
$location = (string) InputFilter::getinstance(
[],
[],
InputFilter::ONLY_BLOCK_DEFINED_TAGS,
InputFilter::ONLY_BLOCK_DEFINED_ATTRIBUTES
)
->clean(base64_decode($this->input->getBase64('address', '')), 'path');
// Access check.
if (!$this->allowEdit())
@ -632,9 +657,15 @@ class TemplateController extends BaseController
/** @var \Joomla\Component\Templates\Administrator\Model\TemplateModel $model */
$model = $this->getModel();
$id = $this->input->get('id');
$file = $this->input->get('file');
$location = base64_decode($this->input->get('address'));
$id = (int) $this->input->get('id', 0, 'int');
$file = (string) $this->input->getCmd('file', '');
$location = (string) InputFilter::getinstance(
[],
[],
InputFilter::ONLY_BLOCK_DEFINED_TAGS,
InputFilter::ONLY_BLOCK_DEFINED_ATTRIBUTES
)
->clean(base64_decode($this->input->getBase64('address', '')), 'path');
// Access check.
if (!$this->allowEdit())
@ -684,8 +715,8 @@ class TemplateController extends BaseController
/** @var \Joomla\Component\Templates\Administrator\Model\TemplateModel $model */
$model = $this->getModel();
$id = $this->input->get('id');
$file = $this->input->get('file');
$id = (int) $this->input->get('id', 0, 'int');
$file = (string) $this->input->getCmd('file', '');
$newName = $this->input->get('new_name');
// Access check.
@ -740,8 +771,8 @@ class TemplateController extends BaseController
// Check for request forgeries
$this->checkToken();
$id = $this->input->get('id');
$file = $this->input->get('file');
$id = (int) $this->input->get('id', 0, 'int');
$file = (string) $this->input->get('file', '', 'cmd');
$x = $this->input->get('x');
$y = $this->input->get('y');
$w = $this->input->get('w');
@ -790,8 +821,8 @@ class TemplateController extends BaseController
// Check for request forgeries
$this->checkToken();
$id = $this->input->get('id');
$file = $this->input->get('file');
$id = (int) $this->input->get('id', 0, 'int');
$file = (string) $this->input->getCmd('file', '');
$width = $this->input->get('width');
$height = $this->input->get('height');
@ -832,10 +863,16 @@ class TemplateController extends BaseController
// Check for request forgeries
$this->checkToken();
$id = $this->input->get('id');
$file = $this->input->get('file');
$id = (int) $this->input->get('id', 0, 'int');
$file = (string) $this->input->getCmd('file', '');
$newName = $this->input->get('new_name');
$location = base64_decode($this->input->get('address'));
$location = (string) InputFilter::getinstance(
[],
[],
InputFilter::ONLY_BLOCK_DEFINED_TAGS,
InputFilter::ONLY_BLOCK_DEFINED_ATTRIBUTES
)
->clean(base64_decode($this->input->getBase64('address', '')), 'path');
/** @var \Joomla\Component\Templates\Administrator\Model\TemplateModel $model */
$model = $this->getModel();
@ -879,8 +916,8 @@ class TemplateController extends BaseController
// Check for request forgeries
$this->checkToken();
$id = $this->input->get('id');
$file = $this->input->get('file');
$id = (int) $this->input->get('id', 0, 'int');
$file = (string) $this->input->getCmd('file', '');
/** @var \Joomla\Component\Templates\Administrator\Model\TemplateModel $model */
$model = $this->getModel();

View File

@ -567,7 +567,7 @@ window.Joomla.Modal = window.Joomla.Modal || {
xhr.setRequestHeader('X-CSRF-Token', token);
}
if (typeof(newOptions.data) === 'string' && (!newOptions.headers || !newOptions.headers['Content-Type'])) {
if (typeof newOptions.data === 'string' && (!newOptions.headers || !newOptions.headers['Content-Type'])) {
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
}
}
@ -622,6 +622,8 @@ window.Joomla.Modal = window.Joomla.Modal || {
/**
* Render messages send via JSON
* Used by some javascripts such as validate.js
* PLEASE NOTE: do NOT use user supplied input in messages as potential HTML markup is NOT
* sanitized!
*
* @param {object} messages JavaScript object containing the messages to render.
* Example:

View File

@ -44,6 +44,7 @@
"joomla/di": "~2.0@beta",
"joomla/event": "~2.0@beta",
"joomla/filter": "~2.0@beta",
"joomla/filesystem": "~2.0@beta",
"joomla/http": "~2.0@beta",
"joomla/input": "~2.0@beta",
"joomla/ldap": "~2.0@beta",

71
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "fc3ee4f2bb425d887d0db9c8414ef048",
"content-hash": "d6ea791308d89b7eb383f389fc52dbc3",
"packages": [
{
"name": "algo26-matthias/idna-convert",
@ -646,20 +646,20 @@
},
{
"name": "joomla/archive",
"version": "2.0.0-beta2",
"version": "2.0.0-beta5",
"source": {
"type": "git",
"url": "https://github.com/joomla-framework/archive.git",
"reference": "d533a68cba5a5d4f3107bb16319fcb7fc226194b"
"reference": "fbaba1042083fb73f11575bc9efef3f583c1861d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/joomla-framework/archive/zipball/d533a68cba5a5d4f3107bb16319fcb7fc226194b",
"reference": "d533a68cba5a5d4f3107bb16319fcb7fc226194b",
"url": "https://api.github.com/repos/joomla-framework/archive/zipball/fbaba1042083fb73f11575bc9efef3f583c1861d",
"reference": "fbaba1042083fb73f11575bc9efef3f583c1861d",
"shasum": ""
},
"require": {
"joomla/filesystem": "^1.3|^2.0",
"joomla/filesystem": "^2.0@beta",
"php": "^7.2.5"
},
"require-dev": {
@ -694,7 +694,21 @@
"framework",
"joomla"
],
"time": "2020-12-17T15:24:30+00:00"
"support": {
"issues": "https://github.com/joomla-framework/archive/issues",
"source": "https://github.com/joomla-framework/archive/tree/2.0.0-beta5"
},
"funding": [
{
"url": "https://community.joomla.org/sponsorship-campaigns.html",
"type": "custom"
},
{
"url": "https://github.com/joomla",
"type": "github"
}
],
"time": "2021-03-06T12:46:31+00:00"
},
{
"name": "joomla/authentication",
@ -1092,35 +1106,31 @@
},
{
"name": "joomla/filesystem",
"version": "1.6.0",
"version": "2.0.0-beta2",
"source": {
"type": "git",
"url": "https://github.com/joomla-framework/filesystem.git",
"reference": "d8801f18db358b0284675381ab4195acd028b420"
"reference": "a4d9a952b43490e4fdfdaff2cfac6c3f31c41782"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/joomla-framework/filesystem/zipball/d8801f18db358b0284675381ab4195acd028b420",
"reference": "d8801f18db358b0284675381ab4195acd028b420",
"url": "https://api.github.com/repos/joomla-framework/filesystem/zipball/a4d9a952b43490e4fdfdaff2cfac6c3f31c41782",
"reference": "a4d9a952b43490e4fdfdaff2cfac6c3f31c41782",
"shasum": ""
},
"require": {
"php": "^5.3.10|~7.0"
"php": "^7.2.5"
},
"require-dev": {
"joomla/coding-standards": "~2.0@alpha",
"joomla/test": "~1.0",
"mikey179/vfsstream": "~1.0",
"paragonie/random_compat": "~1.0|~2.0",
"phpunit/phpunit": "^4.8.35|^5.4.3|~6.0"
},
"suggest": {
"paragonie/random_compat": "Required to use Joomla\\Filesystem\\Path::isOwner()"
"joomla/coding-standards": "^2.0@alpha",
"joomla/test": "^2.0",
"mikey179/vfsstream": "^1.1",
"phpunit/phpunit": "^8.5|^9.0"
},
"type": "joomla-package",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
"dev-2.0-dev": "2.0-dev"
}
},
"autoload": {
@ -1139,7 +1149,21 @@
"framework",
"joomla"
],
"time": "2020-09-02T09:05:23+00:00"
"support": {
"issues": "https://github.com/joomla-framework/filesystem/issues",
"source": "https://github.com/joomla-framework/filesystem/tree/2.0-dev"
},
"funding": [
{
"url": "https://community.joomla.org/sponsorship-campaigns.html",
"type": "custom"
},
{
"url": "https://github.com/joomla",
"type": "github"
}
],
"time": "2020-09-02T17:35:07+00:00"
},
{
"name": "joomla/filter",
@ -8269,6 +8293,7 @@
"joomla/di": 10,
"joomla/event": 10,
"joomla/filter": 10,
"joomla/filesystem": 10,
"joomla/http": 10,
"joomla/input": 10,
"joomla/ldap": 10,
@ -8298,5 +8323,5 @@
"platform-overrides": {
"php": "7.2.5"
},
"plugin-api-version": "1.1.0"
"plugin-api-version": "2.0.0"
}

View File

@ -19,6 +19,7 @@ use Joomla\CMS\Event\ErrorEvent;
use Joomla\CMS\Exception\ExceptionHandler;
use Joomla\CMS\Extension\ExtensionManagerTrait;
use Joomla\CMS\Factory;
use Joomla\CMS\Filter\InputFilter;
use Joomla\CMS\Input\Input;
use Joomla\CMS\Language\Language;
use Joomla\CMS\Language\Text;
@ -203,11 +204,22 @@ abstract class CMSApplication extends WebApplication implements ContainerAwareIn
return;
}
$inputFilter = InputFilter::getInstance(
[],
[],
InputFilter::ONLY_BLOCK_DEFINED_TAGS,
InputFilter::ONLY_BLOCK_DEFINED_ATTRIBUTES
);
// Build the message array and apply the HTML InputFilter with the default blacklist to the message
$message = array(
'message' => $inputFilter->clean($msg, 'html'),
'type' => $inputFilter->clean(strtolower($type), 'cmd'),
);
// For empty queue, if messages exists in the session, enqueue them first.
$messages = $this->getMessageQueue();
$message = array('message' => $msg, 'type' => strtolower($type));
if (!\in_array($message, $this->messageQueue))
{
// Enqueue the message.

View File

@ -1,9 +1,17 @@
<?php
/**
<<<<<<< HEAD:libraries/src/Encrypt/Randval.php
* Joomla! Content Management System
*
* @copyright (C) 2016 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
=======
* @package FrameworkOnFramework
* @subpackage utils
* @copyright Copyright (C) 2010-2016 Nicholas K. Dionysopoulos / Akeeba Ltd. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
* @note This file has been modified by the Joomla! Project and no longer reflects the original work of its author.
>>>>>>> d17dde8:libraries/fof/encrypt/randval.php
*/
namespace Joomla\CMS\Encrypt;
@ -18,159 +26,17 @@ namespace Joomla\CMS\Encrypt;
class Randval implements RandValInterface
{
/**
*
* Returns a cryptographically secure random value.
*
* This method allows us to quickly address any future issues if we ever find problems with PHP's random_bytes() on
* some weird host (you can't be too careful when releasing mass-distributed software).
*
* @param integer $bytes How many bytes to return
*
* @return string
*/
public function generate($bytes = 32)
{
if (\extension_loaded('openssl') && (version_compare(PHP_VERSION, '5.3.4') >= 0 || IS_WIN))
{
$strong = false;
$randBytes = openssl_random_pseudo_bytes($bytes, $strong);
if ($strong)
{
return $randBytes;
}
}
if (\extension_loaded('mcrypt'))
{
return mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM);
}
return $this->genRandomBytes($bytes);
}
/**
* Generate random bytes. Adapted from Joomla! 3.2.
*
* @param integer $length Length of the random data to generate
*
* @return string Random binary data
*/
public function genRandomBytes($length = 32)
{
$length = (int) $length;
$sslStr = '';
/*
* Collect any entropy available in the system along with a number
* of time measurements of operating system randomness.
*/
$bitsPerRound = 2;
$maxTimeMicro = 400;
$shaHashLength = 20;
$randomStr = '';
$total = $length;
// Check if we can use /dev/urandom.
$urandom = false;
$handle = null;
// This is PHP 5.3.3 and up
if (\function_exists('stream_set_read_buffer') && @is_readable('/dev/urandom'))
{
$handle = @fopen('/dev/urandom', 'rb');
if ($handle)
{
$urandom = true;
}
}
while ($length > \strlen($randomStr))
{
$bytes = ($total > $shaHashLength) ? $shaHashLength : $total;
$total -= $bytes;
/*
* Collect any entropy available from the PHP system and filesystem.
* If we have ssl data that isn't strong, we use it once.
*/
$entropy = rand() . uniqid(mt_rand(), true) . $sslStr;
$entropy .= implode('', @fstat(fopen(__FILE__, 'r')));
$entropy .= memory_get_usage();
$sslStr = '';
if ($urandom)
{
stream_set_read_buffer($handle, 0);
$entropy .= @fread($handle, $bytes);
}
else
{
/*
* There is no external source of entropy so we repeat calls
* to mt_rand until we are assured there's real randomness in
* the result.
*
* Measure the time that the operations will take on average.
*/
$samples = 3;
$duration = 0;
for ($pass = 0; $pass < $samples; ++$pass)
{
$microStart = microtime(true) * 1000000;
$hash = sha1(mt_rand(), true);
for ($count = 0; $count < 50; ++$count)
{
$hash = sha1($hash, true);
}
$microEnd = microtime(true) * 1000000;
$entropy .= $microStart . $microEnd;
if ($microStart >= $microEnd)
{
$microEnd += 1000000;
}
$duration += $microEnd - $microStart;
}
$duration = $duration / $samples;
/*
* Based on the average time, determine the total rounds so that
* the total running time is bounded to a reasonable number.
*/
$rounds = (int) (($maxTimeMicro / $duration) * 50);
/*
* Take additional measurements. On average we can expect
* at least $bitsPerRound bits of entropy from each measurement.
*/
$iter = $bytes * (int) ceil(8 / $bitsPerRound);
for ($pass = 0; $pass < $iter; ++$pass)
{
$microStart = microtime(true);
$hash = sha1(mt_rand(), true);
for ($count = 0; $count < $rounds; ++$count)
{
$hash = sha1($hash, true);
}
$entropy .= $microStart . microtime(true);
}
}
$randomStr .= sha1($entropy, true);
}
if ($urandom)
{
@fclose($handle);
}
return substr($randomStr, 0, $length);
return random_bytes($bytes);
}
}

View File

@ -4,6 +4,7 @@
*
* @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
* @note This file has been modified by the Joomla! Project and no longer reflects the original work of its author.
*/
namespace Joomla\CMS\Encrypt;
@ -33,11 +34,13 @@ class Totp
private $_pinModulo;
/**
* Secret length
* The length of the secret in bytes.
* RFC 4226: "The length of the shared secret MUST be atleast 128 bits. This document RECOMMENDs a shared secret length of 160 bits."
* The original value was 10 bytes (80 bits) this value has been increased to 20 (160 bits) with Joomla 3.9.25
*
* @var integer
*/
private $_secretLength = 10;
private $_secretLength = 20;
/**
* Timestep
@ -194,15 +197,7 @@ class Totp
*/
public function generateSecret()
{
$secret = "";
for ($i = 1; $i <= $this->_secretLength; $i++)
{
$c = rand(0, 255);
$secret .= pack("c", $c);
}
$base32 = new Base32;
$secret = random_bytes($this->_secretLength);
return $this->_base32->encode($secret);
}

View File

@ -11,6 +11,7 @@ namespace Joomla\CMS\Feed;
\defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Feed\Parser\NamespaceParserInterface;
use Joomla\CMS\Filter\InputFilter;
/**
* Feed Parser class.
@ -43,16 +44,26 @@ abstract class FeedParser
*/
protected $stream;
/**
* The InputFilter
*
* @var InputFilter
* @since 3.9.26
*/
protected $inputFilter;
/**
* Constructor.
*
* @param \XMLReader $stream The XMLReader stream object for the feed.
* @param \XMLReader $stream The XMLReader stream object for the feed.
* @param InputFilter $inputFilter The InputFilter object to be used
*
* @since 3.1.4
*/
public function __construct(\XMLReader $stream)
public function __construct(\XMLReader $stream, InputFilter $inputFilter = null)
{
$this->stream = $stream;
$this->stream = $stream;
$this->inputFilter = $inputFilter ? $inputFilter : InputFilter::getInstance(array(), array(), 1, 1);
}
/**

View File

@ -42,7 +42,11 @@ class AtomParser extends FeedParser
protected function handleAuthor(Feed $feed, \SimpleXMLElement $el)
{
// Set the author information from the XML element.
$feed->setAuthor((string) $el->name, (string) $el->email, (string) $el->uri);
$feed->setAuthor(
$this->inputFilter->clean((string) $el->name, 'html'),
filter_var((string) $el->email, FILTER_VALIDATE_EMAIL),
filter_var((string) $el->uri, FILTER_VALIDATE_URL)
);
}
/**
@ -57,7 +61,11 @@ class AtomParser extends FeedParser
*/
protected function handleContributor(Feed $feed, \SimpleXMLElement $el)
{
$feed->addContributor((string) $el->name, (string) $el->email, (string) $el->uri);
$feed->addContributor(
$this->inputFilter->clean((string) $el->name, 'html'),
filter_var((string) $el->email, FILTER_VALIDATE_EMAIL),
filter_var((string) $el->uri, FILTER_VALIDATE_URL)
);
}
/**
@ -72,7 +80,7 @@ class AtomParser extends FeedParser
*/
protected function handleGenerator(Feed $feed, \SimpleXMLElement $el)
{
$feed->generator = (string) $el;
$feed->generator = $this->inputFilter->clean((string) $el, 'html');
}
/**
@ -107,7 +115,7 @@ class AtomParser extends FeedParser
$link->language = (string) $el['hreflang'];
$link->length = (int) $el['length'];
$link->relation = (string) $el['rel'];
$link->title = (string) $el['title'];
$link->title = $this->inputFilter->clean((string) $el['title'], 'html');
$link->type = (string) $el['type'];
$feed->link = $link;
@ -125,7 +133,7 @@ class AtomParser extends FeedParser
*/
protected function handleRights(Feed $feed, \SimpleXMLElement $el)
{
$feed->copyright = (string) $el;
$feed->copyright = $this->inputFilter->clean((string) $el, 'html');
}
/**
@ -140,7 +148,7 @@ class AtomParser extends FeedParser
*/
protected function handleSubtitle(Feed $feed, \SimpleXMLElement $el)
{
$feed->description = (string) $el;
$feed->description = $this->inputFilter->clean((string) $el, 'html');
}
/**
@ -155,7 +163,7 @@ class AtomParser extends FeedParser
*/
protected function handleTitle(Feed $feed, \SimpleXMLElement $el)
{
$feed->title = (string) $el;
$feed->title = $this->inputFilter->clean((string) $el, 'html');
}
/**
@ -170,7 +178,7 @@ class AtomParser extends FeedParser
*/
protected function handleUpdated(Feed $feed, \SimpleXMLElement $el)
{
$feed->updatedDate = (string) $el;
$feed->updatedDate = $this->inputFilter->clean((string) $el, 'html');
}
/**
@ -203,13 +211,13 @@ class AtomParser extends FeedParser
protected function processFeedEntry(FeedEntry $entry, \SimpleXMLElement $el)
{
$entry->uri = (string) $el->id;
$entry->title = (string) $el->title;
$entry->updatedDate = (string) $el->updated;
$entry->content = (string) $el->summary;
$entry->title = $this->inputFilter->clean((string) $el->title, 'html');
$entry->updatedDate = $this->inputFilter->clean((string) $el->updated, 'html');
$entry->content = $this->inputFilter->clean((string) $el->summary, 'html');
if (!$entry->content)
{
$entry->content = (string) $el->content;
$entry->content = $this->inputFilter->clean((string) $el->content, 'html');
}
if (filter_var($entry->uri, FILTER_VALIDATE_URL) === false && !\is_null($el->link) && $el->link)

View File

@ -50,7 +50,7 @@ class RssParser extends FeedParser
{
// Get the data from the element.
$domain = (string) $el['domain'];
$category = (string) $el;
$category = $this->inputFilter->clean((string) $el, 'html');
$feed->addCategory($category, $domain);
}
@ -89,7 +89,7 @@ class RssParser extends FeedParser
*/
protected function handleCopyright(Feed $feed, \SimpleXMLElement $el)
{
$feed->copyright = (string) $el;
$feed->copyright = $this->inputFilter->clean((string) $el, 'html');
}
/**
@ -104,7 +104,7 @@ class RssParser extends FeedParser
*/
protected function handleDescription(Feed $feed, \SimpleXMLElement $el)
{
$feed->description = (string) $el;
$feed->description = $this->inputFilter->clean((string) $el, 'html');
}
/**
@ -119,7 +119,7 @@ class RssParser extends FeedParser
*/
protected function handleGenerator(Feed $feed, \SimpleXMLElement $el)
{
$feed->generator = (string) $el;
$feed->generator = $this->inputFilter->clean((string) $el, 'html');
}
/**
@ -140,12 +140,12 @@ class RssParser extends FeedParser
null,
'logo',
null,
(string) $el->title
$this->inputFilter->clean((string) $el->title, 'html')
);
// Populate extra fields if they exist.
$image->link = (string) $el->link;
$image->description = (string) $el->description;
$image->link = (string) filter_var($el->link, FILTER_VALIDATE_URL);
$image->description = $this->inputFilter->clean((string) $el->description, 'html');
$image->height = (string) $el->height;
$image->width = (string) $el->width;
@ -164,7 +164,7 @@ class RssParser extends FeedParser
*/
protected function handleLanguage(Feed $feed, \SimpleXMLElement $el)
{
$feed->language = (string) $el;
$feed->language = $this->inputFilter->clean((string) $el, 'html');
}
/**
@ -179,7 +179,7 @@ class RssParser extends FeedParser
*/
protected function handleLastBuildDate(Feed $feed, \SimpleXMLElement $el)
{
$feed->updatedDate = (string) $el;
$feed->updatedDate = $this->inputFilter->clean((string) $el, 'html');
}
/**
@ -274,7 +274,7 @@ class RssParser extends FeedParser
*/
protected function handlePubDate(Feed $feed, \SimpleXMLElement $el)
{
$feed->publishedDate = (string) $el;
$feed->publishedDate = $this->inputFilter->clean((string) $el, 'html');
}
/**
@ -289,7 +289,7 @@ class RssParser extends FeedParser
*/
protected function handleTitle(Feed $feed, \SimpleXMLElement $el)
{
$feed->title = (string) $el;
$feed->title = $this->inputFilter->clean((string) $el, 'html');
}
/**
@ -304,7 +304,7 @@ class RssParser extends FeedParser
*/
protected function handleTtl(Feed $feed, \SimpleXMLElement $el)
{
$feed->ttl = (integer) $el;
$feed->ttl = (integer) $this->inputFilter->clean((string) $el, 'int');
}
/**
@ -328,10 +328,15 @@ class RssParser extends FeedParser
if (isset($tmp[1]))
{
$name = trim($tmp[1], ' ()');
$name = trim(
$this->inputFilter->clean($tmp[1], 'html'),
' ()'
);
}
$email = trim($tmp[0]);
$email = trim(
filter_var((string) $tmp[0], FILTER_VALIDATE_EMAIL)
);
$feed->addContributor($name, $email, null, 'webmaster');
}
@ -366,17 +371,17 @@ class RssParser extends FeedParser
*/
protected function processFeedEntry(FeedEntry $entry, \SimpleXMLElement $el)
{
$entry->uri = (string) $el->link;
$entry->title = (string) $el->title;
$entry->publishedDate = (string) $el->pubDate;
$entry->updatedDate = (string) $el->pubDate;
$entry->content = (string) $el->description;
$entry->guid = (string) $el->guid;
$entry->uri = (string) filter_var($el->link, FILTER_VALIDATE_URL);
$entry->title = $this->inputFilter->clean((string) $el->title, 'html');
$entry->publishedDate = $this->inputFilter->clean((string) $el->pubDate, 'html');
$entry->updatedDate = $this->inputFilter->clean((string) $el->pubDate, 'html');
$entry->content = $this->inputFilter->clean((string) $el->description, 'html');
$entry->guid = $this->inputFilter->clean((string) $el->guid, 'html');
$entry->isPermaLink = $entry->guid !== '' && (string) $el->guid['isPermaLink'] !== 'false';
$entry->comments = (string) $el->comments;
$entry->comments = $this->inputFilter->clean((string) $el->comments, 'html');
// Add the feed entry author if available.
$author = (string) $el->author;
$author = $this->inputFilter->clean((string) $el->author, 'html');
if (!empty($author))
{
@ -424,11 +429,16 @@ class RssParser extends FeedParser
if (isset($data[1]))
{
$person->name = trim($data[1], ' ()');
$person->name = trim(
$this->inputFilter->clean($data[1], 'html'),
' ()'
);
}
// Set the email for the person.
$person->email = trim($data[0]);
$person->email = trim(
filter_var((string) $data[0], FILTER_VALIDATE_EMAIL)
);
return $person;
}

View File

@ -337,4 +337,49 @@ class Path
// Could not find the file in the set of paths
return false;
}
/**
* Resolves /./, /../ and multiple / in a string and returns the resulting absolute path, inspired by Flysystem
* Removes trailing slashes
*
* @param string $path A path to resolve
*
* @return string The resolved path
*
* @since 1.6.0
*/
public static function resolve($path)
{
$path = static::clean($path);
// Save start character for absolute path
$startCharacter = ($path[0] === DIRECTORY_SEPARATOR) ? DIRECTORY_SEPARATOR : '';
$parts = array();
foreach (explode(DIRECTORY_SEPARATOR, $path) as $part)
{
switch ($part)
{
case '':
case '.':
break;
case '..':
if (empty($parts))
{
throw new \Exception('Path is outside of the defined root');
}
array_pop($parts);
break;
default:
$parts[] = $part;
break;
}
}
return $startCharacter . implode(DIRECTORY_SEPARATOR, $parts);
}
}

View File

@ -49,6 +49,21 @@ class FilePathRule extends FormRule
return true;
}
// Make sure $value starts with an a-z/A-Z character in ordern to not allow to break out of the current path
if (!preg_match("/^[A-Za-z]*$/", substr($value, 0, 1)))
{
return false;
}
// Check the exclude setting from the xml
$exclude = (array) explode('|', (string) $element['exclude']);
$path = explode('/', $value);
if (!empty($exclude) && (in_array(strtolower($path[0]), $exclude) || empty($path[0])))
{
return false;
}
// Append the root path
$value = JPATH_ROOT . '/' . $value;