Skip to content

Commit c2b158f

Browse files
author
Alexander Akimov
authored
Merge pull request #3382 from magento-tsg/2.1.16-develop-pr60
[TSG] Backporting for 2.1 (pr60) (2.1.16)
2 parents ed63da0 + 8c815df commit c2b158f

File tree

22 files changed

+481
-103
lines changed

22 files changed

+481
-103
lines changed

.htaccess

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,15 +114,6 @@ DirectoryIndex index.php
114114
order allow,deny
115115
deny from all
116116
</Files>
117-
<Files .user.ini>
118-
<IfVersion < 2.4>
119-
order allow,deny
120-
deny from all
121-
</IfVersion>
122-
<IfVersion >= 2.4>
123-
Require all denied
124-
</IfVersion>
125-
</Files>
126117
ErrorDocument 404 /pub/errors/404.php
127118
ErrorDocument 403 /pub/errors/404.php
128119
<IfModule mod_headers.c>

.htaccess.sample

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -278,15 +278,6 @@ DirectoryIndex index.php
278278
order allow,deny
279279
deny from all
280280
</Files>
281-
<Files .user.ini>
282-
<IfVersion < 2.4>
283-
order allow,deny
284-
deny from all
285-
</IfVersion>
286-
<IfVersion >= 2.4>
287-
Require all denied
288-
</IfVersion>
289-
</Files>
290281

291282
# For 404s and 403s that aren't handled by the application, show plain 404 response
292283
ErrorDocument 404 /pub/errors/404.php

app/code/Magento/AdminNotification/Block/Grid/Renderer/Actions.php

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@
1010

1111
namespace Magento\AdminNotification\Block\Grid\Renderer;
1212

13-
/**
14-
* Renderer class for action in the admin notifications grid
15-
*/
1613
class Actions extends \Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer
1714
{
1815
/**
@@ -42,9 +39,9 @@ public function __construct(
4239
*/
4340
public function render(\Magento\Framework\DataObject $row)
4441
{
45-
$readDetailsHtml = $row->getUrl() ? '<a class="action-details" target="_blank" href="' .
46-
$this->escapeUrl($row->getUrl()) . '">' .
47-
__('Read Details') . '</a> | ' : '';
42+
$readDetailsHtml = $row->getUrl() ? '<a class="action-details" target="_blank" href="' . $row->getUrl() . '">' . __(
43+
'Read Details'
44+
) . '</a> | ' : '';
4845

4946
$markAsReadHtml = !$row->getIsRead() ? '<a class="action-mark" href="' . $this->getUrl(
5047
'*/*/markAsRead/',

app/code/Magento/CatalogImportExport/Model/Import/Uploader.php

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@
1717
*/
1818
class Uploader extends \Magento\MediaStorage\Model\File\Uploader
1919
{
20+
/**
21+
* HTTP scheme
22+
* used to compare against the filename and select the proper DriverPool adapter
23+
* @var string
24+
*/
25+
private $httpScheme = 'http://';
26+
2027
/**
2128
* Temp directory.
2229
*
@@ -99,7 +106,7 @@ class Uploader extends \Magento\MediaStorage\Model\File\Uploader
99106
* @param \Magento\MediaStorage\Model\File\Validator\NotProtectedExtension $validator
100107
* @param \Magento\Framework\Filesystem $filesystem
101108
* @param \Magento\Framework\Filesystem\File\ReadFactory $readFactory
102-
* @param null $filePath
109+
* @param string|null $filePath
103110
* @param \Magento\Framework\App\Filesystem\DirectoryResolver|null $directoryResolver
104111
* @throws \Magento\Framework\Exception\LocalizedException
105112
*/
@@ -148,23 +155,38 @@ public function init()
148155
* @param string $fileName
149156
* @param bool $renameFileOff
150157
* @return array
158+
* @throws \Magento\Framework\Exception\LocalizedException
151159
*/
152160
public function move($fileName, $renameFileOff = false)
153161
{
154162
if ($renameFileOff) {
155163
$this->setAllowRenameFiles(false);
156164
}
165+
166+
if ($this->getTmpDir()) {
167+
$filePath = $this->getTmpDir() . '/';
168+
} else {
169+
$filePath = '';
170+
}
171+
157172
if (preg_match('/\bhttps?:\/\//i', $fileName, $matches)) {
158173
$url = str_replace($matches[0], '', $fileName);
159-
$read = $this->_readFactory->create($url, DriverPool::HTTP);
174+
$driver = $matches[0] === $this->httpScheme ? DriverPool::HTTP : DriverPool::HTTPS;
175+
$read = $this->_readFactory->create($url, $driver);
176+
177+
$fileExtension = pathinfo($fileName, PATHINFO_EXTENSION);
178+
if ($fileExtension && !$this->checkAllowedExtension($fileExtension)) {
179+
throw new \Magento\Framework\Exception\LocalizedException(__('Disallowed file type.'));
180+
}
181+
160182
$fileName = preg_replace('/[^a-z0-9\._-]+/i', '', $fileName);
161183
$this->_directory->writeFile(
162-
$this->_directory->getRelativePath($this->getTmpDir() . '/' . $fileName),
184+
$this->_directory->getRelativePath($filePath . $fileName),
163185
$read->readAll()
164186
);
165187
}
166188

167-
$filePath = $this->_directory->getRelativePath($this->getTmpDir() . '/' . $fileName);
189+
$filePath = $this->_directory->getRelativePath($filePath . $fileName);
168190
$this->_setUploadFile($filePath);
169191
$destDir = $this->_directory->getAbsolutePath($this->getDestDir());
170192
$result = $this->save($destDir);
@@ -332,7 +354,7 @@ protected function _moveFile($tmpPath, $destPath)
332354
}
333355

334356
/**
335-
* {@inheritdoc}
357+
* @inheritdoc
336358
*/
337359
protected function chmod($file)
338360
{

app/code/Magento/CatalogImportExport/Test/Unit/Model/Import/UploaderTest.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,17 +105,17 @@ protected function setUp()
105105
null,
106106
$this->directoryResolver,
107107
])
108-
->setMethods(['_setUploadFile', 'save', 'getTmpDir'])
108+
->setMethods(['_setUploadFile', 'save', 'getTmpDir', 'checkAllowedExtension'])
109109
->getMock();
110110
}
111111

112112
/**
113113
* @dataProvider moveFileUrlDataProvider
114114
*/
115-
public function testMoveFileUrl($fileUrl, $expectedHost, $expectedFileName)
115+
public function testMoveFileUrl($fileUrl, $expectedHost, $expectedFileName, $checkAllowedExtension)
116116
{
117117
$destDir = 'var/dest/dir';
118-
$expectedRelativeFilePath = $this->uploader->getTmpDir() . '/' . $expectedFileName;
118+
$expectedRelativeFilePath = $expectedFileName;
119119
$this->directoryMock->expects($this->once())->method('isWritable')->with($destDir)->willReturn(true);
120120
$this->directoryMock->expects($this->any())->method('getRelativePath')->with($expectedRelativeFilePath);
121121
$this->directoryMock->expects($this->once())->method('getAbsolutePath')->with($destDir)
@@ -140,6 +140,9 @@ public function testMoveFileUrl($fileUrl, $expectedHost, $expectedFileName)
140140
$this->uploader->expects($this->once())->method('_setUploadFile')->will($this->returnSelf());
141141
$this->uploader->expects($this->once())->method('save')->with($destDir . '/' . $expectedFileName)
142142
->willReturn(['name' => $expectedFileName, 'path' => 'absPath']);
143+
$this->uploader->expects($this->exactly($checkAllowedExtension))
144+
->method('checkAllowedExtension')
145+
->willReturn(true);
143146

144147
$this->uploader->setDestDir($destDir);
145148
$result = $this->uploader->move($fileUrl);
@@ -151,7 +154,7 @@ public function testMoveFileName()
151154
{
152155
$destDir = 'var/dest/dir';
153156
$fileName = 'test_uploader_file';
154-
$expectedRelativeFilePath = $this->uploader->getTmpDir() . '/' . $fileName;
157+
$expectedRelativeFilePath = $fileName;
155158
$this->directoryMock->expects($this->once())->method('isWritable')->with($destDir)->willReturn(true);
156159
$this->directoryMock->expects($this->any())->method('getRelativePath')->with($expectedRelativeFilePath);
157160
$this->directoryMock->expects($this->once())->method('getAbsolutePath')->with($destDir)
@@ -176,11 +179,13 @@ public function moveFileUrlDataProvider()
176179
'$fileUrl' => 'http://test_uploader_file',
177180
'$expectedHost' => 'test_uploader_file',
178181
'$expectedFileName' => 'httptest_uploader_file',
182+
'$checkAllowedExtension' => 0,
179183
],
180184
[
181185
'$fileUrl' => 'https://!:^&`;file',
182186
'$expectedHost' => '!:^&`;file',
183187
'$expectedFileName' => 'httpsfile',
188+
'$checkAllowedExtension' => 0,
184189
],
185190
];
186191
}

app/code/Magento/Checkout/view/frontend/web/js/view/form/element/email.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ define([
3434
listens: {
3535
email: 'emailHasChanged',
3636
emailFocused: 'validateEmail'
37+
},
38+
ignoreTmpls: {
39+
email: true
3740
}
3841
},
3942
checkDelay: 2000,

app/code/Magento/Cms/Controller/Adminhtml/Wysiwyg/Images/DeleteFiles.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public function execute()
8282
$filesystem = $this->_objectManager->get(\Magento\Framework\Filesystem::class);
8383
$dir = $filesystem->getDirectoryRead(DirectoryList::MEDIA);
8484
$filePath = $path . '/' . \Magento\Framework\File\Uploader::getCorrectFileName($file);
85-
if ($dir->isFile($dir->getRelativePath($filePath))) {
85+
if ($dir->isFile($dir->getRelativePath($filePath)) && !preg_match('/^\\.htaccess$/', $file)) {
8686
$this->getStorage()->deleteFile($filePath);
8787
}
8888
}

app/code/Magento/Eav/Model/Attribute/Data/File.php

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,7 @@ public function extractValue(RequestInterface $request)
119119
}
120120

121121
/**
122-
* Validate file by attribute validate rules
123-
* Return array of errors
122+
* Validate file by attribute validate rules and return array of errors.
124123
*
125124
* @param array $value
126125
* @return string[]
@@ -146,7 +145,7 @@ protected function _validateByRules($value)
146145
return $this->_fileValidator->getMessages();
147146
}
148147

149-
if (!is_uploaded_file($value['tmp_name'])) {
148+
if (!empty($value['tmp_name']) && !is_uploaded_file($value['tmp_name'])) {
150149
return [__('"%1" is not a valid file.', $label)];
151150
}
152151

@@ -173,13 +172,23 @@ public function validateValue($value)
173172
if ($this->getIsAjaxRequest()) {
174173
return true;
175174
}
175+
$fileData = $value;
176+
177+
if (is_string($value) && !empty($value)) {
178+
$dir = $this->_directory->getAbsolutePath($this->getAttribute()->getEntityType()->getEntityTypeCode());
179+
$fileData = [
180+
'size' => filesize($dir . $value),
181+
'name' => $value,
182+
'tmp_name' => $dir . $value,
183+
];
184+
}
176185

177186
$errors = [];
178187
$attribute = $this->getAttribute();
179188
$label = $attribute->getStoreLabel();
180189

181190
$toDelete = !empty($value['delete']) ? true : false;
182-
$toUpload = !empty($value['tmp_name']) ? true : false;
191+
$toUpload = !empty($value['tmp_name']) || is_string($value) && !empty($value) ? true : false;
183192

184193
if (!$toUpload && !$toDelete && $this->getEntity()->getData($attribute->getAttributeCode())) {
185194
return true;
@@ -194,11 +203,13 @@ public function validateValue($value)
194203
}
195204

196205
if ($toUpload) {
197-
$errors = array_merge($errors, $this->_validateByRules($value));
206+
$errors = array_merge($errors, $this->_validateByRules($fileData));
198207
}
199208

200209
if (count($errors) == 0) {
201210
return true;
211+
} elseif (is_string($value) && !empty($value)) {
212+
$this->_directory->delete($dir . $value);
202213
}
203214

204215
return $errors;

app/code/Magento/Ui/Controller/Adminhtml/Index/Render/Handle.php

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,33 +9,82 @@
99
use Magento\Ui\Component\Control\ActionPool;
1010
use Magento\Ui\Component\Wrapper\UiComponent;
1111
use Magento\Ui\Controller\Adminhtml\AbstractAction;
12+
use Magento\Backend\App\Action\Context;
13+
use Magento\Framework\View\Element\UiComponent\Config\ManagerInterface;
14+
use Magento\Framework\View\Element\UiComponentFactory;
15+
use Magento\Framework\App\ObjectManager;
1216

1317
/**
1418
* Class Handle
1519
*/
1620
class Handle extends AbstractAction
1721
{
22+
/**
23+
* @var ManagerInterface
24+
*/
25+
private $componentManager;
26+
27+
/**
28+
* @param Context $context
29+
* @param UiComponentFactory $factory
30+
* @param ManagerInterface|null $componentManager
31+
*/
32+
public function __construct(
33+
Context $context,
34+
UiComponentFactory $factory,
35+
ManagerInterface $componentManager = null
36+
) {
37+
parent::__construct($context, $factory);
38+
$this->componentManager = $componentManager ?: ObjectManager::getInstance()->get(ManagerInterface::class);
39+
}
40+
1841
/**
1942
* Render UI component by namespace in handle context
2043
*
2144
* @return void
2245
*/
2346
public function execute()
2447
{
48+
$response = '';
2549
$handle = $this->_request->getParam('handle');
2650
$namespace = $this->_request->getParam('namespace');
2751
$buttons = $this->_request->getParam('buttons', false);
28-
2952
$this->_view->loadLayout(['default', $handle], true, true, false);
53+
$layout = $this->_view->getLayout();
54+
$config = $this->componentManager->getData($namespace);
3055

31-
$uiComponent = $this->_view->getLayout()->getBlock($namespace);
32-
$response = $uiComponent instanceof UiComponent ? $uiComponent->toHtml() : '';
56+
if ($this->validateAclResource($config[$namespace])) {
57+
$uiComponent = $layout->getBlock($namespace);
58+
$response = $uiComponent instanceof UiComponent ? $uiComponent->toHtml() : '';
59+
}
3360

3461
if ($buttons) {
35-
$actionsToolbar = $this->_view->getLayout()->getBlock(ActionPool::ACTIONS_PAGE_TOOLBAR);
62+
$actionsToolbar = $layout->getBlock(ActionPool::ACTIONS_PAGE_TOOLBAR);
3663
$response .= $actionsToolbar instanceof Template ? $actionsToolbar->toHtml() : '';
3764
}
3865

3966
$this->_response->appendBody($response);
4067
}
68+
69+
/**
70+
* Optionally validate ACL resource of components.
71+
*
72+
* @param mixed $dataProviderConfigData
73+
* @return bool
74+
*/
75+
private function validateAclResource($dataProviderConfigData)
76+
{
77+
$aclResource = isset($dataProviderConfigData['arguments']['data']['acl'])
78+
? $dataProviderConfigData['arguments']['data']['acl']
79+
: false;
80+
if ($aclResource !== false && !$this->_authorization->isAllowed($aclResource)) {
81+
if (!$this->_request->isAjax()) {
82+
$this->_redirect('admin/denied');
83+
}
84+
85+
return false;
86+
}
87+
88+
return true;
89+
}
4190
}

0 commit comments

Comments
 (0)