Skip to content

Commit 22714bd

Browse files
committed
Merge remote-tracking branch 'remotes/mainline_ce/develop' into MAGETWO-37070-2
2 parents 98c1d32 + e98a487 commit 22714bd

File tree

13 files changed

+133
-54
lines changed

13 files changed

+133
-54
lines changed

app/code/Magento/Catalog/Model/Observer.php

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -149,27 +149,10 @@ protected function _addCategoriesToMenu($categories, $parentCategoryNode, $block
149149
if (!$category->getIsActive()) {
150150
continue;
151151
}
152-
153-
$nodeId = 'category-node-' . $category->getId();
154-
155152
$block->addIdentity(\Magento\Catalog\Model\Category::CACHE_TAG . '_' . $category->getId());
156153

157154
$tree = $parentCategoryNode->getTree();
158-
159-
$isActiveCategory = false;
160-
/** @var \Magento\Catalog\Model\Category $currentCategory */
161-
$currentCategory = $this->_registry->registry('current_category');
162-
if ($currentCategory && $currentCategory->getId() == $category->getId()) {
163-
$isActiveCategory = true;
164-
}
165-
166-
$categoryData = [
167-
'name' => $category->getName(),
168-
'id' => $nodeId,
169-
'url' => $this->_catalogCategory->getCategoryUrl($category),
170-
'has_active' => $this->hasActive($category),
171-
'is_active' => $isActiveCategory
172-
];
155+
$categoryData = $this->getMenuCategoryData($category);
173156
$categoryNode = new \Magento\Framework\Data\Tree\Node($categoryData, 'id', $tree, $parentCategoryNode);
174157
$parentCategoryNode->addChild($categoryNode);
175158

@@ -183,6 +166,34 @@ protected function _addCategoriesToMenu($categories, $parentCategoryNode, $block
183166
}
184167
}
185168

169+
/**
170+
* Get category data to be added to the Menu
171+
*
172+
* @param \Magento\Framework\Data\Tree\Node $category
173+
* @return array
174+
*/
175+
public function getMenuCategoryData($category)
176+
{
177+
$nodeId = 'category-node-' . $category->getId();
178+
179+
$isActiveCategory = false;
180+
/** @var \Magento\Catalog\Model\Category $currentCategory */
181+
$currentCategory = $this->_registry->registry('current_category');
182+
if ($currentCategory && $currentCategory->getId() == $category->getId()) {
183+
$isActiveCategory = true;
184+
}
185+
186+
$categoryData = [
187+
'name' => $category->getName(),
188+
'id' => $nodeId,
189+
'url' => $this->_catalogCategory->getCategoryUrl($category),
190+
'has_active' => $this->hasActive($category),
191+
'is_active' => $isActiveCategory,
192+
];
193+
194+
return $categoryData;
195+
}
196+
186197
/**
187198
* Checks whether category belongs to active category's path
188199
*

app/code/Magento/Catalog/Test/Unit/Model/ObserverTest.php

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,27 @@ class ObserverTest extends \PHPUnit_Framework_TestCase
1818
protected $_observer;
1919

2020
/**
21-
* @var \Magento\Catalog\Helper\Category
21+
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Catalog\Helper\Category
2222
*/
2323
protected $_catalogCategory;
2424

2525
/**
26-
* @var \Magento\Catalog\Model\Category
26+
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Catalog\Model\Category
2727
*/
2828
protected $_category;
2929

3030
/**
31-
* @var \Magento\Catalog\Model\Category
31+
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Catalog\Model\Category
3232
*/
3333
protected $_childrenCategory;
3434

3535
/**
36-
* @var \Magento\Catalog\Model\Indexer\Category\Flat\State
36+
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Catalog\Model\Indexer\Category\Flat\State
3737
*/
3838
protected $_categoryFlatState;
3939

4040
/**
41-
* @var \Magento\Store\Model\StoreManagerInterface
41+
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Store\Model\StoreManagerInterface
4242
*/
4343
protected $_storeManager;
4444

@@ -64,11 +64,13 @@ public function setUp()
6464
->disableOriginalConstructor()
6565
->getMock();
6666

67+
$layerResolver = $this->_getCleanMock('Magento\Catalog\Model\Layer\Resolver');
68+
$layerResolver->expects($this->once())->method('get')->willReturn(null);
6769
$this->_observer = (new ObjectManager($this))->getObject('Magento\Catalog\Model\Observer', [
6870
'categoryResource' => $this->_getCleanMock('\Magento\Catalog\Model\Resource\Category'),
6971
'catalogProduct' => $this->_getCleanMock('\Magento\Catalog\Model\Resource\Product'),
7072
'storeManager' => $this->_storeManager,
71-
'catalogLayer' => $this->_getCleanMock('\Magento\Catalog\Model\Layer\Category'),
73+
'layerResolver' => $layerResolver,
7274
'indexIndexer' => $this->_getCleanMock('\Magento\Index\Model\Indexer'),
7375
'catalogCategory' => $this->_catalogCategory,
7476
'catalogData' => $this->_getCleanMock('\Magento\Catalog\Helper\Data'),
@@ -176,4 +178,23 @@ public function testAddCatalogToTopMenuItemsWithFlat()
176178

177179
$this->_observer->addCatalogToTopmenuItems($observer);
178180
}
181+
182+
public function testGetMenuCategoryData()
183+
{
184+
$category = $this->getMock('Magento\Catalog\Model\Category', ['getId', 'getName'], [], '', false);
185+
$category->expects($this->once())->method('getId')->willReturn('id');
186+
$category->expects($this->once())->method('getName')->willReturn('name');
187+
$this->_catalogCategory->expects($this->once())->method('getCategoryUrl')->willReturn('url');
188+
189+
$this->assertEquals(
190+
[
191+
'name' => 'name',
192+
'id' => 'category-node-id',
193+
'url' => 'url',
194+
'is_active' => false,
195+
'has_active' => false,
196+
],
197+
$this->_observer->getMenuCategoryData($category)
198+
);
199+
}
179200
}

app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/options.phtml

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
<td id="delete_button_container_<%- data.id %>" class="col-delete">
5959
<input type="hidden" class="delete-flag" name="option[delete][<%- data.id %>]" value="" />
6060
<?php if (!$block->getReadOnly() && !$block->canManageOptionDefaultOnly()):?>
61-
<button title="<?php echo __('Delete') ?>" type="button"
61+
<button id="delete_button_<%- data.id %>" title="<?php echo __('Delete') ?>" type="button"
6262
class="action- scalable delete delete-option"
6363
>
6464
<span><?php echo __('Delete') ?></span>
@@ -100,7 +100,6 @@ require([
100100
if (isNewOption && !this.isReadOnly) {
101101
this.enableNewOptionDeleteButton(data.id);
102102
}
103-
this.bindRemoveButtons();
104103
this.itemCount++;
105104
this.totalItems++;
106105
this.updateItemsCountField();
@@ -139,22 +138,16 @@ require([
139138
button.removeClassName('disabled');
140139
});
141140
},
142-
bindRemoveButtons: function() {
143-
var buttons = $$('.delete-option');
144-
for (var i = 0; i < buttons.length; i++) {
145-
if (!$(buttons[i]).binded) {
146-
$(buttons[i]).binded = true;
147-
Event.observe(buttons[i], 'click', this.remove.bind(this));
148-
}
149-
}
150-
}
151141
};
152142

153-
attributeOption.bindRemoveButtons();
154-
155143
if ($('add_new_option_button')) {
156144
Event.observe('add_new_option_button', 'click', attributeOption.add.bind(attributeOption));
157145
}
146+
147+
$('manage-options-panel').on('click', '.delete-option', function(event, element) {
148+
attributeOption.remove(event);
149+
});
150+
158151
<?php foreach ($block->getOptionValues() as $_value): ?>
159152
attributeOption.add(<?php echo $_value->toJson() ?>);
160153
<?php endforeach; ?>

app/code/Magento/Catalog/view/adminhtml/web/catalog/category/form.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ define([
5757
if (response.error) {
5858
alert(response.message);
5959
} else {
60-
if (this.element.find(this.options.categoryIdSelector).prop('value') === response.id) {
60+
if (this.element.find(this.options.categoryIdSelector).prop('value') == response.id) {
6161
this.element.find(this.options.categoryPathSelector)
6262
.prop('value', response.path);
6363
}

app/code/Magento/OfflinePayments/etc/adminhtml/system.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@
166166
<label>Automatically Invoice All Items</label>
167167
<source_model>Magento\Payment\Model\Source\Invoice</source_model>
168168
<depends>
169-
<field id="order_status" separator=",">processing,processed_ogone</field>
169+
<field id="order_status" separator=",">processing</field>
170170
</depends>
171171
</field>
172172
<field id="sort_order" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="0">

app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ $params = $block->getParams();
1313
<head>
1414
<script>
1515
<?php if (isset($params['redirect'])): ?>
16-
window.location="<?php echo $block->escapeUrl($params['redirect']) ?>";
16+
window.location="<?php echo $block->escapeXssInUrl($params['redirect']) ?>";
1717
<?php elseif (isset($params['redirect_parent'])): ?>
18-
window.top.location="<?php echo $block->escapeUrl($params['redirect_parent']) ?>";
18+
window.top.location="<?php echo $block->escapeXssInUrl($params['redirect_parent']) ?>";
1919
<?php elseif (isset($params['error_msg'])): ?>
2020
window.top.alert(<?php echo $this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode($params['error_msg']) ?>);
2121
<?php elseif (isset($params['order_success'])): ?>

dev/tests/integration/testsuite/Magento/Payment/Block/Transparent/IframeTest.php

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,19 @@
55
*/
66
namespace Magento\Payment\Block\Transparent;
77

8+
/**
9+
* Class IframeTest
10+
* @package Magento\Payment\Block\Transparent
11+
*/
812
class IframeTest extends \PHPUnit_Framework_TestCase
913
{
1014
/**
1115
* @magentoAppIsolation enabled
1216
* @magentoAppArea frontend
17+
* @dataProvider xssDataProvider
1318
*/
14-
public function testToHtml()
19+
public function testToHtml($xssString)
1520
{
16-
$xssString = '</script><script>alert("XSS")</script>';
17-
1821
/** @var $block Iframe */
1922
$block = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
2023
'Magento\Framework\View\LayoutInterface'
@@ -34,7 +37,20 @@ public function testToHtml()
3437

3538
$content = $block->toHtml();
3639

37-
$this->assertNotContains($xssString, $content, 'Params mast be escaped');
38-
$this->assertContains(htmlspecialchars($xssString), $content, 'Content must present');
40+
$this->assertNotContains($xssString, $content, 'Params must be escaped');
41+
$this->assertContains($block->escapeXssInUrl($xssString), $content, 'Content must be present');
42+
}
43+
44+
/**
45+
* @return array
46+
*/
47+
public function xssDataProvider()
48+
{
49+
return [
50+
['</script><script>alert("XSS")</script>'],
51+
['javascript%3Aalert%28String.fromCharCode%280x78%29%2BString.fromCharCode%280x73%29%2BString.'
52+
. 'fromCharCode%280x73%29%29'],
53+
['javascript:alert(String.fromCharCode(0x78)+String.fromCharCode(0x73)+String.fromCharCode(0x73))']
54+
];
3955
}
4056
}

dev/tools/Magento/Tools/Migration/factory_table_names/replace_ce.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,6 @@
230230
'oauth/consumer' => 'oauth_consumer',
231231
'oauth/nonce' => 'oauth_nonce',
232232
'oauth/token' => 'oauth_token',
233-
'ogone/api_debug' => 'ogone_api_debug',
234233
'oscommerce/catalog_category' => 'catalog_category_entity',
235234
'oscommerce/catalog_product_website' => 'catalog_product_website',
236235
'oscommerce/oscommerce' => 'oscommerce_import',

lib/internal/Magento/Framework/Escaper.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,24 @@ public function escapeJsQuote($data, $quote = '\'')
7070
return $result;
7171
}
7272

73+
/**
74+
* Escape xss in urls
75+
*
76+
* @param string $data
77+
* @return string
78+
*/
79+
public function escapeXssInUrl($data)
80+
{
81+
$result = $data;
82+
$urlQuery = parse_url($data, PHP_URL_QUERY);
83+
if ($urlQuery !== null && strpos($urlQuery, 'javascript') !== false) {
84+
$result = str_replace($urlQuery, '', $data);
85+
} elseif (parse_url($data, PHP_URL_HOST) === null) {
86+
$result = str_replace('javascript', '', $data);
87+
}
88+
return htmlspecialchars($result, ENT_COMPAT, 'UTF-8', false);
89+
}
90+
7391
/**
7492
* Escape quotes inside html attributes
7593
* Use $addSlashes = false for escaping js that inside html attribute (onClick, onSubmit etc)

lib/internal/Magento/Framework/Test/Unit/EscaperTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,16 @@ public function testEscapeQuote()
9292
$this->assertEquals($expected[0], $this->_escaper->escapeQuote($data));
9393
$this->assertEquals($expected[1], $this->_escaper->escapeQuote($data, true));
9494
}
95+
96+
/**
97+
* @covers \Magento\Framework\Escaper::escapeXssInUrl
98+
*/
99+
public function testEscapeXssInUrl()
100+
{
101+
$data = 'javascript%3Aalert%28String.fromCharCode%280x78%29%2BString.'
102+
. 'fromCharCode%280x73%29%2BString.fromCharCode%280x73%29%29';
103+
$expected = '%3Aalert%28String.fromCharCode%280x78%29%2BString.'
104+
. 'fromCharCode%280x73%29%2BString.fromCharCode%280x73%29%29';
105+
$this->assertEquals($expected, $this->_escaper->escapeXssInUrl($data));
106+
}
95107
}

0 commit comments

Comments
 (0)