· 9 years ago · Jan 31, 2017, 04:58 PM
1#!/bin/bash
2# Patch apllying tool template
3# v0.1.2
4# (c) Copyright 2013. Magento Inc.
5#
6# DO NOT CHANGE ANY LINE IN THIS FILE.
7
8# 1. Check required system tools
9_check_installed_tools() {
10 local missed=""
11
12 until [ -z "$1" ]; do
13 type -t $1 >/dev/null 2>/dev/null
14 if (( $? != 0 )); then
15 missed="$missed $1"
16 fi
17 shift
18 done
19
20 echo $missed
21}
22
23REQUIRED_UTILS='sed patch'
24MISSED_REQUIRED_TOOLS=`_check_installed_tools $REQUIRED_UTILS`
25if (( `echo $MISSED_REQUIRED_TOOLS | wc -w` > 0 ));
26then
27 echo -e "Error! Some required system tools, that are utilized in this sh script, are not installed:\nTool(s) \"$MISSED_REQUIRED_TOOLS\" is(are) missed, please install it(them)."
28 exit 1
29fi
30
31# 2. Determine bin path for system tools
32CAT_BIN=`which cat`
33PATCH_BIN=`which patch`
34SED_BIN=`which sed`
35PWD_BIN=`which pwd`
36BASENAME_BIN=`which basename`
37
38BASE_NAME=`$BASENAME_BIN "$0"`
39
40# 3. Help menu
41if [ "$1" = "-?" -o "$1" = "-h" -o "$1" = "--help" ]
42then
43 $CAT_BIN << EOFH
44Usage: sh $BASE_NAME [--help] [-R|--revert] [--list]
45Apply embedded patch.
46
47-R, --revert Revert previously applied embedded patch
48--list Show list of applied patches
49--help Show this help message
50EOFH
51 exit 0
52fi
53
54# 4. Get "revert" flag and "list applied patches" flag
55REVERT_FLAG=
56SHOW_APPLIED_LIST=0
57if [ "$1" = "-R" -o "$1" = "--revert" ]
58then
59 REVERT_FLAG=-R
60fi
61if [ "$1" = "--list" ]
62then
63 SHOW_APPLIED_LIST=1
64fi
65
66# 5. File pathes
67CURRENT_DIR=`$PWD_BIN`/
68APP_ETC_DIR=`echo "$CURRENT_DIR""app/etc/"`
69APPLIED_PATCHES_LIST_FILE=`echo "$APP_ETC_DIR""applied.patches.list"`
70
71# 6. Show applied patches list if requested
72if [ "$SHOW_APPLIED_LIST" -eq 1 ] ; then
73 echo -e "Applied/reverted patches list:"
74 if [ -e "$APPLIED_PATCHES_LIST_FILE" ]
75 then
76 if [ ! -r "$APPLIED_PATCHES_LIST_FILE" ]
77 then
78 echo "ERROR: \"$APPLIED_PATCHES_LIST_FILE\" must be readable so applied patches list can be shown."
79 exit 1
80 else
81 $SED_BIN -n "/SUP-\|SUPEE-/p" $APPLIED_PATCHES_LIST_FILE
82 fi
83 else
84 echo "<empty>"
85 fi
86 exit 0
87fi
88
89# 7. Check applied patches track file and its directory
90_check_files() {
91 if [ ! -e "$APP_ETC_DIR" ]
92 then
93 echo "ERROR: \"$APP_ETC_DIR\" must exist for proper tool work."
94 exit 1
95 fi
96
97 if [ ! -w "$APP_ETC_DIR" ]
98 then
99 echo "ERROR: \"$APP_ETC_DIR\" must be writeable for proper tool work."
100 exit 1
101 fi
102
103 if [ -e "$APPLIED_PATCHES_LIST_FILE" ]
104 then
105 if [ ! -w "$APPLIED_PATCHES_LIST_FILE" ]
106 then
107 echo "ERROR: \"$APPLIED_PATCHES_LIST_FILE\" must be writeable for proper tool work."
108 exit 1
109 fi
110 fi
111}
112
113_check_files
114
115# 8. Apply/revert patch
116# Note: there is no need to check files permissions for files to be patched.
117# "patch" tool will not modify any file if there is not enough permissions for all files to be modified.
118# Get start points for additional information and patch data
119SKIP_LINES=$((`$SED_BIN -n "/^__PATCHFILE_FOLLOWS__$/=" "$CURRENT_DIR""$BASE_NAME"` + 1))
120ADDITIONAL_INFO_LINE=$(($SKIP_LINES - 3))p
121
122_apply_revert_patch() {
123 DRY_RUN_FLAG=
124 if [ "$1" = "dry-run" ]
125 then
126 DRY_RUN_FLAG=" --dry-run"
127 echo "Checking if patch can be applied/reverted successfully..."
128 fi
129 PATCH_APPLY_REVERT_RESULT=`$SED_BIN -e '1,/^__PATCHFILE_FOLLOWS__$/d' "$CURRENT_DIR""$BASE_NAME" | $PATCH_BIN $DRY_RUN_FLAG $REVERT_FLAG -p0`
130 PATCH_APPLY_REVERT_STATUS=$?
131 if [ $PATCH_APPLY_REVERT_STATUS -eq 1 ] ; then
132 echo -e "ERROR: Patch can't be applied/reverted successfully.\n\n$PATCH_APPLY_REVERT_RESULT"
133 exit 1
134 fi
135 if [ $PATCH_APPLY_REVERT_STATUS -eq 2 ] ; then
136 echo -e "ERROR: Patch can't be applied/reverted successfully."
137 exit 2
138 fi
139}
140
141REVERTED_PATCH_MARK=
142if [ -n "$REVERT_FLAG" ]
143then
144 REVERTED_PATCH_MARK=" | REVERTED"
145fi
146
147_apply_revert_patch dry-run
148_apply_revert_patch
149
150# 9. Track patch applying result
151echo "Patch was applied/reverted successfully."
152ADDITIONAL_INFO=`$SED_BIN -n ""$ADDITIONAL_INFO_LINE"" "$CURRENT_DIR""$BASE_NAME"`
153APPLIED_REVERTED_ON_DATE=`date -u +"%F %T UTC"`
154APPLIED_REVERTED_PATCH_INFO=`echo -n "$APPLIED_REVERTED_ON_DATE"" | ""$ADDITIONAL_INFO""$REVERTED_PATCH_MARK"`
155echo -e "$APPLIED_REVERTED_PATCH_INFO\n$PATCH_APPLY_REVERT_RESULT\n\n" >> "$APPLIED_PATCHES_LIST_FILE"
156
157exit 0
158
159
160SUPEE-6788 | CE_1.9.0.1 | v1 | be76c3faa9d26b74a513463408211e9921b09341 | Fri Oct 23 14:59:13 2015 +0300 | ea98922
161
162__PATCHFILE_FOLLOWS__
163diff --git .htaccess .htaccess
164index 60e1795..aca7f55 100644
165--- .htaccess
166+++ .htaccess
167@@ -207,3 +207,28 @@
168 ## http://developer.yahoo.com/performance/rules.html#etags
169
170 #FileETag none
171+
172+###########################################
173+## Deny access to cron.php
174+ <Files cron.php>
175+
176+############################################
177+## uncomment next lines to enable cron access with base HTTP authorization
178+## http://httpd.apache.org/docs/2.2/howto/auth.html
179+##
180+## Warning: .htpasswd file should be placed somewhere not accessible from the web.
181+## This is so that folks cannot download the password file.
182+## For example, if your documents are served out of /usr/local/apache/htdocs
183+## you might want to put the password file(s) in /usr/local/apache/.
184+
185+ #AuthName "Cron auth"
186+ #AuthUserFile ../.htpasswd
187+ #AuthType basic
188+ #Require valid-user
189+
190+############################################
191+
192+ Order allow,deny
193+ Deny from all
194+
195+ </Files>
196diff --git .htaccess.sample .htaccess.sample
197index b8821af..383313a 100644
198--- .htaccess.sample
199+++ .htaccess.sample
200@@ -176,3 +176,27 @@
201
202 #FileETag none
203
204+###########################################
205+## Deny access to cron.php
206+ <Files cron.php>
207+
208+############################################
209+## uncomment next lines to enable cron access with base HTTP authorization
210+## http://httpd.apache.org/docs/2.2/howto/auth.html
211+##
212+## Warning: .htpasswd file should be placed somewhere not accessible from the web.
213+## This is so that folks cannot download the password file.
214+## For example, if your documents are served out of /usr/local/apache/htdocs
215+## you might want to put the password file(s) in /usr/local/apache/.
216+
217+ #AuthName "Cron auth"
218+ #AuthUserFile ../.htpasswd
219+ #AuthType basic
220+ #Require valid-user
221+
222+############################################
223+
224+ Order allow,deny
225+ Deny from all
226+
227+ </Files>
228diff --git app/code/core/Mage/Admin/Model/Block.php app/code/core/Mage/Admin/Model/Block.php
229new file mode 100644
230index 0000000..b33db1b
231--- /dev/null
232+++ app/code/core/Mage/Admin/Model/Block.php
233@@ -0,0 +1,84 @@
234+<?php
235+/**
236+ * Magento
237+ *
238+ * NOTICE OF LICENSE
239+ *
240+ * This source file is subject to the Open Software License (OSL 3.0)
241+ * that is bundled with this package in the file LICENSE.txt.
242+ * It is also available through the world-wide-web at this URL:
243+ * http://opensource.org/licenses/osl-3.0.php
244+ * If you did not receive a copy of the license and are unable to
245+ * obtain it through the world-wide-web, please send an email
246+ * to license@magentocommerce.com so we can send you a copy immediately.
247+ *
248+ * DISCLAIMER
249+ *
250+ * Do not edit or add to this file if you wish to upgrade Magento to newer
251+ * versions in the future. If you wish to customize Magento for your
252+ * needs please refer to http://www.magentocommerce.com for more information.
253+ *
254+ * @category Mage
255+ * @package Mage_Admin
256+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
257+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
258+ */
259+
260+/**
261+ * Class Mage_Admin_Model_Block
262+ *
263+ * @category Mage
264+ * @package Mage_Adminhtml
265+ * @author Magento Core Team <core@magentocommerce.com>
266+ */
267+class Mage_Admin_Model_Block extends Mage_Core_Model_Abstract
268+{
269+ /**
270+ * Initialize variable model
271+ */
272+ protected function _construct()
273+ {
274+ $this->_init('admin/block');
275+ }
276+
277+ /**
278+ * @return array|bool
279+ * @throws Exception
280+ * @throws Zend_Validate_Exception
281+ */
282+ public function validate()
283+ {
284+ $errors = array();
285+
286+ if (!Zend_Validate::is($this->getBlockName(), 'NotEmpty')) {
287+ $errors[] = Mage::helper('adminhtml')->__('Block Name is required field.');
288+ }
289+ if (!Zend_Validate::is($this->getBlockName(), 'Regex', array('/^[-_a-zA-Z0-9\/]*$/'))) {
290+ $errors[] = Mage::helper('adminhtml')->__('Block Name is incorrect.');
291+ }
292+
293+ if (!in_array($this->getIsAllowed(), array('0', '1'))) {
294+ $errors[] = Mage::helper('adminhtml')->__('Is Allowed is required field.');
295+ }
296+
297+ if (empty($errors)) {
298+ return true;
299+ }
300+ return $errors;
301+ }
302+
303+ /**
304+ * Check is block with such type allowed for parsinf via blockDirective method
305+ *
306+ * @param $type
307+ * @return int
308+ */
309+ public function isTypeAllowed($type)
310+ {
311+ /** @var Mage_Admin_Model_Resource_Block_Collection $collection */
312+ $collection = Mage::getResourceModel('admin/block_collection');
313+ $collection->addFieldToFilter('block_name', array('eq' => $type))
314+ ->addFieldToFilter('is_allowed', array('eq' => 1));
315+ return $collection->load()->count();
316+ }
317+}
318diff --git app/code/core/Mage/Admin/Model/Resource/Block.php app/code/core/Mage/Admin/Model/Resource/Block.php
319new file mode 100644
320index 0000000..99b1c33
321--- /dev/null
322+++ app/code/core/Mage/Admin/Model/Resource/Block.php
323@@ -0,0 +1,44 @@
324+<?php
325+/**
326+ * Magento
327+ *
328+ * NOTICE OF LICENSE
329+ *
330+ * This source file is subject to the Open Software License (OSL 3.0)
331+ * that is bundled with this package in the file LICENSE.txt.
332+ * It is also available through the world-wide-web at this URL:
333+ * http://opensource.org/licenses/osl-3.0.php
334+ * If you did not receive a copy of the license and are unable to
335+ * obtain it through the world-wide-web, please send an email
336+ * to license@magentocommerce.com so we can send you a copy immediately.
337+ *
338+ * DISCLAIMER
339+ *
340+ * Do not edit or add to this file if you wish to upgrade Magento to newer
341+ * versions in the future. If you wish to customize Magento for your
342+ * needs please refer to http://www.magentocommerce.com for more information.
343+ *
344+ * @category Mage
345+ * @package Mage_Admin
346+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
347+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
348+ */
349+
350+/**
351+ * Class Mage_Admin_Model_Resource_Block
352+ *
353+ * @category Mage
354+ * @package Mage_Adminhtml
355+ * @author Magento Core Team <core@magentocommerce.com>
356+ */
357+class Mage_Admin_Model_Resource_Block extends Mage_Core_Model_Resource_Db_Abstract
358+{
359+ /**
360+ * Define main table
361+ *
362+ */
363+ protected function _construct()
364+ {
365+ $this->_init('admin/permission_block', 'block_id');
366+ }
367+}
368diff --git app/code/core/Mage/Admin/Model/Resource/Block/Collection.php app/code/core/Mage/Admin/Model/Resource/Block/Collection.php
369new file mode 100644
370index 0000000..4b64825
371--- /dev/null
372+++ app/code/core/Mage/Admin/Model/Resource/Block/Collection.php
373@@ -0,0 +1,44 @@
374+<?php
375+/**
376+ * Magento
377+ *
378+ * NOTICE OF LICENSE
379+ *
380+ * This source file is subject to the Open Software License (OSL 3.0)
381+ * that is bundled with this package in the file LICENSE.txt.
382+ * It is also available through the world-wide-web at this URL:
383+ * http://opensource.org/licenses/osl-3.0.php
384+ * If you did not receive a copy of the license and are unable to
385+ * obtain it through the world-wide-web, please send an email
386+ * to license@magentocommerce.com so we can send you a copy immediately.
387+ *
388+ * DISCLAIMER
389+ *
390+ * Do not edit or add to this file if you wish to upgrade Magento to newer
391+ * versions in the future. If you wish to customize Magento for your
392+ * needs please refer to http://www.magentocommerce.com for more information.
393+ *
394+ * @category Mage
395+ * @package Mage_Admin
396+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
397+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
398+ */
399+
400+/**
401+ * Admin permissions block collection
402+ *
403+ * @category Mage
404+ * @package Mage_Adminhtml
405+ * @author Magento Core Team <core@magentocommerce.com>
406+ */
407+class Mage_Admin_Model_Resource_Block_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract
408+{
409+ /**
410+ * Define resource model
411+ *
412+ */
413+ protected function _construct()
414+ {
415+ $this->_init('admin/block');
416+ }
417+}
418diff --git app/code/core/Mage/Admin/Model/Resource/Variable.php app/code/core/Mage/Admin/Model/Resource/Variable.php
419new file mode 100644
420index 0000000..b742097
421--- /dev/null
422+++ app/code/core/Mage/Admin/Model/Resource/Variable.php
423@@ -0,0 +1,43 @@
424+<?php
425+/**
426+ * Magento
427+ *
428+ * NOTICE OF LICENSE
429+ *
430+ * This source file is subject to the Open Software License (OSL 3.0)
431+ * that is bundled with this package in the file LICENSE.txt.
432+ * It is also available through the world-wide-web at this URL:
433+ * http://opensource.org/licenses/osl-3.0.php
434+ * If you did not receive a copy of the license and are unable to
435+ * obtain it through the world-wide-web, please send an email
436+ * to license@magentocommerce.com so we can send you a copy immediately.
437+ *
438+ * DISCLAIMER
439+ *
440+ * Do not edit or add to this file if you wish to upgrade Magento to newer
441+ * versions in the future. If you wish to customize Magento for your
442+ * needs please refer to http://www.magentocommerce.com for more information.
443+ *
444+ * @category Mage
445+ * @package Mage_Admin
446+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
447+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
448+ */
449+
450+/**
451+ * Resource model for manipulate system variables
452+ *
453+ * @category Mage
454+ * @package Mage_Admin
455+ * @author Magento Core Team <core@magentocommerce.com>
456+ */
457+class Mage_Admin_Model_Resource_Variable extends Mage_Core_Model_Resource_Db_Abstract
458+{
459+ /**
460+ * Define main table
461+ */
462+ protected function _construct()
463+ {
464+ $this->_init('admin/permission_variable', 'variable_id');
465+ }
466+}
467diff --git app/code/core/Mage/Admin/Model/Resource/Variable/Collection.php app/code/core/Mage/Admin/Model/Resource/Variable/Collection.php
468new file mode 100644
469index 0000000..54ab1e5
470--- /dev/null
471+++ app/code/core/Mage/Admin/Model/Resource/Variable/Collection.php
472@@ -0,0 +1,44 @@
473+<?php
474+/**
475+ * Magento
476+ *
477+ * NOTICE OF LICENSE
478+ *
479+ * This source file is subject to the Open Software License (OSL 3.0)
480+ * that is bundled with this package in the file LICENSE.txt.
481+ * It is also available through the world-wide-web at this URL:
482+ * http://opensource.org/licenses/osl-3.0.php
483+ * If you did not receive a copy of the license and are unable to
484+ * obtain it through the world-wide-web, please send an email
485+ * to license@magentocommerce.com so we can send you a copy immediately.
486+ *
487+ * DISCLAIMER
488+ *
489+ * Do not edit or add to this file if you wish to upgrade Magento to newer
490+ * versions in the future. If you wish to customize Magento for your
491+ * needs please refer to http://www.magentocommerce.com for more information.
492+ *
493+ * @category Mage
494+ * @package Mage_Admin
495+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
496+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
497+ */
498+
499+/**
500+ * Admin permissions variable collection
501+ *
502+ * @category Mage
503+ * @package Mage_Admin
504+ * @author Magento Core Team <core@magentocommerce.com>
505+ */
506+class Mage_Admin_Model_Resource_Variable_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract
507+{
508+ /**
509+ * Define resource model
510+ *
511+ */
512+ protected function _construct()
513+ {
514+ $this->_init('admin/variable');
515+ }
516+}
517diff --git app/code/core/Mage/Admin/Model/Variable.php app/code/core/Mage/Admin/Model/Variable.php
518new file mode 100644
519index 0000000..e353a2c
520--- /dev/null
521+++ app/code/core/Mage/Admin/Model/Variable.php
522@@ -0,0 +1,80 @@
523+<?php
524+/**
525+ * Magento
526+ *
527+ * NOTICE OF LICENSE
528+ *
529+ * This source file is subject to the Open Software License (OSL 3.0)
530+ * that is bundled with this package in the file LICENSE.txt.
531+ * It is also available through the world-wide-web at this URL:
532+ * http://opensource.org/licenses/osl-3.0.php
533+ * If you did not receive a copy of the license and are unable to
534+ * obtain it through the world-wide-web, please send an email
535+ * to license@magentocommerce.com so we can send you a copy immediately.
536+ *
537+ * DISCLAIMER
538+ *
539+ * Do not edit or add to this file if you wish to upgrade Magento to newer
540+ * versions in the future. If you wish to customize Magento for your
541+ * needs please refer to http://www.magentocommerce.com for more information.
542+ *
543+ * @category Mage
544+ * @package Mage_Admin
545+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
546+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
547+ */
548+
549+/**
550+ * Class Mage_Admin_Model_Variable
551+ */
552+class Mage_Admin_Model_Variable extends Mage_Core_Model_Abstract
553+{
554+ /**
555+ * Initialize variable model
556+ */
557+ protected function _construct()
558+ {
559+ $this->_init('admin/variable');
560+ }
561+
562+ /**
563+ * @return array|bool
564+ * @throws Exception
565+ * @throws Zend_Validate_Exception
566+ */
567+ public function validate()
568+ {
569+ $errors = array();
570+
571+ if (!Zend_Validate::is($this->getVariableName(), 'NotEmpty')) {
572+ $errors[] = Mage::helper('adminhtml')->__('Variable Name is required field.');
573+ }
574+ if (!Zend_Validate::is($this->getVariableName(), 'Regex', array('/^[-_a-zA-Z0-9\/]*$/'))) {
575+ $errors[] = Mage::helper('adminhtml')->__('Variable Name is incorrect.');
576+ }
577+
578+ if (!in_array($this->getIsAllowed(), array('0', '1'))) {
579+ $errors[] = Mage::helper('adminhtml')->__('Is Allowed is required field.');
580+ }
581+
582+ if (empty($errors)) {
583+ return true;
584+ }
585+ return $errors;
586+ }
587+
588+ /**
589+ * Check is config directive with given path can be parsed via configDirective method
590+ *
591+ * @param $path string
592+ * @return int
593+ */
594+ public function isPathAllowed($path)
595+ {
596+ /** @var Mage_Admin_Model_Resource_Variable_Collection $collection */
597+ $collection = Mage::getResourceModel('admin/variable_collection');
598+ $collection->addFieldToFilter('variable_name', array('eq' => $path))
599+ ->addFieldToFilter('is_allowed', array('eq' => 1));
600+ return $collection->load()->count();
601+ }
602+}
603diff --git app/code/core/Mage/Admin/etc/config.xml app/code/core/Mage/Admin/etc/config.xml
604index 6e1abd0..fee8d53 100644
605--- app/code/core/Mage/Admin/etc/config.xml
606+++ app/code/core/Mage/Admin/etc/config.xml
607@@ -28,7 +28,7 @@
608 <config>
609 <modules>
610 <Mage_Admin>
611- <version>1.6.1.1</version>
612+ <version>1.6.1.2</version>
613 </Mage_Admin>
614 </modules>
615 <global>
616@@ -50,6 +50,12 @@
617 <rule>
618 <table>admin_rule</table>
619 </rule>
620+ <permission_variable>
621+ <table>permission_variable</table>
622+ </permission_variable>
623+ <permission_block>
624+ <table>permission_block</table>
625+ </permission_block>
626 <assert>
627 <table>admin_assert</table>
628 </assert>
629diff --git app/code/core/Mage/Admin/sql/admin_setup/upgrade-1.6.1.1-1.6.1.2.php app/code/core/Mage/Admin/sql/admin_setup/upgrade-1.6.1.1-1.6.1.2.php
630new file mode 100644
631index 0000000..1846958
632--- /dev/null
633+++ app/code/core/Mage/Admin/sql/admin_setup/upgrade-1.6.1.1-1.6.1.2.php
634@@ -0,0 +1,103 @@
635+<?php
636+/**
637+ * Magento
638+ *
639+ * NOTICE OF LICENSE
640+ *
641+ * This source file is subject to the Open Software License (OSL 3.0)
642+ * that is bundled with this package in the file LICENSE.txt.
643+ * It is also available through the world-wide-web at this URL:
644+ * http://opensource.org/licenses/osl-3.0.php
645+ * If you did not receive a copy of the license and are unable to
646+ * obtain it through the world-wide-web, please send an email
647+ * to license@magentocommerce.com so we can send you a copy immediately.
648+ *
649+ * DISCLAIMER
650+ *
651+ * Do not edit or add to this file if you wish to upgrade Magento to newer
652+ * versions in the future. If you wish to customize Magento for your
653+ * needs please refer to http://www.magentocommerce.com for more information.
654+ *
655+ * @category Mage
656+ * @package Mage_Admin
657+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
658+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
659+ */
660+
661+/** @var $installer Mage_Core_Model_Resource_Setup */
662+$installer = $this;
663+$installer->startSetup();
664+
665+$table = $installer->getConnection()
666+ ->newTable($installer->getTable('admin/permission_variable'))
667+ ->addColumn('variable_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
668+ 'identity' => true,
669+ 'unsigned' => true,
670+ 'nullable' => false,
671+ 'primary' => true,
672+ ), 'Variable ID')
673+ ->addColumn('variable_name', Varien_Db_Ddl_Table::TYPE_VARCHAR, 255, array(
674+ 'primary' => true,
675+ 'nullable' => false,
676+ 'default' => "",
677+ ), 'Config Path')
678+ ->addColumn('is_allowed', Varien_Db_Ddl_Table::TYPE_BOOLEAN, null, array(
679+ 'nullable' => false,
680+ 'default' => 0,
681+ ), 'Mark that config can be processed by filters')
682+ ->addIndex($installer->getIdxName('admin/permission_variable', array('variable_name'), Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE),
683+ array('variable_name'), array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE))
684+ ->setComment('System variables that can be processed via content filter');
685+$installer->getConnection()->createTable($table);
686+
687+$installer->getConnection()->insertMultiple(
688+ $installer->getTable('admin/permission_variable'),
689+ array(
690+ array('variable_name' => 'trans_email/ident_support/name', 'is_allowed' => 1),
691+ array('variable_name' => 'trans_email/ident_support/email','is_allowed' => 1),
692+ array('variable_name' => 'web/unsecure/base_url','is_allowed' => 1),
693+ array('variable_name' => 'web/secure/base_url','is_allowed' => 1),
694+ array('variable_name' => 'trans_email/ident_general/name','is_allowed' => 1),
695+ array('variable_name' => 'trans_email/ident_general/email', 'is_allowed' => 1),
696+ array('variable_name' => 'trans_email/ident_sales/name','is_allowed' => 1),
697+ array('variable_name' => 'trans_email/ident_sales/email','is_allowed' => 1),
698+ array('variable_name' => 'trans_email/ident_custom1/name','is_allowed' => 1),
699+ array('variable_name' => 'trans_email/ident_custom1/email','is_allowed' => 1),
700+ array('variable_name' => 'trans_email/ident_custom2/name','is_allowed' => 1),
701+ array('variable_name' => 'trans_email/ident_custom2/email','is_allowed' => 1),
702+ array('variable_name' => 'general/store_information/name', 'is_allowed' => 1),
703+ array('variable_name' => 'general/store_information/phone','is_allowed' => 1),
704+ array('variable_name' => 'general/store_information/address', 'is_allowed' => 1),
705+ )
706+);
707+
708+$table = $installer->getConnection()
709+ ->newTable($installer->getTable('admin/permission_block'))
710+ ->addColumn('block_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
711+ 'identity' => true,
712+ 'unsigned' => true,
713+ 'nullable' => false,
714+ 'primary' => true,
715+ ), 'Block ID')
716+ ->addColumn('block_name', Varien_Db_Ddl_Table::TYPE_VARCHAR, 255, array(
717+ 'nullable' => false,
718+ 'default' => "",
719+ ), 'Block Name')
720+ ->addColumn('is_allowed', Varien_Db_Ddl_Table::TYPE_BOOLEAN, null, array(
721+ 'nullable' => false,
722+ 'default' => 0,
723+ ), 'Mark that block can be processed by filters')
724+ ->addIndex($installer->getIdxName('admin/permission_block', array('block_name'), Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE),
725+ array('block_name'), array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE))
726+ ->setComment('System blocks that can be processed via content filter');
727+$installer->getConnection()->createTable($table);
728+
729+$installer->getConnection()->insertMultiple(
730+ $installer->getTable('admin/permission_block'),
731+ array(
732+ array('block_name' => 'core/template', 'is_allowed' => 1),
733+ array('block_name' => 'catalog/product_new', 'is_allowed' => 1),
734+ )
735+);
736+
737+$installer->endSetup();
738diff --git app/code/core/Mage/Adminhtml/Block/Permissions/Block.php app/code/core/Mage/Adminhtml/Block/Permissions/Block.php
739new file mode 100644
740index 0000000..c096cde
741--- /dev/null
742+++ app/code/core/Mage/Adminhtml/Block/Permissions/Block.php
743@@ -0,0 +1,57 @@
744+<?php
745+/**
746+ * Magento
747+ *
748+ * NOTICE OF LICENSE
749+ *
750+ * This source file is subject to the Open Software License (OSL 3.0)
751+ * that is bundled with this package in the file LICENSE.txt.
752+ * It is also available through the world-wide-web at this URL:
753+ * http://opensource.org/licenses/osl-3.0.php
754+ * If you did not receive a copy of the license and are unable to
755+ * obtain it through the world-wide-web, please send an email
756+ * to license@magentocommerce.com so we can send you a copy immediately.
757+ *
758+ * DISCLAIMER
759+ *
760+ * Do not edit or add to this file if you wish to upgrade Magento to newer
761+ * versions in the future. If you wish to customize Magento for your
762+ * needs please refer to http://www.magentocommerce.com for more information.
763+ *
764+ * @category Mage
765+ * @package Mage_Adminhtml
766+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
767+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
768+ */
769+
770+/**
771+ * Adminhtml permissions block
772+ *
773+ * @category Mage
774+ * @package Mage_Adminhtml
775+ * @author Magento Core Team <core@magentocommerce.com>
776+ */
777+class Mage_Adminhtml_Block_Permissions_Block extends Mage_Adminhtml_Block_Widget_Grid_Container
778+{
779+ /**
780+ * Construct
781+ */
782+ public function __construct()
783+ {
784+ $this->_controller = 'permissions_block';
785+ $this->_headerText = Mage::helper('adminhtml')->__('Blocks');
786+ $this->_addButtonLabel = Mage::helper('adminhtml')->__('Add New Block');
787+ parent::__construct();
788+ }
789+
790+ /**
791+ * Prepare output HTML
792+ *
793+ * @return string
794+ */
795+ protected function _toHtml()
796+ {
797+ Mage::dispatchEvent('permissions_block_html_before', array('block' => $this));
798+ return parent::_toHtml();
799+ }
800+}
801diff --git app/code/core/Mage/Adminhtml/Block/Permissions/Block/Edit.php app/code/core/Mage/Adminhtml/Block/Permissions/Block/Edit.php
802new file mode 100644
803index 0000000..75cc9ef
804--- /dev/null
805+++ app/code/core/Mage/Adminhtml/Block/Permissions/Block/Edit.php
806@@ -0,0 +1,64 @@
807+<?php
808+/**
809+ * Magento
810+ *
811+ * NOTICE OF LICENSE
812+ *
813+ * This source file is subject to the Open Software License (OSL 3.0)
814+ * that is bundled with this package in the file LICENSE.txt.
815+ * It is also available through the world-wide-web at this URL:
816+ * http://opensource.org/licenses/osl-3.0.php
817+ * If you did not receive a copy of the license and are unable to
818+ * obtain it through the world-wide-web, please send an email
819+ * to license@magentocommerce.com so we can send you a copy immediately.
820+ *
821+ * DISCLAIMER
822+ *
823+ * Do not edit or add to this file if you wish to upgrade Magento to newer
824+ * versions in the future. If you wish to customize Magento for your
825+ * needs please refer to http://www.magentocommerce.com for more information.
826+ *
827+ * @category Mage
828+ * @package Mage_Adminhtml
829+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
830+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
831+ */
832+
833+/**
834+ * Adminhtml permissions block edit page
835+ *
836+ * @category Mage
837+ * @package Mage_Adminhtml
838+ * @author Magento Core Team <core@magentocommerce.com>
839+ */
840+class Mage_Adminhtml_Block_Permissions_Block_Edit extends Mage_Adminhtml_Block_Widget_Form_Container
841+{
842+ /**
843+ * Construct
844+ */
845+ public function __construct()
846+ {
847+ $this->_objectId = 'block_id';
848+ $this->_controller = 'permissions_block';
849+
850+ parent::__construct();
851+
852+ $this->_updateButton('save', 'label', Mage::helper('adminhtml')->__('Save Block'));
853+ $this->_updateButton('delete', 'label', Mage::helper('adminhtml')->__('Delete Block'));
854+ }
855+
856+ /**
857+ * Return text that to be placed to block header
858+ *
859+ * @return string
860+ */
861+ public function getHeaderText()
862+ {
863+ if (Mage::registry('permissions_block')->getId()) {
864+ return Mage::helper('adminhtml')->__("Edit Block '%s'", $this->escapeHtml(Mage::registry('permissions_block')->getBlockName()));
865+ }
866+ else {
867+ return Mage::helper('adminhtml')->__('New block');
868+ }
869+ }
870+}
871diff --git app/code/core/Mage/Adminhtml/Block/Permissions/Block/Edit/Form.php app/code/core/Mage/Adminhtml/Block/Permissions/Block/Edit/Form.php
872new file mode 100644
873index 0000000..8d29480
874--- /dev/null
875+++ app/code/core/Mage/Adminhtml/Block/Permissions/Block/Edit/Form.php
876@@ -0,0 +1,84 @@
877+<?php
878+/**
879+ * Magento
880+ *
881+ * NOTICE OF LICENSE
882+ *
883+ * This source file is subject to the Open Software License (OSL 3.0)
884+ * that is bundled with this package in the file LICENSE.txt.
885+ * It is also available through the world-wide-web at this URL:
886+ * http://opensource.org/licenses/osl-3.0.php
887+ * If you did not receive a copy of the license and are unable to
888+ * obtain it through the world-wide-web, please send an email
889+ * to license@magentocommerce.com so we can send you a copy immediately.
890+ *
891+ * DISCLAIMER
892+ *
893+ * Do not edit or add to this file if you wish to upgrade Magento to newer
894+ * versions in the future. If you wish to customize Magento for your
895+ * needs please refer to http://www.magentocommerce.com for more information.
896+ *
897+ * @category Mage
898+ * @package Mage_Adminhtml
899+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
900+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
901+ */
902+
903+/**
904+ * Adminhtml permissions user edit form
905+ *
906+ * @category Mage
907+ * @package Mage_Adminhtml
908+ * @author Magento Core Team <core@magentocommerce.com>
909+ */
910+class Mage_Adminhtml_Block_Permissions_Block_Edit_Form extends Mage_Adminhtml_Block_Widget_Form
911+{
912+
913+ /**
914+ * @return Mage_Adminhtml_Block_Widget_Form
915+ * @throws Exception
916+ */
917+ protected function _prepareForm()
918+ {
919+ $block = Mage::getModel('admin/block')->load((int) $this->getRequest()->getParam('block_id'));
920+
921+ $form = new Varien_Data_Form(array(
922+ 'id' => 'edit_form',
923+ 'action' => $this->getUrl('*/*/save', array('block_id' => (int) $this->getRequest()->getParam('block_id'))),
924+ 'method' => 'post'
925+ ));
926+ $fieldset = $form->addFieldset(
927+ 'block_details', array('legend' => $this->__('Block Details'))
928+ );
929+
930+ $fieldset->addField('block_name', 'text', array(
931+ 'label' => $this->__('Block Name'),
932+ 'required' => true,
933+ 'name' => 'block_name',
934+ ));
935+
936+
937+ $yesno = array(
938+ array(
939+ 'value' => 0,
940+ 'label' => $this->__('No')
941+ ),
942+ array(
943+ 'value' => 1,
944+ 'label' => $this->__('Yes')
945+ ));
946+
947+
948+ $fieldset->addField('is_allowed', 'select', array(
949+ 'name' => 'is_allowed',
950+ 'label' => $this->__('Is Allowed'),
951+ 'title' => $this->__('Is Allowed'),
952+ 'values' => $yesno,
953+ ));
954+
955+ $form->setUseContainer(true);
956+ $form->setValues($block->getData());
957+ $this->setForm($form);
958+ return parent::_prepareForm();
959+ }
960+}
961diff --git app/code/core/Mage/Adminhtml/Block/Permissions/Block/Grid.php app/code/core/Mage/Adminhtml/Block/Permissions/Block/Grid.php
962new file mode 100644
963index 0000000..426fd38
964--- /dev/null
965+++ app/code/core/Mage/Adminhtml/Block/Permissions/Block/Grid.php
966@@ -0,0 +1,103 @@
967+<?php
968+/**
969+ * Magento
970+ *
971+ * NOTICE OF LICENSE
972+ *
973+ * This source file is subject to the Open Software License (OSL 3.0)
974+ * that is bundled with this package in the file LICENSE.txt.
975+ * It is also available through the world-wide-web at this URL:
976+ * http://opensource.org/licenses/osl-3.0.php
977+ * If you did not receive a copy of the license and are unable to
978+ * obtain it through the world-wide-web, please send an email
979+ * to license@magentocommerce.com so we can send you a copy immediately.
980+ *
981+ * DISCLAIMER
982+ *
983+ * Do not edit or add to this file if you wish to upgrade Magento to newer
984+ * versions in the future. If you wish to customize Magento for your
985+ * needs please refer to http://www.magentocommerce.com for more information.
986+ *
987+ * @category Mage
988+ * @package Mage_Adminhtml
989+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
990+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
991+ */
992+
993+/**
994+ * Adminhtml permissions block grid
995+ *
996+ * @category Mage
997+ * @package Mage_Adminhtml
998+ * @author Magento Core Team <core@magentocommerce.com>
999+ */
1000+class Mage_Adminhtml_Block_Permissions_Block_Grid extends Mage_Adminhtml_Block_Widget_Grid
1001+{
1002+ /**
1003+ * Construct
1004+ */
1005+ public function __construct()
1006+ {
1007+ parent::__construct();
1008+ $this->setId('permissionsBlockGrid');
1009+ $this->setDefaultSort('block_id');
1010+ $this->setDefaultDir('asc');
1011+ $this->setUseAjax(true);
1012+ }
1013+
1014+ /**
1015+ * @return Mage_Adminhtml_Block_Widget_Grid
1016+ */
1017+ protected function _prepareCollection()
1018+ {
1019+ $collection = Mage::getResourceModel('admin/block_collection');
1020+ $this->setCollection($collection);
1021+ return parent::_prepareCollection();
1022+ }
1023+
1024+ /**
1025+ * @return $this
1026+ * @throws Exception
1027+ */
1028+ protected function _prepareColumns()
1029+ {
1030+ $this->addColumn('block_id', array(
1031+ 'header' => Mage::helper('adminhtml')->__('ID'),
1032+ 'width' => 5,
1033+ 'align' => 'right',
1034+ 'sortable' => true,
1035+ 'index' => 'block_id'
1036+ ));
1037+
1038+ $this->addColumn('block_name', array(
1039+ 'header' => Mage::helper('adminhtml')->__('Block Name'),
1040+ 'index' => 'block_name'
1041+ ));
1042+
1043+ $this->addColumn('is_allowed', array(
1044+ 'header' => Mage::helper('adminhtml')->__('Status'),
1045+ 'index' => 'is_allowed',
1046+ 'type' => 'options',
1047+ 'options' => array('1' => Mage::helper('adminhtml')->__('Allowed'), '0' => Mage::helper('adminhtml')->__('Not allowed')),
1048+ ));
1049+
1050+ return parent::_prepareColumns();
1051+ }
1052+
1053+ /**
1054+ * @param $row
1055+ * @return string
1056+ */
1057+ public function getRowUrl($row)
1058+ {
1059+ return $this->getUrl('*/*/edit', array('block_id' => $row->getId()));
1060+ }
1061+
1062+ /**
1063+ * @return string
1064+ */
1065+ public function getGridUrl()
1066+ {
1067+ return $this->getUrl('*/*/blockGrid', array());
1068+ }
1069+}
1070diff --git app/code/core/Mage/Adminhtml/Block/Permissions/Variable.php app/code/core/Mage/Adminhtml/Block/Permissions/Variable.php
1071new file mode 100644
1072index 0000000..37cd6e6
1073--- /dev/null
1074+++ app/code/core/Mage/Adminhtml/Block/Permissions/Variable.php
1075@@ -0,0 +1,57 @@
1076+<?php
1077+/**
1078+ * Magento
1079+ *
1080+ * NOTICE OF LICENSE
1081+ *
1082+ * This source file is subject to the Open Software License (OSL 3.0)
1083+ * that is bundled with this package in the file LICENSE.txt.
1084+ * It is also available through the world-wide-web at this URL:
1085+ * http://opensource.org/licenses/osl-3.0.php
1086+ * If you did not receive a copy of the license and are unable to
1087+ * obtain it through the world-wide-web, please send an email
1088+ * to license@magentocommerce.com so we can send you a copy immediately.
1089+ *
1090+ * DISCLAIMER
1091+ *
1092+ * Do not edit or add to this file if you wish to upgrade Magento to newer
1093+ * versions in the future. If you wish to customize Magento for your
1094+ * needs please refer to http://www.magentocommerce.com for more information.
1095+ *
1096+ * @category Mage
1097+ * @package Mage_Adminhtml
1098+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
1099+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
1100+ */
1101+
1102+/**
1103+ * Variables block
1104+ *
1105+ * @category Mage
1106+ * @package Mage_Adminhtml
1107+ * @author Magento Core Team <core@magentocommerce.com>
1108+ */
1109+class Mage_Adminhtml_Block_Permissions_Variable extends Mage_Adminhtml_Block_Widget_Grid_Container
1110+{
1111+ /**
1112+ * Construct
1113+ */
1114+ public function __construct()
1115+ {
1116+ $this->_controller = 'permissions_variable';
1117+ $this->_headerText = Mage::helper('adminhtml')->__('Variables');
1118+ $this->_addButtonLabel = Mage::helper('adminhtml')->__('Add new variable');
1119+ parent::__construct();
1120+ }
1121+
1122+ /**
1123+ * Prepare output HTML
1124+ *
1125+ * @return string
1126+ */
1127+ protected function _toHtml()
1128+ {
1129+ Mage::dispatchEvent('permissions_variable_html_before', array('block' => $this));
1130+ return parent::_toHtml();
1131+ }
1132+}
1133diff --git app/code/core/Mage/Adminhtml/Block/Permissions/Variable/Edit.php app/code/core/Mage/Adminhtml/Block/Permissions/Variable/Edit.php
1134new file mode 100644
1135index 0000000..0642944
1136--- /dev/null
1137+++ app/code/core/Mage/Adminhtml/Block/Permissions/Variable/Edit.php
1138@@ -0,0 +1,62 @@
1139+<?php
1140+/**
1141+ * Magento
1142+ *
1143+ * NOTICE OF LICENSE
1144+ *
1145+ * This source file is subject to the Open Software License (OSL 3.0)
1146+ * that is bundled with this package in the file LICENSE.txt.
1147+ * It is also available through the world-wide-web at this URL:
1148+ * http://opensource.org/licenses/osl-3.0.php
1149+ * If you did not receive a copy of the license and are unable to
1150+ * obtain it through the world-wide-web, please send an email
1151+ * to license@magentocommerce.com so we can send you a copy immediately.
1152+ *
1153+ * DISCLAIMER
1154+ *
1155+ * Do not edit or add to this file if you wish to upgrade Magento to newer
1156+ * versions in the future. If you wish to customize Magento for your
1157+ * needs please refer to http://www.magentocommerce.com for more information.
1158+ *
1159+ * @category Mage
1160+ * @package Mage_Adminhtml
1161+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
1162+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
1163+ */
1164+
1165+/**
1166+ * Adminhtml permissions variable edit page
1167+ *
1168+ * @category Mage
1169+ * @package Mage_Adminhtml
1170+ * @author Magento Core Team <core@magentocommerce.com>
1171+ */
1172+class Mage_Adminhtml_Block_Permissions_Variable_Edit extends Mage_Adminhtml_Block_Widget_Form_Container
1173+{
1174+ /**
1175+ * Construct
1176+ */
1177+ public function __construct()
1178+ {
1179+ $this->_objectId = 'variable_id';
1180+ $this->_controller = 'permissions_variable';
1181+
1182+ parent::__construct();
1183+
1184+ $this->_updateButton('save', 'label', Mage::helper('adminhtml')->__('Save Variable'));
1185+ $this->_updateButton('delete', 'label', Mage::helper('adminhtml')->__('Delete Variable'));
1186+ }
1187+
1188+ /**
1189+ * @return string
1190+ */
1191+ public function getHeaderText()
1192+ {
1193+ if (Mage::registry('permissions_variable')->getId()) {
1194+ return Mage::helper('adminhtml')->__("Edit Variable '%s'", $this->escapeHtml(Mage::registry('permissions_variable')->getVariableName()));
1195+ }
1196+ else {
1197+ return Mage::helper('adminhtml')->__('New Variable');
1198+ }
1199+ }
1200+}
1201diff --git app/code/core/Mage/Adminhtml/Block/Permissions/Variable/Edit/Form.php app/code/core/Mage/Adminhtml/Block/Permissions/Variable/Edit/Form.php
1202new file mode 100644
1203index 0000000..0b71406
1204--- /dev/null
1205+++ app/code/core/Mage/Adminhtml/Block/Permissions/Variable/Edit/Form.php
1206@@ -0,0 +1,88 @@
1207+<?php
1208+/**
1209+ * Magento
1210+ *
1211+ * NOTICE OF LICENSE
1212+ *
1213+ * This source file is subject to the Open Software License (OSL 3.0)
1214+ * that is bundled with this package in the file LICENSE.txt.
1215+ * It is also available through the world-wide-web at this URL:
1216+ * http://opensource.org/licenses/osl-3.0.php
1217+ * If you did not receive a copy of the license and are unable to
1218+ * obtain it through the world-wide-web, please send an email
1219+ * to license@magentocommerce.com so we can send you a copy immediately.
1220+ *
1221+ * DISCLAIMER
1222+ *
1223+ * Do not edit or add to this file if you wish to upgrade Magento to newer
1224+ * versions in the future. If you wish to customize Magento for your
1225+ * needs please refer to http://www.magentocommerce.com for more information.
1226+ *
1227+ * @category Mage
1228+ * @package Mage_Adminhtml
1229+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
1230+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
1231+ */
1232+
1233+/**
1234+ * Adminhtml permissions variable edit form
1235+ *
1236+ * @category Mage
1237+ * @package Mage_Adminhtml
1238+ * @author Magento Core Team <core@magentocommerce.com>
1239+ */
1240+class Mage_Adminhtml_Block_Permissions_Variable_Edit_Form extends Mage_Adminhtml_Block_Widget_Form
1241+{
1242+ /**
1243+ * @return Mage_Adminhtml_Block_Widget_Form
1244+ * @throws Exception
1245+ */
1246+ protected function _prepareForm()
1247+ {
1248+ $block = Mage::getModel('admin/variable')->load((int) $this->getRequest()->getParam('variable_id'));
1249+
1250+ $form = new Varien_Data_Form(array(
1251+ 'id' => 'edit_form',
1252+ 'action' => $this->getUrl(
1253+ '*/*/save',
1254+ array(
1255+ 'variable_id' => (int) $this->getRequest()->getParam('variable_id')
1256+ )
1257+ ),
1258+ 'method' => 'post'
1259+ ));
1260+ $fieldset = $form->addFieldset(
1261+ 'variable_details', array('legend' => $this->__('Variable Details'))
1262+ );
1263+
1264+ $fieldset->addField('variable_name', 'text', array(
1265+ 'label' => $this->__('Variable Name'),
1266+ 'required' => true,
1267+ 'name' => 'variable_name',
1268+ ));
1269+
1270+
1271+ $yesno = array(
1272+ array(
1273+ 'value' => 0,
1274+ 'label' => $this->__('No')
1275+ ),
1276+ array(
1277+ 'value' => 1,
1278+ 'label' => $this->__('Yes')
1279+ ));
1280+
1281+
1282+ $fieldset->addField('is_allowed', 'select', array(
1283+ 'name' => 'is_allowed',
1284+ 'label' => $this->__('Is Allowed'),
1285+ 'title' => $this->__('Is Allowed'),
1286+ 'values' => $yesno,
1287+ ));
1288+
1289+ $form->setUseContainer(true);
1290+ $form->setValues($block->getData());
1291+ $this->setForm($form);
1292+ return parent::_prepareForm();
1293+ }
1294+}
1295diff --git app/code/core/Mage/Adminhtml/Block/Permissions/Variable/Grid.php app/code/core/Mage/Adminhtml/Block/Permissions/Variable/Grid.php
1296new file mode 100644
1297index 0000000..df186e8
1298--- /dev/null
1299+++ app/code/core/Mage/Adminhtml/Block/Permissions/Variable/Grid.php
1300@@ -0,0 +1,104 @@
1301+<?php
1302+/**
1303+ * Magento
1304+ *
1305+ * NOTICE OF LICENSE
1306+ *
1307+ * This source file is subject to the Open Software License (OSL 3.0)
1308+ * that is bundled with this package in the file LICENSE.txt.
1309+ * It is also available through the world-wide-web at this URL:
1310+ * http://opensource.org/licenses/osl-3.0.php
1311+ * If you did not receive a copy of the license and are unable to
1312+ * obtain it through the world-wide-web, please send an email
1313+ * to license@magentocommerce.com so we can send you a copy immediately.
1314+ *
1315+ * DISCLAIMER
1316+ *
1317+ * Do not edit or add to this file if you wish to upgrade Magento to newer
1318+ * versions in the future. If you wish to customize Magento for your
1319+ * needs please refer to http://www.magentocommerce.com for more information.
1320+ *
1321+ * @category Mage
1322+ * @package Mage_Adminhtml
1323+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
1324+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
1325+ */
1326+
1327+/**
1328+ * Adminhtml permissions variable grid
1329+ *
1330+ * @category Mage
1331+ * @package Mage_Adminhtml
1332+ * @author Magento Core Team <core@magentocommerce.com>
1333+ */
1334+class Mage_Adminhtml_Block_Permissions_Variable_Grid extends Mage_Adminhtml_Block_Widget_Grid
1335+{
1336+ /**
1337+ * Construct
1338+ */
1339+ public function __construct()
1340+ {
1341+ parent::__construct();
1342+ $this->setId('permissionsVariableGrid');
1343+ $this->setDefaultSort('variable_id');
1344+ $this->setDefaultDir('asc');
1345+ $this->setUseAjax(true);
1346+ }
1347+
1348+ /**
1349+ * @return Mage_Adminhtml_Block_Widget_Grid
1350+ */
1351+ protected function _prepareCollection()
1352+ {
1353+ /** @var Mage_Admin_Model_Resource_Variable_Collection $collection */
1354+ $collection = Mage::getResourceModel('admin/variable_collection');
1355+ $this->setCollection($collection);
1356+ return parent::_prepareCollection();
1357+ }
1358+
1359+ /**
1360+ * @throws Exception
1361+ */
1362+ protected function _prepareColumns()
1363+ {
1364+ $this->addColumn('variable_id', array(
1365+ 'header' => Mage::helper('adminhtml')->__('ID'),
1366+ 'width' => 5,
1367+ 'align' => 'right',
1368+ 'sortable' => true,
1369+ 'index' => 'variable_id'
1370+ ));
1371+ $this->addColumn('variable_name', array(
1372+ 'header' => Mage::helper('adminhtml')->__('Variable'),
1373+ 'index' => 'variable_name'
1374+ ));
1375+ $this->addColumn('is_allowed', array(
1376+ 'header' => Mage::helper('adminhtml')->__('Status'),
1377+ 'index' => 'is_allowed',
1378+ 'type' => 'options',
1379+ 'options' => array(
1380+ '1' => Mage::helper('adminhtml')->__('Allowed'),
1381+ '0' => Mage::helper('adminhtml')->__('Not allowed')),
1382+ )
1383+ );
1384+
1385+ parent::_prepareColumns();
1386+ }
1387+
1388+ /**
1389+ * @param $row
1390+ * @return string
1391+ */
1392+ public function getRowUrl($row)
1393+ {
1394+ return $this->getUrl('*/*/edit', array('variable_id' => $row->getId()));
1395+ }
1396+
1397+ /**
1398+ * @return string
1399+ */
1400+ public function getGridUrl()
1401+ {
1402+ return $this->getUrl('*/*/variableGrid', array());
1403+ }
1404+}
1405diff --git app/code/core/Mage/Adminhtml/controllers/Permissions/BlockController.php app/code/core/Mage/Adminhtml/controllers/Permissions/BlockController.php
1406new file mode 100644
1407index 0000000..eb91f85
1408--- /dev/null
1409+++ app/code/core/Mage/Adminhtml/controllers/Permissions/BlockController.php
1410@@ -0,0 +1,216 @@
1411+<?php
1412+/**
1413+ * Magento
1414+ *
1415+ * NOTICE OF LICENSE
1416+ *
1417+ * This source file is subject to the Open Software License (OSL 3.0)
1418+ * that is bundled with this package in the file LICENSE.txt.
1419+ * It is also available through the world-wide-web at this URL:
1420+ * http://opensource.org/licenses/osl-3.0.php
1421+ * If you did not receive a copy of the license and are unable to
1422+ * obtain it through the world-wide-web, please send an email
1423+ * to license@magentocommerce.com so we can send you a copy immediately.
1424+ *
1425+ * DISCLAIMER
1426+ *
1427+ * Do not edit or add to this file if you wish to upgrade Magento to newer
1428+ * versions in the future. If you wish to customize Magento for your
1429+ * needs please refer to http://www.magentocommerce.com for more information.
1430+ *
1431+ * @category Mage
1432+ * @package Mage_Adminhtml
1433+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
1434+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
1435+ */
1436+
1437+/**
1438+ * Class Mage_Adminhtml_Permissions_BlockController
1439+ *
1440+ * @category Mage
1441+ * @package Mage_Adminhtml
1442+ * @author Magento Core Team <core@magentocommerce.com>
1443+ */
1444+class Mage_Adminhtml_Permissions_BlockController extends Mage_Adminhtml_Controller_Action
1445+{
1446+ /**
1447+ * @return $this
1448+ */
1449+ protected function _initAction()
1450+ {
1451+ $this->loadLayout()
1452+ ->_setActiveMenu('system/acl')
1453+ ->_addBreadcrumb($this->__('System'), $this->__('System'))
1454+ ->_addBreadcrumb($this->__('Permissions'), $this->__('Permissions'))
1455+ ->_addBreadcrumb($this->__('Blocks'), $this->__('Blocks'));
1456+ return $this;
1457+ }
1458+
1459+ /**
1460+ * Index action
1461+ */
1462+ public function indexAction()
1463+ {
1464+ $this->_title($this->__('System'))
1465+ ->_title($this->__('Permissions'))
1466+ ->_title($this->__('Blocks'));
1467+
1468+ /** @var Mage_Adminhtml_Block_Permissions_Block $block */
1469+ $block = $this->getLayout()->createBlock('adminhtml/permissions_block');
1470+ $this->_initAction()
1471+ ->_addContent($block)
1472+ ->renderLayout();
1473+ }
1474+
1475+ /**
1476+ * New action
1477+ */
1478+ public function newAction()
1479+ {
1480+ $this->_forward('edit');
1481+ }
1482+
1483+ /**
1484+ * Edit action
1485+ */
1486+ public function editAction()
1487+ {
1488+ $this->_title($this->__('System'))
1489+ ->_title($this->__('Permissions'))
1490+ ->_title($this->__('Blocks'));
1491+
1492+ $id = (int) $this->getRequest()->getParam('block_id');
1493+ $model = Mage::getModel('admin/block');
1494+
1495+ if ($id) {
1496+ $model->load($id);
1497+ if (! $model->getId()) {
1498+ Mage::getSingleton('adminhtml/session')->addError($this->__('This block no longer exists.'));
1499+ $this->_redirect('*/*/');
1500+ return;
1501+ }
1502+ }
1503+
1504+ $this->_title($model->getId() ? $model->getBlockName() : $this->__('New Block'));
1505+
1506+ // Restore previously entered form data from session
1507+ $data = Mage::getSingleton('adminhtml/session')->getUserData(true);
1508+ if (!empty($data)) {
1509+ $model->setData($data);
1510+ }
1511+
1512+ Mage::register('permissions_block', $model);
1513+
1514+ if (isset($id)) {
1515+ $breadcrumb = $this->__('Edit Block');
1516+ } else {
1517+ $breadcrumb = $this->__('New Block');
1518+ }
1519+ $this->_initAction()
1520+ ->_addBreadcrumb($breadcrumb, $breadcrumb);
1521+
1522+ $this->getLayout()->getBlock('adminhtml.permissions.block.edit')
1523+ ->setData('action', $this->getUrl('*/permissions_block/save'));
1524+
1525+ $this->renderLayout();
1526+ }
1527+
1528+ /**
1529+ * Save action
1530+ *
1531+ * @return $this|void
1532+ */
1533+ public function saveAction()
1534+ {
1535+ if ($data = $this->getRequest()->getPost()) {
1536+ $id = (int) $this->getRequest()->getParam('block_id');
1537+ $model = Mage::getModel('admin/block')->load($id);
1538+ if (!$model->getId() && $id) {
1539+ Mage::getSingleton('adminhtml/session')->addError($this->__('This block no longer exists.'));
1540+ $this->_redirect('*/*/');
1541+ return;
1542+ }
1543+
1544+ $model->setData($data);
1545+ if ($id) {
1546+ $model->setId($id);
1547+ }
1548+ $result = $model->validate();
1549+
1550+ if (is_array($result)) {
1551+ Mage::getSingleton('adminhtml/session')->setUserData($data);
1552+ foreach ($result as $message) {
1553+ Mage::getSingleton('adminhtml/session')->addError($message);
1554+ }
1555+ $this->_redirect('*/*/edit', array('block_id' => $id));
1556+ return $this;
1557+ }
1558+ try {
1559+ $model->save();
1560+ Mage::getSingleton('adminhtml/session')->addSuccess($this->__('The block has been saved.'));
1561+ // clear previously saved data from session
1562+ Mage::getSingleton('adminhtml/session')->setFormData(false);
1563+
1564+ $this->_redirect('*/*/');
1565+ return;
1566+
1567+ } catch (Exception $e) {
1568+ // display error message
1569+ Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
1570+ // save data in session
1571+ Mage::getSingleton('adminhtml/session')->setFormData($data);
1572+ // redirect to edit form
1573+ $this->_redirect('*/*/edit', array('block_id' => $id));
1574+ return;
1575+ }
1576+ }
1577+ $this->_redirect('*/*/');
1578+ }
1579+
1580+ /**
1581+ * Delete action
1582+ */
1583+ public function deleteAction()
1584+ {
1585+ $id = (int) $this->getRequest()->getParam('block_id');
1586+ if ($id) {
1587+ try {
1588+ $model = Mage::getModel('admin/block');
1589+ $model->setId($id);
1590+ $model->delete();
1591+ Mage::getSingleton('adminhtml/session')->addSuccess($this->__('Block has been deleted.'));
1592+ $this->_redirect('*/*/');
1593+ return;
1594+ }
1595+ catch (Exception $e) {
1596+ Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
1597+ $this->_redirect('*/*/edit', array('block_id' => $id));
1598+ return;
1599+ }
1600+ }
1601+ Mage::getSingleton('adminhtml/session')->addError($this->__('Unable to find a block to delete.'));
1602+ $this->_redirect('*/*/');
1603+ }
1604+
1605+ /**
1606+ * Grid action
1607+ */
1608+ public function blockGridAction()
1609+ {
1610+ $this->getResponse()
1611+ ->setBody($this->getLayout()
1612+ ->createBlock('adminhtml/permissions_block_grid')
1613+ ->toHtml()
1614+ );
1615+ }
1616+
1617+ /**
1618+ * Check permissions before allow edit list of blocks
1619+ *
1620+ * @return bool
1621+ */
1622+ protected function _isAllowed()
1623+ {
1624+ return Mage::getSingleton('admin/session')->isAllowed('system/acl/blocks');
1625+ }
1626+}
1627diff --git app/code/core/Mage/Adminhtml/controllers/Permissions/VariableController.php app/code/core/Mage/Adminhtml/controllers/Permissions/VariableController.php
1628new file mode 100644
1629index 0000000..d8f34ac
1630--- /dev/null
1631+++ app/code/core/Mage/Adminhtml/controllers/Permissions/VariableController.php
1632@@ -0,0 +1,215 @@
1633+<?php
1634+/**
1635+ * Magento
1636+ *
1637+ * NOTICE OF LICENSE
1638+ *
1639+ * This source file is subject to the Open Software License (OSL 3.0)
1640+ * that is bundled with this package in the file LICENSE.txt.
1641+ * It is also available through the world-wide-web at this URL:
1642+ * http://opensource.org/licenses/osl-3.0.php
1643+ * If you did not receive a copy of the license and are unable to
1644+ * obtain it through the world-wide-web, please send an email
1645+ * to license@magentocommerce.com so we can send you a copy immediately.
1646+ *
1647+ * DISCLAIMER
1648+ *
1649+ * Do not edit or add to this file if you wish to upgrade Magento to newer
1650+ * versions in the future. If you wish to customize Magento for your
1651+ * needs please refer to http://www.magentocommerce.com for more information.
1652+ *
1653+ * @category Mage
1654+ * @package Mage_Adminhtml
1655+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
1656+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
1657+ */
1658+
1659+/**
1660+ * Class Mage_Adminhtml_Permissions_VariableController
1661+ *
1662+ * @category Mage
1663+ * @package Mage_Adminhtml
1664+ * @author Magento Core Team <core@magentocommerce.com>
1665+ */
1666+class Mage_Adminhtml_Permissions_VariableController extends Mage_Adminhtml_Controller_Action
1667+{
1668+ /**
1669+ * @return $this
1670+ */
1671+ protected function _initAction()
1672+ {
1673+ $this->loadLayout()
1674+ ->_setActiveMenu('system/acl')
1675+ ->_addBreadcrumb($this->__('System'), $this->__('System'))
1676+ ->_addBreadcrumb($this->__('Permissions'), $this->__('Permissions'))
1677+ ->_addBreadcrumb($this->__('Variables'), $this->__('Variables'));
1678+ return $this;
1679+ }
1680+
1681+ /**
1682+ * Index action
1683+ */
1684+ public function indexAction()
1685+ {
1686+ $this->_title($this->__('System'))
1687+ ->_title($this->__('Permissions'))
1688+ ->_title($this->__('Variables'));
1689+
1690+ /** @var Mage_Adminhtml_Block_Permissions_Variables $block */
1691+ $block = $this->getLayout()->createBlock('adminhtml/permissions_variable');
1692+ $this->_initAction()
1693+ ->_addContent($block)
1694+ ->renderLayout();
1695+ }
1696+
1697+ /**
1698+ * New action
1699+ */
1700+ public function newAction()
1701+ {
1702+ $this->_forward('edit');
1703+ }
1704+
1705+ /**
1706+ * Edit action
1707+ */
1708+ public function editAction()
1709+ {
1710+ $this->_title($this->__('System'))
1711+ ->_title($this->__('Permissions'))
1712+ ->_title($this->__('Variables'));
1713+
1714+ $id = (int) $this->getRequest()->getParam('variable_id');
1715+ $model = Mage::getModel('admin/variable');
1716+
1717+ if ($id) {
1718+ $model->load($id);
1719+ if (!$model->getId()) {
1720+ Mage::getSingleton('adminhtml/session')->addError($this->__('This variable no longer exists.'));
1721+ $this->_redirect('*/*/');
1722+ return;
1723+ }
1724+ }
1725+
1726+ $this->_title($model->getId() ? $model->getVariableName() : $this->__('New Variable'));
1727+
1728+ // Restore previously entered form data from session
1729+ $data = Mage::getSingleton('adminhtml/session')->getUserData(true);
1730+ if (!empty($data)) {
1731+ $model->setData($data);
1732+ }
1733+
1734+ Mage::register('permissions_variable', $model);
1735+
1736+ if (isset($id)) {
1737+ $breadcrumb = $this->__('Edit Variable');
1738+ } else {
1739+ $breadcrumb = $this->__('New Variable');
1740+ }
1741+ $this->_initAction()
1742+ ->_addBreadcrumb($breadcrumb, $breadcrumb);
1743+
1744+ $this->getLayout()->getBlock('adminhtml.permissions.variable.edit')
1745+ ->setData('action', $this->getUrl('*/permissions_variable/save'));
1746+
1747+ $this->renderLayout();
1748+ }
1749+
1750+ /**
1751+ * Save action
1752+ *
1753+ * @return $this|void
1754+ */
1755+ public function saveAction()
1756+ {
1757+ if ($data = $this->getRequest()->getPost()) {
1758+ $id = (int) $this->getRequest()->getParam('variable_id');
1759+ $model = Mage::getModel('admin/variable')->load($id);
1760+ if (!$model->getId() && $id) {
1761+ Mage::getSingleton('adminhtml/session')->addError($this->__('This variable no longer exists.'));
1762+ $this->_redirect('*/*/');
1763+ return;
1764+ }
1765+
1766+ $model->setData($data);
1767+ if ($id) {
1768+ $model->setId($id);
1769+ }
1770+ $result = $model->validate();
1771+
1772+ if (is_array($result)) {
1773+ Mage::getSingleton('adminhtml/session')->setUserData($data);
1774+ foreach ($result as $message) {
1775+ Mage::getSingleton('adminhtml/session')->addError($message);
1776+ }
1777+ $this->_redirect('*/*/edit', array('variable_id' => $id));
1778+ return $this;
1779+ }
1780+ try {
1781+ $model->save();
1782+ Mage::getSingleton('adminhtml/session')->addSuccess($this->__('The variable has been saved.'));
1783+ // clear previously saved data from session
1784+ Mage::getSingleton('adminhtml/session')->setFormData(false);
1785+
1786+ $this->_redirect('*/*/');
1787+ return;
1788+
1789+ } catch (Exception $e) {
1790+ // display error message
1791+ Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
1792+ // save data in session
1793+ Mage::getSingleton('adminhtml/session')->setFormData($data);
1794+ // redirect to edit form
1795+ $this->_redirect('*/*/edit', array('variable_id' => $id));
1796+ return;
1797+ }
1798+ }
1799+ $this->_redirect('*/*/');
1800+ }
1801+
1802+ /**
1803+ * Delete action
1804+ */
1805+ public function deleteAction()
1806+ {
1807+ $id = (int) $this->getRequest()->getParam('variable_id');
1808+ if ($id) {
1809+ try {
1810+ $model = Mage::getModel('admin/variable');
1811+ $model->setId($id);
1812+ $model->delete();
1813+ Mage::getSingleton('adminhtml/session')->addSuccess($this->__('Variable has been deleted.'));
1814+ $this->_redirect('*/*/');
1815+ return;
1816+ } catch (Exception $e) {
1817+ Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
1818+ $this->_redirect('*/*/edit', array('variable_id' => $id));
1819+ return;
1820+ }
1821+ }
1822+ Mage::getSingleton('adminhtml/session')->addError($this->__('Unable to find a variable to delete.'));
1823+ $this->_redirect('*/*/');
1824+ }
1825+
1826+ /**
1827+ * Grid action
1828+ */
1829+ public function variableGridAction()
1830+ {
1831+ $this->getResponse()
1832+ ->setBody($this->getLayout()
1833+ ->createBlock('adminhtml/permissions_variable_grid')
1834+ ->toHtml()
1835+ );
1836+ }
1837+
1838+ /**
1839+ * Check permissions before allow edit list of config variables
1840+ *
1841+ * @return bool
1842+ */
1843+ protected function _isAllowed()
1844+ {
1845+ return Mage::getSingleton('admin/session')->isAllowed('system/acl/variables');
1846+ }
1847+}
1848diff --git app/code/core/Mage/Adminhtml/etc/adminhtml.xml app/code/core/Mage/Adminhtml/etc/adminhtml.xml
1849index 0f5a1cc..f546540 100644
1850--- app/code/core/Mage/Adminhtml/etc/adminhtml.xml
1851+++ app/code/core/Mage/Adminhtml/etc/adminhtml.xml
1852@@ -94,6 +94,14 @@
1853 <title>Roles</title>
1854 <action>adminhtml/permissions_role</action>
1855 </roles>
1856+ <variables translate="title">
1857+ <title>Variables</title>
1858+ <action>adminhtml/permissions_variable</action>
1859+ </variables>
1860+ <blocks translate="title">
1861+ <title>Blocks</title>
1862+ <action>adminhtml/permissions_block</action>
1863+ </blocks>
1864 </children>
1865 </acl>
1866 <cache translate="title">
1867@@ -142,6 +150,12 @@
1868 <title>Users</title>
1869 <sort_order>20</sort_order>
1870 </users>
1871+ <variables translate="title">
1872+ <title>Variables</title>
1873+ </variables>
1874+ <blocks translate="title">
1875+ <title>Blocks</title>
1876+ </blocks>
1877 </children>
1878 </acl>
1879 <store translate="title">
1880diff --git app/code/core/Mage/Catalog/Model/Product/Option/Type/File.php app/code/core/Mage/Catalog/Model/Product/Option/Type/File.php
1881index 60a5395..f2ed4b9 100644
1882--- app/code/core/Mage/Catalog/Model/Product/Option/Type/File.php
1883+++ app/code/core/Mage/Catalog/Model/Product/Option/Type/File.php
1884@@ -126,17 +126,9 @@ class Mage_Catalog_Model_Product_Option_Type_File extends Mage_Catalog_Model_Pro
1885 * Check whether we receive uploaded file or restore file by: reorder/edit configuration or
1886 * previous configuration with no newly uploaded file
1887 */
1888- $fileInfo = null;
1889- if (isset($values[$option->getId()]) && is_array($values[$option->getId()])) {
1890- // Legacy style, file info comes in array with option id index
1891- $fileInfo = $values[$option->getId()];
1892- } else {
1893- /*
1894- * New recommended style - file info comes in request processing parameters and we
1895- * sure that this file info originates from Magento, not from manually formed POST request
1896- */
1897- $fileInfo = $this->_getCurrentConfigFileInfo();
1898- }
1899+
1900+ $fileInfo = $this->_getCurrentConfigFileInfo();
1901+
1902 if ($fileInfo !== null) {
1903 if (is_array($fileInfo) && $this->_validateFile($fileInfo)) {
1904 $value = $fileInfo;
1905@@ -448,6 +440,11 @@ class Mage_Catalog_Model_Product_Option_Type_File extends Mage_Catalog_Model_Pro
1906 // Save option in request, because we have no $_FILES['options']
1907 $requestOptions[$this->getOption()->getId()] = $value;
1908 $result = serialize($value);
1909+ try {
1910+ Mage::helper('core/unserializeArray')->unserialize($result);
1911+ } catch (Exception $e) {
1912+ Mage::throwException(Mage::helper('catalog')->__("File options format is not valid."));
1913+ }
1914 } else {
1915 /*
1916 * Clear option info from request, so it won't be stored in our db upon
1917@@ -478,7 +475,7 @@ class Mage_Catalog_Model_Product_Option_Type_File extends Mage_Catalog_Model_Pro
1918 {
1919 if ($this->_formattedOptionValue === null) {
1920 try {
1921- $value = unserialize($optionValue);
1922+ $value = Mage::helper('core/unserializeArray')->unserialize($optionValue);
1923
1924 $customOptionUrlParams = $this->getCustomOptionUrlParams()
1925 ? $this->getCustomOptionUrlParams()
1926@@ -542,7 +539,7 @@ class Mage_Catalog_Model_Product_Option_Type_File extends Mage_Catalog_Model_Pro
1927 if (is_array($value)) {
1928 return $value;
1929 } elseif (is_string($value) && !empty($value)) {
1930- return unserialize($value);
1931+ return Mage::helper('core/unserializeArray')->unserialize($value);
1932 } else {
1933 return array();
1934 }
1935@@ -568,7 +565,7 @@ class Mage_Catalog_Model_Product_Option_Type_File extends Mage_Catalog_Model_Pro
1936 public function getEditableOptionValue($optionValue)
1937 {
1938 try {
1939- $value = unserialize($optionValue);
1940+ $value = Mage::helper('core/unserializeArray')->unserialize($optionValue);
1941 return sprintf('%s [%d]',
1942 Mage::helper('core')->escapeHtml($value['title']),
1943 $this->getConfigurationItemOption()->getId()
1944@@ -593,7 +590,6 @@ class Mage_Catalog_Model_Product_Option_Type_File extends Mage_Catalog_Model_Pro
1945 $confItemOptionId = $matches[1];
1946 $option = Mage::getModel('sales/quote_item_option')->load($confItemOptionId);
1947 try {
1948- unserialize($option->getValue());
1949 return $option->getValue();
1950 } catch (Exception $e) {
1951 return null;
1952@@ -612,7 +608,7 @@ class Mage_Catalog_Model_Product_Option_Type_File extends Mage_Catalog_Model_Pro
1953 public function prepareOptionValueForRequest($optionValue)
1954 {
1955 try {
1956- $result = unserialize($optionValue);
1957+ $result = Mage::helper('core/unserializeArray')->unserialize($optionValue);
1958 return $result;
1959 } catch (Exception $e) {
1960 return null;
1961@@ -628,7 +624,7 @@ class Mage_Catalog_Model_Product_Option_Type_File extends Mage_Catalog_Model_Pro
1962 {
1963 $quoteOption = $this->getQuoteItemOption();
1964 try {
1965- $value = unserialize($quoteOption->getValue());
1966+ $value = Mage::helper('core/unserializeArray')->unserialize($quoteOption->getValue());
1967 if (!isset($value['quote_path'])) {
1968 throw new Exception();
1969 }
1970diff --git app/code/core/Mage/Core/Controller/Request/Http.php app/code/core/Mage/Core/Controller/Request/Http.php
1971index 156bb32..9e2100a 100644
1972--- app/code/core/Mage/Core/Controller/Request/Http.php
1973+++ app/code/core/Mage/Core/Controller/Request/Http.php
1974@@ -298,11 +298,19 @@ class Mage_Core_Controller_Request_Http extends Zend_Controller_Request_Http
1975 if (!isset($_SERVER['HTTP_HOST'])) {
1976 return false;
1977 }
1978+ $host = $_SERVER['HTTP_HOST'];
1979 if ($trimPort) {
1980- $host = explode(':', $_SERVER['HTTP_HOST']);
1981- return $host[0];
1982+ $hostParts = explode(':', $_SERVER['HTTP_HOST']);
1983+ $host = $hostParts[0];
1984 }
1985- return $_SERVER['HTTP_HOST'];
1986+
1987+ if (strpos($host, ',') !== false || strpos($host, ';') !== false) {
1988+ $response = new Zend_Controller_Response_Http();
1989+ $response->setHttpResponseCode(400)->sendHeaders();
1990+ exit();
1991+ }
1992+
1993+ return $host;
1994 }
1995
1996 /**
1997diff --git app/code/core/Mage/Core/Controller/Varien/Router/Admin.php app/code/core/Mage/Core/Controller/Varien/Router/Admin.php
1998index 132b26d..015ee84 100644
1999--- app/code/core/Mage/Core/Controller/Varien/Router/Admin.php
2000+++ app/code/core/Mage/Core/Controller/Varien/Router/Admin.php
2001@@ -131,6 +131,29 @@ class Mage_Core_Controller_Varien_Router_Admin extends Mage_Core_Controller_Vari
2002 }
2003
2004 /**
2005+ * Add module definition to routes.
2006+ *
2007+ * @param string $frontName
2008+ * @param mixed $moduleName
2009+ * @param string $routeName
2010+ * @return $this
2011+ */
2012+ public function addModule($frontName, $moduleName, $routeName)
2013+ {
2014+ $isExtensionsCompatibilityMode = (bool)(string)Mage::getConfig()->getNode(
2015+ 'default/admin/security/extensions_compatibility_mode'
2016+ );
2017+ $configRouterFrontName = (string)Mage::getConfig()->getNode(
2018+ Mage_Adminhtml_Helper_Data::XML_PATH_ADMINHTML_ROUTER_FRONTNAME
2019+ );
2020+ if ($isExtensionsCompatibilityMode || ($frontName == $configRouterFrontName)) {
2021+ return parent::addModule($frontName, $moduleName, $routeName);
2022+ } else {
2023+ return $this;
2024+ }
2025+ }
2026+
2027+ /**
2028 * Check if current controller instance is allowed in current router.
2029 *
2030 * @param Mage_Core_Controller_Varien_Action $controllerInstance
2031diff --git app/code/core/Mage/Core/Helper/UnserializeArray.php app/code/core/Mage/Core/Helper/UnserializeArray.php
2032new file mode 100644
2033index 0000000..2e80ab4
2034--- /dev/null
2035+++ app/code/core/Mage/Core/Helper/UnserializeArray.php
2036@@ -0,0 +1,46 @@
2037+<?php
2038+/**
2039+ * Magento
2040+ *
2041+ * NOTICE OF LICENSE
2042+ *
2043+ * This source file is subject to the Open Software License (OSL 3.0)
2044+ * that is bundled with this package in the file LICENSE.txt.
2045+ * It is also available through the world-wide-web at this URL:
2046+ * http://opensource.org/licenses/osl-3.0.php
2047+ * If you did not receive a copy of the license and are unable to
2048+ * obtain it through the world-wide-web, please send an email
2049+ * to license@magentocommerce.com so we can send you a copy immediately.
2050+ *
2051+ * DISCLAIMER
2052+ *
2053+ * Do not edit or add to this file if you wish to upgrade Magento to newer
2054+ * versions in the future. If you wish to customize Magento for your
2055+ * needs please refer to http://www.magentocommerce.com for more information.
2056+ *
2057+ * @category Mage
2058+ * @package Mage_Core
2059+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
2060+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
2061+ */
2062+
2063+/**
2064+ * Core unserialize helper
2065+ *
2066+ * @category Mage
2067+ * @package Mage_Core
2068+ * @author Magento Core Team <core@magentocommerce.com>
2069+ */
2070+class Mage_Core_Helper_UnserializeArray
2071+{
2072+ /**
2073+ * @param string $str
2074+ * @return array
2075+ * @throws Exception
2076+ */
2077+ public function unserialize($str)
2078+ {
2079+ $parser = new Unserialize_Parser();
2080+ return $parser->unserialize($str);
2081+ }
2082+}
2083diff --git app/code/core/Mage/Core/Model/Email/Template/Filter.php app/code/core/Mage/Core/Model/Email/Template/Filter.php
2084index 065159a..d50ca5a 100644
2085--- app/code/core/Mage/Core/Model/Email/Template/Filter.php
2086+++ app/code/core/Mage/Core/Model/Email/Template/Filter.php
2087@@ -65,6 +65,12 @@ class Mage_Core_Model_Email_Template_Filter extends Varien_Filter_Template
2088
2089 protected $_plainTemplateMode = false;
2090
2091+ /** @var Mage_Admin_Model_Variable */
2092+ protected $_permissionVariable;
2093+
2094+ /** @var Mage_Admin_Model_Block */
2095+ protected $_permissionBlock;
2096+
2097 /**
2098 * Setup callbacks for filters
2099 *
2100@@ -72,6 +78,8 @@ class Mage_Core_Model_Email_Template_Filter extends Varien_Filter_Template
2101 public function __construct()
2102 {
2103 $this->_modifiers['escape'] = array($this, 'modifierEscape');
2104+ $this->_permissionVariable = Mage::getModel('admin/variable');
2105+ $this->_permissionBlock = Mage::getModel('admin/block');
2106 }
2107
2108 /**
2109@@ -160,8 +168,10 @@ class Mage_Core_Model_Email_Template_Filter extends Varien_Filter_Template
2110 $layout = Mage::app()->getLayout();
2111
2112 if (isset($blockParameters['type'])) {
2113- $type = $blockParameters['type'];
2114- $block = $layout->createBlock($type, null, $blockParameters);
2115+ if ($this->_permissionBlock->isTypeAllowed($blockParameters['type'])) {
2116+ $type = $blockParameters['type'];
2117+ $block = $layout->createBlock($type, null, $blockParameters);
2118+ }
2119 } elseif (isset($blockParameters['id'])) {
2120 $block = $layout->createBlock('cms/block');
2121 if ($block) {
2122@@ -461,7 +471,7 @@ class Mage_Core_Model_Email_Template_Filter extends Varien_Filter_Template
2123 $configValue = '';
2124 $params = $this->_getIncludeParameters($construction[2]);
2125 $storeId = $this->getStoreId();
2126- if (isset($params['path'])) {
2127+ if (isset($params['path']) && $this->_permissionVariable->isPathAllowed($params['path'])) {
2128 $configValue = Mage::getStoreConfig($params['path'], $storeId);
2129 }
2130 return $configValue;
2131diff --git app/code/core/Mage/Core/Model/Resource/Setup.php app/code/core/Mage/Core/Model/Resource/Setup.php
2132index 049948a..3ea4791 100644
2133--- app/code/core/Mage/Core/Model/Resource/Setup.php
2134+++ app/code/core/Mage/Core/Model/Resource/Setup.php
2135@@ -641,7 +641,6 @@ class Mage_Core_Model_Resource_Setup
2136 $this->_setResourceVersion($actionType, $file['toVersion']);
2137 }
2138 } catch (Exception $e) {
2139- printf('<pre>%s</pre>', print_r($e, true));
2140 throw Mage::exception('Mage_Core', Mage::helper('core')->__('Error in file: "%s" - %s', $fileName, $e->getMessage()));
2141 }
2142 $version = $file['toVersion'];
2143diff --git app/code/core/Mage/Core/etc/config.xml app/code/core/Mage/Core/etc/config.xml
2144index 317b8b5..747d6f4 100644
2145--- app/code/core/Mage/Core/etc/config.xml
2146+++ app/code/core/Mage/Core/etc/config.xml
2147@@ -390,6 +390,7 @@
2148 <use_form_key>1</use_form_key>
2149 <domain_policy_backend>2</domain_policy_backend>
2150 <domain_policy_frontend>2</domain_policy_frontend>
2151+ <extensions_compatibility_mode>1</extensions_compatibility_mode>
2152 </security>
2153 </admin>
2154 <general>
2155diff --git app/code/core/Mage/Core/etc/system.xml app/code/core/Mage/Core/etc/system.xml
2156index 5cf12a9..df51dd1 100644
2157--- app/code/core/Mage/Core/etc/system.xml
2158+++ app/code/core/Mage/Core/etc/system.xml
2159@@ -1110,7 +1110,7 @@
2160 <show_in_website>0</show_in_website>
2161 <show_in_store>0</show_in_store>
2162 </session_cookie_lifetime>
2163- <domain_policy_backend translate="label">
2164+ <domain_policy_backend translate="label comment">
2165 <label>Allow Magento Backend to run in frame</label>
2166 <frontend_type>select</frontend_type>
2167 <comment>Enabling ability to run Magento in a frame is not recommended for security reasons.</comment>
2168@@ -1120,7 +1120,7 @@
2169 <show_in_website>0</show_in_website>
2170 <show_in_store>0</show_in_store>
2171 </domain_policy_backend>
2172- <domain_policy_frontend translate="label">
2173+ <domain_policy_frontend translate="label comment">
2174 <label>Allow Magento Frontend to run in frame</label>
2175 <comment>Enabling ability to run Magento in a frame is not recommended for security reasons.</comment>
2176 <frontend_type>select</frontend_type>
2177@@ -1130,6 +1130,16 @@
2178 <show_in_website>0</show_in_website>
2179 <show_in_store>0</show_in_store>
2180 </domain_policy_frontend>
2181+ <extensions_compatibility_mode translate="label comment">
2182+ <label>Admin routing compatibility mode for extensions</label>
2183+ <comment>Enabling this setting increases risk of automated attacks against admin functionality.</comment>
2184+ <frontend_type>select</frontend_type>
2185+ <sort_order>6</sort_order>
2186+ <source_model>adminhtml/system_config_source_enabledisable</source_model>
2187+ <show_in_default>1</show_in_default>
2188+ <show_in_website>0</show_in_website>
2189+ <show_in_store>0</show_in_store>
2190+ </extensions_compatibility_mode>
2191 </fields>
2192 </security>
2193 <dashboard translate="label">
2194diff --git app/code/core/Mage/Customer/Block/Account/Changeforgotten.php app/code/core/Mage/Customer/Block/Account/Changeforgotten.php
2195new file mode 100644
2196index 0000000..9c08a7d
2197--- /dev/null
2198+++ app/code/core/Mage/Customer/Block/Account/Changeforgotten.php
2199@@ -0,0 +1,38 @@
2200+<?php
2201+/**
2202+ * Magento
2203+ *
2204+ * NOTICE OF LICENSE
2205+ *
2206+ * This source file is subject to the Open Software License (OSL 3.0)
2207+ * that is bundled with this package in the file LICENSE.txt.
2208+ * It is also available through the world-wide-web at this URL:
2209+ * http://opensource.org/licenses/osl-3.0.php
2210+ * If you did not receive a copy of the license and are unable to
2211+ * obtain it through the world-wide-web, please send an email
2212+ * to license@magentocommerce.com so we can send you a copy immediately.
2213+ *
2214+ * DISCLAIMER
2215+ *
2216+ * Do not edit or add to this file if you wish to upgrade Magento to newer
2217+ * versions in the future. If you wish to customize Magento for your
2218+ * needs please refer to http://www.magentocommerce.com for more information.
2219+ *
2220+ * @category Mage
2221+ * @package Mage_Customer
2222+ * @copyright Copyright (c) 2014 Magento Inc. (http://www.magentocommerce.com)
2223+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
2224+ */
2225+
2226+/**
2227+ * Customer reset password form
2228+ *
2229+ * @category Mage
2230+ * @package Mage_Customer
2231+ * @author Magento Core Team <core@magentocommerce.com>
2232+ */
2233+
2234+class Mage_Customer_Block_Account_Changeforgotten extends Mage_Core_Block_Template
2235+{
2236+
2237+}
2238diff --git app/code/core/Mage/Customer/Block/Account/Resetpassword.php app/code/core/Mage/Customer/Block/Account/Resetpassword.php
2239index 11f00de..38ad433 100644
2240--- app/code/core/Mage/Customer/Block/Account/Resetpassword.php
2241+++ app/code/core/Mage/Customer/Block/Account/Resetpassword.php
2242@@ -32,6 +32,9 @@
2243 * @author Magento Core Team <core@magentocommerce.com>
2244 */
2245
2246+/**
2247+ * @deprecated
2248+ */
2249 class Mage_Customer_Block_Account_Resetpassword extends Mage_Core_Block_Template
2250 {
2251
2252diff --git app/code/core/Mage/Customer/controllers/AccountController.php app/code/core/Mage/Customer/controllers/AccountController.php
2253index ab1f691..19c4507 100644
2254--- app/code/core/Mage/Customer/controllers/AccountController.php
2255+++ app/code/core/Mage/Customer/controllers/AccountController.php
2256@@ -33,6 +33,9 @@
2257 */
2258 class Mage_Customer_AccountController extends Mage_Core_Controller_Front_Action
2259 {
2260+ const CUSTOMER_ID_SESSION_NAME = "customerId";
2261+ const TOKEN_SESSION_NAME = "token";
2262+
2263 /**
2264 * Action list where need check enabled cookie
2265 *
2266@@ -72,6 +75,7 @@ class Mage_Customer_AccountController extends Mage_Core_Controller_Front_Action
2267 'logoutsuccess',
2268 'forgotpassword',
2269 'forgotpasswordpost',
2270+ 'changeforgotten',
2271 'resetpassword',
2272 'resetpasswordpost',
2273 'confirm',
2274@@ -263,15 +267,21 @@ class Mage_Customer_AccountController extends Mage_Core_Controller_Front_Action
2275 */
2276 public function createPostAction()
2277 {
2278+ $errUrl = $this->_getUrl('*/*/create', array('_secure' => true));
2279+
2280+ if (!$this->_validateFormKey()) {
2281+ $this->_redirectError($errUrl);
2282+ return;
2283+ }
2284+
2285 /** @var $session Mage_Customer_Model_Session */
2286 $session = $this->_getSession();
2287 if ($session->isLoggedIn()) {
2288 $this->_redirect('*/*/');
2289 return;
2290 }
2291- $session->setEscapeMessages(true); // prevent XSS injection in user input
2292+
2293 if (!$this->getRequest()->isPost()) {
2294- $errUrl = $this->_getUrl('*/*/create', array('_secure' => true));
2295 $this->_redirectError($errUrl);
2296 return;
2297 }
2298@@ -294,16 +304,15 @@ class Mage_Customer_AccountController extends Mage_Core_Controller_Front_Action
2299 if ($e->getCode() === Mage_Customer_Model_Customer::EXCEPTION_EMAIL_EXISTS) {
2300 $url = $this->_getUrl('customer/account/forgotpassword');
2301 $message = $this->__('There is already an account with this email address. If you are sure that it is your email address, <a href="%s">click here</a> to get your password and access your account.', $url);
2302- $session->setEscapeMessages(false);
2303 } else {
2304- $message = $e->getMessage();
2305+ $message = $this->_escapeHtml($e->getMessage());
2306 }
2307 $session->addError($message);
2308 } catch (Exception $e) {
2309- $session->setCustomerFormData($this->getRequest()->getPost())
2310- ->addException($e, $this->__('Cannot save the customer.'));
2311+ $session->setCustomerFormData($this->getRequest()->getPost());
2312+ $session->addException($e, $this->__('Cannot save the customer.'));
2313 }
2314- $errUrl = $this->_getUrl('*/*/create', array('_secure' => true));
2315+
2316 $this->_redirectError($errUrl);
2317 }
2318
2319@@ -371,7 +380,7 @@ class Mage_Customer_AccountController extends Mage_Core_Controller_Front_Action
2320 $session->setCustomerFormData($this->getRequest()->getPost());
2321 if (is_array($errors)) {
2322 foreach ($errors as $errorMessage) {
2323- $session->addError($errorMessage);
2324+ $session->addError($this->_escapeHtml($errorMessage));
2325 }
2326 } else {
2327 $session->addError($this->__('Invalid customer data'));
2328@@ -379,6 +388,17 @@ class Mage_Customer_AccountController extends Mage_Core_Controller_Front_Action
2329 }
2330
2331 /**
2332+ * Escape message text HTML.
2333+ *
2334+ * @param string $text
2335+ * @return string
2336+ */
2337+ protected function _escapeHtml($text)
2338+ {
2339+ return Mage::helper('core')->escapeHtml($text);
2340+ }
2341+
2342+ /**
2343 * Validate customer data and return errors if they are
2344 *
2345 * @param Mage_Customer_Model_Customer $customer
2346@@ -735,23 +755,39 @@ class Mage_Customer_AccountController extends Mage_Core_Controller_Front_Action
2347 /**
2348 * Display reset forgotten password form
2349 *
2350- * User is redirected on this action when he clicks on the corresponding link in password reset confirmation email
2351- *
2352 */
2353- public function resetPasswordAction()
2354+ public function changeForgottenAction()
2355 {
2356- $resetPasswordLinkToken = (string) $this->getRequest()->getQuery('token');
2357- $customerId = (int) $this->getRequest()->getQuery('id');
2358 try {
2359+ list($customerId, $resetPasswordLinkToken) = $this->_getRestorePasswordParameters($this->_getSession());
2360 $this->_validateResetPasswordLinkToken($customerId, $resetPasswordLinkToken);
2361 $this->loadLayout();
2362- // Pass received parameters to the reset forgotten password form
2363- $this->getLayout()->getBlock('resetPassword')
2364- ->setCustomerId($customerId)
2365- ->setResetPasswordLinkToken($resetPasswordLinkToken);
2366 $this->renderLayout();
2367+
2368 } catch (Exception $exception) {
2369- $this->_getSession()->addError( $this->_getHelper('customer')->__('Your password reset link has expired.'));
2370+ $this->_getSession()->addError($this->_getHelper('customer')->__('Your password reset link has expired.'));
2371+ $this->_redirect('*/*/forgotpassword');
2372+ }
2373+ }
2374+
2375+ /**
2376+ * Checks reset forgotten password token
2377+ *
2378+ * User is redirected on this action when he clicks on the corresponding link in password reset confirmation email.
2379+ *
2380+ */
2381+ public function resetPasswordAction()
2382+ {
2383+ try {
2384+ $customerId = (int)$this->getRequest()->getQuery("id");
2385+ $resetPasswordLinkToken = (string)$this->getRequest()->getQuery('token');
2386+
2387+ $this->_validateResetPasswordLinkToken($customerId, $resetPasswordLinkToken);
2388+ $this->_saveRestorePasswordParameters($customerId, $resetPasswordLinkToken)
2389+ ->_redirect('*/*/changeforgotten');
2390+
2391+ } catch (Exception $exception) {
2392+ $this->_getSession()->addError($this->_getHelper('customer')->__('Your password reset link has expired.'));
2393 $this->_redirect('*/*/forgotpassword');
2394 }
2395 }
2396@@ -762,15 +798,14 @@ class Mage_Customer_AccountController extends Mage_Core_Controller_Front_Action
2397 */
2398 public function resetPasswordPostAction()
2399 {
2400- $resetPasswordLinkToken = (string) $this->getRequest()->getQuery('token');
2401- $customerId = (int) $this->getRequest()->getQuery('id');
2402- $password = (string) $this->getRequest()->getPost('password');
2403- $passwordConfirmation = (string) $this->getRequest()->getPost('confirmation');
2404+ list($customerId, $resetPasswordLinkToken) = $this->_getRestorePasswordParameters($this->_getSession());
2405+ $password = (string)$this->getRequest()->getPost('password');
2406+ $passwordConfirmation = (string)$this->getRequest()->getPost('confirmation');
2407
2408 try {
2409 $this->_validateResetPasswordLinkToken($customerId, $resetPasswordLinkToken);
2410 } catch (Exception $exception) {
2411- $this->_getSession()->addError( $this->_getHelper('customer')->__('Your password reset link has expired.'));
2412+ $this->_getSession()->addError($this->_getHelper('customer')->__('Your password reset link has expired.'));
2413 $this->_redirect('*/*/');
2414 return;
2415 }
2416@@ -794,10 +829,7 @@ class Mage_Customer_AccountController extends Mage_Core_Controller_Front_Action
2417 foreach ($errorMessages as $errorMessage) {
2418 $this->_getSession()->addError($errorMessage);
2419 }
2420- $this->_redirect('*/*/resetpassword', array(
2421- 'id' => $customerId,
2422- 'token' => $resetPasswordLinkToken
2423- ));
2424+ $this->_redirect('*/*/changeforgotten');
2425 return;
2426 }
2427
2428@@ -807,14 +839,15 @@ class Mage_Customer_AccountController extends Mage_Core_Controller_Front_Action
2429 $customer->setRpTokenCreatedAt(null);
2430 $customer->setConfirmation(null);
2431 $customer->save();
2432- $this->_getSession()->addSuccess( $this->_getHelper('customer')->__('Your password has been updated.'));
2433+
2434+ $this->_getSession()->unsetData(self::TOKEN_SESSION_NAME);
2435+ $this->_getSession()->unsetData(self::CUSTOMER_ID_SESSION_NAME);
2436+
2437+ $this->_getSession()->addSuccess($this->_getHelper('customer')->__('Your password has been updated.'));
2438 $this->_redirect('*/*/login');
2439 } catch (Exception $exception) {
2440 $this->_getSession()->addException($exception, $this->__('Cannot save a new password.'));
2441- $this->_redirect('*/*/resetpassword', array(
2442- 'id' => $customerId,
2443- 'token' => $resetPasswordLinkToken
2444- ));
2445+ $this->_redirect('*/*/changeforgotten');
2446 return;
2447 }
2448 }
2449@@ -991,4 +1024,34 @@ class Mage_Customer_AccountController extends Mage_Core_Controller_Front_Action
2450 {
2451 return $this->_getHelper('customer/address')->isVatValidationEnabled($store);
2452 }
2453+
2454+ /**
2455+ * Get restore password params.
2456+ *
2457+ * @param Mage_Customer_Model_Session $session
2458+ * @return array array ($customerId, $resetPasswordToken)
2459+ */
2460+ protected function _getRestorePasswordParameters(Mage_Customer_Model_Session $session)
2461+ {
2462+ return array(
2463+ (int) $session->getData(self::CUSTOMER_ID_SESSION_NAME),
2464+ (string) $session->getData(self::TOKEN_SESSION_NAME)
2465+ );
2466+ }
2467+
2468+ /**
2469+ * Save restore password params to session.
2470+ *
2471+ * @param int $customerId
2472+ * @param string $resetPasswordLinkToken
2473+ * @return $this
2474+ */
2475+ protected function _saveRestorePasswordParameters($customerId, $resetPasswordLinkToken)
2476+ {
2477+ $this->_getSession()
2478+ ->setData(self::CUSTOMER_ID_SESSION_NAME, $customerId)
2479+ ->setData(self::TOKEN_SESSION_NAME, $resetPasswordLinkToken);
2480+
2481+ return $this;
2482+ }
2483 }
2484diff --git app/code/core/Mage/Downloadable/Model/Product/Type.php app/code/core/Mage/Downloadable/Model/Product/Type.php
2485index 9628884..9c8cc71 100644
2486--- app/code/core/Mage/Downloadable/Model/Product/Type.php
2487+++ app/code/core/Mage/Downloadable/Model/Product/Type.php
2488@@ -178,6 +178,10 @@ class Mage_Downloadable_Model_Product_Type extends Mage_Catalog_Model_Product_Ty
2489 unset($sampleItem['file']);
2490 }
2491
2492+ if (isset($sampleItem['sample_url'])) {
2493+ $sampleItem['sample_url'] = Mage::helper('core')->escapeUrl($sampleItem['sample_url']);
2494+ }
2495+
2496 $sampleModel->setData($sampleItem)
2497 ->setSampleType($sampleItem['type'])
2498 ->setProductId($product->getId())
2499@@ -220,6 +224,9 @@ class Mage_Downloadable_Model_Product_Type extends Mage_Catalog_Model_Product_Ty
2500 $sample = $linkItem['sample'];
2501 unset($linkItem['sample']);
2502 }
2503+ if (isset($linkItem['link_url'])) {
2504+ $linkItem['link_url'] = Mage::helper('core')->escapeUrl($linkItem['link_url']);
2505+ }
2506 $linkModel = Mage::getModel('downloadable/link')
2507 ->setData($linkItem)
2508 ->setLinkType($linkItem['type'])
2509@@ -236,7 +243,7 @@ class Mage_Downloadable_Model_Product_Type extends Mage_Catalog_Model_Product_Ty
2510 $sampleFile = array();
2511 if ($sample && isset($sample['type'])) {
2512 if ($sample['type'] == 'url' && $sample['url'] != '') {
2513- $linkModel->setSampleUrl($sample['url']);
2514+ $linkModel->setSampleUrl(Mage::helper('core')->escapeUrl($sample['url']));
2515 }
2516 $linkModel->setSampleType($sample['type']);
2517 $sampleFile = Mage::helper('core')->jsonDecode($sample['file']);
2518diff --git app/code/core/Mage/Eav/Model/Resource/Attribute/Collection.php app/code/core/Mage/Eav/Model/Resource/Attribute/Collection.php
2519index bdb5335..d32aba8 100755
2520--- app/code/core/Mage/Eav/Model/Resource/Attribute/Collection.php
2521+++ app/code/core/Mage/Eav/Model/Resource/Attribute/Collection.php
2522@@ -216,7 +216,9 @@ abstract class Mage_Eav_Model_Resource_Attribute_Collection
2523 public function addSystemHiddenFilter()
2524 {
2525 $field = '(CASE WHEN additional_table.is_system = 1 AND additional_table.is_visible = 0 THEN 1 ELSE 0 END)';
2526- return $this->addFieldToFilter($field, 0);
2527+ $resultCondition = $this->_getConditionSql($field, 0);
2528+ $this->_select->where($resultCondition);
2529+ return $this;
2530 }
2531
2532 /**
2533@@ -228,7 +230,8 @@ abstract class Mage_Eav_Model_Resource_Attribute_Collection
2534 {
2535 $field = '(CASE WHEN additional_table.is_system = 1 AND additional_table.is_visible = 0
2536 AND main_table.attribute_code != "' . self::EAV_CODE_PASSWORD_HASH . '" THEN 1 ELSE 0 END)';
2537- $this->addFieldToFilter($field, 0);
2538+ $resultCondition = $this->_getConditionSql($field, 0);
2539+ $this->_select->where($resultCondition);
2540 return $this;
2541 }
2542
2543diff --git app/code/core/Mage/Sales/Model/Resource/Order/Item/Collection.php app/code/core/Mage/Sales/Model/Resource/Order/Item/Collection.php
2544index 8408ac6..8d9df1e 100755
2545--- app/code/core/Mage/Sales/Model/Resource/Order/Item/Collection.php
2546+++ app/code/core/Mage/Sales/Model/Resource/Order/Item/Collection.php
2547@@ -139,4 +139,17 @@ class Mage_Sales_Model_Resource_Order_Item_Collection extends Mage_Sales_Model_R
2548 }
2549 return $this;
2550 }
2551+
2552+ /**
2553+ * Filter only available items.
2554+ *
2555+ * @return Mage_Sales_Model_Resource_Order_Item_Collection
2556+ */
2557+ public function addAvailableFilter()
2558+ {
2559+ $fieldExpression = '(qty_shipped - qty_returned)';
2560+ $resultCondition = $this->_getConditionSql($fieldExpression, array("gt" => 0));
2561+ $this->getSelect()->where($resultCondition);
2562+ return $this;
2563+ }
2564 }
2565diff --git app/code/core/Mage/Sales/controllers/DownloadController.php app/code/core/Mage/Sales/controllers/DownloadController.php
2566index 22d61c3..bb5d2da 100644
2567--- app/code/core/Mage/Sales/controllers/DownloadController.php
2568+++ app/code/core/Mage/Sales/controllers/DownloadController.php
2569@@ -48,6 +48,8 @@ class Mage_Sales_DownloadController extends Mage_Core_Controller_Front_Action
2570 throw new Exception();
2571 }
2572
2573+ $this->_validateFilePath($info);
2574+
2575 $filePath = Mage::getBaseDir() . $info['order_path'];
2576 if ((!is_file($filePath) || !is_readable($filePath)) && !$this->_processDatabaseFile($filePath)) {
2577 //try get file from quote
2578@@ -66,6 +68,19 @@ class Mage_Sales_DownloadController extends Mage_Core_Controller_Front_Action
2579 }
2580
2581 /**
2582+ * @param array $info
2583+ * @throws Exception
2584+ */
2585+ protected function _validateFilePath($info)
2586+ {
2587+ $optionFile = Mage::getModel('catalog/product_option_type_file');
2588+ $optionStoragePath = $optionFile->getOrderTargetDir(true);
2589+ if (strpos($info['order_path'], $optionStoragePath) !== 0) {
2590+ throw new Exception('Unexpected file path');
2591+ }
2592+ }
2593+
2594+ /**
2595 * Check file in database storage if needed and place it on file system
2596 *
2597 * @param string $filePath
2598@@ -176,7 +191,7 @@ class Mage_Sales_DownloadController extends Mage_Core_Controller_Front_Action
2599 }
2600
2601 try {
2602- $info = unserialize($option->getValue());
2603+ $info = Mage::helper('core/unserializeArray')->unserialize($option->getValue());
2604 $this->_downloadFileAction($info);
2605 } catch (Exception $e) {
2606 $this->_forward('noRoute');
2607diff --git app/code/core/Mage/SalesRule/Model/Resource/Coupon/Collection.php app/code/core/Mage/SalesRule/Model/Resource/Coupon/Collection.php
2608index c00a6c7..f71c896 100755
2609--- app/code/core/Mage/SalesRule/Model/Resource/Coupon/Collection.php
2610+++ app/code/core/Mage/SalesRule/Model/Resource/Coupon/Collection.php
2611@@ -97,9 +97,9 @@ class Mage_SalesRule_Model_Resource_Coupon_Collection extends Mage_Core_Model_Re
2612 public function addIsUsedFilterCallback($collection, $column)
2613 {
2614 $filterValue = $column->getFilter()->getCondition();
2615- $collection->addFieldToFilter(
2616- $this->getConnection()->getCheckSql('main_table.times_used > 0', 1, 0),
2617- array('eq' => $filterValue)
2618- );
2619+
2620+ $fieldExpression = $this->getConnection()->getCheckSql('main_table.times_used > 0', 1, 0);
2621+ $resultCondition = $this->_getConditionSql($fieldExpression, array('eq' => $filterValue));
2622+ $collection->getSelect()->where($resultCondition);
2623 }
2624 }
2625diff --git app/code/core/Zend/Soap/Server.php app/code/core/Zend/Soap/Server.php
2626new file mode 100644
2627index 0000000..19259c5
2628--- /dev/null
2629+++ app/code/core/Zend/Soap/Server.php
2630@@ -0,0 +1,1022 @@
2631+<?php
2632+/**
2633+ * Zend Framework
2634+ *
2635+ * LICENSE
2636+ *
2637+ * This source file is subject to the new BSD license that is bundled
2638+ * with this package in the file LICENSE.txt.
2639+ * It is also available through the world-wide-web at this URL:
2640+ * http://framework.zend.com/license/new-bsd
2641+ * If you did not receive a copy of the license and are unable to
2642+ * obtain it through the world-wide-web, please send an email
2643+ * to license@zend.com so we can send you a copy immediately.
2644+ *
2645+ * @category Zend
2646+ * @package Zend_Soap
2647+ * @subpackage Server
2648+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
2649+ * @license http://framework.zend.com/license/new-bsd New BSD License
2650+ */
2651+
2652+/**
2653+ * @see Zend_Server_Interface
2654+ */
2655+#require_once 'Zend/Server/Interface.php';
2656+
2657+/** @see Zend_Xml_Security */
2658+#require_once 'Zend/Xml/Security.php';
2659+
2660+/** @see Zend_Xml_Exception */
2661+#require_once 'Zend/Xml/Exception.php';
2662+
2663+/**
2664+ * Zend_Soap_Server
2665+ *
2666+ * @category Zend
2667+ * @package Zend_Soap
2668+ * @subpackage Server
2669+ * @uses Zend_Server_Interface
2670+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
2671+ * @license http://framework.zend.com/license/new-bsd New BSD License
2672+ * @version $Id$
2673+ */
2674+class Zend_Soap_Server implements Zend_Server_Interface
2675+{
2676+ /**
2677+ * Actor URI
2678+ * @var string URI
2679+ */
2680+ protected $_actor;
2681+
2682+ /**
2683+ * Class registered with this server
2684+ * @var string
2685+ */
2686+ protected $_class;
2687+
2688+ /**
2689+ * Arguments to pass to {@link $_class} constructor
2690+ * @var array
2691+ */
2692+ protected $_classArgs = array();
2693+
2694+ /**
2695+ * Object registered with this server
2696+ */
2697+ protected $_object;
2698+
2699+ /**
2700+ * Array of SOAP type => PHP class pairings for handling return/incoming values
2701+ * @var array
2702+ */
2703+ protected $_classmap;
2704+
2705+ /**
2706+ * Encoding
2707+ * @var string
2708+ */
2709+ protected $_encoding;
2710+
2711+ /**
2712+ * SOAP Server Features
2713+ *
2714+ * @var int
2715+ */
2716+ protected $_features;
2717+
2718+ /**
2719+ * WSDL Caching Options of SOAP Server
2720+ *
2721+ * @var mixed
2722+ */
2723+ protected $_wsdlCache;
2724+
2725+ /**
2726+ * WS-I compliant
2727+ *
2728+ * @var boolean
2729+ */
2730+ protected $_wsiCompliant;
2731+
2732+ /**
2733+ * Registered fault exceptions
2734+ * @var array
2735+ */
2736+ protected $_faultExceptions = array();
2737+
2738+ /**
2739+ * Functions registered with this server; may be either an array or the SOAP_FUNCTIONS_ALL
2740+ * constant
2741+ * @var array|int
2742+ */
2743+ protected $_functions = array();
2744+
2745+ /**
2746+ * Persistence mode; should be one of the SOAP persistence constants
2747+ * @var int
2748+ */
2749+ protected $_persistence;
2750+
2751+ /**
2752+ * Request XML
2753+ * @var string
2754+ */
2755+ protected $_request;
2756+
2757+ /**
2758+ * Response XML
2759+ * @var string
2760+ */
2761+ protected $_response;
2762+
2763+ /**
2764+ * Flag: whether or not {@link handle()} should return a response instead
2765+ * of automatically emitting it.
2766+ * @var boolean
2767+ */
2768+ protected $_returnResponse = false;
2769+
2770+ /**
2771+ * SOAP version to use; SOAP_1_2 by default, to allow processing of headers
2772+ * @var int
2773+ */
2774+ protected $_soapVersion = SOAP_1_2;
2775+
2776+ /**
2777+ * URI or path to WSDL
2778+ * @var string
2779+ */
2780+ protected $_wsdl;
2781+
2782+ /**
2783+ * URI namespace for SOAP server
2784+ * @var string URI
2785+ */
2786+ protected $_uri;
2787+
2788+ /**
2789+ * Constructor
2790+ *
2791+ * Sets display_errors INI setting to off (prevent client errors due to bad
2792+ * XML in response). Registers {@link handlePhpErrors()} as error handler
2793+ * for E_USER_ERROR.
2794+ *
2795+ * If $wsdl is provided, it is passed on to {@link setWsdl()}; if any
2796+ * options are specified, they are passed on to {@link setOptions()}.
2797+ *
2798+ * @param string $wsdl
2799+ * @param array $options
2800+ * @return void
2801+ */
2802+ public function __construct($wsdl = null, array $options = null)
2803+ {
2804+ if (!extension_loaded('soap')) {
2805+ #require_once 'Zend/Soap/Server/Exception.php';
2806+ throw new Zend_Soap_Server_Exception('SOAP extension is not loaded.');
2807+ }
2808+
2809+ if (null !== $wsdl) {
2810+ $this->setWsdl($wsdl);
2811+ }
2812+
2813+ if (null !== $options) {
2814+ $this->setOptions($options);
2815+ }
2816+ }
2817+
2818+ /**
2819+ * Set Options
2820+ *
2821+ * Allows setting options as an associative array of option => value pairs.
2822+ *
2823+ * @param array|Zend_Config $options
2824+ * @return Zend_Soap_Server
2825+ */
2826+ public function setOptions($options)
2827+ {
2828+ if($options instanceof Zend_Config) {
2829+ $options = $options->toArray();
2830+ }
2831+
2832+ foreach ($options as $key => $value) {
2833+ switch ($key) {
2834+ case 'actor':
2835+ $this->setActor($value);
2836+ break;
2837+ case 'classmap':
2838+ case 'classMap':
2839+ $this->setClassmap($value);
2840+ break;
2841+ case 'encoding':
2842+ $this->setEncoding($value);
2843+ break;
2844+ case 'soapVersion':
2845+ case 'soap_version':
2846+ $this->setSoapVersion($value);
2847+ break;
2848+ case 'uri':
2849+ $this->setUri($value);
2850+ break;
2851+ case 'wsdl':
2852+ $this->setWsdl($value);
2853+ break;
2854+ case 'featues':
2855+ trigger_error(__METHOD__ . ': the option "featues" is deprecated as of 1.10.x and will be removed with 2.0.0; use "features" instead', E_USER_NOTICE);
2856+ case 'features':
2857+ $this->setSoapFeatures($value);
2858+ break;
2859+ case 'cache_wsdl':
2860+ $this->setWsdlCache($value);
2861+ break;
2862+ case 'wsi_compliant':
2863+ $this->setWsiCompliant($value);
2864+ break;
2865+ default:
2866+ break;
2867+ }
2868+ }
2869+
2870+ return $this;
2871+ }
2872+
2873+ /**
2874+ * Return array of options suitable for using with SoapServer constructor
2875+ *
2876+ * @return array
2877+ */
2878+ public function getOptions()
2879+ {
2880+ $options = array();
2881+ if (null !== $this->_actor) {
2882+ $options['actor'] = $this->_actor;
2883+ }
2884+
2885+ if (null !== $this->_classmap) {
2886+ $options['classmap'] = $this->_classmap;
2887+ }
2888+
2889+ if (null !== $this->_encoding) {
2890+ $options['encoding'] = $this->_encoding;
2891+ }
2892+
2893+ if (null !== $this->_soapVersion) {
2894+ $options['soap_version'] = $this->_soapVersion;
2895+ }
2896+
2897+ if (null !== $this->_uri) {
2898+ $options['uri'] = $this->_uri;
2899+ }
2900+
2901+ if (null !== $this->_features) {
2902+ $options['features'] = $this->_features;
2903+ }
2904+
2905+ if (null !== $this->_wsdlCache) {
2906+ $options['cache_wsdl'] = $this->_wsdlCache;
2907+ }
2908+
2909+ if (null !== $this->_wsiCompliant) {
2910+ $options['wsi_compliant'] = $this->_wsiCompliant;
2911+ }
2912+
2913+ return $options;
2914+ }
2915+ /**
2916+ * Set WS-I compliant
2917+ *
2918+ * @param boolean $value
2919+ * @return Zend_Soap_Server
2920+ */
2921+ public function setWsiCompliant($value)
2922+ {
2923+ if (is_bool($value)) {
2924+ $this->_wsiCompliant = $value;
2925+ }
2926+ return $this;
2927+ }
2928+ /**
2929+ * Gt WS-I compliant
2930+ *
2931+ * @return boolean
2932+ */
2933+ public function getWsiCompliant()
2934+ {
2935+ return $this->_wsiCompliant;
2936+ }
2937+ /**
2938+ * Set encoding
2939+ *
2940+ * @param string $encoding
2941+ * @return Zend_Soap_Server
2942+ * @throws Zend_Soap_Server_Exception with invalid encoding argument
2943+ */
2944+ public function setEncoding($encoding)
2945+ {
2946+ if (!is_string($encoding)) {
2947+ #require_once 'Zend/Soap/Server/Exception.php';
2948+ throw new Zend_Soap_Server_Exception('Invalid encoding specified');
2949+ }
2950+
2951+ $this->_encoding = $encoding;
2952+ return $this;
2953+ }
2954+
2955+ /**
2956+ * Get encoding
2957+ *
2958+ * @return string
2959+ */
2960+ public function getEncoding()
2961+ {
2962+ return $this->_encoding;
2963+ }
2964+
2965+ /**
2966+ * Set SOAP version
2967+ *
2968+ * @param int $version One of the SOAP_1_1 or SOAP_1_2 constants
2969+ * @return Zend_Soap_Server
2970+ * @throws Zend_Soap_Server_Exception with invalid soap version argument
2971+ */
2972+ public function setSoapVersion($version)
2973+ {
2974+ if (!in_array($version, array(SOAP_1_1, SOAP_1_2))) {
2975+ #require_once 'Zend/Soap/Server/Exception.php';
2976+ throw new Zend_Soap_Server_Exception('Invalid soap version specified');
2977+ }
2978+
2979+ $this->_soapVersion = $version;
2980+ return $this;
2981+ }
2982+
2983+ /**
2984+ * Get SOAP version
2985+ *
2986+ * @return int
2987+ */
2988+ public function getSoapVersion()
2989+ {
2990+ return $this->_soapVersion;
2991+ }
2992+
2993+ /**
2994+ * Check for valid URN
2995+ *
2996+ * @param string $urn
2997+ * @return true
2998+ * @throws Zend_Soap_Server_Exception on invalid URN
2999+ */
3000+ public function validateUrn($urn)
3001+ {
3002+ $scheme = parse_url($urn, PHP_URL_SCHEME);
3003+ if ($scheme === false || $scheme === null) {
3004+ #require_once 'Zend/Soap/Server/Exception.php';
3005+ throw new Zend_Soap_Server_Exception('Invalid URN');
3006+ }
3007+
3008+ return true;
3009+ }
3010+
3011+ /**
3012+ * Set actor
3013+ *
3014+ * Actor is the actor URI for the server.
3015+ *
3016+ * @param string $actor
3017+ * @return Zend_Soap_Server
3018+ */
3019+ public function setActor($actor)
3020+ {
3021+ $this->validateUrn($actor);
3022+ $this->_actor = $actor;
3023+ return $this;
3024+ }
3025+
3026+ /**
3027+ * Retrieve actor
3028+ *
3029+ * @return string
3030+ */
3031+ public function getActor()
3032+ {
3033+ return $this->_actor;
3034+ }
3035+
3036+ /**
3037+ * Set URI
3038+ *
3039+ * URI in SoapServer is actually the target namespace, not a URI; $uri must begin with 'urn:'.
3040+ *
3041+ * @param string $uri
3042+ * @return Zend_Soap_Server
3043+ * @throws Zend_Soap_Server_Exception with invalid uri argument
3044+ */
3045+ public function setUri($uri)
3046+ {
3047+ $this->validateUrn($uri);
3048+ $this->_uri = $uri;
3049+ return $this;
3050+ }
3051+
3052+ /**
3053+ * Retrieve URI
3054+ *
3055+ * @return string
3056+ */
3057+ public function getUri()
3058+ {
3059+ return $this->_uri;
3060+ }
3061+
3062+ /**
3063+ * Set classmap
3064+ *
3065+ * @param array $classmap
3066+ * @return Zend_Soap_Server
3067+ * @throws Zend_Soap_Server_Exception for any invalid class in the class map
3068+ */
3069+ public function setClassmap($classmap)
3070+ {
3071+ if (!is_array($classmap)) {
3072+ /**
3073+ * @see Zend_Soap_Server_Exception
3074+ */
3075+ #require_once 'Zend/Soap/Server/Exception.php';
3076+ throw new Zend_Soap_Server_Exception('Classmap must be an array');
3077+ }
3078+ foreach ($classmap as $type => $class) {
3079+ if (!class_exists($class)) {
3080+ /**
3081+ * @see Zend_Soap_Server_Exception
3082+ */
3083+ #require_once 'Zend/Soap/Server/Exception.php';
3084+ throw new Zend_Soap_Server_Exception('Invalid class in class map');
3085+ }
3086+ }
3087+
3088+ $this->_classmap = $classmap;
3089+ return $this;
3090+ }
3091+
3092+ /**
3093+ * Retrieve classmap
3094+ *
3095+ * @return mixed
3096+ */
3097+ public function getClassmap()
3098+ {
3099+ return $this->_classmap;
3100+ }
3101+
3102+ /**
3103+ * Set wsdl
3104+ *
3105+ * @param string $wsdl URI or path to a WSDL
3106+ * @return Zend_Soap_Server
3107+ */
3108+ public function setWsdl($wsdl)
3109+ {
3110+ $this->_wsdl = $wsdl;
3111+ return $this;
3112+ }
3113+
3114+ /**
3115+ * Retrieve wsdl
3116+ *
3117+ * @return string
3118+ */
3119+ public function getWsdl()
3120+ {
3121+ return $this->_wsdl;
3122+ }
3123+
3124+ /**
3125+ * Set the SOAP Feature options.
3126+ *
3127+ * @param string|int $feature
3128+ * @return Zend_Soap_Server
3129+ */
3130+ public function setSoapFeatures($feature)
3131+ {
3132+ $this->_features = $feature;
3133+ return $this;
3134+ }
3135+
3136+ /**
3137+ * Return current SOAP Features options
3138+ *
3139+ * @return int
3140+ */
3141+ public function getSoapFeatures()
3142+ {
3143+ return $this->_features;
3144+ }
3145+
3146+ /**
3147+ * Set the SOAP Wsdl Caching Options
3148+ *
3149+ * @param string|int|boolean $caching
3150+ * @return Zend_Soap_Server
3151+ */
3152+ public function setWsdlCache($options)
3153+ {
3154+ $this->_wsdlCache = $options;
3155+ return $this;
3156+ }
3157+
3158+ /**
3159+ * Get current SOAP Wsdl Caching option
3160+ */
3161+ public function getWsdlCache()
3162+ {
3163+ return $this->_wsdlCache;
3164+ }
3165+
3166+ /**
3167+ * Attach a function as a server method
3168+ *
3169+ * @param array|string $function Function name, array of function names to attach,
3170+ * or SOAP_FUNCTIONS_ALL to attach all functions
3171+ * @param string $namespace Ignored
3172+ * @return Zend_Soap_Server
3173+ * @throws Zend_Soap_Server_Exception on invalid functions
3174+ */
3175+ public function addFunction($function, $namespace = '')
3176+ {
3177+ // Bail early if set to SOAP_FUNCTIONS_ALL
3178+ if ($this->_functions == SOAP_FUNCTIONS_ALL) {
3179+ return $this;
3180+ }
3181+
3182+ if (is_array($function)) {
3183+ foreach ($function as $func) {
3184+ if (is_string($func) && function_exists($func)) {
3185+ $this->_functions[] = $func;
3186+ } else {
3187+ #require_once 'Zend/Soap/Server/Exception.php';
3188+ throw new Zend_Soap_Server_Exception('One or more invalid functions specified in array');
3189+ }
3190+ }
3191+ $this->_functions = array_merge($this->_functions, $function);
3192+ } elseif (is_string($function) && function_exists($function)) {
3193+ $this->_functions[] = $function;
3194+ } elseif ($function == SOAP_FUNCTIONS_ALL) {
3195+ $this->_functions = SOAP_FUNCTIONS_ALL;
3196+ } else {
3197+ #require_once 'Zend/Soap/Server/Exception.php';
3198+ throw new Zend_Soap_Server_Exception('Invalid function specified');
3199+ }
3200+
3201+ if (is_array($this->_functions)) {
3202+ $this->_functions = array_unique($this->_functions);
3203+ }
3204+
3205+ return $this;
3206+ }
3207+
3208+ /**
3209+ * Attach a class to a server
3210+ *
3211+ * Accepts a class name to use when handling requests. Any additional
3212+ * arguments will be passed to that class' constructor when instantiated.
3213+ *
3214+ * See {@link setObject()} to set preconfigured object instances as request handlers.
3215+ *
3216+ * @param string $class Class Name which executes SOAP Requests at endpoint.
3217+ * @return Zend_Soap_Server
3218+ * @throws Zend_Soap_Server_Exception if called more than once, or if class
3219+ * does not exist
3220+ */
3221+ public function setClass($class, $namespace = '', $argv = null)
3222+ {
3223+ if (isset($this->_class)) {
3224+ #require_once 'Zend/Soap/Server/Exception.php';
3225+ throw new Zend_Soap_Server_Exception('A class has already been registered with this soap server instance');
3226+ }
3227+
3228+ if (!is_string($class)) {
3229+ #require_once 'Zend/Soap/Server/Exception.php';
3230+ throw new Zend_Soap_Server_Exception('Invalid class argument (' . gettype($class) . ')');
3231+ }
3232+
3233+ if (!class_exists($class)) {
3234+ #require_once 'Zend/Soap/Server/Exception.php';
3235+ throw new Zend_Soap_Server_Exception('Class "' . $class . '" does not exist');
3236+ }
3237+
3238+ $this->_class = $class;
3239+ if (1 < func_num_args()) {
3240+ $argv = func_get_args();
3241+ array_shift($argv);
3242+ $this->_classArgs = $argv;
3243+ }
3244+
3245+ return $this;
3246+ }
3247+
3248+ /**
3249+ * Attach an object to a server
3250+ *
3251+ * Accepts an instanciated object to use when handling requests.
3252+ *
3253+ * @param object $object
3254+ * @return Zend_Soap_Server
3255+ */
3256+ public function setObject($object)
3257+ {
3258+ if(!is_object($object)) {
3259+ #require_once 'Zend/Soap/Server/Exception.php';
3260+ throw new Zend_Soap_Server_Exception('Invalid object argument ('.gettype($object).')');
3261+ }
3262+
3263+ if(isset($this->_object)) {
3264+ #require_once 'Zend/Soap/Server/Exception.php';
3265+ throw new Zend_Soap_Server_Exception('An object has already been registered with this soap server instance');
3266+ }
3267+
3268+ if ($this->_wsiCompliant) {
3269+ #require_once 'Zend/Soap/Server/Proxy.php';
3270+ $this->_object = new Zend_Soap_Server_Proxy($object);
3271+ } else {
3272+ $this->_object = $object;
3273+ }
3274+
3275+ return $this;
3276+ }
3277+
3278+ /**
3279+ * Return a server definition array
3280+ *
3281+ * Returns a list of all functions registered with {@link addFunction()},
3282+ * merged with all public methods of the class set with {@link setClass()}
3283+ * (if any).
3284+ *
3285+ * @access public
3286+ * @return array
3287+ */
3288+ public function getFunctions()
3289+ {
3290+ $functions = array();
3291+ if (null !== $this->_class) {
3292+ $functions = get_class_methods($this->_class);
3293+ } elseif (null !== $this->_object) {
3294+ $functions = get_class_methods($this->_object);
3295+ }
3296+
3297+ return array_merge((array) $this->_functions, $functions);
3298+ }
3299+
3300+ /**
3301+ * Unimplemented: Load server definition
3302+ *
3303+ * @param array $array
3304+ * @return void
3305+ * @throws Zend_Soap_Server_Exception Unimplemented
3306+ */
3307+ public function loadFunctions($definition)
3308+ {
3309+ #require_once 'Zend/Soap/Server/Exception.php';
3310+ throw new Zend_Soap_Server_Exception('Unimplemented');
3311+ }
3312+
3313+ /**
3314+ * Set server persistence
3315+ *
3316+ * @param int $mode
3317+ * @return Zend_Soap_Server
3318+ */
3319+ public function setPersistence($mode)
3320+ {
3321+ if (!in_array($mode, array(SOAP_PERSISTENCE_SESSION, SOAP_PERSISTENCE_REQUEST))) {
3322+ #require_once 'Zend/Soap/Server/Exception.php';
3323+ throw new Zend_Soap_Server_Exception('Invalid persistence mode specified');
3324+ }
3325+
3326+ $this->_persistence = $mode;
3327+ return $this;
3328+ }
3329+
3330+ /**
3331+ * Get server persistence
3332+ *
3333+ * @return Zend_Soap_Server
3334+ */
3335+ public function getPersistence()
3336+ {
3337+ return $this->_persistence;
3338+ }
3339+
3340+ /**
3341+ * Set request
3342+ *
3343+ * $request may be any of:
3344+ * - DOMDocument; if so, then cast to XML
3345+ * - DOMNode; if so, then grab owner document and cast to XML
3346+ * - SimpleXMLElement; if so, then cast to XML
3347+ * - stdClass; if so, calls __toString() and verifies XML
3348+ * - string; if so, verifies XML
3349+ *
3350+ * @param DOMDocument|DOMNode|SimpleXMLElement|stdClass|string $request
3351+ * @return Zend_Soap_Server
3352+ */
3353+ protected function _setRequest($request)
3354+ {
3355+ if ($request instanceof DOMDocument) {
3356+ $xml = $request->saveXML();
3357+ } elseif ($request instanceof DOMNode) {
3358+ $xml = $request->ownerDocument->saveXML();
3359+ } elseif ($request instanceof SimpleXMLElement) {
3360+ $xml = $request->asXML();
3361+ } elseif (is_object($request) || is_string($request)) {
3362+ if (is_object($request)) {
3363+ $xml = $request->__toString();
3364+ } else {
3365+ $xml = $request;
3366+ }
3367+
3368+ $dom = new DOMDocument();
3369+ try {
3370+ if(strlen($xml) == 0 || (!$dom = Zend_Xml_Security::scan($xml, $dom))) {
3371+ #require_once 'Zend/Soap/Server/Exception.php';
3372+ throw new Zend_Soap_Server_Exception('Invalid XML');
3373+ }
3374+ } catch (Zend_Xml_Exception $e) {
3375+ #require_once 'Zend/Soap/Server/Exception.php';
3376+ throw new Zend_Soap_Server_Exception(
3377+ $e->getMessage()
3378+ );
3379+ }
3380+ }
3381+ $this->_request = $xml;
3382+ return $this;
3383+ }
3384+
3385+ /**
3386+ * Retrieve request XML
3387+ *
3388+ * @return string
3389+ */
3390+ public function getLastRequest()
3391+ {
3392+ return $this->_request;
3393+ }
3394+
3395+ /**
3396+ * Set return response flag
3397+ *
3398+ * If true, {@link handle()} will return the response instead of
3399+ * automatically sending it back to the requesting client.
3400+ *
3401+ * The response is always available via {@link getResponse()}.
3402+ *
3403+ * @param boolean $flag
3404+ * @return Zend_Soap_Server
3405+ */
3406+ public function setReturnResponse($flag)
3407+ {
3408+ $this->_returnResponse = ($flag) ? true : false;
3409+ return $this;
3410+ }
3411+
3412+ /**
3413+ * Retrieve return response flag
3414+ *
3415+ * @return boolean
3416+ */
3417+ public function getReturnResponse()
3418+ {
3419+ return $this->_returnResponse;
3420+ }
3421+
3422+ /**
3423+ * Get response XML
3424+ *
3425+ * @return string
3426+ */
3427+ public function getLastResponse()
3428+ {
3429+ return $this->_response;
3430+ }
3431+
3432+ /**
3433+ * Get SoapServer object
3434+ *
3435+ * Uses {@link $_wsdl} and return value of {@link getOptions()} to instantiate
3436+ * SoapServer object, and then registers any functions or class with it, as
3437+ * well as peristence.
3438+ *
3439+ * @return SoapServer
3440+ */
3441+ protected function _getSoap()
3442+ {
3443+ $options = $this->getOptions();
3444+ $server = new SoapServer($this->_wsdl, $options);
3445+
3446+ if (!empty($this->_functions)) {
3447+ $server->addFunction($this->_functions);
3448+ }
3449+
3450+ if (!empty($this->_class)) {
3451+ $args = $this->_classArgs;
3452+ array_unshift($args, $this->_class);
3453+ if ($this->_wsiCompliant) {
3454+ #require_once 'Zend/Soap/Server/Proxy.php';
3455+ array_unshift($args, 'Zend_Soap_Server_Proxy');
3456+ }
3457+ call_user_func_array(array($server, 'setClass'), $args);
3458+ }
3459+
3460+ if (!empty($this->_object)) {
3461+ $server->setObject($this->_object);
3462+ }
3463+
3464+ if (null !== $this->_persistence) {
3465+ $server->setPersistence($this->_persistence);
3466+ }
3467+
3468+ return $server;
3469+ }
3470+
3471+ /**
3472+ * Handle a request
3473+ *
3474+ * Instantiates SoapServer object with options set in object, and
3475+ * dispatches its handle() method.
3476+ *
3477+ * $request may be any of:
3478+ * - DOMDocument; if so, then cast to XML
3479+ * - DOMNode; if so, then grab owner document and cast to XML
3480+ * - SimpleXMLElement; if so, then cast to XML
3481+ * - stdClass; if so, calls __toString() and verifies XML
3482+ * - string; if so, verifies XML
3483+ *
3484+ * If no request is passed, pulls request using php:://input (for
3485+ * cross-platform compatability purposes).
3486+ *
3487+ * @param DOMDocument|DOMNode|SimpleXMLElement|stdClass|string $request Optional request
3488+ * @return void|string
3489+ */
3490+ public function handle($request = null)
3491+ {
3492+ if (null === $request) {
3493+ $request = file_get_contents('php://input');
3494+ }
3495+
3496+ // Set Zend_Soap_Server error handler
3497+ $displayErrorsOriginalState = $this->_initializeSoapErrorContext();
3498+
3499+ $setRequestException = null;
3500+ /**
3501+ * @see Zend_Soap_Server_Exception
3502+ */
3503+ #require_once 'Zend/Soap/Server/Exception.php';
3504+ try {
3505+ $this->_setRequest($request);
3506+ } catch (Zend_Soap_Server_Exception $e) {
3507+ $setRequestException = $e;
3508+ }
3509+
3510+ $soap = $this->_getSoap();
3511+
3512+ $fault = false;
3513+ ob_start();
3514+ if ($setRequestException instanceof Exception) {
3515+ // Create SOAP fault message if we've caught a request exception
3516+ $fault = $this->fault($setRequestException->getMessage(), 'Sender');
3517+ } else {
3518+ try {
3519+ $soap->handle($this->_request);
3520+ } catch (Exception $e) {
3521+ $fault = $this->fault($e);
3522+ }
3523+ }
3524+ $this->_response = ob_get_clean();
3525+
3526+ // Restore original error handler
3527+ restore_error_handler();
3528+ ini_set('display_errors', $displayErrorsOriginalState);
3529+
3530+ // Send a fault, if we have one
3531+ if ($fault) {
3532+ $soap->fault($fault->faultcode, $fault->faultstring);
3533+ }
3534+
3535+ if (!$this->_returnResponse) {
3536+ echo $this->_response;
3537+ return;
3538+ }
3539+
3540+ return $this->_response;
3541+ }
3542+
3543+ /**
3544+ * Method initalizes the error context that the SOAPServer enviroment will run in.
3545+ *
3546+ * @return boolean display_errors original value
3547+ */
3548+ protected function _initializeSoapErrorContext()
3549+ {
3550+ $displayErrorsOriginalState = ini_get('display_errors');
3551+ ini_set('display_errors', false);
3552+ set_error_handler(array($this, 'handlePhpErrors'), E_USER_ERROR);
3553+ return $displayErrorsOriginalState;
3554+ }
3555+
3556+ /**
3557+ * Register a valid fault exception
3558+ *
3559+ * @param string|array $class Exception class or array of exception classes
3560+ * @return Zend_Soap_Server
3561+ */
3562+ public function registerFaultException($class)
3563+ {
3564+ $this->_faultExceptions = array_merge($this->_faultExceptions, (array) $class);
3565+ return $this;
3566+ }
3567+
3568+ /**
3569+ * Deregister a fault exception from the fault exception stack
3570+ *
3571+ * @param string $class
3572+ * @return boolean
3573+ */
3574+ public function deregisterFaultException($class)
3575+ {
3576+ if (in_array($class, $this->_faultExceptions, true)) {
3577+ $index = array_search($class, $this->_faultExceptions);
3578+ unset($this->_faultExceptions[$index]);
3579+ return true;
3580+ }
3581+
3582+ return false;
3583+ }
3584+
3585+ /**
3586+ * Return fault exceptions list
3587+ *
3588+ * @return array
3589+ */
3590+ public function getFaultExceptions()
3591+ {
3592+ return $this->_faultExceptions;
3593+ }
3594+
3595+ /**
3596+ * Generate a server fault
3597+ *
3598+ * Note that the arguments are reverse to those of SoapFault.
3599+ *
3600+ * If an exception is passed as the first argument, its message and code
3601+ * will be used to create the fault object if it has been registered via
3602+ * {@Link registerFaultException()}.
3603+ *
3604+ * @link http://www.w3.org/TR/soap12-part1/#faultcodes
3605+ * @param string|Exception $fault
3606+ * @param string $code SOAP Fault Codes
3607+ * @return SoapFault
3608+ */
3609+ public function fault($fault = null, $code = "Receiver")
3610+ {
3611+ if ($fault instanceof Exception) {
3612+ $class = get_class($fault);
3613+ if (in_array($class, $this->_faultExceptions)) {
3614+ $message = $fault->getMessage();
3615+ $eCode = $fault->getCode();
3616+ $code = empty($eCode) ? $code : $eCode;
3617+ } else {
3618+ $message = 'Unknown error';
3619+ }
3620+ } elseif(is_string($fault)) {
3621+ $message = $fault;
3622+ } else {
3623+ $message = 'Unknown error';
3624+ }
3625+
3626+ $allowedFaultModes = array(
3627+ 'VersionMismatch', 'MustUnderstand', 'DataEncodingUnknown',
3628+ 'Sender', 'Receiver', 'Server'
3629+ );
3630+ if(!in_array($code, $allowedFaultModes)) {
3631+ $code = "Receiver";
3632+ }
3633+
3634+ return new SoapFault($code, $message);
3635+ }
3636+
3637+ /**
3638+ * Throw PHP errors as SoapFaults
3639+ *
3640+ * @param int $errno
3641+ * @param string $errstr
3642+ * @param string $errfile
3643+ * @param int $errline
3644+ * @param array $errcontext
3645+ * @return void
3646+ * @throws SoapFault
3647+ */
3648+ public function handlePhpErrors($errno, $errstr, $errfile = null, $errline = null, array $errcontext = null)
3649+ {
3650+ throw $this->fault($errstr, "Receiver");
3651+ }
3652+}
3653diff --git app/code/core/Zend/Xml/Exception.php app/code/core/Zend/Xml/Exception.php
3654new file mode 100644
3655index 0000000..3418f35
3656--- /dev/null
3657+++ app/code/core/Zend/Xml/Exception.php
3658@@ -0,0 +1,36 @@
3659+<?php
3660+/**
3661+ * Zend Framework
3662+ *
3663+ * LICENSE
3664+ *
3665+ * This source file is subject to the new BSD license that is bundled
3666+ * with this package in the file LICENSE.txt.
3667+ * It is also available through the world-wide-web at this URL:
3668+ * http://framework.zend.com/license/new-bsd
3669+ * If you did not receive a copy of the license and are unable to
3670+ * obtain it through the world-wide-web, please send an email
3671+ * to license@zend.com so we can send you a copy immediately.
3672+ *
3673+ * @category Zend
3674+ * @package Zend_Xml
3675+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
3676+ * @license http://framework.zend.com/license/new-bsd New BSD License
3677+ * @version $Id$
3678+ */
3679+
3680+
3681+/**
3682+ * @see Zend_Exception
3683+ */
3684+#require_once 'Zend/Exception.php';
3685+
3686+
3687+/**
3688+ * @category Zend
3689+ * @package Zend_Xml
3690+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
3691+ * @license http://framework.zend.com/license/new-bsd New BSD License
3692+ */
3693+class Zend_Xml_Exception extends Zend_Exception
3694+{}
3695diff --git app/code/core/Zend/Xml/Security.php app/code/core/Zend/Xml/Security.php
3696new file mode 100644
3697index 0000000..a3cdbc8
3698--- /dev/null
3699+++ app/code/core/Zend/Xml/Security.php
3700@@ -0,0 +1,488 @@
3701+<?php
3702+/**
3703+ * Zend Framework
3704+ *
3705+ * LICENSE
3706+ *
3707+ * This source file is subject to the new BSD license that is bundled
3708+ * with this package in the file LICENSE.txt.
3709+ * It is also available through the world-wide-web at this URL:
3710+ * http://framework.zend.com/license/new-bsd
3711+ * If you did not receive a copy of the license and are unable to
3712+ * obtain it through the world-wide-web, please send an email
3713+ * to license@zend.com so we can send you a copy immediately.
3714+ *
3715+ * @category Zend
3716+ * @package Zend_Xml
3717+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
3718+ * @license http://framework.zend.com/license/new-bsd New BSD License
3719+ * @version $Id$
3720+ */
3721+
3722+
3723+/**
3724+ * @category Zend
3725+ * @package Zend_Xml_SecurityScan
3726+ * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
3727+ * @license http://framework.zend.com/license/new-bsd New BSD License
3728+ */
3729+class Zend_Xml_Security
3730+{
3731+ const ENTITY_DETECT = 'Detected use of ENTITY in XML, disabled to prevent XXE/XEE attacks';
3732+
3733+ /**
3734+ * Heuristic scan to detect entity in XML
3735+ *
3736+ * @param string $xml
3737+ * @throws Zend_Xml_Exception If entity expansion or external entity declaration was discovered.
3738+ */
3739+ protected static function heuristicScan($xml)
3740+ {
3741+ foreach (self::getEntityComparison($xml) as $compare) {
3742+ if (strpos($xml, $compare) !== false) {
3743+ throw new Zend_Xml_Exception(self::ENTITY_DETECT);
3744+ }
3745+ }
3746+ }
3747+
3748+ /**
3749+ * @param integer $errno
3750+ * @param string $errstr
3751+ * @param string $errfile
3752+ * @param integer $errline
3753+ * @return bool
3754+ */
3755+ public static function loadXmlErrorHandler($errno, $errstr, $errfile, $errline)
3756+ {
3757+ if (substr_count($errstr, 'DOMDocument::loadXML()') > 0) {
3758+ return true;
3759+ }
3760+ return false;
3761+ }
3762+
3763+ /**
3764+ * Scan XML string for potential XXE and XEE attacks
3765+ *
3766+ * @param string $xml
3767+ * @param DomDocument $dom
3768+ * @throws Zend_Xml_Exception
3769+ * @return SimpleXMLElement|DomDocument|boolean
3770+ */
3771+ public static function scan($xml, DOMDocument $dom = null)
3772+ {
3773+ // If running with PHP-FPM we perform an heuristic scan
3774+ // We cannot use libxml_disable_entity_loader because of this bug
3775+ // @see https://bugs.php.net/bug.php?id=64938
3776+ if (self::isPhpFpm()) {
3777+ self::heuristicScan($xml);
3778+ }
3779+
3780+ if (null === $dom) {
3781+ $simpleXml = true;
3782+ $dom = new DOMDocument();
3783+ }
3784+
3785+ if (!self::isPhpFpm()) {
3786+ $loadEntities = libxml_disable_entity_loader(true);
3787+ $useInternalXmlErrors = libxml_use_internal_errors(true);
3788+ }
3789+
3790+ // Load XML with network access disabled (LIBXML_NONET)
3791+ // error disabled with @ for PHP-FPM scenario
3792+ set_error_handler(array('Zend_Xml_Security', 'loadXmlErrorHandler'), E_WARNING);
3793+
3794+ $result = $dom->loadXml($xml, LIBXML_NONET);
3795+ restore_error_handler();
3796+
3797+ if (!$result) {
3798+ // Entity load to previous setting
3799+ if (!self::isPhpFpm()) {
3800+ libxml_disable_entity_loader($loadEntities);
3801+ libxml_use_internal_errors($useInternalXmlErrors);
3802+ }
3803+ return false;
3804+ }
3805+
3806+ // Scan for potential XEE attacks using ENTITY, if not PHP-FPM
3807+ if (!self::isPhpFpm()) {
3808+ foreach ($dom->childNodes as $child) {
3809+ if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) {
3810+ if ($child->entities->length > 0) {
3811+ #require_once 'Exception.php';
3812+ throw new Zend_Xml_Exception(self::ENTITY_DETECT);
3813+ }
3814+ }
3815+ }
3816+ }
3817+
3818+ // Entity load to previous setting
3819+ if (!self::isPhpFpm()) {
3820+ libxml_disable_entity_loader($loadEntities);
3821+ libxml_use_internal_errors($useInternalXmlErrors);
3822+ }
3823+
3824+ if (isset($simpleXml)) {
3825+ $result = simplexml_import_dom($dom);
3826+ if (!$result instanceof SimpleXMLElement) {
3827+ return false;
3828+ }
3829+ return $result;
3830+ }
3831+ return $dom;
3832+ }
3833+
3834+ /**
3835+ * Scan XML file for potential XXE/XEE attacks
3836+ *
3837+ * @param string $file
3838+ * @param DOMDocument $dom
3839+ * @throws Zend_Xml_Exception
3840+ * @return SimpleXMLElement|DomDocument
3841+ */
3842+ public static function scanFile($file, DOMDocument $dom = null)
3843+ {
3844+ if (!file_exists($file)) {
3845+ #require_once 'Exception.php';
3846+ throw new Zend_Xml_Exception(
3847+ "The file $file specified doesn't exist"
3848+ );
3849+ }
3850+ return self::scan(file_get_contents($file), $dom);
3851+ }
3852+
3853+ /**
3854+ * Return true if PHP is running with PHP-FPM
3855+ *
3856+ * This method is mainly used to determine whether or not heuristic checks
3857+ * (vs libxml checks) should be made, due to threading issues in libxml;
3858+ * under php-fpm, threading becomes a concern.
3859+ *
3860+ * However, PHP versions 5.5.22+ and 5.6.6+ contain a patch to the
3861+ * libxml support in PHP that makes the libxml checks viable; in such
3862+ * versions, this method will return false to enforce those checks, which
3863+ * are more strict and accurate than the heuristic checks.
3864+ *
3865+ * @return boolean
3866+ */
3867+ public static function isPhpFpm()
3868+ {
3869+ $isVulnerableVersion = (
3870+ version_compare(PHP_VERSION, '5.5.22', 'lt')
3871+ || (
3872+ version_compare(PHP_VERSION, '5.6', 'gte')
3873+ && version_compare(PHP_VERSION, '5.6.6', 'lt')
3874+ )
3875+ );
3876+
3877+ if (substr(php_sapi_name(), 0, 3) === 'fpm' && $isVulnerableVersion) {
3878+ return true;
3879+ }
3880+ return false;
3881+ }
3882+
3883+ /**
3884+ * Determine and return the string(s) to use for the <!ENTITY comparison.
3885+ *
3886+ * @param string $xml
3887+ * @return string[]
3888+ */
3889+ protected static function getEntityComparison($xml)
3890+ {
3891+ $encodingMap = self::getAsciiEncodingMap();
3892+ return array_map(
3893+ array(__CLASS__, 'generateEntityComparison'),
3894+ self::detectXmlEncoding($xml, self::detectStringEncoding($xml))
3895+ );
3896+ }
3897+
3898+ /**
3899+ * Determine the string encoding.
3900+ *
3901+ * Determines string encoding from either a detected BOM or a
3902+ * heuristic.
3903+ *
3904+ * @param string $xml
3905+ * @return string File encoding
3906+ */
3907+ protected static function detectStringEncoding($xml)
3908+ {
3909+ $encoding = self::detectBom($xml);
3910+ return ($encoding) ? $encoding : self::detectXmlStringEncoding($xml);
3911+ }
3912+
3913+ /**
3914+ * Attempt to match a known BOM.
3915+ *
3916+ * Iterates through the return of getBomMap(), comparing the initial bytes
3917+ * of the provided string to the BOM of each; if a match is determined,
3918+ * it returns the encoding.
3919+ *
3920+ * @param string $string
3921+ * @return false|string Returns encoding on success.
3922+ */
3923+ protected static function detectBom($string)
3924+ {
3925+ foreach (self::getBomMap() as $criteria) {
3926+ if (0 === strncmp($string, $criteria['bom'], $criteria['length'])) {
3927+ return $criteria['encoding'];
3928+ }
3929+ }
3930+ return false;
3931+ }
3932+
3933+ /**
3934+ * Attempt to detect the string encoding of an XML string.
3935+ *
3936+ * @param string $xml
3937+ * @return string Encoding
3938+ */
3939+ protected static function detectXmlStringEncoding($xml)
3940+ {
3941+ foreach (self::getAsciiEncodingMap() as $encoding => $generator) {
3942+ $prefix = call_user_func($generator, '<' . '?xml');
3943+ if (0 === strncmp($xml, $prefix, strlen($prefix))) {
3944+ return $encoding;
3945+ }
3946+ }
3947+
3948+ // Fallback
3949+ return 'UTF-8';
3950+ }
3951+
3952+ /**
3953+ * Attempt to detect the specified XML encoding.
3954+ *
3955+ * Using the file's encoding, determines if an "encoding" attribute is
3956+ * present and well-formed in the XML declaration; if so, it returns a
3957+ * list with both the ASCII representation of that declaration and the
3958+ * original file encoding.
3959+ *
3960+ * If not, a list containing only the provided file encoding is returned.
3961+ *
3962+ * @param string $xml
3963+ * @param string $fileEncoding
3964+ * @return string[] Potential XML encodings
3965+ */
3966+ protected static function detectXmlEncoding($xml, $fileEncoding)
3967+ {
3968+ $encodingMap = self::getAsciiEncodingMap();
3969+ $generator = $encodingMap[$fileEncoding];
3970+ $encAttr = call_user_func($generator, 'encoding="');
3971+ $quote = call_user_func($generator, '"');
3972+ $close = call_user_func($generator, '>');
3973+
3974+ $closePos = strpos($xml, $close);
3975+ if (false === $closePos) {
3976+ return array($fileEncoding);
3977+ }
3978+
3979+ $encPos = strpos($xml, $encAttr);
3980+ if (false === $encPos
3981+ || $encPos > $closePos
3982+ ) {
3983+ return array($fileEncoding);
3984+ }
3985+
3986+ $encPos += strlen($encAttr);
3987+ $quotePos = strpos($xml, $quote, $encPos);
3988+ if (false === $quotePos) {
3989+ return array($fileEncoding);
3990+ }
3991+
3992+ $encoding = self::substr($xml, $encPos, $quotePos);
3993+ return array(
3994+ // Following line works because we're only supporting 8-bit safe encodings at this time.
3995+ str_replace('\0', '', $encoding), // detected encoding
3996+ $fileEncoding, // file encoding
3997+ );
3998+ }
3999+
4000+ /**
4001+ * Return a list of BOM maps.
4002+ *
4003+ * Returns a list of common encoding -> BOM maps, along with the character
4004+ * length to compare against.
4005+ *
4006+ * @link https://en.wikipedia.org/wiki/Byte_order_mark
4007+ * @return array
4008+ */
4009+ protected static function getBomMap()
4010+ {
4011+ return array(
4012+ array(
4013+ 'encoding' => 'UTF-32BE',
4014+ 'bom' => pack('CCCC', 0x00, 0x00, 0xfe, 0xff),
4015+ 'length' => 4,
4016+ ),
4017+ array(
4018+ 'encoding' => 'UTF-32LE',
4019+ 'bom' => pack('CCCC', 0xff, 0xfe, 0x00, 0x00),
4020+ 'length' => 4,
4021+ ),
4022+ array(
4023+ 'encoding' => 'GB-18030',
4024+ 'bom' => pack('CCCC', 0x84, 0x31, 0x95, 0x33),
4025+ 'length' => 4,
4026+ ),
4027+ array(
4028+ 'encoding' => 'UTF-16BE',
4029+ 'bom' => pack('CC', 0xfe, 0xff),
4030+ 'length' => 2,
4031+ ),
4032+ array(
4033+ 'encoding' => 'UTF-16LE',
4034+ 'bom' => pack('CC', 0xff, 0xfe),
4035+ 'length' => 2,
4036+ ),
4037+ array(
4038+ 'encoding' => 'UTF-8',
4039+ 'bom' => pack('CCC', 0xef, 0xbb, 0xbf),
4040+ 'length' => 3,
4041+ ),
4042+ );
4043+ }
4044+
4045+ /**
4046+ * Return a map of encoding => generator pairs.
4047+ *
4048+ * Returns a map of encoding => generator pairs, where the generator is a
4049+ * callable that accepts a string and returns the appropriate byte order
4050+ * sequence of that string for the encoding.
4051+ *
4052+ * @return array
4053+ */
4054+ protected static function getAsciiEncodingMap()
4055+ {
4056+ return array(
4057+ 'UTF-32BE' => array(__CLASS__, 'encodeToUTF32BE'),
4058+ 'UTF-32LE' => array(__CLASS__, 'encodeToUTF32LE'),
4059+ 'UTF-32odd1' => array(__CLASS__, 'encodeToUTF32odd1'),
4060+ 'UTF-32odd2' => array(__CLASS__, 'encodeToUTF32odd2'),
4061+ 'UTF-16BE' => array(__CLASS__, 'encodeToUTF16BE'),
4062+ 'UTF-16LE' => array(__CLASS__, 'encodeToUTF16LE'),
4063+ 'UTF-8' => array(__CLASS__, 'encodeToUTF8'),
4064+ 'GB-18030' => array(__CLASS__, 'encodeToUTF8'),
4065+ );
4066+ }
4067+
4068+ /**
4069+ * Binary-safe substr.
4070+ *
4071+ * substr() is not binary-safe; this method loops by character to ensure
4072+ * multi-byte characters are aggregated correctly.
4073+ *
4074+ * @param string $string
4075+ * @param int $start
4076+ * @param int $end
4077+ * @return string
4078+ */
4079+ protected static function substr($string, $start, $end)
4080+ {
4081+ $substr = '';
4082+ for ($i = $start; $i < $end; $i += 1) {
4083+ $substr .= $string[$i];
4084+ }
4085+ return $substr;
4086+ }
4087+
4088+ /**
4089+ * Generate an entity comparison based on the given encoding.
4090+ *
4091+ * This patch is internal only, and public only so it can be used as a
4092+ * callable to pass to array_map.
4093+ *
4094+ * @internal
4095+ * @param string $encoding
4096+ * @return string
4097+ */
4098+ public static function generateEntityComparison($encoding)
4099+ {
4100+ $encodingMap = self::getAsciiEncodingMap();
4101+ $generator = isset($encodingMap[$encoding]) ? $encodingMap[$encoding] : $encodingMap['UTF-8'];
4102+ return call_user_func($generator, '<!ENTITY');
4103+ }
4104+
4105+ /**
4106+ * Encode an ASCII string to UTF-32BE
4107+ *
4108+ * @internal
4109+ * @param string $ascii
4110+ * @return string
4111+ */
4112+ public static function encodeToUTF32BE($ascii)
4113+ {
4114+ return preg_replace('/(.)/', "\0\0\0\\1", $ascii);
4115+ }
4116+
4117+ /**
4118+ * Encode an ASCII string to UTF-32LE
4119+ *
4120+ * @internal
4121+ * @param string $ascii
4122+ * @return string
4123+ */
4124+ public static function encodeToUTF32LE($ascii)
4125+ {
4126+ return preg_replace('/(.)/', "\\1\0\0\0", $ascii);
4127+ }
4128+
4129+ /**
4130+ * Encode an ASCII string to UTF-32odd1
4131+ *
4132+ * @internal
4133+ * @param string $ascii
4134+ * @return string
4135+ */
4136+ public static function encodeToUTF32odd1($ascii)
4137+ {
4138+ return preg_replace('/(.)/', "\0\\1\0\0", $ascii);
4139+ }
4140+
4141+ /**
4142+ * Encode an ASCII string to UTF-32odd2
4143+ *
4144+ * @internal
4145+ * @param string $ascii
4146+ * @return string
4147+ */
4148+ public static function encodeToUTF32odd2($ascii)
4149+ {
4150+ return preg_replace('/(.)/', "\0\0\\1\0", $ascii);
4151+ }
4152+
4153+ /**
4154+ * Encode an ASCII string to UTF-16BE
4155+ *
4156+ * @internal
4157+ * @param string $ascii
4158+ * @return string
4159+ */
4160+ public static function encodeToUTF16BE($ascii)
4161+ {
4162+ return preg_replace('/(.)/', "\0\\1", $ascii);
4163+ }
4164+
4165+ /**
4166+ * Encode an ASCII string to UTF-16LE
4167+ *
4168+ * @internal
4169+ * @param string $ascii
4170+ * @return string
4171+ */
4172+ public static function encodeToUTF16LE($ascii)
4173+ {
4174+ return preg_replace('/(.)/', "\\1\0", $ascii);
4175+ }
4176+
4177+ /**
4178+ * Encode an ASCII string to UTF-8
4179+ *
4180+ * @internal
4181+ * @param string $ascii
4182+ * @return string
4183+ */
4184+ public static function encodeToUTF8($ascii)
4185+ {
4186+ return $ascii;
4187+ }
4188+}
4189diff --git app/code/core/Zend/XmlRpc/Request.php app/code/core/Zend/XmlRpc/Request.php
4190index 402c38a..17a176e 100644
4191--- app/code/core/Zend/XmlRpc/Request.php
4192+++ app/code/core/Zend/XmlRpc/Request.php
4193@@ -28,6 +28,13 @@
4194 */
4195 #require_once 'Zend/XmlRpc/Fault.php';
4196
4197+/** @see Zend_Xml_Security */
4198+#require_once 'Zend/Xml/Security.php';
4199+
4200+/** @see Zend_Xml_Exception */
4201+#require_once 'Zend/Xml/Exception.php';
4202+
4203+
4204 /**
4205 * XmlRpc Request object
4206 *
4207@@ -303,15 +310,12 @@ class Zend_XmlRpc_Request
4208 return false;
4209 }
4210
4211- $loadEntities = libxml_disable_entity_loader(true);
4212 try {
4213- $xml = new SimpleXMLElement($request);
4214- libxml_disable_entity_loader($loadEntities);
4215- } catch (Exception $e) {
4216+ $xml = Zend_Xml_Security::scan($request);
4217+ } catch (Zend_Xml_Exception $e) {
4218 // Not valid XML
4219 $this->_fault = new Zend_XmlRpc_Fault(631);
4220 $this->_fault->setEncoding($this->getEncoding());
4221- libxml_disable_entity_loader($loadEntities);
4222 return false;
4223 }
4224
4225diff --git app/code/core/Zend/XmlRpc/Response.php app/code/core/Zend/XmlRpc/Response.php
4226index f4d46d1..7c1c601 100644
4227--- app/code/core/Zend/XmlRpc/Response.php
4228+++ app/code/core/Zend/XmlRpc/Response.php
4229@@ -28,6 +28,12 @@
4230 */
4231 #require_once 'Zend/XmlRpc/Fault.php';
4232
4233+/** @see Zend_Xml_Security */
4234+#require_once 'Zend/Xml/Security.php';
4235+
4236+/** @see Zend_Xml_Exception */
4237+#require_once 'Zend/Xml/Exception.php';
4238+
4239 /**
4240 * XmlRpc Response
4241 *
4242@@ -176,15 +182,9 @@ class Zend_XmlRpc_Response
4243 return false;
4244 }
4245
4246- $loadEntities = libxml_disable_entity_loader(true);
4247- $useInternalXmlErrors = libxml_use_internal_errors(true);
4248 try {
4249- $xml = new SimpleXMLElement($response);
4250- libxml_disable_entity_loader($loadEntities);
4251- libxml_use_internal_errors($useInternalXmlErrors);
4252- } catch (Exception $e) {
4253- libxml_disable_entity_loader($loadEntities);
4254- libxml_use_internal_errors($useInternalXmlErrors);
4255+ $xml = Zend_Xml_Security::scan($response);
4256+ } catch (Zend_Xml_Exception $e) {
4257 // Not valid XML
4258 $this->_fault = new Zend_XmlRpc_Fault(651);
4259 $this->_fault->setEncoding($this->getEncoding());
4260diff --git app/design/adminhtml/default/default/layout/admin.xml app/design/adminhtml/default/default/layout/admin.xml
4261index a68a596..f883aa8 100644
4262--- app/design/adminhtml/default/default/layout/admin.xml
4263+++ app/design/adminhtml/default/default/layout/admin.xml
4264@@ -39,7 +39,18 @@
4265 <block type="adminhtml/template" name="adminhtml.permissions.user.roles.grid.js" template="permissions/user_roles_grid_js.phtml"/>
4266 </reference>
4267 </adminhtml_permissions_user_edit>
4268-
4269+ <!-- admin permissions block edit page -->
4270+ <adminhtml_permissions_block_edit>
4271+ <reference name="content">
4272+ <block type="adminhtml/permissions_block_edit" name="adminhtml.permissions.block.edit"/>
4273+ </reference>
4274+ </adminhtml_permissions_block_edit>
4275+ <!-- admin permissions variable edit page -->
4276+ <adminhtml_permissions_variable_edit>
4277+ <reference name="content">
4278+ <block type="adminhtml/permissions_variable_edit" name="adminhtml.permissions.variable.edit"/>
4279+ </reference>
4280+ </adminhtml_permissions_variable_edit>
4281 <!-- admin acl roles grid page -->
4282 <adminhtml_permissions_role_index>
4283 <reference name="content">
4284diff --git app/design/frontend/base/default/layout/customer.xml app/design/frontend/base/default/layout/customer.xml
4285index 29f7cb7..a7cfc3a 100644
4286--- app/design/frontend/base/default/layout/customer.xml
4287+++ app/design/frontend/base/default/layout/customer.xml
4288@@ -153,7 +153,7 @@ New customer registration
4289 </reference>
4290 </customer_account_forgotpassword>
4291
4292- <customer_account_resetpassword translate="label">
4293+ <customer_account_changeforgotten translate="label">
4294 <label>Reset a Password</label>
4295 <remove name="right"/>
4296 <remove name="left"/>
4297@@ -172,9 +172,9 @@ New customer registration
4298 </action>
4299 </reference>
4300 <reference name="content">
4301- <block type="customer/account_resetpassword" name="resetPassword" template="customer/form/resetforgottenpassword.phtml"/>
4302+ <block type="customer/account_changeforgotten" name="changeForgottenPassword" template="customer/form/resetforgottenpassword.phtml"/>
4303 </reference>
4304- </customer_account_resetpassword>
4305+ </customer_account_changeforgotten>
4306
4307 <customer_account_confirmation>
4308 <remove name="right"/>
4309diff --git app/design/frontend/base/default/template/customer/form/register.phtml app/design/frontend/base/default/template/customer/form/register.phtml
4310index 65439b7..b26113d 100644
4311--- app/design/frontend/base/default/template/customer/form/register.phtml
4312+++ app/design/frontend/base/default/template/customer/form/register.phtml
4313@@ -43,6 +43,7 @@
4314 <div class="fieldset">
4315 <input type="hidden" name="success_url" value="<?php echo $this->getSuccessUrl() ?>" />
4316 <input type="hidden" name="error_url" value="<?php echo $this->getErrorUrl() ?>" />
4317+ <input type="hidden" name="form_key" value="<?php echo Mage::getSingleton('core/session')->getFormKey() ?>" />
4318 <h2 class="legend"><?php echo $this->__('Personal Information') ?></h2>
4319 <ul class="form-list">
4320 <li class="fields">
4321diff --git app/design/frontend/base/default/template/customer/form/resetforgottenpassword.phtml app/design/frontend/base/default/template/customer/form/resetforgottenpassword.phtml
4322index b892632..e475ccc 100644
4323--- app/design/frontend/base/default/template/customer/form/resetforgottenpassword.phtml
4324+++ app/design/frontend/base/default/template/customer/form/resetforgottenpassword.phtml
4325@@ -28,7 +28,7 @@
4326 <h1><?php echo $this->__('Reset a Password'); ?></h1>
4327 </div>
4328 <?php echo $this->getMessagesBlock()->getGroupedHtml(); ?>
4329-<form action="<?php echo $this->getUrl('*/*/resetpasswordpost', array('_query' => array('id' => $this->getCustomerId(), 'token' => $this->getResetPasswordLinkToken()))); ?>" method="post" id="form-validate">
4330+<form action="<?php echo $this->getUrl('*/*/resetpasswordpost'); ?>" method="post" id="form-validate">
4331 <div class="fieldset" style="margin-top: 70px;">
4332 <ul class="form-list">
4333 <li class="fields">
4334diff --git app/design/frontend/base/default/template/page/js/cookie.phtml app/design/frontend/base/default/template/page/js/cookie.phtml
4335index 9111c01..f62ce8e 100644
4336--- app/design/frontend/base/default/template/page/js/cookie.phtml
4337+++ app/design/frontend/base/default/template/page/js/cookie.phtml
4338@@ -34,7 +34,7 @@
4339
4340 <script type="text/javascript">
4341 //<![CDATA[
4342-Mage.Cookies.path = '<?php echo $this->getPath()?>';
4343-Mage.Cookies.domain = '<?php echo $this->getDomain()?>';
4344+Mage.Cookies.path = '<?php echo Mage::helper('core')->jsQuoteEscape($this->getPath()) ?>';
4345+Mage.Cookies.domain = '<?php echo Mage::helper('core')->jsQuoteEscape($this->getDomain()) ?>';
4346 //]]>
4347 </script>
4348diff --git app/design/frontend/base/default/template/persistent/customer/form/register.phtml app/design/frontend/base/default/template/persistent/customer/form/register.phtml
4349index 4c41435..cf4337d 100644
4350--- app/design/frontend/base/default/template/persistent/customer/form/register.phtml
4351+++ app/design/frontend/base/default/template/persistent/customer/form/register.phtml
4352@@ -42,6 +42,7 @@
4353 <div class="fieldset">
4354 <input type="hidden" name="success_url" value="<?php echo $this->getSuccessUrl() ?>" />
4355 <input type="hidden" name="error_url" value="<?php echo $this->getErrorUrl() ?>" />
4356+ <input type="hidden" name="form_key" value="<?php echo Mage::getSingleton('core/session')->getFormKey() ?>" />
4357 <h2 class="legend"><?php echo $this->__('Personal Information') ?></h2>
4358 <ul class="form-list">
4359 <li class="fields">
4360diff --git app/design/frontend/default/iphone/layout/customer.xml app/design/frontend/default/iphone/layout/customer.xml
4361index 1633e89..ebad42e 100644
4362--- app/design/frontend/default/iphone/layout/customer.xml
4363+++ app/design/frontend/default/iphone/layout/customer.xml
4364@@ -141,7 +141,7 @@ New customer registration
4365 </reference>
4366 </customer_account_forgotpassword>
4367
4368- <customer_account_resetpassword translate="label">
4369+ <customer_account_changeforgotten translate="label">
4370 <label>Reset a Password</label>
4371 <remove name="right"/>
4372 <remove name="left"/>
4373@@ -160,9 +160,9 @@ New customer registration
4374 </action>
4375 </reference>
4376 <reference name="content">
4377- <block type="customer/account_resetpassword" name="resetPassword" template="customer/form/resetforgottenpassword.phtml"/>
4378+ <block type="customer/account_changeforgotten" name="changeForgottenPassword" template="customer/form/resetforgottenpassword.phtml"/>
4379 </reference>
4380- </customer_account_resetpassword>
4381+ </customer_account_changeforgotten>
4382
4383 <customer_account_confirmation>
4384 <remove name="right"/>
4385diff --git app/design/frontend/default/modern/layout/customer.xml app/design/frontend/default/modern/layout/customer.xml
4386index f1fd04f..95c6603 100644
4387--- app/design/frontend/default/modern/layout/customer.xml
4388+++ app/design/frontend/default/modern/layout/customer.xml
4389@@ -156,7 +156,7 @@ New customer registration
4390 </reference>
4391 </customer_account_forgotpassword>
4392
4393- <customer_account_resetpassword translate="label">
4394+ <customer_account_changeforgotten translate="label">
4395 <label>Reset a Password</label>
4396 <remove name="right"/>
4397 <remove name="left"/>
4398@@ -175,9 +175,9 @@ New customer registration
4399 </action>
4400 </reference>
4401 <reference name="content">
4402- <block type="customer/account_resetpassword" name="resetPassword" template="customer/form/resetforgottenpassword.phtml"/>
4403+ <block type="customer/account_changeforgotten" name="changeForgottenPassword" template="customer/form/resetforgottenpassword.phtml"/>
4404 </reference>
4405- </customer_account_resetpassword>
4406+ </customer_account_changeforgotten>
4407
4408 <customer_account_confirmation>
4409 <remove name="right"/>
4410diff --git app/design/frontend/rwd/default/layout/customer.xml app/design/frontend/rwd/default/layout/customer.xml
4411index 2fa3cf5..5a47d5e 100644
4412--- app/design/frontend/rwd/default/layout/customer.xml
4413+++ app/design/frontend/rwd/default/layout/customer.xml
4414@@ -158,7 +158,7 @@ New customer registration
4415 </reference>
4416 </customer_account_forgotpassword>
4417
4418- <customer_account_resetpassword translate="label">
4419+ <customer_account_changeforgotten translate="label">
4420 <label>Reset a Password</label>
4421 <remove name="right"/>
4422 <remove name="left"/>
4423@@ -177,9 +177,9 @@ New customer registration
4424 </action>
4425 </reference>
4426 <reference name="content">
4427- <block type="customer/account_resetpassword" name="resetPassword" template="customer/form/resetforgottenpassword.phtml"/>
4428+ <block type="customer/account_changeforgotten" name="changeForgottenPassword" template="customer/form/resetforgottenpassword.phtml"/>
4429 </reference>
4430- </customer_account_resetpassword>
4431+ </customer_account_changeforgotten>
4432
4433 <customer_account_confirmation>
4434 <remove name="right"/>
4435diff --git app/design/frontend/rwd/default/template/customer/form/resetforgottenpassword.phtml app/design/frontend/rwd/default/template/customer/form/resetforgottenpassword.phtml
4436index abdaae8..c079fcc 100644
4437--- app/design/frontend/rwd/default/template/customer/form/resetforgottenpassword.phtml
4438+++ app/design/frontend/rwd/default/template/customer/form/resetforgottenpassword.phtml
4439@@ -28,7 +28,7 @@
4440 <h1><?php echo $this->__('Reset a Password'); ?></h1>
4441 </div>
4442 <?php echo $this->getMessagesBlock()->getGroupedHtml(); ?>
4443-<form action="<?php echo $this->getUrl('*/*/resetpasswordpost', array('_query' => array('id' => $this->getCustomerId(), 'token' => $this->getResetPasswordLinkToken()))); ?>" method="post" id="form-validate" class="scaffold-form">
4444+<form action="<?php echo $this->getUrl('*/*/resetpasswordpost'); ?>" method="post" id="form-validate" class="scaffold-form">
4445 <div class="fieldset" style="margin-top: 70px;">
4446 <p class="required"><?php echo $this->__('* Required Fields'); ?></p>
4447 <ul class="form-list">
4448diff --git app/design/frontend/rwd/default/template/persistent/customer/form/register.phtml app/design/frontend/rwd/default/template/persistent/customer/form/register.phtml
4449index f947b45..b46b6fc 100644
4450--- app/design/frontend/rwd/default/template/persistent/customer/form/register.phtml
4451+++ app/design/frontend/rwd/default/template/persistent/customer/form/register.phtml
4452@@ -42,6 +42,7 @@
4453 <div class="fieldset">
4454 <input type="hidden" name="success_url" value="<?php echo $this->getSuccessUrl() ?>" />
4455 <input type="hidden" name="error_url" value="<?php echo $this->getErrorUrl() ?>" />
4456+ <input type="hidden" name="form_key" value="<?php echo Mage::getSingleton('core/session')->getFormKey() ?>" />
4457 <p class="form-instructions"><?php echo $this->__('Please enter the following information to create your account.') ?></p>
4458 <p class="required"><?php echo $this->__('* Required Fields') ?></p>
4459 <ul class="form-list">
4460diff --git cron.php cron.php
4461index bacabce..8bb6415 100644
4462--- cron.php
4463+++ cron.php
4464@@ -59,10 +59,11 @@ try {
4465 Mage::throwException('Unrecognized cron mode was defined');
4466 }
4467 } else if (!$isShellDisabled) {
4468- $fileName = basename(__FILE__);
4469- $baseDir = dirname(__FILE__);
4470- shell_exec("/bin/sh $baseDir/cron.sh $fileName -mdefault 1 > /dev/null 2>&1 &");
4471- shell_exec("/bin/sh $baseDir/cron.sh $fileName -malways 1 > /dev/null 2>&1 &");
4472+ $fileName = escapeshellarg(basename(__FILE__));
4473+ $cronPath = escapeshellarg(dirname(__FILE__) . '/cron.sh');
4474+
4475+ shell_exec(escapeshellcmd("/bin/sh $cronPath $fileName -mdefault 1 > /dev/null 2>&1 &"));
4476+ shell_exec(escapeshellcmd("/bin/sh $cronPath $fileName -malways 1 > /dev/null 2>&1 &"));
4477 exit;
4478 }
4479 }
4480diff --git errors/processor.php errors/processor.php
4481index 9083d24..6ddd78d 100644
4482--- errors/processor.php
4483+++ errors/processor.php
4484@@ -463,6 +463,7 @@ class Error_Processor
4485 @mkdir($this->_reportDir, 0750, true);
4486 }
4487
4488+ $reportData = array_map('strip_tags', $reportData);
4489 @file_put_contents($this->_reportFile, serialize($reportData));
4490 @chmod($this->_reportFile, 0640);
4491
4492diff --git lib/Unserialize/Parser.php lib/Unserialize/Parser.php
4493new file mode 100644
4494index 0000000..423902a
4495--- /dev/null
4496+++ lib/Unserialize/Parser.php
4497@@ -0,0 +1,61 @@
4498+<?php
4499+/**
4500+ * Magento
4501+ *
4502+ * NOTICE OF LICENSE
4503+ *
4504+ * This source file is subject to the Open Software License (OSL 3.0)
4505+ * that is bundled with this package in the file LICENSE.txt.
4506+ * It is also available through the world-wide-web at this URL:
4507+ * http://opensource.org/licenses/osl-3.0.php
4508+ * If you did not receive a copy of the license and are unable to
4509+ * obtain it through the world-wide-web, please send an email
4510+ * to license@magentocommerce.com so we can send you a copy immediately.
4511+ *
4512+ * DISCLAIMER
4513+ *
4514+ * Do not edit or add to this file if you wish to upgrade Magento to newer
4515+ * versions in the future. If you wish to customize Magento for your
4516+ * needs please refer to http://www.magentocommerce.com for more information.
4517+ *
4518+ * @category Mage
4519+ * @package Unserialize
4520+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
4521+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
4522+ */
4523+
4524+/**
4525+ * Class Unserialize_Parser
4526+ */
4527+class Unserialize_Parser
4528+{
4529+ const TYPE_STRING = 's';
4530+ const TYPE_INT = 'i';
4531+ const TYPE_DOUBLE = 'd';
4532+ const TYPE_ARRAY = 'a';
4533+ const TYPE_BOOL = 'b';
4534+
4535+ const SYMBOL_QUOTE = '"';
4536+ const SYMBOL_SEMICOLON = ';';
4537+ const SYMBOL_COLON = ':';
4538+
4539+ /**
4540+ * @param $str
4541+ * @return array|null
4542+ * @throws Exception
4543+ */
4544+ public function unserialize($str)
4545+ {
4546+ $reader = new Unserialize_Reader_Arr();
4547+ $prevChar = null;
4548+ for ($i = 0; $i < strlen($str); $i++) {
4549+ $char = $str[$i];
4550+ $arr = $reader->read($char, $prevChar);
4551+ if (!is_null($arr)) {
4552+ return $arr;
4553+ }
4554+ $prevChar = $char;
4555+ }
4556+ throw new Exception('Error during unserialization');
4557+ }
4558+}
4559diff --git lib/Unserialize/Reader/Arr.php lib/Unserialize/Reader/Arr.php
4560new file mode 100644
4561index 0000000..caa979e
4562--- /dev/null
4563+++ lib/Unserialize/Reader/Arr.php
4564@@ -0,0 +1,122 @@
4565+<?php
4566+/**
4567+ * Magento
4568+ *
4569+ * NOTICE OF LICENSE
4570+ *
4571+ * This source file is subject to the Open Software License (OSL 3.0)
4572+ * that is bundled with this package in the file LICENSE.txt.
4573+ * It is also available through the world-wide-web at this URL:
4574+ * http://opensource.org/licenses/osl-3.0.php
4575+ * If you did not receive a copy of the license and are unable to
4576+ * obtain it through the world-wide-web, please send an email
4577+ * to license@magentocommerce.com so we can send you a copy immediately.
4578+ *
4579+ * DISCLAIMER
4580+ *
4581+ * Do not edit or add to this file if you wish to upgrade Magento to newer
4582+ * versions in the future. If you wish to customize Magento for your
4583+ * needs please refer to http://www.magentocommerce.com for more information.
4584+ *
4585+ * @category Mage
4586+ * @package Unserialize
4587+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
4588+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
4589+ */
4590+
4591+/**
4592+ * Class Unserialize_Reader_Arr
4593+ */
4594+class Unserialize_Reader_Arr
4595+{
4596+ /**
4597+ * @var array
4598+ */
4599+ protected $_result = null;
4600+
4601+ /**
4602+ * @var string|int
4603+ */
4604+ protected $_length = '';
4605+
4606+ /**
4607+ * @var int|null
4608+ */
4609+ protected $_status = null;
4610+
4611+ /**
4612+ * @var object
4613+ */
4614+ protected $_reader = null;
4615+
4616+ const READING_LENGTH = 1;
4617+ const FINISHED_LENGTH = 2;
4618+ const READING_KEY = 3;
4619+ const READING_VALUE = 4;
4620+ const FINISHED_ARR = 5;
4621+
4622+ /**
4623+ * @param $char
4624+ * @param $prevChar
4625+ * @return array|null
4626+ * @throws Exception
4627+ */
4628+ public function read($char, $prevChar)
4629+ {
4630+ $this->_result = !is_null($this->_result) ? $this->_result : array();
4631+
4632+ if (is_null($this->_status) && $prevChar == Unserialize_Parser::SYMBOL_COLON) {
4633+ $this->_length .= $char;
4634+ $this->_status = self::READING_LENGTH;
4635+ return null;
4636+ }
4637+
4638+ if ($this->_status == self::READING_LENGTH) {
4639+ if ($char == Unserialize_Parser::SYMBOL_COLON) {
4640+ $this->_length = (int)$this->_length;
4641+ if ($this->_length == 0) {
4642+ $this->_status = self::FINISHED_ARR;
4643+ return null;
4644+ }
4645+ $this->_status = self::FINISHED_LENGTH;
4646+ } else {
4647+ $this->_length .= $char;
4648+ }
4649+ }
4650+
4651+ if ($this->_status == self::FINISHED_LENGTH && $prevChar == '{') {
4652+ $this->_reader = new Unserialize_Reader_ArrKey();
4653+ $this->_status = self::READING_KEY;
4654+ }
4655+
4656+ if ($this->_status == self::READING_KEY) {
4657+ $key = $this->_reader->read($char, $prevChar);
4658+ if (!is_null($key)) {
4659+ $this->_status = self::READING_VALUE;
4660+ $this->_reader = new Unserialize_Reader_ArrValue($key);
4661+ return null;
4662+ }
4663+ }
4664+
4665+ if ($this->_status == self::READING_VALUE) {
4666+ $value = $this->_reader->read($char, $prevChar);
4667+ if (!is_null($value)) {
4668+ $this->_result[$this->_reader->key] = $value;
4669+ if (count($this->_result) < $this->_length) {
4670+ $this->_reader = new Unserialize_Reader_ArrKey();
4671+ $this->_status = self::READING_KEY;
4672+ return null;
4673+ } else {
4674+ $this->_status = self::FINISHED_ARR;
4675+ return null;
4676+ }
4677+ }
4678+ }
4679+
4680+ if ($this->_status == self::FINISHED_ARR) {
4681+ if ($char == '}') {
4682+ return $this->_result;
4683+ }
4684+ }
4685+ }
4686+}
4687diff --git lib/Unserialize/Reader/ArrKey.php lib/Unserialize/Reader/ArrKey.php
4688new file mode 100644
4689index 0000000..830e928
4690--- /dev/null
4691+++ lib/Unserialize/Reader/ArrKey.php
4692@@ -0,0 +1,84 @@
4693+<?php
4694+/**
4695+ * Magento
4696+ *
4697+ * NOTICE OF LICENSE
4698+ *
4699+ * This source file is subject to the Open Software License (OSL 3.0)
4700+ * that is bundled with this package in the file LICENSE.txt.
4701+ * It is also available through the world-wide-web at this URL:
4702+ * http://opensource.org/licenses/osl-3.0.php
4703+ * If you did not receive a copy of the license and are unable to
4704+ * obtain it through the world-wide-web, please send an email
4705+ * to license@magentocommerce.com so we can send you a copy immediately.
4706+ *
4707+ * DISCLAIMER
4708+ *
4709+ * Do not edit or add to this file if you wish to upgrade Magento to newer
4710+ * versions in the future. If you wish to customize Magento for your
4711+ * needs please refer to http://www.magentocommerce.com for more information.
4712+ *
4713+ * @category Mage
4714+ * @package Unserialize
4715+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
4716+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
4717+ */
4718+
4719+/**
4720+ * Class Unserialize_Reader_ArrKey
4721+ */
4722+class Unserialize_Reader_ArrKey
4723+{
4724+ /**
4725+ * @var int
4726+ */
4727+ protected $_status;
4728+
4729+ /**
4730+ * @object
4731+ */
4732+ protected $_reader;
4733+
4734+ const NOT_STARTED = 1;
4735+ const READING_KEY = 2;
4736+
4737+ /**
4738+ * Construct
4739+ */
4740+ public function __construct()
4741+ {
4742+ $this->_status = self::NOT_STARTED;
4743+ }
4744+
4745+ /**
4746+ * @param string $char
4747+ * @param string $prevChar
4748+ * @return mixed|null
4749+ * @throws Exception
4750+ */
4751+ public function read($char, $prevChar)
4752+ {
4753+ if ($this->_status == self::NOT_STARTED) {
4754+ switch ($char) {
4755+ case Unserialize_Parser::TYPE_STRING:
4756+ $this->_reader = new Unserialize_Reader_Str();
4757+ $this->_status = self::READING_KEY;
4758+ break;
4759+ case Unserialize_Parser::TYPE_INT:
4760+ $this->_reader = new Unserialize_Reader_Int();
4761+ $this->_status = self::READING_KEY;
4762+ break;
4763+ default:
4764+ throw new Exception('Unsupported data type ' . $char);
4765+ }
4766+ }
4767+
4768+ if ($this->_status == self::READING_KEY) {
4769+ $key = $this->_reader->read($char, $prevChar);
4770+ if (!is_null($key)) {
4771+ return $key;
4772+ }
4773+ }
4774+ return null;
4775+ }
4776+}
4777diff --git lib/Unserialize/Reader/ArrValue.php lib/Unserialize/Reader/ArrValue.php
4778new file mode 100644
4779index 0000000..d2a4937
4780--- /dev/null
4781+++ lib/Unserialize/Reader/ArrValue.php
4782@@ -0,0 +1,100 @@
4783+<?php
4784+/**
4785+ * Magento
4786+ *
4787+ * NOTICE OF LICENSE
4788+ *
4789+ * This source file is subject to the Open Software License (OSL 3.0)
4790+ * that is bundled with this package in the file LICENSE.txt.
4791+ * It is also available through the world-wide-web at this URL:
4792+ * http://opensource.org/licenses/osl-3.0.php
4793+ * If you did not receive a copy of the license and are unable to
4794+ * obtain it through the world-wide-web, please send an email
4795+ * to license@magentocommerce.com so we can send you a copy immediately.
4796+ *
4797+ * DISCLAIMER
4798+ *
4799+ * Do not edit or add to this file if you wish to upgrade Magento to newer
4800+ * versions in the future. If you wish to customize Magento for your
4801+ * needs please refer to http://www.magentocommerce.com for more information.
4802+ *
4803+ * @category Mage
4804+ * @package Unserialize
4805+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
4806+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
4807+ */
4808+
4809+/**
4810+ * Class Unserialize_Reader_ArrValue
4811+ */
4812+class Unserialize_Reader_ArrValue
4813+{
4814+
4815+ /**
4816+ * @var
4817+ */
4818+ public $key;
4819+
4820+ /**
4821+ * @var int
4822+ */
4823+ protected $_status;
4824+
4825+ /**
4826+ * @object
4827+ */
4828+ protected $_reader;
4829+
4830+ const NOT_STARTED = 1;
4831+ const READING_VALUE = 2;
4832+
4833+ public function __construct($key)
4834+ {
4835+ $this->_status = self::NOT_STARTED;
4836+ $this->key = $key;
4837+ }
4838+
4839+ /**
4840+ * @param string $char
4841+ * @param string $prevChar
4842+ * @return mixed|null
4843+ * @throws Exception
4844+ */
4845+ public function read($char, $prevChar)
4846+ {
4847+ if ($this->_status == self::NOT_STARTED) {
4848+ switch ($char) {
4849+ case Unserialize_Parser::TYPE_STRING:
4850+ $this->_reader = new Unserialize_Reader_Str();
4851+ $this->_status = self::READING_VALUE;
4852+ break;
4853+ case Unserialize_Parser::TYPE_ARRAY:
4854+ $this->_reader = new Unserialize_Reader_Arr();
4855+ $this->_status = self::READING_VALUE;
4856+ break;
4857+ case Unserialize_Parser::TYPE_INT:
4858+ $this->_reader = new Unserialize_Reader_Int();
4859+ $this->_status = self::READING_VALUE;
4860+ break;
4861+ case Unserialize_Parser::TYPE_BOOL:
4862+ $this->_reader = new Unserialize_Reader_Bool();
4863+ $this->_status = self::READING_VALUE;
4864+ break;
4865+ case Unserialize_Parser::TYPE_DOUBLE:
4866+ $this->_reader = new Unserialize_Reader_Dbl();
4867+ $this->_status = self::READING_VALUE;
4868+ break;
4869+ default:
4870+ throw new Exception('Unsupported data type ' . $char);
4871+ }
4872+ }
4873+
4874+ if ($this->_status == self::READING_VALUE) {
4875+ $value = $this->_reader->read($char, $prevChar);
4876+ if (!is_null($value)) {
4877+ return $value;
4878+ }
4879+ }
4880+ return null;
4881+ }
4882+}
4883diff --git lib/Unserialize/Reader/Bool.php lib/Unserialize/Reader/Bool.php
4884new file mode 100644
4885index 0000000..5e1a132
4886--- /dev/null
4887+++ lib/Unserialize/Reader/Bool.php
4888@@ -0,0 +1,66 @@
4889+<?php
4890+/**
4891+ * Magento
4892+ *
4893+ * NOTICE OF LICENSE
4894+ *
4895+ * This source file is subject to the Open Software License (OSL 3.0)
4896+ * that is bundled with this package in the file LICENSE.txt.
4897+ * It is also available through the world-wide-web at this URL:
4898+ * http://opensource.org/licenses/osl-3.0.php
4899+ * If you did not receive a copy of the license and are unable to
4900+ * obtain it through the world-wide-web, please send an email
4901+ * to license@magentocommerce.com so we can send you a copy immediately.
4902+ *
4903+ * DISCLAIMER
4904+ *
4905+ * Do not edit or add to this file if you wish to upgrade Magento to newer
4906+ * versions in the future. If you wish to customize Magento for your
4907+ * needs please refer to http://www.magentocommerce.com for more information.
4908+ *
4909+ * @category Mage
4910+ * @package Unserialize
4911+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
4912+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
4913+ */
4914+
4915+/**
4916+ * Class Unserialize_Reader_Int
4917+ */
4918+class Unserialize_Reader_Bool
4919+{
4920+ /**
4921+ * @var int
4922+ */
4923+ protected $_status;
4924+
4925+ /**
4926+ * @var string|int
4927+ */
4928+ protected $_value;
4929+
4930+ const READING_VALUE = 1;
4931+
4932+ /**
4933+ * @param string $char
4934+ * @param string $prevChar
4935+ * @return int|null
4936+ */
4937+ public function read($char, $prevChar)
4938+ {
4939+ if ($prevChar == Unserialize_Parser::SYMBOL_COLON) {
4940+ $this->_value .= $char;
4941+ $this->_status = self::READING_VALUE;
4942+ return null;
4943+ }
4944+
4945+ if ($this->_status == self::READING_VALUE) {
4946+ if ($char !== Unserialize_Parser::SYMBOL_SEMICOLON) {
4947+ $this->_value .= $char;
4948+ } else {
4949+ return (bool)$this->_value;
4950+ }
4951+ }
4952+ return null;
4953+ }
4954+}
4955diff --git lib/Unserialize/Reader/Dbl.php lib/Unserialize/Reader/Dbl.php
4956new file mode 100644
4957index 0000000..48367c8
4958--- /dev/null
4959+++ lib/Unserialize/Reader/Dbl.php
4960@@ -0,0 +1,66 @@
4961+<?php
4962+/**
4963+ * Magento
4964+ *
4965+ * NOTICE OF LICENSE
4966+ *
4967+ * This source file is subject to the Open Software License (OSL 3.0)
4968+ * that is bundled with this package in the file LICENSE.txt.
4969+ * It is also available through the world-wide-web at this URL:
4970+ * http://opensource.org/licenses/osl-3.0.php
4971+ * If you did not receive a copy of the license and are unable to
4972+ * obtain it through the world-wide-web, please send an email
4973+ * to license@magentocommerce.com so we can send you a copy immediately.
4974+ *
4975+ * DISCLAIMER
4976+ *
4977+ * Do not edit or add to this file if you wish to upgrade Magento to newer
4978+ * versions in the future. If you wish to customize Magento for your
4979+ * needs please refer to http://www.magentocommerce.com for more information.
4980+ *
4981+ * @category Mage
4982+ * @package Unserialize
4983+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
4984+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
4985+ */
4986+
4987+/**
4988+ * Class Unserialize_Reader_Dbl
4989+ */
4990+class Unserialize_Reader_Dbl
4991+{
4992+ /**
4993+ * @var int
4994+ */
4995+ protected $_status;
4996+
4997+ /**
4998+ * @var string|int
4999+ */
5000+ protected $_value;
5001+
5002+ const READING_VALUE = 1;
5003+
5004+ /**
5005+ * @param string $char
5006+ * @param string $prevChar
5007+ * @return float|null
5008+ */
5009+ public function read($char, $prevChar)
5010+ {
5011+ if ($prevChar == Unserialize_Parser::SYMBOL_COLON) {
5012+ $this->_value .= $char;
5013+ $this->_status = self::READING_VALUE;
5014+ return null;
5015+ }
5016+
5017+ if ($this->_status == self::READING_VALUE) {
5018+ if ($char !== Unserialize_Parser::SYMBOL_SEMICOLON) {
5019+ $this->_value .= $char;
5020+ } else {
5021+ return (float)$this->_value;
5022+ }
5023+ }
5024+ return null;
5025+ }
5026+}
5027diff --git lib/Unserialize/Reader/Int.php lib/Unserialize/Reader/Int.php
5028new file mode 100644
5029index 0000000..7bf6c40
5030--- /dev/null
5031+++ lib/Unserialize/Reader/Int.php
5032@@ -0,0 +1,66 @@
5033+<?php
5034+/**
5035+ * Magento
5036+ *
5037+ * NOTICE OF LICENSE
5038+ *
5039+ * This source file is subject to the Open Software License (OSL 3.0)
5040+ * that is bundled with this package in the file LICENSE.txt.
5041+ * It is also available through the world-wide-web at this URL:
5042+ * http://opensource.org/licenses/osl-3.0.php
5043+ * If you did not receive a copy of the license and are unable to
5044+ * obtain it through the world-wide-web, please send an email
5045+ * to license@magentocommerce.com so we can send you a copy immediately.
5046+ *
5047+ * DISCLAIMER
5048+ *
5049+ * Do not edit or add to this file if you wish to upgrade Magento to newer
5050+ * versions in the future. If you wish to customize Magento for your
5051+ * needs please refer to http://www.magentocommerce.com for more information.
5052+ *
5053+ * @category Mage
5054+ * @package Unserialize
5055+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
5056+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
5057+ */
5058+
5059+/**
5060+ * Class Unserialize_Reader_Int
5061+ */
5062+class Unserialize_Reader_Int
5063+{
5064+ /**
5065+ * @var int
5066+ */
5067+ protected $_status;
5068+
5069+ /**
5070+ * @var string|int
5071+ */
5072+ protected $_value;
5073+
5074+ const READING_VALUE = 1;
5075+
5076+ /**
5077+ * @param string $char
5078+ * @param string $prevChar
5079+ * @return int|null
5080+ */
5081+ public function read($char, $prevChar)
5082+ {
5083+ if ($prevChar == Unserialize_Parser::SYMBOL_COLON) {
5084+ $this->_value .= $char;
5085+ $this->_status = self::READING_VALUE;
5086+ return null;
5087+ }
5088+
5089+ if ($this->_status == self::READING_VALUE) {
5090+ if ($char !== Unserialize_Parser::SYMBOL_SEMICOLON) {
5091+ $this->_value .= $char;
5092+ } else {
5093+ return (int)$this->_value;
5094+ }
5095+ }
5096+ return null;
5097+ }
5098+}
5099diff --git lib/Unserialize/Reader/Str.php lib/Unserialize/Reader/Str.php
5100new file mode 100644
5101index 0000000..e62b38f
5102--- /dev/null
5103+++ lib/Unserialize/Reader/Str.php
5104@@ -0,0 +1,93 @@
5105+<?php
5106+/**
5107+ * Magento
5108+ *
5109+ * NOTICE OF LICENSE
5110+ *
5111+ * This source file is subject to the Open Software License (OSL 3.0)
5112+ * that is bundled with this package in the file LICENSE.txt.
5113+ * It is also available through the world-wide-web at this URL:
5114+ * http://opensource.org/licenses/osl-3.0.php
5115+ * If you did not receive a copy of the license and are unable to
5116+ * obtain it through the world-wide-web, please send an email
5117+ * to license@magentocommerce.com so we can send you a copy immediately.
5118+ *
5119+ * DISCLAIMER
5120+ *
5121+ * Do not edit or add to this file if you wish to upgrade Magento to newer
5122+ * versions in the future. If you wish to customize Magento for your
5123+ * needs please refer to http://www.magentocommerce.com for more information.
5124+ *
5125+ * @category Mage
5126+ * @package Unserialize
5127+ * @copyright Copyright (c) 2015 Magento Inc. (http://www.magentocommerce.com)
5128+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
5129+ */
5130+
5131+/**
5132+ * Class Unserialize_Reader_Str
5133+ */
5134+class Unserialize_Reader_Str
5135+{
5136+ /**
5137+ * @var int|null
5138+ */
5139+ protected $_status = null;
5140+
5141+ /**
5142+ * @var int|string
5143+ */
5144+ protected $_length;
5145+
5146+ /**
5147+ * @var string
5148+ */
5149+ protected $_value;
5150+
5151+ const READING_LENGTH = 1;
5152+ const FINISHED_LENGTH = 2;
5153+ const READING_VALUE = 3;
5154+
5155+ /**
5156+ * @param string $char
5157+ * @param string $prevChar
5158+ * @return null|string
5159+ */
5160+ public function read($char, $prevChar)
5161+ {
5162+
5163+ if (is_null($this->_status) && $prevChar == Unserialize_Parser::SYMBOL_COLON) {
5164+ $this->_status = self::READING_LENGTH;
5165+ }
5166+
5167+ if ($this->_status == self::READING_LENGTH) {
5168+ if ($char != Unserialize_Parser::SYMBOL_COLON) {
5169+ $this->_length .= $char;
5170+ } else {
5171+ $this->_length = (int)$this->_length;
5172+ $this->_status = self::FINISHED_LENGTH;
5173+ }
5174+ }
5175+
5176+ if ($this->_status == self::FINISHED_LENGTH) {
5177+ if ($char == Unserialize_Parser::SYMBOL_QUOTE) {
5178+ $this->_status = self::READING_VALUE;
5179+ return null;
5180+ }
5181+ }
5182+
5183+ if ($this->_status == self::READING_VALUE) {
5184+ if (strlen($this->_value) < $this->_length) {
5185+ $this->_value .= $char;
5186+ return null;
5187+ }
5188+
5189+ if (strlen($this->_value) == $this->_length) {
5190+ if ($char == Unserialize_Parser::SYMBOL_SEMICOLON && $prevChar == Unserialize_Parser::SYMBOL_QUOTE) {
5191+ return (string)$this->_value;
5192+ }
5193+ }
5194+ }
5195+ return null;
5196+ }
5197+}
5198diff --git lib/Varien/Data/Collection/Db.php lib/Varien/Data/Collection/Db.php
5199index b941cb5..b98efd2 100644
5200--- lib/Varien/Data/Collection/Db.php
5201+++ lib/Varien/Data/Collection/Db.php
5202@@ -410,8 +410,14 @@ class Varien_Data_Collection_Db extends Varien_Data_Collection
5203 */
5204 protected function _translateCondition($field, $condition)
5205 {
5206- $field = $this->_getMappedField($field);
5207- return $this->_getConditionSql($field, $condition);
5208+ $mappedField = $this->_getMappedField($field);
5209+
5210+ $quotedField = $mappedField;
5211+ if ($mappedField === $field) {
5212+ $quotedField = $this->getConnection()->quoteIdentifier($field);
5213+ }
5214+
5215+ return $this->_getConditionSql($quotedField, $condition);
5216 }
5217
5218 /**
5219@@ -474,7 +480,7 @@ class Varien_Data_Collection_Db extends Varien_Data_Collection
5220 * If non matched - sequential array is expected and OR conditions
5221 * will be built using above mentioned structure
5222 *
5223- * @param string $fieldName
5224+ * @param string $fieldName Field name must be already escaped with Varien_Db_Adapter_Interface::quoteIdentifier()
5225 * @param integer|string|array $condition
5226 * @return string
5227 */