diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 52214a54ef..18f7d0e59c 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,3 +1,13 @@ +==== 1.9.4.0 ==== +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +] NOTE: Current Release Notes are maintained at: [ +] [ +] http://devdocs.magento.com/guides/m1x/ce19-ee114/ce1.9_release-notes.html [ +] [ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ==== 1.9.3.10 ==== ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/app/Mage.php b/app/Mage.php index 75506fbc8c..99bd4e5d3d 100644 --- a/app/Mage.php +++ b/app/Mage.php @@ -53,6 +53,9 @@ Varien_Autoload::register(); +include_once "phpseclib/bootstrap.php"; +include_once "mcryptcompat/mcrypt.php"; + /** * Main Mage hub class * @@ -170,8 +173,8 @@ public static function getVersionInfo() return array( 'major' => '1', 'minor' => '9', - 'revision' => '3', - 'patch' => '10', + 'revision' => '4', + 'patch' => '0', 'stability' => '', 'number' => '', ); diff --git a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Attribute/Edit/Tab/Main.php b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Attribute/Edit/Tab/Main.php index 019c9954d7..1e3a8f0a4b 100644 --- a/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Attribute/Edit/Tab/Main.php +++ b/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Attribute/Edit/Tab/Main.php @@ -32,7 +32,8 @@ * @package Mage_Adminhtml * @author Magento Core Team */ -class Mage_Adminhtml_Block_Catalog_Product_Attribute_Edit_Tab_Main extends Mage_Eav_Block_Adminhtml_Attribute_Edit_Main_Abstract +class Mage_Adminhtml_Block_Catalog_Product_Attribute_Edit_Tab_Main + extends Mage_Eav_Block_Adminhtml_Attribute_Edit_Main_Abstract { /** * Adding product form elements for editing attribute @@ -48,6 +49,17 @@ protected function _prepareForm() /* @var $fieldset Varien_Data_Form_Element_Fieldset */ $fieldset = $form->getElement('base_fieldset'); + $fieldset->getElements() + ->searchById('attribute_code') + ->setData( + 'class', + 'validate-code-event ' . $fieldset->getElements()->searchById('attribute_code')->getData('class') + )->setData( + 'note', + $fieldset->getElements()->searchById('attribute_code')->getData('note') + . Mage::helper('eav')->__('. Do not use "event" for an attribute code, it is a reserved keyword.') + ); + $frontendInputElm = $form->getElement('frontend_input'); $additionalTypes = array( array( @@ -94,7 +106,10 @@ protected function _prepareForm() Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL =>Mage::helper('catalog')->__('Global'), ); - if ($attributeObject->getAttributeCode() == 'status' || $attributeObject->getAttributeCode() == 'tax_class_id') { + if ( + $attributeObject->getAttributeCode() == 'status' + || $attributeObject->getAttributeCode() == 'tax_class_id' + ) { unset($scopes[Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE]); } diff --git a/app/code/core/Mage/Adminhtml/Block/Customer/Group/Edit.php b/app/code/core/Mage/Adminhtml/Block/Customer/Group/Edit.php index ddef716f27..8d3c526c28 100644 --- a/app/code/core/Mage/Adminhtml/Block/Customer/Group/Edit.php +++ b/app/code/core/Mage/Adminhtml/Block/Customer/Group/Edit.php @@ -49,6 +49,18 @@ public function __construct() } } + public function getDeleteUrl() + { + if (!Mage::getSingleton('adminhtml/url')->useSecretKey()) { + return $this->getUrl('*/*/delete', array( + $this->_objectId => $this->getRequest()->getParam($this->_objectId), + 'form_key' => Mage::getSingleton('core/session')->getFormKey() + )); + } else { + parent::getDeleteUrl(); + } + } + public function getHeaderText() { if(!is_null(Mage::registry('current_group')->getId())) { diff --git a/app/code/core/Mage/Adminhtml/Block/Newsletter/Template/Edit.php b/app/code/core/Mage/Adminhtml/Block/Newsletter/Template/Edit.php index 86e5ceb346..8283aded90 100644 --- a/app/code/core/Mage/Adminhtml/Block/Newsletter/Template/Edit.php +++ b/app/code/core/Mage/Adminhtml/Block/Newsletter/Template/Edit.php @@ -275,7 +275,7 @@ public function getForm() */ public function getJsTemplateName() { - return addcslashes($this->getModel()->getTemplateCode(), "\"\r\n\\"); + return addcslashes($this->escapeHtml($this->getModel()->getTemplateCode()), "\"\r\n\\"); } /** diff --git a/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/AttributeController.php b/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/AttributeController.php index 3add46675c..0510fd9135 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/AttributeController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Catalog/Product/AttributeController.php @@ -208,10 +208,10 @@ public function saveAction() //validate attribute_code if (isset($data['attribute_code'])) { - $validatorAttrCode = new Zend_Validate_Regex(array('pattern' => '/^[a-z][a-z_0-9]{1,254}$/')); + $validatorAttrCode = new Zend_Validate_Regex(array('pattern' => '/[a-z][a-z_0-9]{1,254}[^event]/')); if (!$validatorAttrCode->isValid($data['attribute_code'])) { $session->addError( - Mage::helper('catalog')->__('Attribute code is invalid. Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter.') + Mage::helper('catalog')->__('Attribute code is invalid. Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter. Do not use "event" for an attribute code.') ); $this->_redirect('*/*/edit', array('attribute_id' => $id, '_current' => true)); return; diff --git a/app/code/core/Mage/Adminhtml/controllers/Cms/BlockController.php b/app/code/core/Mage/Adminhtml/controllers/Cms/BlockController.php index f10c2c1c7d..fe56e01845 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Cms/BlockController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Cms/BlockController.php @@ -34,6 +34,17 @@ */ class Mage_Adminhtml_Cms_BlockController extends Mage_Adminhtml_Controller_Action { + /** + * Controller predispatch method + * + * @return Mage_Adminhtml_Controller_Action + */ + public function preDispatch() + { + $this->_setForcedFormKeyActions('delete'); + return parent::preDispatch(); + } + /** * Init actions * diff --git a/app/code/core/Mage/Adminhtml/controllers/Customer/GroupController.php b/app/code/core/Mage/Adminhtml/controllers/Customer/GroupController.php index f94fd360a2..7d9177ea38 100644 --- a/app/code/core/Mage/Adminhtml/controllers/Customer/GroupController.php +++ b/app/code/core/Mage/Adminhtml/controllers/Customer/GroupController.php @@ -33,6 +33,17 @@ */ class Mage_Adminhtml_Customer_GroupController extends Mage_Adminhtml_Controller_Action { + /** + * Controller predispatch method + * + * @return Mage_Adminhtml_Controller_Action + */ + public function preDispatch() + { + $this->_setForcedFormKeyActions('delete'); + return parent::preDispatch(); + } + protected function _initGroup() { $this->_title($this->__('Customers'))->_title($this->__('Customer Groups')); diff --git a/app/code/core/Mage/Adminhtml/controllers/SitemapController.php b/app/code/core/Mage/Adminhtml/controllers/SitemapController.php index 8b817fc1f4..4bb55c8dfa 100644 --- a/app/code/core/Mage/Adminhtml/controllers/SitemapController.php +++ b/app/code/core/Mage/Adminhtml/controllers/SitemapController.php @@ -33,6 +33,17 @@ */ class Mage_Adminhtml_SitemapController extends Mage_Adminhtml_Controller_Action { + /** + * Controller predispatch method + * + * @return Mage_Adminhtml_Controller_Action + */ + public function preDispatch() + { + $this->_setForcedFormKeyActions('delete'); + return parent::preDispatch(); + } + /** * Init actions * diff --git a/app/code/core/Mage/Adminhtml/controllers/System/BackupController.php b/app/code/core/Mage/Adminhtml/controllers/System/BackupController.php index 5e05f4066f..0f2dad07a7 100644 --- a/app/code/core/Mage/Adminhtml/controllers/System/BackupController.php +++ b/app/code/core/Mage/Adminhtml/controllers/System/BackupController.php @@ -369,7 +369,9 @@ public function massDeleteAction() */ protected function _isAllowed() { - return Mage::getSingleton('admin/session')->isAllowed('system/tools/backup' ); + return Mage::getSingleton('admin/session')->isAllowed('system/tools/backup') + && Mage::helper('core')->isModuleEnabled('Mage_Backup') + && !Mage::getStoreConfigFlag('advanced/modules_disable_output/Mage_Backup'); } /** diff --git a/app/code/core/Mage/Captcha/Model/Observer.php b/app/code/core/Mage/Captcha/Model/Observer.php index 4b3e041b8c..a42db5cc53 100644 --- a/app/code/core/Mage/Captcha/Model/Observer.php +++ b/app/code/core/Mage/Captcha/Model/Observer.php @@ -289,4 +289,57 @@ protected function _getCaptchaString($request, $formId) $captchaParams = $request->getPost(Mage_Captcha_Helper_Data::INPUT_NAME_FIELD_VALUE); return $captchaParams[$formId]; } + + /** + * Check Captcha On Share Wishlist Page + * + * @param Varien_Event_Observer $observer + * @return Mage_Captcha_Model_Observer + */ + public function checkWishlistSharing($observer) + { + $formId = 'wishlist_sharing'; + $captchaModel = Mage::helper('captcha')->getCaptcha($formId); + if ($captchaModel->isRequired()) { + $controller = $observer->getControllerAction(); + $request = $controller->getRequest(); + if (!$captchaModel->isCorrect($this->_getCaptchaString($request, $formId))) { + Mage::getSingleton('wishlist/session')->addError(Mage::helper('captcha')->__('Incorrect CAPTCHA.')); + $controller->setFlag('', Mage_Core_Controller_Varien_Action::FLAG_NO_DISPATCH, true); + Mage::getSingleton('wishlist/session')->setSharingForm($request->getPost()); + $wishlistId = (int)$request->getParam('wishlist_id'); + $controller->getResponse() + ->setRedirect(Mage::getUrl('wishlist/index/share/wishlist_id/' . $wishlistId)); + } + } + return $this; + } + + /** + * Check Captcha On Email Product To A Friend Page + * + * @param Varien_Event_Observer $observer + * @return Mage_Captcha_Model_Observer + */ + public function checkSendfriendSend($observer) + { + $formId = 'sendfriend_send'; + $captchaModel = Mage::helper('captcha')->getCaptcha($formId); + if ($captchaModel->isRequired()) { + $controller = $observer->getControllerAction(); + $request = $controller->getRequest(); + if (!$captchaModel->isCorrect($this->_getCaptchaString($request, $formId))) { + Mage::getSingleton('catalog/session')->addError(Mage::helper('captcha')->__('Incorrect CAPTCHA.')); + $controller->setFlag('', Mage_Core_Controller_Varien_Action::FLAG_NO_DISPATCH, true); + Mage::getSingleton('catalog/session')->setFormData($request->getPost()); + $id = (int)$request->getParam('id'); + $catId = $request->getParam('cat_id'); + if (null !== $catId) { + $id .= '/cat_id/' . (int)$catId; + } + $controller->getResponse()->setRedirect(Mage::getUrl('*/*/send/id/' . $id)); + } + } + return $this; + } } diff --git a/app/code/core/Mage/Captcha/Model/Zend.php b/app/code/core/Mage/Captcha/Model/Zend.php index 84a0849aeb..02dedfcbe4 100644 --- a/app/code/core/Mage/Captcha/Model/Zend.php +++ b/app/code/core/Mage/Captcha/Model/Zend.php @@ -116,7 +116,11 @@ public function getBlockName() */ public function isRequired($login = null) { - if ($this->_isUserAuth() || !$this->_isEnabled() || !in_array($this->_formId, $this->_getTargetForms())) { + $nonAuthForms = array('wishlist_sharing', 'sendfriend_send'); + + if ((!in_array($this->_formId, $nonAuthForms) && $this->_isUserAuth()) + || !$this->_isEnabled() || !in_array($this->_formId, $this->_getTargetForms()) + ) { return false; } diff --git a/app/code/core/Mage/Captcha/etc/config.xml b/app/code/core/Mage/Captcha/etc/config.xml index 33392b4db3..8c2ed500e2 100644 --- a/app/code/core/Mage/Captcha/etc/config.xml +++ b/app/code/core/Mage/Captcha/etc/config.xml @@ -78,6 +78,14 @@ + + + + captcha/observer + checkWishlistSharing + + + @@ -122,6 +130,14 @@ + + + + captcha/observer + checkSendfriendSend + + + @@ -206,6 +222,8 @@ 1 1 1 + 1 + 1 @@ -233,6 +251,12 @@ + + + + + + diff --git a/app/code/core/Mage/Catalog/Helper/Product/Flat.php b/app/code/core/Mage/Catalog/Helper/Product/Flat.php index c8e78ea61b..d461b565b6 100644 --- a/app/code/core/Mage/Catalog/Helper/Product/Flat.php +++ b/app/code/core/Mage/Catalog/Helper/Product/Flat.php @@ -80,6 +80,22 @@ class Mage_Catalog_Helper_Product_Flat extends Mage_Catalog_Helper_Flat_Abstract */ protected $_flagObject; + /** + * Catalog Product Flat force status enable/disable + * to force EAV for products in quote + * store settings will be used by default + * + * @var boolean + */ + protected $_forceFlatStatus = false; + + /** + * Old Catalog Product Flat forced status + * + * @var boolean + */ + protected $_forceFlatStatusOld; + /** * Retrieve Catalog Product Flat Flag object * @@ -155,4 +171,40 @@ public function isAddChildData() { return intval(Mage::getConfig()->getNode(self::XML_NODE_ADD_CHILD_DATA)); } + + /** + * Disable Catalog Product Flat + * + * @param $save bool + */ + public function disableFlatCollection($save = false) + { + $this->_forceFlatStatus = true; + + if ($save) { + $this->_forceFlatStatusOld = $this->_forceFlatStatus; + } + } + + /** + * Reset Catalog Product Flat + */ + public function resetFlatCollection() + { + if (isset($this->_forceFlatStatusOld)) { + $this->_forceFlatStatus = $this->_forceFlatStatusOld; + } else { + $this->_forceFlatStatus = false; + } + } + + /** + * Checks if Catalog Product Flat was forced disabled + * + * @return bool + */ + public function isFlatCollectionDisabled() + { + return $this->_forceFlatStatus; + } } diff --git a/app/code/core/Mage/Catalog/Model/Api2/Product/Image/Rest/Admin/V1.php b/app/code/core/Mage/Catalog/Model/Api2/Product/Image/Rest/Admin/V1.php index deb20d3c4a..465b6abd5d 100644 --- a/app/code/core/Mage/Catalog/Model/Api2/Product/Image/Rest/Admin/V1.php +++ b/app/code/core/Mage/Catalog/Model/Api2/Product/Image/Rest/Admin/V1.php @@ -69,7 +69,9 @@ protected function _create(array $data) // try to create Image object to check if image data is valid try { - new Varien_Image($apiTempDir . DS . $imageFileName); + $filePath = $apiTempDir . DS . $imageFileName; + new Varien_Image($filePath); + Mage::getModel('core/file_validator_image')->validate($filePath); } catch (Exception $e) { $ioAdapter->rmdir($apiTempDir, true); $this->_critical($e->getMessage(), Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR); diff --git a/app/code/core/Mage/Catalog/Model/Product.php b/app/code/core/Mage/Catalog/Model/Product.php index f6fe5d5529..294323c46f 100644 --- a/app/code/core/Mage/Catalog/Model/Product.php +++ b/app/code/core/Mage/Catalog/Model/Product.php @@ -2096,4 +2096,19 @@ public function afterCommitCallback() return $this; } + + /** + * Checks event attribute for initialization as an event object + * + * @return bool | Enterprise_CatalogEvent_Model_Event + */ + public function getEvent() + { + $event = parent::getEvent(); + if (is_string($event)) { + $event = false; + } + + return $event; + } } diff --git a/app/code/core/Mage/Catalog/Model/Product/Attribute/Media/Api.php b/app/code/core/Mage/Catalog/Model/Product/Attribute/Media/Api.php index f5c8f900ac..c40cf54715 100644 --- a/app/code/core/Mage/Catalog/Model/Product/Attribute/Media/Api.php +++ b/app/code/core/Mage/Catalog/Model/Product/Attribute/Media/Api.php @@ -155,7 +155,9 @@ public function create($productId, $data, $store = null, $identifierType = null) // try to create Image object - it fails with Exception if image is not supported try { - new Varien_Image($tmpDirectory . DS . $fileName); + $filePath = $tmpDirectory . DS . $fileName; + new Varien_Image($filePath); + Mage::getModel('core/file_validator_image')->validate($filePath); } catch (Exception $e) { // Remove temporary directory $ioAdapter->rmdir($tmpDirectory, true); diff --git a/app/code/core/Mage/Catalog/Model/Resource/Product/Collection.php b/app/code/core/Mage/Catalog/Model/Resource/Product/Collection.php index 45e0b26842..d9957074ba 100644 --- a/app/code/core/Mage/Catalog/Model/Resource/Product/Collection.php +++ b/app/code/core/Mage/Catalog/Model/Resource/Product/Collection.php @@ -330,7 +330,7 @@ public function getFlatHelper() public function isEnabledFlat() { // Flat Data can be used only on frontend - if (Mage::app()->getStore()->isAdmin()) { + if (Mage::app()->getStore()->isAdmin() || $this->getFlatHelper()->isFlatCollectionDisabled()) { return false; } $storeId = $this->getStoreId(); diff --git a/app/code/core/Mage/Checkout/controllers/CartController.php b/app/code/core/Mage/Checkout/controllers/CartController.php index 1b52698b39..28a26479d7 100644 --- a/app/code/core/Mage/Checkout/controllers/CartController.php +++ b/app/code/core/Mage/Checkout/controllers/CartController.php @@ -127,6 +127,7 @@ protected function _initProduct() public function preDispatch() { parent::preDispatch(); + Mage::helper('catalog/product_flat')->disableFlatCollection(true); $cart = $this->_getCart(); if ($cart->getQuote()->getIsMultiShipping()) { diff --git a/app/code/core/Mage/Checkout/controllers/MultishippingController.php b/app/code/core/Mage/Checkout/controllers/MultishippingController.php index ab3e033d24..309578274c 100644 --- a/app/code/core/Mage/Checkout/controllers/MultishippingController.php +++ b/app/code/core/Mage/Checkout/controllers/MultishippingController.php @@ -86,6 +86,9 @@ public function preDispatch() return $this; } + // Disable flat for product collection + Mage::helper('catalog/product_flat')->disableFlatCollection(true); + $action = strtolower($this->getRequest()->getActionName()); $checkoutSessionQuote = $this->_getCheckoutSession()->getQuote(); diff --git a/app/code/core/Mage/Checkout/controllers/OnepageController.php b/app/code/core/Mage/Checkout/controllers/OnepageController.php index 0a7744db93..97f6252731 100644 --- a/app/code/core/Mage/Checkout/controllers/OnepageController.php +++ b/app/code/core/Mage/Checkout/controllers/OnepageController.php @@ -59,6 +59,9 @@ public function preDispatch() parent::preDispatch(); $this->_preDispatchValidateCustomer(); + // Disable flat for product collection + Mage::helper('catalog/product_flat')->disableFlatCollection(true); + $checkoutSessionQuote = Mage::getSingleton('checkout/session')->getQuote(); if ($checkoutSessionQuote->getIsMultiShipping()) { $checkoutSessionQuote->setIsMultiShipping(false); diff --git a/app/code/core/Mage/Cms/Model/Wysiwyg/Images/Storage.php b/app/code/core/Mage/Cms/Model/Wysiwyg/Images/Storage.php index 1407a2860c..8e0ad13f2a 100644 --- a/app/code/core/Mage/Cms/Model/Wysiwyg/Images/Storage.php +++ b/app/code/core/Mage/Cms/Model/Wysiwyg/Images/Storage.php @@ -137,7 +137,9 @@ public function getFilesCollection($path, $type = null) $item->setUrl($helper->getCurrentUrl() . $item->getBasename()); if ($this->isImage($item->getBasename())) { - $thumbUrl = $this->getThumbnailUrl($item->getFilename(), true); + $thumbUrl = $this->getThumbnailUrl( + Mage_Core_Model_File_Uploader::getCorrectFileName($item->getFilename()), + true); // generate thumbnail "on the fly" if it does not exists if(! $thumbUrl) { $thumbUrl = Mage::getSingleton('adminhtml/url')->getUrl('*/*/thumbnail', array('file' => $item->getId())); @@ -386,7 +388,9 @@ public function resizeFile($source, $keepRation = true) $height = $this->getConfigData('resize_height'); $image->keepAspectRatio($keepRation); $image->resize($width, $height); - $dest = $targetDir . DS . pathinfo($source, PATHINFO_BASENAME); + $dest = $targetDir + . DS + . Mage_Core_Model_File_Uploader::getCorrectFileName(pathinfo($source, PATHINFO_BASENAME)); $image->save($dest); if (is_file($dest)) { return $dest; diff --git a/app/code/core/Mage/ConfigurableSwatches/Helper/Productimg.php b/app/code/core/Mage/ConfigurableSwatches/Helper/Productimg.php index fd71520cb3..4db2c44b8b 100644 --- a/app/code/core/Mage/ConfigurableSwatches/Helper/Productimg.php +++ b/app/code/core/Mage/ConfigurableSwatches/Helper/Productimg.php @@ -141,12 +141,12 @@ public function indexProductImages($product, $preValues = null) $swatchLabel = $label . self::SWATCH_LABEL_SUFFIX; $imageKeys[$label] = array_search($label, $imageHaystack); - if ($imageKeys[$label] === false) { + if ($imageKeys[$label] === false && isset($mapping[$label]['default_label'])) { $imageKeys[$label] = array_search($mapping[$label]['default_label'], $imageHaystack); } $imageKeys[$swatchLabel] = array_search($swatchLabel, $imageHaystack); - if ($imageKeys[$swatchLabel] === false) { + if ($imageKeys[$swatchLabel] === false && isset($mapping[$label]['default_label'])) { $imageKeys[$swatchLabel] = array_search( $mapping[$label]['default_label'] . self::SWATCH_LABEL_SUFFIX, $imageHaystack ); diff --git a/app/code/core/Mage/Core/Helper/Data.php b/app/code/core/Mage/Core/Helper/Data.php index 021120dfe5..f55957a721 100644 --- a/app/code/core/Mage/Core/Helper/Data.php +++ b/app/code/core/Mage/Core/Helper/Data.php @@ -651,11 +651,30 @@ public function jsonEncode($valueToEncode, $cycleCheck = false, $options = array * Decodes the given $encodedValue string which is * encoded in the JSON format * + * switch added to prevent exceptions in json_decode + * * @param string $encodedValue * @return mixed */ public function jsonDecode($encodedValue, $objectDecodeType = Zend_Json::TYPE_ARRAY) { + switch (true) { + case (null === $encodedValue): + $encodedValue = 'null'; + break; + case (true === $encodedValue): + $encodedValue = 'true'; + break; + case (false === $encodedValue): + $encodedValue = 'false'; + break; + case ('' === $encodedValue): + $encodedValue = '""'; + break; + default: + // do nothing + } + return Zend_Json::decode($encodedValue, $objectDecodeType); } diff --git a/app/code/core/Mage/Core/Model/Resource/Session.php b/app/code/core/Mage/Core/Model/Resource/Session.php index d5d0ad4962..520fcef21e 100644 --- a/app/code/core/Mage/Core/Model/Resource/Session.php +++ b/app/code/core/Mage/Core/Model/Resource/Session.php @@ -215,7 +215,7 @@ public function read($sessId) $data = $this->_read->fetchOne($select, $bind); - return $data; + return (string)$data; } /** diff --git a/app/code/core/Mage/Core/Model/Session/Abstract/Varien.php b/app/code/core/Mage/Core/Model/Session/Abstract/Varien.php index 490fcda071..33e5a4800f 100644 --- a/app/code/core/Mage/Core/Model/Session/Abstract/Varien.php +++ b/app/code/core/Mage/Core/Model/Session/Abstract/Varien.php @@ -62,7 +62,6 @@ public function start($sessionName=null) * backward compatibility with db argument (option is @deprecated after 1.12.0.2) */ case 'db': - $moduleName = 'user'; /* @var $sessionResource Mage_Core_Model_Resource_Session */ $sessionResource = Mage::getResourceSingleton('core/session'); $sessionResource->setSaveHandler(); @@ -78,9 +77,9 @@ public function start($sessionName=null) } default: session_save_path($this->getSessionSavePath()); + session_module_name($moduleName); break; } - session_module_name($moduleName); $cookie = $this->getCookie(); if (Mage::app()->getStore()->isAdmin()) { diff --git a/app/code/core/Mage/Core/etc/config.xml b/app/code/core/Mage/Core/etc/config.xml index ff8a1477a8..2e5da43aa4 100644 --- a/app/code/core/Mage/Core/etc/config.xml +++ b/app/code/core/Mage/Core/etc/config.xml @@ -28,7 +28,7 @@ - 1.6.0.7 + 1.6.0.8 @@ -428,8 +428,13 @@ - + php + php3 + php4 + php5 + php7 + htaccess @@ -447,6 +452,7 @@ htm html + pht phtml shtml diff --git a/app/code/core/Mage/Core/etc/jstranslator.xml b/app/code/core/Mage/Core/etc/jstranslator.xml index f6c43d3218..dd04c22eea 100644 --- a/app/code/core/Mage/Core/etc/jstranslator.xml +++ b/app/code/core/Mage/Core/etc/jstranslator.xml @@ -54,6 +54,9 @@ Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter. + + Please do not use "event" for an attribute code. + Please use only letters (a-z or A-Z) or numbers (0-9) only in this field. No spaces or other characters are allowed. diff --git a/app/code/core/Mage/Core/functions.php b/app/code/core/Mage/Core/functions.php index f2daa922a7..1bdb70d0a6 100644 --- a/app/code/core/Mage/Core/functions.php +++ b/app/code/core/Mage/Core/functions.php @@ -50,24 +50,6 @@ function mageUndoMagicQuotes($array, $topLevel=true) { $_REQUEST = mageUndoMagicQuotes($_REQUEST); } -/** - * Class autoload - * - * @todo change to spl_autoload_register - * @deprecated - * @param string $class - */ -function __autoload($class) -{ - if (defined('COMPILER_INCLUDE_PATH')) { - $classFile = $class.'.php'; - } else { - $classFile = uc_words($class, DIRECTORY_SEPARATOR).'.php'; - } - - include($classFile); -} - /** * Object destructor * @@ -178,6 +160,11 @@ function mageCoreErrorHandler($errno, $errstr, $errfile, $errline){ define('E_DEPRECATED', 8192); } + // Suppress deprecation warnings on PHP 7.x + if ($errno == E_DEPRECATED && version_compare(PHP_VERSION, '7.0.0', '>=')) { + return true; + } + // PEAR specific message handling if (stripos($errfile.$errstr, 'pear') !== false) { // ignore strict and deprecated notices diff --git a/app/code/core/Mage/Core/sql/core_setup/upgrade-1.6.0.7-1.6.0.8.php b/app/code/core/Mage/Core/sql/core_setup/upgrade-1.6.0.7-1.6.0.8.php new file mode 100644 index 0000000000..f9da012fca --- /dev/null +++ b/app/code/core/Mage/Core/sql/core_setup/upgrade-1.6.0.7-1.6.0.8.php @@ -0,0 +1,41 @@ +startSetup(); +$connection = $installer->getConnection(); + +$connection->delete( + $this->getTable('core_config_data'), + $connection->prepareSqlCondition('path', array( + 'like' => 'system/backup/enabled' + )) +); +$installer->setConfigData('advanced/modules_disable_output/Mage_Backup', 1); + +$installer->endSetup(); diff --git a/app/code/core/Mage/Customer/Model/Customer/Attribute/Source/Group.php b/app/code/core/Mage/Customer/Model/Customer/Attribute/Source/Group.php index 6bc1ac5582..722a69dffb 100644 --- a/app/code/core/Mage/Customer/Model/Customer/Attribute/Source/Group.php +++ b/app/code/core/Mage/Customer/Model/Customer/Attribute/Source/Group.php @@ -33,7 +33,7 @@ */ class Mage_Customer_Model_Customer_Attribute_Source_Group extends Mage_Eav_Model_Entity_Attribute_Source_Table { - public function getAllOptions() + public function getAllOptions($withEmpty = true, $defaultValues = false) { if (!$this->_options) { $this->_options = Mage::getResourceModel('customer/group_collection') diff --git a/app/code/core/Mage/Customer/Model/Customer/Attribute/Source/Store.php b/app/code/core/Mage/Customer/Model/Customer/Attribute/Source/Store.php index 8f22d32aab..e13b6a8645 100644 --- a/app/code/core/Mage/Customer/Model/Customer/Attribute/Source/Store.php +++ b/app/code/core/Mage/Customer/Model/Customer/Attribute/Source/Store.php @@ -33,7 +33,7 @@ */ class Mage_Customer_Model_Customer_Attribute_Source_Store extends Mage_Eav_Model_Entity_Attribute_Source_Table { - public function getAllOptions() + public function getAllOptions($withEmpty = true, $defaultValues = false) { if (!$this->_options) { $collection = Mage::getResourceModel('core/store_collection'); diff --git a/app/code/core/Mage/Customer/Model/Customer/Attribute/Source/Website.php b/app/code/core/Mage/Customer/Model/Customer/Attribute/Source/Website.php index 4bf3be0321..eba5d25919 100644 --- a/app/code/core/Mage/Customer/Model/Customer/Attribute/Source/Website.php +++ b/app/code/core/Mage/Customer/Model/Customer/Attribute/Source/Website.php @@ -33,7 +33,7 @@ */ class Mage_Customer_Model_Customer_Attribute_Source_Website extends Mage_Eav_Model_Entity_Attribute_Source_Table { - public function getAllOptions() + public function getAllOptions($withEmpty = true, $defaultValues = false) { if (!$this->_options) { $this->_options = Mage::getSingleton('adminhtml/system_store')->getWebsiteValuesForForm(true, true); diff --git a/app/code/core/Mage/Customer/Model/Entity/Address/Attribute/Source/Country.php b/app/code/core/Mage/Customer/Model/Entity/Address/Attribute/Source/Country.php index 974092d0e8..ea6e831760 100644 --- a/app/code/core/Mage/Customer/Model/Entity/Address/Attribute/Source/Country.php +++ b/app/code/core/Mage/Customer/Model/Entity/Address/Attribute/Source/Country.php @@ -56,7 +56,7 @@ public function __construct(array $args = array()) * * @return array */ - public function getAllOptions() + public function getAllOptions($withEmpty = true, $defaultValues = false) { if (!$this->_options) { $this->_options = $this->_factory->getResourceModel('directory/country_collection') diff --git a/app/code/core/Mage/Customer/Model/Resource/Address/Attribute/Source/Country.php b/app/code/core/Mage/Customer/Model/Resource/Address/Attribute/Source/Country.php index cb724721ac..8632c8b97b 100644 --- a/app/code/core/Mage/Customer/Model/Resource/Address/Attribute/Source/Country.php +++ b/app/code/core/Mage/Customer/Model/Resource/Address/Attribute/Source/Country.php @@ -39,7 +39,7 @@ class Mage_Customer_Model_Resource_Address_Attribute_Source_Country extends Mage * * @return array */ - public function getAllOptions() + public function getAllOptions($withEmpty = true, $defaultValues = false) { if (!$this->_options) { $this->_options = Mage::getResourceModel('directory/country_collection') diff --git a/app/code/core/Mage/Customer/Model/Resource/Address/Attribute/Source/Region.php b/app/code/core/Mage/Customer/Model/Resource/Address/Attribute/Source/Region.php index 0c19f0266e..15ad619e38 100644 --- a/app/code/core/Mage/Customer/Model/Resource/Address/Attribute/Source/Region.php +++ b/app/code/core/Mage/Customer/Model/Resource/Address/Attribute/Source/Region.php @@ -39,7 +39,7 @@ class Mage_Customer_Model_Resource_Address_Attribute_Source_Region extends Mage_ * * @return array */ - public function getAllOptions() + public function getAllOptions($withEmpty = true, $defaultValues = false) { if (!$this->_options) { $this->_options = Mage::getResourceModel('directory/region_collection')->load()->toOptionArray(); diff --git a/app/code/core/Mage/Dataflow/Model/Convert/Container/Abstract.php b/app/code/core/Mage/Dataflow/Model/Convert/Container/Abstract.php index 17a98b6768..eef2300f16 100644 --- a/app/code/core/Mage/Dataflow/Model/Convert/Container/Abstract.php +++ b/app/code/core/Mage/Dataflow/Model/Convert/Container/Abstract.php @@ -55,7 +55,8 @@ abstract class Mage_Dataflow_Model_Convert_Container_Abstract */ protected function isSerialized($data) { - $pattern = '/^a:\d+:\{(i:\d+;|s:\d+:\".+\";|N;|O:\d+:\"\w+\":\d+:\{\w:\d+:)+|^O:\d+:\"\w+\":\d+:\{s:\d+:\"/'; + $pattern = + '/^a:\d+:\{(i:\d+;|s:\d+:\".+\";|N;|O:\d+:\"\w+\":\d+:\{\w:\d+:)+|^O:\d+:\"\w+\":\d+:\{(s:\d+:\"|i:\d+;)/'; return (is_string($data) && preg_match($pattern, $data)); } @@ -140,7 +141,7 @@ public function validateDataSerialized($data = null) $result = true; if ($this->isSerialized($data)) { try { - $dataArray = Mage::helper('core/unserializeArray')->unserialize($data); + Mage::helper('core/unserializeArray')->unserialize($data); } catch (Exception $e) { $result = false; $this->addException( diff --git a/app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Store.php b/app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Store.php index 43336bef40..e9d1b95311 100644 --- a/app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Store.php +++ b/app/code/core/Mage/Eav/Model/Entity/Attribute/Source/Store.php @@ -38,7 +38,7 @@ class Mage_Eav_Model_Entity_Attribute_Source_Store extends Mage_Eav_Model_Entity * * @return array */ - public function getAllOptions() + public function getAllOptions($withEmpty = true, $defaultValues = false) { if ($this->_options === null) { $this->_options = Mage::getResourceModel('core/store_collection')->load()->toOptionArray(); diff --git a/app/code/core/Mage/ImportExport/Model/Export/Entity/Customer.php b/app/code/core/Mage/ImportExport/Model/Export/Entity/Customer.php index b595aaae56..36f7d77add 100644 --- a/app/code/core/Mage/ImportExport/Model/Export/Entity/Customer.php +++ b/app/code/core/Mage/ImportExport/Model/Export/Entity/Customer.php @@ -423,7 +423,9 @@ protected function _prepareExportRow($customer, &$attributeMultiSelect) $row[$attrCode] = $attrValue; } } - $row[self::COL_WEBSITE] = $this->_websiteIdToCode[$customer['website_id']]; + $row[self::COL_WEBSITE] = $this->_websiteIdToCode[ + $customer['website_id'] === null ? 0 : $customer['website_id'] + ]; $row[self::COL_STORE] = $this->_storeIdToCode[$customer['store_id']]; return $row; diff --git a/app/code/core/Mage/ImportExport/Model/Export/Entity/Product.php b/app/code/core/Mage/ImportExport/Model/Export/Entity/Product.php index 6d504f4c1e..ac40f159d1 100644 --- a/app/code/core/Mage/ImportExport/Model/Export/Entity/Product.php +++ b/app/code/core/Mage/ImportExport/Model/Export/Entity/Product.php @@ -594,6 +594,7 @@ protected function _prepareExport() $memoryLimit = trim(ini_get('memory_limit')); $lastMemoryLimitLetter = strtolower($memoryLimit[strlen($memoryLimit)-1]); + $memoryLimit = (int) filter_var($memoryLimit, FILTER_SANITIZE_NUMBER_INT); switch($lastMemoryLimitLetter) { case 'g': $memoryLimit *= 1024; @@ -918,22 +919,16 @@ protected function _prepareExport() '_media_lable', '_media_position', '_media_is_disabled' + ), + $customOptCols, + array( + '_super_products_sku', + '_super_attribute_code', + '_super_attribute_option', + '_super_attribute_price_corr' ) ); - // have we merge custom options columns - if ($customOptionsData) { - $headerCols = array_merge($headerCols, $customOptCols); - } - - // have we merge configurable products data - if ($configurableData) { - $headerCols = array_merge($headerCols, array( - '_super_products_sku', '_super_attribute_code', - '_super_attribute_option', '_super_attribute_price_corr' - )); - } - $writer->setHeaderCols($headerCols); } diff --git a/app/code/core/Mage/ImportExport/Model/Import/Entity/Customer.php b/app/code/core/Mage/ImportExport/Model/Import/Entity/Customer.php index 75fa560120..2ebff1b466 100644 --- a/app/code/core/Mage/ImportExport/Model/Import/Entity/Customer.php +++ b/app/code/core/Mage/ImportExport/Model/Import/Entity/Customer.php @@ -289,7 +289,9 @@ protected function _initAttributes() 'id' => $attribute->getId(), 'is_required' => $attribute->getIsRequired(), 'is_static' => $attribute->isStatic(), - 'rules' => $attribute->getValidateRules() ? unserialize($attribute->getValidateRules()) : null, + 'rules' => $attribute->getValidateRules() + ? Mage::helper('core/unserializeArray')->unserialize($attribute->getValidateRules()) + : null, 'type' => Mage_ImportExport_Model_Import::getAttributeType($attribute), 'options' => $this->getAttributeOptions($attribute) ); diff --git a/app/code/core/Mage/ImportExport/Model/Import/Entity/Customer/Address.php b/app/code/core/Mage/ImportExport/Model/Import/Entity/Customer/Address.php index 346e9e5742..3c17249cd2 100644 --- a/app/code/core/Mage/ImportExport/Model/Import/Entity/Customer/Address.php +++ b/app/code/core/Mage/ImportExport/Model/Import/Entity/Customer/Address.php @@ -303,7 +303,9 @@ protected function _initAttributes() 'code' => $attribute->getAttributeCode(), 'table' => $attribute->getBackend()->getTable(), 'is_required' => $attribute->getIsRequired(), - 'rules' => $attribute->getValidateRules() ? unserialize($attribute->getValidateRules()) : null, + 'rules' => $attribute->getValidateRules() + ? Mage::helper('core/unserializeArray')->unserialize($attribute->getValidateRules()) + : null, 'type' => Mage_ImportExport_Model_Import::getAttributeType($attribute), 'options' => $this->getAttributeOptions($attribute) ); diff --git a/app/code/core/Mage/Index/Model/Process.php b/app/code/core/Mage/Index/Model/Process.php index 0c2a7909e6..d344dcfd2e 100644 --- a/app/code/core/Mage/Index/Model/Process.php +++ b/app/code/core/Mage/Index/Model/Process.php @@ -442,7 +442,7 @@ protected function _getLockInstance() */ public function lock() { - $this->_getLockInstance()->setLock($this->getProcessLockName(), $this->getData('use_file_lock')); + $this->_getLockInstance()->setLock($this->getProcessLockName(), true); return $this; } @@ -455,7 +455,7 @@ public function lock() */ public function lockAndBlock() { - $this->_getLockInstance()->setLock($this->getProcessLockName(), $this->getData('use_file_lock'), true); + $this->_getLockInstance()->setLock($this->getProcessLockName(), true, true); return $this; } @@ -466,7 +466,7 @@ public function lockAndBlock() */ public function unlock() { - $this->_getLockInstance()->releaseLock($this->getProcessLockName(), $this->getData('use_file_lock')); + $this->_getLockInstance()->releaseLock($this->getProcessLockName(), true); return $this; } @@ -477,7 +477,7 @@ public function unlock() */ public function isLocked() { - return $this->_getLockInstance()->isLockExists($this->getProcessLockName(), $this->getData('use_file_lock')); + return $this->_getLockInstance()->isLockExists($this->getProcessLockName(), true); } /** diff --git a/app/code/core/Mage/Install/etc/install.xml b/app/code/core/Mage/Install/etc/install.xml index 1088acd5bf..e347021b11 100644 --- a/app/code/core/Mage/Install/etc/install.xml +++ b/app/code/core/Mage/Install/etc/install.xml @@ -88,6 +88,10 @@ + + + + diff --git a/app/code/core/Mage/Payment/etc/config.xml b/app/code/core/Mage/Payment/etc/config.xml index 0fa1396c88..18eca28e7c 100644 --- a/app/code/core/Mage/Payment/etc/config.xml +++ b/app/code/core/Mage/Payment/etc/config.xml @@ -28,7 +28,7 @@ - 1.6.0.0 + 1.6.0.1 @@ -36,6 +36,9 @@ Mage_Payment_Model + + Mage_Core_Model_Resource + @@ -166,15 +169,6 @@ - - 1 - AE,VI,MC,DI - payment/method_ccsave - pending - Credit Card (saved) - 0 - offline - 1 payment/method_checkmo diff --git a/app/code/core/Mage/Payment/etc/system.xml b/app/code/core/Mage/Payment/etc/system.xml index 7ff6f25e10..101bae7bf9 100644 --- a/app/code/core/Mage/Payment/etc/system.xml +++ b/app/code/core/Mage/Payment/etc/system.xml @@ -36,140 +36,6 @@ 1 1 - - - text - 27 - 1 - 1 - 1 - - - - select - adminhtml/system_config_source_yesno - 1 - 1 - 1 - 0 - - - - multiselect - adminhtml/system_config_source_payment_cctype - 4 - 1 - 1 - 0 - 1 - - - - select - adminhtml/system_config_source_order_status_new - 2 - 1 - 1 - 0 - - - - text - 100 - 1 - 1 - 0 - validate-number - - - <label>Title</label> - <frontend_type>text</frontend_type> - <sort_order>1</sort_order> - <show_in_default>1</show_in_default> - <show_in_website>1</show_in_website> - <show_in_store>1</show_in_store> - - - - select - adminhtml/system_config_source_yesno - 5 - 1 - 1 - 0 - - - - - select - adminhtml/system_config_source_yesno - 20 - 1 - 1 - 0 - - - - Severe validation removes chargeback liability on merchant. - select - adminhtml/system_config_source_yesno - 25 - 1 - 1 - 0 - 1 - - - - A value is required for live mode. Refer to your CardinalCommerce agreement. - text - adminhtml/system_config_source_yesno - 30 - 1 - 1 - 0 - 1 - - - - - allowspecific - 50 - adminhtml/system_config_source_payment_allspecificcountries - 1 - 1 - 0 - - - - multiselect - 51 - adminhtml/system_config_source_country - 1 - 1 - 0 - 1 - - - - text - 98 - 1 - 1 - 0 - - - - text - 99 - 1 - 1 - 0 - - - - - text diff --git a/app/code/core/Mage/Payment/sql/payment_setup/upgrade-1.6.0.0-1.6.0.1.php b/app/code/core/Mage/Payment/sql/payment_setup/upgrade-1.6.0.0-1.6.0.1.php new file mode 100644 index 0000000000..37eaac6201 --- /dev/null +++ b/app/code/core/Mage/Payment/sql/payment_setup/upgrade-1.6.0.0-1.6.0.1.php @@ -0,0 +1,40 @@ +startSetup(); +$connection = $installer->getConnection(); + +$connection->delete( + $this->getTable('core_config_data'), + $connection->prepareSqlCondition('path', array( + 'like' => 'payment/ccsave/active' + )) +); + +$installer->endSetup(); diff --git a/app/code/core/Mage/Sales/Model/Resource/Quote/Item/Collection.php b/app/code/core/Mage/Sales/Model/Resource/Quote/Item/Collection.php index c1e5603d05..c85693c734 100644 --- a/app/code/core/Mage/Sales/Model/Resource/Quote/Item/Collection.php +++ b/app/code/core/Mage/Sales/Model/Resource/Quote/Item/Collection.php @@ -169,6 +169,9 @@ protected function _assignOptions() protected function _assignProducts() { Varien_Profiler::start('QUOTE:'.__METHOD__); + $productFlatHelper = Mage::helper('catalog/product_flat'); + $productFlatHelper->disableFlatCollection(); + $productIds = array(); foreach ($this as $item) { $productIds[] = (int)$item->getProductId(); @@ -234,8 +237,9 @@ protected function _assignProducts() if ($recollectQuote && $this->_quote) { $this->_quote->collectTotals(); } - Varien_Profiler::stop('QUOTE:'.__METHOD__); + $productFlatHelper->resetFlatCollection(); + Varien_Profiler::stop('QUOTE:'.__METHOD__); return $this; } } diff --git a/app/code/core/Mage/Sales/etc/config.xml b/app/code/core/Mage/Sales/etc/config.xml index 6f3d023515..5f86f21715 100644 --- a/app/code/core/Mage/Sales/etc/config.xml +++ b/app/code/core/Mage/Sales/etc/config.xml @@ -1218,7 +1218,7 @@ sales/quote_address_total_shipping - subtotal,freeshipping,tax_subtotal + subtotal,freeshipping,tax_subtotal,msrp grand_total @@ -1227,6 +1227,7 @@ sales/quote_address_total_msrp + grand_total diff --git a/app/code/core/Mage/Sendfriend/Block/Send.php b/app/code/core/Mage/Sendfriend/Block/Send.php index 0850a678a1..a7a5456aa5 100644 --- a/app/code/core/Mage/Sendfriend/Block/Send.php +++ b/app/code/core/Mage/Sendfriend/Block/Send.php @@ -97,7 +97,11 @@ public function getFormData() { $data = $this->getData('form_data'); if (!$data instanceof Varien_Object) { + $formData = Mage::getSingleton('catalog/session')->getFormData(true); $data = new Varien_Object(); + if ($formData) { + $data->addData($formData); + } $this->setData('form_data', $data); } @@ -149,6 +153,17 @@ public function getMaxRecipients() return Mage::helper('sendfriend')->getMaxRecipients(); } + /** + * Retrieve count of recipients + * + * @return int + */ + public function getRecipientsCount() + { + $recipientsEmail = $this->getFormData()->getData('recipients/email'); + return (is_array($recipientsEmail)) ? count($recipientsEmail) : 0; + } + /** * Retrieve Send URL for Form Action * diff --git a/app/code/core/Mage/Shipping/Model/Carrier/Abstract.php b/app/code/core/Mage/Shipping/Model/Carrier/Abstract.php index 2015b0bd6e..95e0c57fbf 100644 --- a/app/code/core/Mage/Shipping/Model/Carrier/Abstract.php +++ b/app/code/core/Mage/Shipping/Model/Carrier/Abstract.php @@ -417,7 +417,7 @@ public function getMethodPrice($cost, $method = '') */ public function getFinalPriceWithHandlingFee($cost) { - $handlingFee = $this->getConfigData('handling_fee'); + $handlingFee = (float)$this->getConfigData('handling_fee'); $handlingType = $this->getConfigData('handling_type'); if (!$handlingType) { $handlingType = self::HANDLING_TYPE_FIXED; diff --git a/app/code/core/Mage/Shipping/Model/Carrier/Flatrate.php b/app/code/core/Mage/Shipping/Model/Carrier/Flatrate.php index 9a1fae3382..a9e39d85ac 100644 --- a/app/code/core/Mage/Shipping/Model/Carrier/Flatrate.php +++ b/app/code/core/Mage/Shipping/Model/Carrier/Flatrate.php @@ -74,11 +74,12 @@ public function collectRates(Mage_Shipping_Model_Rate_Request $request) $this->setFreeBoxes($freeBoxes); $result = Mage::getModel('shipping/rate_result'); - if ($this->getConfigData('type') == 'O') { // per order - $shippingPrice = $this->getConfigData('price'); - } elseif ($this->getConfigData('type') == 'I') { // per item - $shippingPrice = ($request->getPackageQty() * $this->getConfigData('price')) - ($this->getFreeBoxes() * $this->getConfigData('price')); - } else { + + $shippingType = $this->getConfigData('type'); + $shippingPrice = (float)$this->getConfigData('price'); + if ('I' == $shippingType) { // per item + $shippingPrice = ($request->getPackageQty() * $shippingPrice) - ($this->getFreeBoxes() * $shippingPrice); + } elseif ('O' != $shippingType) { // not per order $shippingPrice = false; } diff --git a/app/code/core/Mage/Tax/Model/Resource/Calculation.php b/app/code/core/Mage/Tax/Model/Resource/Calculation.php index fe0e89c0a4..49294b590c 100644 --- a/app/code/core/Mage/Tax/Model/Resource/Calculation.php +++ b/app/code/core/Mage/Tax/Model/Resource/Calculation.php @@ -164,14 +164,15 @@ public function getCalculationProcess($request, $rates = null) } $row['rates'][] = $oneRate; + $ruleId = null; if (isset($rates[$i + 1]['tax_calculation_rule_id'])) { - $rule = $rate['tax_calculation_rule_id']; + $ruleId = $rate['tax_calculation_rule_id']; } $priority = $rate['priority']; $ids[] = $rate['code']; if (isset($rates[$i + 1]['tax_calculation_rule_id'])) { - while (isset($rates[$i + 1]) && $rates[$i + 1]['tax_calculation_rule_id'] == $rule) { + while (isset($rates[$i + 1]) && $rates[$i + 1]['tax_calculation_rule_id'] == $ruleId) { $i++; } } @@ -188,7 +189,7 @@ public function getCalculationProcess($request, $rates = null) $row['percent'] = $this->_collectPercent($totalPercent, $currentRate); $totalPercent += $row['percent']; } - $row['id'] = implode($ids); + $row['id'] = implode('', $ids); $result[] = $row; $row = array(); $ids = array(); @@ -251,7 +252,7 @@ protected function _getRates($request) $customerClassId = $request->getCustomerClassId(); $countryId = $request->getCountryId(); $regionId = $request->getRegionId(); - $postcode = $request->getPostcode(); + $postcode = trim($request->getPostcode()); // Process productClassId as it can be array or usual value. Form best key for cache. $productClassId = $request->getProductClassId(); @@ -311,10 +312,15 @@ protected function _getRates($request) ->where('rate.tax_country_id = ?', $countryId) ->where("rate.tax_region_id IN(?)", array(0, (int)$regionId)); $postcodeIsNumeric = is_numeric($postcode); - $postcodeIsRange = is_string($postcode) && preg_match('/^(.+)-(.+)$/', $postcode, $matches); - if ($postcodeIsRange) { - $zipFrom = $matches[1]; - $zipTo = $matches[2]; + $postcodeIsRange = false; + if (is_string($postcode) && preg_match('/^(.+)-(.+)$/', $postcode, $matches)) { + if (is_numeric($matches[2]) && strlen($matches[2]) < 5) { + $postcodeIsNumeric = true; + } else { + $postcodeIsRange = true; + $zipFrom = $matches[1]; + $zipTo = $matches[2]; + } } if ($postcodeIsNumeric || $postcodeIsRange) { diff --git a/app/code/core/Mage/Wishlist/Model/Observer.php b/app/code/core/Mage/Wishlist/Model/Observer.php index 7aff05fdb3..cc5759d2f9 100644 --- a/app/code/core/Mage/Wishlist/Model/Observer.php +++ b/app/code/core/Mage/Wishlist/Model/Observer.php @@ -102,7 +102,7 @@ public function processAddToCart($observer) $wishlistIds = array($singleWishlistId); } - if (count($wishlistIds) && $request->getParam('wishlist_next')){ + if (empty($wishlistIds) && $request->getParam('wishlist_next')){ $wishlistId = array_shift($wishlistIds); if (Mage::getSingleton('customer/session')->isLoggedIn()) { @@ -125,7 +125,7 @@ public function processAddToCart($observer) Mage::getSingleton('checkout/session')->setSingleWishlistId(null); } - if ($request->getParam('wishlist_next') && count($urls)) { + if ($request->getParam('wishlist_next') && empty($urls)) { $url = array_shift($urls); $message = array_shift($messages); diff --git a/app/code/core/Mage/Wishlist/controllers/IndexController.php b/app/code/core/Mage/Wishlist/controllers/IndexController.php index 4d95856cd2..926adb3332 100644 --- a/app/code/core/Mage/Wishlist/controllers/IndexController.php +++ b/app/code/core/Mage/Wishlist/controllers/IndexController.php @@ -637,6 +637,9 @@ public function sendAction() if (empty($emails)) { $error = $this->__('Email address can\'t be empty.'); } + elseif (count($emails) > 5) { + $error = $this->__('Please enter no more than 5 email addresses.'); + } else { foreach ($emails as $index => $email) { $email = trim($email); diff --git a/app/code/core/Zend/Controller/Request/Http.php b/app/code/core/Zend/Controller/Request/Http.php new file mode 100644 index 0000000000..ac4eae6a60 --- /dev/null +++ b/app/code/core/Zend/Controller/Request/Http.php @@ -0,0 +1,1088 @@ +valid()) { + $path = $uri->getPath(); + $query = $uri->getQuery(); + if (!empty($query)) { + $path .= '?' . $query; + } + + $this->setRequestUri($path); + } else { + #require_once 'Zend/Controller/Request/Exception.php'; + throw new Zend_Controller_Request_Exception('Invalid URI provided to constructor'); + } + } else { + $this->setRequestUri(); + } + } + + /** + * Access values contained in the superglobals as public members + * Order of precedence: 1. GET, 2. POST, 3. COOKIE, 4. SERVER, 5. ENV + * + * @see http://msdn.microsoft.com/en-us/library/system.web.httprequest.item.aspx + * @param string $key + * @return mixed + */ + public function __get($key) + { + switch (true) { + case isset($this->_params[$key]): + return $this->_params[$key]; + case isset($_GET[$key]): + return $_GET[$key]; + case isset($_POST[$key]): + return $_POST[$key]; + case isset($_COOKIE[$key]): + return $_COOKIE[$key]; + case ($key == 'REQUEST_URI'): + return $this->getRequestUri(); + case ($key == 'PATH_INFO'): + return $this->getPathInfo(); + case isset($_SERVER[$key]): + return $_SERVER[$key]; + case isset($_ENV[$key]): + return $_ENV[$key]; + default: + return null; + } + } + + /** + * Alias to __get + * + * @param string $key + * @return mixed + */ + public function get($key) + { + return $this->__get($key); + } + + /** + * Set values + * + * In order to follow {@link __get()}, which operates on a number of + * superglobals, setting values through overloading is not allowed and will + * raise an exception. Use setParam() instead. + * + * @param string $key + * @param mixed $value + * @return void + * @throws Zend_Controller_Request_Exception + */ + public function __set($key, $value) + { + #require_once 'Zend/Controller/Request/Exception.php'; + throw new Zend_Controller_Request_Exception('Setting values in superglobals not allowed; please use setParam()'); + } + + /** + * Alias to __set() + * + * @param string $key + * @param mixed $value + * @return void + */ + public function set($key, $value) + { + return $this->__set($key, $value); + } + + /** + * Check to see if a property is set + * + * @param string $key + * @return boolean + */ + public function __isset($key) + { + switch (true) { + case isset($this->_params[$key]): + return true; + case isset($_GET[$key]): + return true; + case isset($_POST[$key]): + return true; + case isset($_COOKIE[$key]): + return true; + case isset($_SERVER[$key]): + return true; + case isset($_ENV[$key]): + return true; + default: + return false; + } + } + + /** + * Alias to __isset() + * + * @param string $key + * @return boolean + */ + public function has($key) + { + return $this->__isset($key); + } + + /** + * Set GET values + * + * @param string|array $spec + * @param null|mixed $value + * @return Zend_Controller_Request_Http + */ + public function setQuery($spec, $value = null) + { + if ((null === $value) && !is_array($spec)) { + #require_once 'Zend/Controller/Exception.php'; + throw new Zend_Controller_Exception('Invalid value passed to setQuery(); must be either array of values or key/value pair'); + } + if ((null === $value) && is_array($spec)) { + foreach ($spec as $key => $value) { + $this->setQuery($key, $value); + } + return $this; + } + $_GET[(string) $spec] = $value; + return $this; + } + + /** + * Retrieve a member of the $_GET superglobal + * + * If no $key is passed, returns the entire $_GET array. + * + * @todo How to retrieve from nested arrays + * @param string $key + * @param mixed $default Default value to use if key not found + * @return mixed Returns null if key does not exist + */ + public function getQuery($key = null, $default = null) + { + if (null === $key) { + return $_GET; + } + + return (isset($_GET[$key])) ? $_GET[$key] : $default; + } + + /** + * Set POST values + * + * @param string|array $spec + * @param null|mixed $value + * @return Zend_Controller_Request_Http + */ + public function setPost($spec, $value = null) + { + if ((null === $value) && !is_array($spec)) { + #require_once 'Zend/Controller/Exception.php'; + throw new Zend_Controller_Exception('Invalid value passed to setPost(); must be either array of values or key/value pair'); + } + if ((null === $value) && is_array($spec)) { + foreach ($spec as $key => $value) { + $this->setPost($key, $value); + } + return $this; + } + $_POST[(string) $spec] = $value; + return $this; + } + + /** + * Retrieve a member of the $_POST superglobal + * + * If no $key is passed, returns the entire $_POST array. + * + * @todo How to retrieve from nested arrays + * @param string $key + * @param mixed $default Default value to use if key not found + * @return mixed Returns null if key does not exist + */ + public function getPost($key = null, $default = null) + { + if (null === $key) { + return $_POST; + } + + return (isset($_POST[$key])) ? $_POST[$key] : $default; + } + + /** + * Retrieve a member of the $_COOKIE superglobal + * + * If no $key is passed, returns the entire $_COOKIE array. + * + * @todo How to retrieve from nested arrays + * @param string $key + * @param mixed $default Default value to use if key not found + * @return mixed Returns null if key does not exist + */ + public function getCookie($key = null, $default = null) + { + if (null === $key) { + return $_COOKIE; + } + + return (isset($_COOKIE[$key])) ? $_COOKIE[$key] : $default; + } + + /** + * Retrieve a member of the $_SERVER superglobal + * + * If no $key is passed, returns the entire $_SERVER array. + * + * @param string $key + * @param mixed $default Default value to use if key not found + * @return mixed Returns null if key does not exist + */ + public function getServer($key = null, $default = null) + { + if (null === $key) { + return $_SERVER; + } + + return (isset($_SERVER[$key])) ? $_SERVER[$key] : $default; + } + + /** + * Retrieve a member of the $_ENV superglobal + * + * If no $key is passed, returns the entire $_ENV array. + * + * @param string $key + * @param mixed $default Default value to use if key not found + * @return mixed Returns null if key does not exist + */ + public function getEnv($key = null, $default = null) + { + if (null === $key) { + return $_ENV; + } + + return (isset($_ENV[$key])) ? $_ENV[$key] : $default; + } + + /** + * Set the REQUEST_URI on which the instance operates + * + * If no request URI is passed, uses the value in $_SERVER['REQUEST_URI'], + * $_SERVER['HTTP_X_REWRITE_URL'], or $_SERVER['ORIG_PATH_INFO'] + $_SERVER['QUERY_STRING']. + * + * @param string $requestUri + * @return Zend_Controller_Request_Http + */ + public function setRequestUri($requestUri = null) + { + if ($requestUri === null) { + if ( + // IIS7 with URL Rewrite: make sure we get the unencoded url (double slash problem) + isset($_SERVER['IIS_WasUrlRewritten']) + && $_SERVER['IIS_WasUrlRewritten'] == '1' + && isset($_SERVER['UNENCODED_URL']) + && $_SERVER['UNENCODED_URL'] != '' + ) { + $requestUri = $_SERVER['UNENCODED_URL']; + } elseif (isset($_SERVER['REQUEST_URI'])) { + $requestUri = $_SERVER['REQUEST_URI']; + // Http proxy reqs setup request uri with scheme and host [and port] + the url path, only use url path + $schemeAndHttpHost = $this->getScheme() . '://' . $this->getHttpHost(); + if (strpos($requestUri, $schemeAndHttpHost) === 0) { + $requestUri = substr($requestUri, strlen($schemeAndHttpHost)); + } + } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0, PHP as CGI + $requestUri = $_SERVER['ORIG_PATH_INFO']; + if (!empty($_SERVER['QUERY_STRING'])) { + $requestUri .= '?' . $_SERVER['QUERY_STRING']; + } + } else { + return $this; + } + } elseif (!is_string($requestUri)) { + return $this; + } else { + // Set GET items, if available + if (false !== ($pos = strpos($requestUri, '?'))) { + // Get key => value pairs and set $_GET + $query = substr($requestUri, $pos + 1); + parse_str($query, $vars); + $this->setQuery($vars); + } + } + + $this->_requestUri = $requestUri; + return $this; + } + + /** + * Returns the REQUEST_URI taking into account + * platform differences between Apache and IIS + * + * @return string + */ + public function getRequestUri() + { + if (empty($this->_requestUri)) { + $this->setRequestUri(); + } + + return $this->_requestUri; + } + + /** + * Set the base URL of the request; i.e., the segment leading to the script name + * + * E.g.: + * - /admin + * - /myapp + * - /subdir/index.php + * + * Do not use the full URI when providing the base. The following are + * examples of what not to use: + * - http://example.com/admin (should be just /admin) + * - http://example.com/subdir/index.php (should be just /subdir/index.php) + * + * If no $baseUrl is provided, attempts to determine the base URL from the + * environment, using SCRIPT_FILENAME, SCRIPT_NAME, PHP_SELF, and + * ORIG_SCRIPT_NAME in its determination. + * + * @param mixed $baseUrl + * @return Zend_Controller_Request_Http + */ + public function setBaseUrl($baseUrl = null) + { + if ((null !== $baseUrl) && !is_string($baseUrl)) { + return $this; + } + + if ($baseUrl === null) { + $filename = (isset($_SERVER['SCRIPT_FILENAME'])) ? basename($_SERVER['SCRIPT_FILENAME']) : ''; + + if (isset($_SERVER['SCRIPT_NAME']) && basename($_SERVER['SCRIPT_NAME']) === $filename) { + $baseUrl = $_SERVER['SCRIPT_NAME']; + } elseif (isset($_SERVER['PHP_SELF']) && basename($_SERVER['PHP_SELF']) === $filename) { + $baseUrl = $_SERVER['PHP_SELF']; + } elseif (isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME']) === $filename) { + $baseUrl = $_SERVER['ORIG_SCRIPT_NAME']; // 1and1 shared hosting compatibility + } else { + // Backtrack up the script_filename to find the portion matching + // php_self + $path = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : ''; + $file = isset($_SERVER['SCRIPT_FILENAME']) ? $_SERVER['SCRIPT_FILENAME'] : ''; + $segs = explode('/', trim($file, '/')); + $segs = array_reverse($segs); + $index = 0; + $last = count($segs); + $baseUrl = ''; + do { + $seg = $segs[$index]; + $baseUrl = '/' . $seg . $baseUrl; + ++$index; + } while (($last > $index) && (false !== ($pos = strpos($path, $baseUrl))) && (0 != $pos)); + } + + // Does the baseUrl have anything in common with the request_uri? + $requestUri = $this->getRequestUri(); + + if (0 === strpos($requestUri, $baseUrl)) { + // full $baseUrl matches + $this->_baseUrl = $baseUrl; + return $this; + } + + if (0 === strpos($requestUri, dirname($baseUrl))) { + // directory portion of $baseUrl matches + $this->_baseUrl = rtrim(dirname($baseUrl), '/'); + return $this; + } + + $truncatedRequestUri = $requestUri; + if (($pos = strpos($requestUri, '?')) !== false) { + $truncatedRequestUri = substr($requestUri, 0, $pos); + } + + $basename = basename($baseUrl); + if (empty($basename) || !strpos($truncatedRequestUri, $basename)) { + // no match whatsoever; set it blank + $this->_baseUrl = ''; + return $this; + } + + // If using mod_rewrite or ISAPI_Rewrite strip the script filename + // out of baseUrl. $pos !== 0 makes sure it is not matching a value + // from PATH_INFO or QUERY_STRING + if ((strlen($requestUri) >= strlen($baseUrl)) + && ((false !== ($pos = strpos($requestUri, $baseUrl))) && ($pos !== 0))) + { + $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl)); + } + } + + $this->_baseUrl = rtrim($baseUrl, '/'); + return $this; + } + + /** + * Everything in REQUEST_URI before PATH_INFO + *
+ * + * @return string + */ + public function getBaseUrl($raw = false) + { + if (null === $this->_baseUrl) { + $this->setBaseUrl(); + } + + return (($raw == false) ? urldecode($this->_baseUrl) : $this->_baseUrl); + } + + /** + * Set the base path for the URL + * + * @param string|null $basePath + * @return Zend_Controller_Request_Http + */ + public function setBasePath($basePath = null) + { + if ($basePath === null) { + $filename = (isset($_SERVER['SCRIPT_FILENAME'])) + ? basename($_SERVER['SCRIPT_FILENAME']) + : ''; + + $baseUrl = $this->getBaseUrl(); + if (empty($baseUrl)) { + $this->_basePath = ''; + return $this; + } + + if (basename($baseUrl) === $filename) { + $basePath = dirname($baseUrl); + } else { + $basePath = $baseUrl; + } + } + + if (substr(PHP_OS, 0, 3) === 'WIN') { + $basePath = str_replace('\\', '/', $basePath); + } + + $this->_basePath = rtrim($basePath, '/'); + return $this; + } + + /** + * Everything in REQUEST_URI before PATH_INFO not including the filename + * + * + * @return string + */ + public function getBasePath() + { + if (null === $this->_basePath) { + $this->setBasePath(); + } + + return $this->_basePath; + } + + /** + * Set the PATH_INFO string + * + * @param string|null $pathInfo + * @return Zend_Controller_Request_Http + */ + public function setPathInfo($pathInfo = null) + { + if ($pathInfo === null) { + $baseUrl = $this->getBaseUrl(); // this actually calls setBaseUrl() & setRequestUri() + $baseUrlRaw = $this->getBaseUrl(false); + $baseUrlEncoded = urlencode($baseUrlRaw); + + if (null === ($requestUri = $this->getRequestUri())) { + return $this; + } + + // Remove the query string from REQUEST_URI + if ($pos = strpos($requestUri, '?')) { + $requestUri = substr($requestUri, 0, $pos); + } + + if (!empty($baseUrl) || !empty($baseUrlRaw)) { + if (strpos($requestUri, $baseUrl) === 0) { + $pathInfo = substr($requestUri, strlen($baseUrl)); + } elseif (strpos($requestUri, $baseUrlRaw) === 0) { + $pathInfo = substr($requestUri, strlen($baseUrlRaw)); + } elseif (strpos($requestUri, $baseUrlEncoded) === 0) { + $pathInfo = substr($requestUri, strlen($baseUrlEncoded)); + } else { + $pathInfo = $requestUri; + } + } else { + $pathInfo = $requestUri; + } + + } + + $this->_pathInfo = (string) $pathInfo; + return $this; + } + + /** + * Returns everything between the BaseUrl and QueryString. + * This value is calculated instead of reading PATH_INFO + * directly from $_SERVER due to cross-platform differences. + * + * @return string + */ + public function getPathInfo() + { + if (empty($this->_pathInfo)) { + $this->setPathInfo(); + } + + return $this->_pathInfo; + } + + /** + * Set allowed parameter sources + * + * Can be empty array, or contain one or more of '_GET' or '_POST'. + * + * @param array $paramSoures + * @return Zend_Controller_Request_Http + */ + public function setParamSources(array $paramSources = array()) + { + $this->_paramSources = $paramSources; + return $this; + } + + /** + * Get list of allowed parameter sources + * + * @return array + */ + public function getParamSources() + { + return $this->_paramSources; + } + + /** + * Set a userland parameter + * + * Uses $key to set a userland parameter. If $key is an alias, the actual + * key will be retrieved and used to set the parameter. + * + * @param mixed $key + * @param mixed $value + * @return Zend_Controller_Request_Http + */ + public function setParam($key, $value) + { + $key = (null !== ($alias = $this->getAlias($key))) ? $alias : $key; + parent::setParam($key, $value); + return $this; + } + + /** + * Retrieve a parameter + * + * Retrieves a parameter from the instance. Priority is in the order of + * userland parameters (see {@link setParam()}), $_GET, $_POST. If a + * parameter matching the $key is not found, null is returned. + * + * If the $key is an alias, the actual key aliased will be used. + * + * @param mixed $key + * @param mixed $default Default value to use if key not found + * @return mixed + */ + public function getParam($key, $default = null) + { + $keyName = (null !== ($alias = $this->getAlias($key))) ? $alias : $key; + + $paramSources = $this->getParamSources(); + if (isset($this->_params[$keyName])) { + return $this->_params[$keyName]; + } elseif (in_array('_GET', $paramSources) && (isset($_GET[$keyName]))) { + return $_GET[$keyName]; + } elseif (in_array('_POST', $paramSources) && (isset($_POST[$keyName]))) { + return $_POST[$keyName]; + } + + return $default; + } + + /** + * Retrieve an array of parameters + * + * Retrieves a merged array of parameters, with precedence of userland + * params (see {@link setParam()}), $_GET, $_POST (i.e., values in the + * userland params will take precedence over all others). + * + * @return array + */ + public function getParams() + { + $return = $this->_params; + $paramSources = $this->getParamSources(); + if (in_array('_GET', $paramSources) + && isset($_GET) + && is_array($_GET) + ) { + $return += $_GET; + } + if (in_array('_POST', $paramSources) + && isset($_POST) + && is_array($_POST) + ) { + $return += $_POST; + } + return $return; + } + + /** + * Set parameters + * + * Set one or more parameters. Parameters are set as userland parameters, + * using the keys specified in the array. + * + * @param array $params + * @return Zend_Controller_Request_Http + */ + public function setParams(array $params) + { + foreach ($params as $key => $value) { + $this->setParam($key, $value); + } + return $this; + } + + /** + * Set a key alias + * + * Set an alias used for key lookups. $name specifies the alias, $target + * specifies the actual key to use. + * + * @param string $name + * @param string $target + * @return Zend_Controller_Request_Http + */ + public function setAlias($name, $target) + { + $this->_aliases[$name] = $target; + return $this; + } + + /** + * Retrieve an alias + * + * Retrieve the actual key represented by the alias $name. + * + * @param string $name + * @return string|null Returns null when no alias exists + */ + public function getAlias($name) + { + if (isset($this->_aliases[$name])) { + return $this->_aliases[$name]; + } + + return null; + } + + /** + * Retrieve the list of all aliases + * + * @return array + */ + public function getAliases() + { + return $this->_aliases; + } + + /** + * Return the method by which the request was made + * + * @return string + */ + public function getMethod() + { + return $this->getServer('REQUEST_METHOD'); + } + + /** + * Was the request made by POST? + * + * @return boolean + */ + public function isPost() + { + if ('POST' == $this->getMethod()) { + return true; + } + + return false; + } + + /** + * Was the request made by GET? + * + * @return boolean + */ + public function isGet() + { + if ('GET' == $this->getMethod()) { + return true; + } + + return false; + } + + /** + * Was the request made by PUT? + * + * @return boolean + */ + public function isPut() + { + if ('PUT' == $this->getMethod()) { + return true; + } + + return false; + } + + /** + * Was the request made by DELETE? + * + * @return boolean + */ + public function isDelete() + { + if ('DELETE' == $this->getMethod()) { + return true; + } + + return false; + } + + /** + * Was the request made by HEAD? + * + * @return boolean + */ + public function isHead() + { + if ('HEAD' == $this->getMethod()) { + return true; + } + + return false; + } + + /** + * Was the request made by OPTIONS? + * + * @return boolean + */ + public function isOptions() + { + if ('OPTIONS' == $this->getMethod()) { + return true; + } + + return false; + } + + /** + * Was the request made by PATCH? + * + * @return boolean + */ + public function isPatch() + { + if ('PATCH' == $this->getMethod()) { + return true; + } + + return false; + } + + /** + * Is the request a Javascript XMLHttpRequest? + * + * Should work with Prototype/Script.aculo.us, possibly others. + * + * @return boolean + */ + public function isXmlHttpRequest() + { + return ($this->getHeader('X_REQUESTED_WITH') == 'XMLHttpRequest'); + } + + /** + * Is this a Flash request? + * + * @return boolean + */ + public function isFlashRequest() + { + $header = strtolower($this->getHeader('USER_AGENT')); + return (strstr($header, ' flash')) ? true : false; + } + + /** + * Is https secure request + * + * @return boolean + */ + public function isSecure() + { + return ($this->getScheme() === self::SCHEME_HTTPS); + } + + /** + * Return the raw body of the request, if present + * + * @return string|false Raw body, or false if not present + */ + public function getRawBody() + { + if (null === $this->_rawBody) { + $body = file_get_contents('php://input'); + + if (strlen(trim($body)) > 0) { + $this->_rawBody = $body; + } else { + $this->_rawBody = false; + } + } + return $this->_rawBody; + } + + /** + * Return the value of the given HTTP header. Pass the header name as the + * plain, HTTP-specified header name. Ex.: Ask for 'Accept' to get the + * Accept header, 'Accept-Encoding' to get the Accept-Encoding header. + * + * @param string $header HTTP header name + * @return string|false HTTP header value, or false if not found + * @throws Zend_Controller_Request_Exception + */ + public function getHeader($header) + { + if (empty($header)) { + #require_once 'Zend/Controller/Request/Exception.php'; + throw new Zend_Controller_Request_Exception('An HTTP header name is required'); + } + + // Try to get it from the $_SERVER array first + $temp = strtoupper(str_replace('-', '_', $header)); + if (isset($_SERVER['HTTP_' . $temp])) { + return $_SERVER['HTTP_' . $temp]; + } + + /* + * Try to get it from the $_SERVER array on POST request or CGI environment + * @see https://www.ietf.org/rfc/rfc3875 (4.1.2. and 4.1.3.) + */ + if (isset($_SERVER[$temp]) + && in_array($temp, array('CONTENT_TYPE', 'CONTENT_LENGTH')) + ) { + return $_SERVER[$temp]; + } + + // This seems to be the only way to get the Authorization header on + // Apache + if (function_exists('apache_request_headers')) { + $headers = apache_request_headers(); + if (isset($headers[$header])) { + return $headers[$header]; + } + $header = strtolower($header); + foreach ($headers as $key => $value) { + if (strtolower($key) == $header) { + return $value; + } + } + } + + return false; + } + + /** + * Get the request URI scheme + * + * @return string + */ + public function getScheme() + { + return ($this->getServer('HTTPS') == 'on') ? self::SCHEME_HTTPS : self::SCHEME_HTTP; + } + + /** + * Get the HTTP host. + * + * "Host" ":" host [ ":" port ] ; Section 3.2.2 + * Note the HTTP Host header is not the same as the URI host. + * It includes the port while the URI host doesn't. + * + * @return string + */ + public function getHttpHost() + { + $host = $this->getServer('HTTP_HOST'); + if (!empty($host)) { + return $host; + } + + $scheme = $this->getScheme(); + $name = $this->getServer('SERVER_NAME'); + $port = $this->getServer('SERVER_PORT'); + + if(null === $name) { + return ''; + } + elseif (($scheme == self::SCHEME_HTTP && $port == 80) || ($scheme == self::SCHEME_HTTPS && $port == 443)) { + return $name; + } else { + return $name . ':' . $port; + } + } + + /** + * Get the client's IP addres + * + * @param boolean $checkProxy + * @return string + */ + public function getClientIp($checkProxy = true) + { + if ($checkProxy && $this->getServer('HTTP_CLIENT_IP') != null) { + $ip = $this->getServer('HTTP_CLIENT_IP'); + } else if ($checkProxy && $this->getServer('HTTP_X_FORWARDED_FOR') != null) { + $ip = $this->getServer('HTTP_X_FORWARDED_FOR'); + } else { + $ip = $this->getServer('REMOTE_ADDR'); + } + + return $ip; + } +} diff --git a/app/code/core/Zend/Locale/Math/PhpMath.php b/app/code/core/Zend/Locale/Math/PhpMath.php new file mode 100644 index 0000000000..850940a9bf --- /dev/null +++ b/app/code/core/Zend/Locale/Math/PhpMath.php @@ -0,0 +1,254 @@ + $precision)) { + #require_once 'Zend/Locale/Math/Exception.php'; + throw new Zend_Locale_Math_Exception("addition overflow: $op1 + $op2 != $result", $op1, $op2, $result); + } + + return self::round(self::normalize($result), $scale); + } + + public static function Sub($op1, $op2, $scale = null) + { + if ($scale === null) { + $scale = Zend_Locale_Math_PhpMath::$defaultScale; + $precision = Zend_Locale_Math_PhpMath::$defaultPrecision; + } else { + $precision = pow(10, -$scale); + } + + if (empty($op1)) { + $op1 = 0; + } + if (empty($op2)) { + $op2 = 0; + } + $op1 = self::normalize($op1); + $op2 = self::normalize($op2); + $result = $op1 - $op2; + if (is_infinite($result) or (abs($result + $op2 - $op1) > $precision)) { + #require_once 'Zend/Locale/Math/Exception.php'; + throw new Zend_Locale_Math_Exception("subtraction overflow: $op1 - $op2 != $result", $op1, $op2, $result); + } + + return self::round(self::normalize($result), $scale); + } + + public static function Pow($op1, $op2, $scale = null) + { + if ($scale === null) { + $scale = Zend_Locale_Math_PhpMath::$defaultScale; + } + + $op1 = self::normalize($op1); + $op2 = self::normalize($op2); + + // BCMath extension doesn't use decimal part of the power + // Provide the same behavior + $op2 = ($op2 > 0) ? floor($op2) : ceil($op2); + + $result = pow($op1, $op2); + if (is_infinite($result) or is_nan($result)) { + #require_once 'Zend/Locale/Math/Exception.php'; + throw new Zend_Locale_Math_Exception("power overflow: $op1 ^ $op2", $op1, $op2, $result); + } + + return self::round(self::normalize($result), $scale); + } + + public static function Mul($op1, $op2, $scale = null) + { + if ($scale === null) { + $scale = Zend_Locale_Math_PhpMath::$defaultScale; + } + + if (empty($op1)) { + $op1 = 0; + } + $op1 = self::normalize($op1); + $op2 = self::normalize($op2); + $result = $op1 * $op2; + if (is_infinite($result) or is_nan($result)) { + #require_once 'Zend/Locale/Math/Exception.php'; + throw new Zend_Locale_Math_Exception("multiplication overflow: $op1 * $op2 != $result", $op1, $op2, $result); + } + + return self::round(self::normalize($result), $scale); + } + + public static function Div($op1, $op2, $scale = null) + { + if ($scale === null) { + $scale = Zend_Locale_Math_PhpMath::$defaultScale; + } + + if (empty($op2)) { + #require_once 'Zend/Locale/Math/Exception.php'; + throw new Zend_Locale_Math_Exception("can not divide by zero", $op1, $op2, null); + } + if (empty($op1)) { + $op1 = 0; + } + $op1 = self::normalize($op1); + $op2 = self::normalize($op2); + $result = $op1 / $op2; + if (is_infinite($result) or is_nan($result)) { + #require_once 'Zend/Locale/Math/Exception.php'; + throw new Zend_Locale_Math_Exception("division overflow: $op1 / $op2 != $result", $op1, $op2, $result); + } + + return self::round(self::normalize($result), $scale); + } + + public static function Sqrt($op1, $scale = null) + { + if ($scale === null) { + $scale = Zend_Locale_Math_PhpMath::$defaultScale; + } + + if (empty($op1)) { + $op1 = 0; + } + $op1 = self::normalize($op1); + $result = sqrt($op1); + if (is_nan($result)) { + return NULL; + } + + return self::round(self::normalize($result), $scale); + } + + public static function Mod($op1, $op2) + { + if (empty($op1)) { + $op1 = 0; + } + if (empty($op2)) { + return NULL; + } + $op1 = self::normalize($op1); + $op2 = self::normalize($op2); + if ((int)$op2 == 0) { + return NULL; + } + $result = $op1 % $op2; + if (is_nan($result) or (($op1 - $result) % $op2 != 0)) { + #require_once 'Zend/Locale/Math/Exception.php'; + throw new Zend_Locale_Math_Exception( + "modulus calculation error: $op1 % $op2 != $result", $op1, $op2, $result); + } + + return self::normalize($result); + } + + public static function Comp($op1, $op2, $scale = null) + { + if ($scale === null) { + $scale = Zend_Locale_Math_PhpMath::$defaultScale; + } + + if (empty($op1)) { + $op1 = 0; + } + $op1 = self::normalize($op1); + $op2 = self::normalize($op2); + if ($scale <> 0) { + $op1 = self::round($op1, $scale); + $op2 = self::round($op2, $scale); + } else { + $op1 = ($op1 > 0) ? floor($op1) : ceil($op1); + $op2 = ($op2 > 0) ? floor($op2) : ceil($op2); + } + if ($op1 > $op2) { + return 1; + } else if ($op1 < $op2) { + return -1; + } + return 0; + } + + public static function Scale($scale) + { + if ($scale > 9) { + #require_once 'Zend/Locale/Math/Exception.php'; + throw new Zend_Locale_Math_Exception("can not scale to precision $scale", $scale, null, null); + } + self::$defaultScale = $scale; + self::$defaultPrecision = pow(10, -$scale); + return true; + } +} + +Zend_Locale_Math_PhpMath::disable(); // disable use of bcmath functions diff --git a/app/code/core/Zend/Validate/File/Upload.php b/app/code/core/Zend/Validate/File/Upload.php new file mode 100644 index 0000000000..ccca1c36f3 --- /dev/null +++ b/app/code/core/Zend/Validate/File/Upload.php @@ -0,0 +1,254 @@ + "File '%value%' exceeds the defined ini size", + self::FORM_SIZE => "File '%value%' exceeds the defined form size", + self::PARTIAL => "File '%value%' was only partially uploaded", + self::NO_FILE => "File '%value%' was not uploaded", + self::NO_TMP_DIR => "No temporary directory was found for file '%value%'", + self::CANT_WRITE => "File '%value%' can't be written", + self::EXTENSION => "A PHP extension returned an error while uploading the file '%value%'", + self::ATTACK => "File '%value%' was illegally uploaded. This could be a possible attack", + self::FILE_NOT_FOUND => "File '%value%' was not found", + self::UNKNOWN => "Unknown error while uploading file '%value%'" + ); + + /** + * Internal array of files + * @var array + */ + protected $_files = array(); + + /** + * Sets validator options + * + * The array $files must be given in syntax of Zend_File_Transfer to be checked + * If no files are given the $_FILES array will be used automatically. + * NOTE: This validator will only work with HTTP POST uploads! + * + * @param array|Zend_Config $files Array of files in syntax of Zend_File_Transfer + */ + public function __construct($files = array()) + { + if ($files instanceof Zend_Config) { + $files = $files->toArray(); + } + + $this->setFiles($files); + } + + /** + * Returns the array of set files + * + * @param string $file (Optional) The file to return in detail + * @return array + * @throws Zend_Validate_Exception If file is not found + */ + public function getFiles($file = null) + { + if ($file !== null) { + $return = array(); + foreach ($this->_files as $name => $content) { + if ($name === $file) { + $return[$file] = $this->_files[$name]; + } + + if ($content['name'] === $file) { + $return[$name] = $this->_files[$name]; + } + } + + if (count($return) === 0) { + #require_once 'Zend/Validate/Exception.php'; + throw new Zend_Validate_Exception("The file '$file' was not found"); + } + + return $return; + } + + return $this->_files; + } + + /** + * Sets the files to be checked + * + * @param array $files The files to check in syntax of Zend_File_Transfer + * @return Zend_Validate_File_Upload Provides a fluent interface + */ + public function setFiles($files = array()) + { + if (count($files) === 0) { + $this->_files = $_FILES; + } else { + $this->_files = $files; + } + + // see ZF-10738 + if (is_null($this->_files)) { + $this->_files = array(); + } + + foreach($this->_files as $file => $content) { + if (!isset($content['error'])) { + unset($this->_files[$file]); + } + } + + return $this; + } + + /** + * Defined by Zend_Validate_Interface + * + * Returns true if and only if the file was uploaded without errors + * + * @param string $value Single file to check for upload errors, when giving null the $_FILES array + * from initialization will be used + * @param string|null $file + * @return boolean + */ + public function isValid($value, $file = null) + { + $this->_messages = null; + if (array_key_exists($value, $this->_files)) { + $files[$value] = $this->_files[$value]; + } else { + foreach ($this->_files as $file => $content) { + if (isset($content['name']) && ($content['name'] === $value)) { + $files[$file] = $this->_files[$file]; + } + + if (isset($content['tmp_name']) && ($content['tmp_name'] === $value)) { + $files[$file] = $this->_files[$file]; + } + } + } + + if (empty($files)) { + return $this->_throw($file, self::FILE_NOT_FOUND); + } + + foreach ($files as $file => $content) { + $this->_value = $file; + switch($content['error']) { + case 0: + if (!is_uploaded_file($content['tmp_name'])) { + $this->_throw($content, self::ATTACK); + } + break; + + case 1: + $this->_throw($content, self::INI_SIZE); + break; + + case 2: + $this->_throw($content, self::FORM_SIZE); + break; + + case 3: + $this->_throw($content, self::PARTIAL); + break; + + case 4: + $this->_throw($content, self::NO_FILE); + break; + + case 6: + $this->_throw($content, self::NO_TMP_DIR); + break; + + case 7: + $this->_throw($content, self::CANT_WRITE); + break; + + case 8: + $this->_throw($content, self::EXTENSION); + break; + + default: + $this->_throw($content, self::UNKNOWN); + break; + } + } + /** + * PHP7.2 compatibility fix. + * More info https://wiki.php.net/rfc/counting_non_countables + */ + if (isset($this->_messages) && count($this->_messages) > 0) { + return false; + } else { + return true; + } + } + + /** + * Throws an error of the given type + * + * @param string $file + * @param string $errorType + * @return false + */ + protected function _throw($file, $errorType) + { + if ($file !== null) { + if (is_array($file) and !empty($file['name'])) { + $this->_value = $file['name']; + } + } + + $this->_error($errorType); + return false; + } +} diff --git a/app/design/adminhtml/default/default/template/cms/browser/content/files.phtml b/app/design/adminhtml/default/default/template/cms/browser/content/files.phtml index d4429d90d2..edff349c09 100644 --- a/app/design/adminhtml/default/default/template/cms/browser/content/files.phtml +++ b/app/design/adminhtml/default/default/template/cms/browser/content/files.phtml @@ -40,7 +40,7 @@ $_height = $this->getImagesHeight();

getFileThumbUrl($file)):?> - <?php echo $this->getFileName($file) ?> + <?php echo $this->escapeHtml($this->getFileName($file)) ?>

getFileWidth($file)): ?> diff --git a/app/design/frontend/base/default/layout/captcha.xml b/app/design/frontend/base/default/layout/captcha.xml index 8ad68ecef5..7c09b29b78 100644 --- a/app/design/frontend/base/default/layout/captcha.xml +++ b/app/design/frontend/base/default/layout/captcha.xml @@ -103,4 +103,32 @@ + + + + + + mage/captcha.js + + wishlist_sharing + 230 + 50 + + + + + + + + + + mage/captcha.js + + sendfriend_send + 230 + 50 + + + + diff --git a/app/design/frontend/base/default/template/wishlist/sharing.phtml b/app/design/frontend/base/default/template/wishlist/sharing.phtml index b464ba1d3a..cb06ff0bb9 100644 --- a/app/design/frontend/base/default/template/wishlist/sharing.phtml +++ b/app/design/frontend/base/default/template/wishlist/sharing.phtml @@ -34,7 +34,7 @@

__('Sharing Information') ?>

  • - +
    @@ -42,7 +42,7 @@
  • - +
  • helper('wishlist')->isRssAllow()): ?> @@ -53,6 +53,7 @@ + getChildHtml('wishlist.sharing.form.additional.info'); ?>
diff --git a/app/design/frontend/rwd/default/layout/page.xml b/app/design/frontend/rwd/default/layout/page.xml index e9f38bde0d..de124bd916 100644 --- a/app/design/frontend/rwd/default/layout/page.xml +++ b/app/design/frontend/rwd/default/layout/page.xml @@ -36,7 +36,7 @@ - + diff --git a/app/design/frontend/rwd/default/template/sendfriend/send.phtml b/app/design/frontend/rwd/default/template/sendfriend/send.phtml index 4dd63a79f5..235a58b132 100644 --- a/app/design/frontend/rwd/default/template/sendfriend/send.phtml +++ b/app/design/frontend/rwd/default/template/sendfriend/send.phtml @@ -30,11 +30,20 @@ * @see Mage_Sendfriend_Block_Send */ ?> +getRecipientsCount(); ?> @@ -103,16 +113,72 @@
- +
- +
+ + + +
  • +

    + + __('Remove Email'); ?> + +

    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
  • + + + getChildHtml('sendfriend.send.form.additional.info'); ?>
    diff --git a/app/etc/modules/Mage_All.xml b/app/etc/modules/Mage_All.xml index e04b320a4a..25c3f3ac4a 100644 --- a/app/etc/modules/Mage_All.xml +++ b/app/etc/modules/Mage_All.xml @@ -234,7 +234,7 @@ - true + false core diff --git a/app/etc/modules/Mage_Captcha.xml b/app/etc/modules/Mage_Captcha.xml index ae301136af..2fe3f70865 100644 --- a/app/etc/modules/Mage_Captcha.xml +++ b/app/etc/modules/Mage_Captcha.xml @@ -33,6 +33,8 @@ + + diff --git a/app/locale/en_US/Mage_Catalog.csv b/app/locale/en_US/Mage_Catalog.csv index 35f80dc8a1..eb6c7d148a 100644 --- a/app/locale/en_US/Mage_Catalog.csv +++ b/app/locale/en_US/Mage_Catalog.csv @@ -101,7 +101,8 @@ "Attribute Set","Attribute Set" "Attribute Sets","Attribute Sets" "Attribute add","Attribute add" -"Attribute code is invalid. Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter.","Attribute code is invalid. Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter." +"Attribute code is invalid. Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter. Do not use ""event"" for an attribute code.","Attribute code is invalid. Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter. Do not use ""event"" for an attribute code." +"Attribute code is invalid. Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter. Do not use event"" for an attribute code.""","Attribute code is invalid. Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter. Do not use event"" for an attribute code.""" "Attribute group with the \"/name/\" name already exists","Attribute group with the \"/name/\" name already exists" "Attribute remove","Attribute remove" "Attribute with the same code already exists","Attribute with the same code already exists" diff --git a/app/locale/en_US/Mage_Core.csv b/app/locale/en_US/Mage_Core.csv index c0d7e8e653..4f110055c3 100644 --- a/app/locale/en_US/Mage_Core.csv +++ b/app/locale/en_US/Mage_Core.csv @@ -223,6 +223,8 @@ "Path ""%value%"" is protected and cannot be used.","Path ""%value%"" is protected and cannot be used." "Path ""%value%"" may not include parent directory traversal (""../"", ""..\\).""","Path ""%value%"" may not include parent directory traversal (""../"", ""..\\).""" "Please define flag code.","Please define flag code." +"Please do not use ""event"" for an attribute code.","Please do not use ""event"" for an attribute code." +"Please do not use event"" for an attribute code.""","Please do not use event"" for an attribute code.""" "Please enter 6 or more characters without leading or trailing spaces.","Please enter 6 or more characters without leading or trailing spaces." "Please enter 7 or more characters. Password should contain both numeric and alphabetic characters.","Please enter 7 or more characters. Password should contain both numeric and alphabetic characters." "Please enter a number 0 or greater in this field.","Please enter a number 0 or greater in this field." diff --git a/app/locale/en_US/Mage_Eav.csv b/app/locale/en_US/Mage_Eav.csv index 2b490b2bc4..906aa8477e 100644 --- a/app/locale/en_US/Mage_Eav.csv +++ b/app/locale/en_US/Mage_Eav.csv @@ -29,6 +29,8 @@ "'%value%' does not appear to be a valid URI hostname","'%value%' does not appear to be a valid URI hostname" "'%value%' does not appear to be a valid local network name","'%value%' does not appear to be a valid local network name" "'%value%' does not match the expected structure for a DNS hostname","'%value%' does not match the expected structure for a DNS hostname" +". Do not use ""event"" for an attribute code, it is a reserved keyword.",". Do not use ""event"" for an attribute code, it is a reserved keyword." +". Do not use event"" for an attribute code"," it is a reserved keyword.""" "A joint field with this alias (%s) is already declared","A joint field with this alias (%s) is already declared" "Add Option","Add Option" "An error occurred while loading a record, aborting. Error: %s","An error occurred while loading a record, aborting. Error: %s" diff --git a/app/locale/en_US/Mage_Wishlist.csv b/app/locale/en_US/Mage_Wishlist.csv index 9f987d079b..1182a51f0a 100644 --- a/app/locale/en_US/Mage_Wishlist.csv +++ b/app/locale/en_US/Mage_Wishlist.csv @@ -66,6 +66,7 @@ "Options Details","Options Details" "Out of stock","Out of stock" "Please enter a valid email addresses, separated by commas. For example johndoe@domain.com, johnsmith@domain.com.","Please enter a valid email addresses, separated by commas. For example johndoe@domain.com, johnsmith@domain.com." +"Please enter no more than 5 email addresses.","Please enter no more than 5 email addresses." "Please input a valid email address.","Please input a valid email address." "Please, enter your comments...","Please, enter your comments..." "Price","Price" @@ -89,6 +90,7 @@ "This Wishlist has no Items","This Wishlist has no Items" "This product(s) is currently out of stock","This product(s) is currently out of stock" "Unable to add the following product(s) to shopping cart: %s.","Unable to add the following product(s) to shopping cart: %s." +"Up to 5 email addresses, separated by commas","Up to 5 email addresses, separated by commas" "Update Wishlist","Update Wishlist" "User Description","User Description" "View Details","View Details" diff --git a/dev/tests/functional/lib/Magento/Mtf/Client/Driver/Selenium/Driver.php b/dev/tests/functional/lib/Magento/Mtf/Client/Driver/Selenium/Driver.php new file mode 100644 index 0000000000..f83e6a7a53 --- /dev/null +++ b/dev/tests/functional/lib/Magento/Mtf/Client/Driver/Selenium/Driver.php @@ -0,0 +1,891 @@ +configuration = $configuration; + $this->remoteDriverFactory = $remoteDriverFactory; + $this->eventManager = $eventManager; + $this->objectManager = $objectManager; + $this->pageLoader = $pageLoader; + + $this->init(); + } + + /** + * Destructor. + * + * @return void + */ + public function __destruct() + { + if ($this->driver->getSessionId()) { + $this->driver->stop(); + } + } + + /** + * Initial web driver. + * + * @return void + */ + protected function init() + { + $this->driver = $this->remoteDriverFactory->create(); + + $this->driver->setBrowserUrl('about:blank'); + $params = $this->configuration->get('server/0/item/selenium'); + $this->driver->setupSpecificBrowser($params); + $this->driver->prepareSession(); + $this->driver->currentWindow()->maximize(); + $this->driver->cookie()->clear(); + $this->driver->refresh(); + } + + /** + * Get native element by locator. + * + * @param Locator $locator + * @param \PHPUnit_Extensions_Selenium2TestCase_Element $context + * @param bool $wait + * @return \PHPUnit_Extensions_Selenium2TestCase_Element + * @throws \Exception + */ + protected function findElement( + Locator $locator, + \PHPUnit_Extensions_Selenium2TestCase_Element $context = null, + $wait = true + ) { + $context = $context === null + ? $this->driver + : $context; + + $criteria = $this->getSearchCriteria($locator); + $this->pageLoader->setDriver($this->driver)->wait(); + if ($wait) { + return $this->waitUntil( + function () use ($context, $criteria) { + $element = $context->element($criteria); + return $element->displayed() ? $element : null; + } + ); + } + + $this->pageLoader->wait(); + + return $context->element($criteria); + } + + /** + * Get native element by Mtf Element. + * + * @param ElementInterface $element + * @param bool $wait + * @return null|\PHPUnit_Extensions_Selenium2TestCase_Element + * @throws \PHPUnit_Extensions_Selenium2TestCase_WebDriverException + */ + protected function getNativeElement(ElementInterface $element, $wait = true) + { + $chainElements = [$element]; + while ($element = $element->getContext()) { + $chainElements[] = $element; + } + + $contextElement = null; + /** @var ElementInterface $context */ + foreach (array_reverse($chainElements) as $chainElement) { + /** @var ElementInterface $chainElement */ + try { + // First call "getElement" with $resultElement equal "null" value + $contextElement = $this->findElement($chainElement->getLocator(), $contextElement, $wait); + } catch (\PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) { + throw new \PHPUnit_Extensions_Selenium2TestCase_WebDriverException( + sprintf( + 'Error occurred on attempt to get element. Message: "%s". Locator: "%s" . Wait: "%s"', + $e->getMessage(), + $chainElement->getAbsoluteSelector(), + $wait + ) + ); + } + } + + return $contextElement; + } + + /** + * Get search criteria. + * + * @param Locator $locator + * @return \PHPUnit_Extensions_Selenium2TestCase_ElementCriteria + */ + public function getSearchCriteria(Locator $locator) + { + $criteria = new \PHPUnit_Extensions_Selenium2TestCase_ElementCriteria($locator['using']); + $criteria->value($locator['value']); + + return $criteria; + } + + /** + * Inject Js Error collector. + * + * @return void + */ + public function injectJsErrorCollector() + { + $this->driver->execute( + [ + 'script' => 'window.onerror = function(msg, url, line) { + var errors = {}; + if (localStorage.getItem("errorsHistory")) { + errors = JSON.parse(localStorage.getItem("errorsHistory")); + } + if (!(window.location.href in errors)) { + errors[window.location.href] = []; + } + errors[window.location.href].push("error: \'" + msg + "\' " + "file: " + url + " " + "line: " + line); + localStorage.setItem("errorsHistory", JSON.stringify(errors)); + }', + 'args' => [] + ] + ); + } + + /** + * Get js errors. + * + * @return string[] + */ + public function getJsErrors() + { + return $this->driver->execute( + [ + 'script' => 'errors = JSON.parse(localStorage.getItem("errorsHistory")); + localStorage.removeItem("errorsHistory"); + return errors;', + 'args' => [] + ] + ); + } + + /** + * Click. + * + * @param ElementInterface $element + * @return void + */ + public function click(ElementInterface $element) + { + $absoluteSelector = $element->getAbsoluteSelector(); + $this->eventManager->dispatchEvent(['click_before'], [__METHOD__, $absoluteSelector]); + + $wrapperElement = $this->getNativeElement($element); + $this->driver->moveto($wrapperElement); + $wrapperElement->click(); + + $this->eventManager->dispatchEvent(['click_after'], [__METHOD__, $absoluteSelector]); + } + + /** + * Double click. + * + * @param ElementInterface $element + * @return void + */ + public function doubleClick(ElementInterface $element) + { + $this->eventManager->dispatchEvent(['double_click_before'], [__METHOD__, $element->getAbsoluteSelector()]); + + $this->driver->moveto($this->getNativeElement($element)); + $this->driver->doubleclick(); + } + + /** + * Right click. + * + * @param ElementInterface $element + * @return void + */ + public function rightClick(ElementInterface $element) + { + $this->eventManager->dispatchEvent(['right_click_before'], [__METHOD__, $element->getAbsoluteSelector()]); + + $this->driver->moveto($this->getNativeElement($element)); + $this->driver->click(\PHPUnit_Extensions_Selenium2TestCase_SessionCommand_Click::RIGHT); + } + + /** + * Check whether element is present in the DOM. + * + * @param ElementInterface $element + * @return bool + */ + public function isPresent(ElementInterface $element) + { + $isPresent = true; + $nativeElement = null; + try { + $this->eventManager->dispatchEvent(['is_present'], [__METHOD__, $element->getAbsoluteSelector()]); + $nativeElement = $this->getNativeElement($element, false); + } catch (\PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) { + $isPresent = false; + } + return $nativeElement !== null && $isPresent; + } + + /** + * Check whether element is visible. + * + * @param ElementInterface $element + * @return bool + */ + public function isVisible(ElementInterface $element) + { + try { + $this->eventManager->dispatchEvent(['is_visible'], [__METHOD__, $element->getAbsoluteSelector()]); + $visible = $this->getNativeElement($element, false)->displayed(); + } catch (\PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) { + $visible = false; + } + + return $visible; + } + + /** + * Check whether element is enabled. + * + * @param ElementInterface $element + * @return bool + */ + public function isDisabled(ElementInterface $element) + { + return !$this->getNativeElement($element)->enabled(); + } + + /** + * Check whether element is selected. + * + * @param ElementInterface $element + * @return bool + */ + public function isSelected(ElementInterface $element) + { + return $this->getNativeElement($element)->selected(); + } + + /** + * Set the value. + * + * @param ElementInterface $element + * @param string|array $value + * @return void + */ + public function setValue(ElementInterface $element, $value) + { + $this->eventManager->dispatchEvent(['set_value'], [__METHOD__, $element->getAbsoluteSelector()]); + + $wrappedElement = $this->getNativeElement($element); + $this->driver->moveto($wrappedElement); + $wrappedElement->clear(); + $this->focus($element); + + $wrappedElement->value($value); + $this->triggerChangeEvent($element); + } + + /** + * Get the value. + * + * @param ElementInterface $element + * @return null|string + */ + public function getValue(ElementInterface $element) + { + $this->eventManager->dispatchEvent(['get_value'], [__METHOD__, $element->getAbsoluteSelector()]); + return $this->getNativeElement($element)->value(); + } + + /** + * Get content. + * + * @param ElementInterface $element + * @return string + */ + public function getText(ElementInterface $element) + { + return $this->getNativeElement($element)->text(); + } + + /** + * Find element on the page. + * + * @param string $selector + * @param string $strategy + * @param string $type = select|multiselect|checkbox|null OR custom class with full namespace + * @param ElementInterface $context + * @return ElementInterface + * @throws \Exception + */ + public function find( + $selector, + $strategy = Locator::SELECTOR_CSS, + $type = null, + ElementInterface $context = null + ) { + $locator = new Locator($selector, $strategy); + + $this->eventManager->dispatchEvent(['find'], [__METHOD__, $locator]); + + $className = 'Magento\Mtf\Client\ElementInterface'; + if (null !== $type) { + if (strpos($type, '\\') === false) { + $type = ucfirst(strtolower($type)); + if (class_exists('Magento\Mtf\Client\Element\\' . $type . 'Element')) { + $className = 'Magento\Mtf\Client\Element\\' . $type . 'Element'; + } + } else { + if (!class_exists($type) && !interface_exists($type)) { + throw new \Exception( + sprintf('Requested interface or class "%s" does not exists!', $type) + ); + } + $className = $type; + } + } + + return $this->objectManager->create( + $className, + [ + 'driver' => $this, + 'locator' => $locator, + 'context' => $context + ] + ); + } + + /** + * Drag and drop element to(between) another element(s). + * + * @param ElementInterface $element + * @param ElementInterface $target + * @return void + */ + public function dragAndDrop(ElementInterface $element, ElementInterface $target) + { + $this->driver->moveto($this->getNativeElement($element)); + $this->driver->buttondown(); + + $this->driver->moveto($this->getNativeElement($target)); + $this->driver->buttonup(); + } + + /** + * Hover mouse over an element. + * + * @param ElementInterface $element + * @return void + */ + public function hover(ElementInterface $element) + { + $this->driver->moveto($this->getNativeElement($element)); + } + + /** + * Send a sequence of key strokes to the active element. + * + * @param ElementInterface $element + * @param array $keys + * @return void + */ + public function keys(ElementInterface $element, array $keys) + { + $wrappedElement = $this->getNativeElement($element); + $wrappedElement->clear(); + $this->focus($element); + foreach ($keys as $key) { + $this->driver->keys($key); + } + } + + /** + * Wait until callback isn't null or timeout occurs. + * + * @param callable $callback + * @return mixed + * @throws \Exception + */ + public function waitUntil($callback) + { + return $this->driver->waitUntil($callback); + } + + /** + * Get all elements by locator. + * + * @param ElementInterface $context + * @param string $selector + * @param string $strategy + * @param null|string $type + * @param bool $wait + * @return ElementInterface[] + * @throws \Exception + */ + public function getElements( + ElementInterface $context, + $selector, + $strategy = Locator::SELECTOR_CSS, + $type = null, + $wait = true + ) { + $locator = new Locator($selector, $strategy); + $criteria = $this->getSearchCriteria($locator); + $nativeContext = $this->getNativeElement($context); + $resultElements = []; + if ($wait) { + try { + $nativeElements = $this->waitUntil( + function () use ($nativeContext, $criteria) { + return $nativeContext->elements($criteria); + } + ); + } catch (\Exception $e) { + throw new \Exception( + sprintf( + 'Error occurred during waiting for an elements. Message: "%s". Locator: "%s"', + $e->getMessage(), + $context->getAbsoluteSelector() . ' -> ' . $locator + ) + ); + } + } else { + $nativeElements = $nativeContext->elements($criteria); + } + + foreach ($nativeElements as $key => $element) { + $resultElements[] = $this->find( + $this->getRelativeXpath($element, $nativeContext), + Locator::SELECTOR_XPATH, + $type, + $context + ); + } + + return $resultElements; + } + + /** + * Retrieve relative xpath from context to element. + * + * @param \PHPUnit_Extensions_Selenium2TestCase_Element $element + * @param \PHPUnit_Extensions_Selenium2TestCase_Element $context + * @param string $path + * @param bool $includeLastIndex + * @return null + */ + protected function getRelativeXpath( + \PHPUnit_Extensions_Selenium2TestCase_Element $element, + \PHPUnit_Extensions_Selenium2TestCase_Element $context, + $path = '', + $includeLastIndex = true + ) { + if ($element->equals($context)) { + return '.' . $path; + } + + $parentLocator = new Locator('..', Locator::SELECTOR_XPATH); + $parentElement = $element->element($this->getSearchCriteria($parentLocator)); + + $childrenLocator = new Locator('*', Locator::SELECTOR_XPATH); + + $index = 1; + $tag = $element->name(); + if (!$includeLastIndex) { + return $this->getRelativeXpath($parentElement, $context, '/' . $tag); + } + foreach ($parentElement->elements($this->getSearchCriteria($childrenLocator)) as $child) { + if ($child->equals($element)) { + return $this->getRelativeXpath($parentElement, $context, '/' . $tag . '[' . $index . ']' . $path); + } + if ($child->name() == $tag) { + ++$index; + } + } + return null; + } + + /** + * Get the value of a the given attribute of the element. + * + * @param ElementInterface $element + * @param string $name + * @return string + */ + public function getAttribute(ElementInterface $element, $name) + { + return $this->getNativeElement($element)->attribute($name); + } + + /** + * Open page. + * + * @param string $url + * @return void + */ + public function open($url) + { + $this->eventManager->dispatchEvent(['open_before'], [__METHOD__, $url]); + $this->driver->url($url); + $this->eventManager->dispatchEvent(['open_after'], [__METHOD__, $url]); + } + + /** + * Back to previous page. + * + * @return void + */ + public function back() + { + $this->driver->back(); + $this->eventManager->dispatchEvent(['back'], [__METHOD__]); + } + + /** + * Forward page. + * + * @return void + */ + public function forward() + { + $this->driver->forward(); + $this->eventManager->dispatchEvent(['forward'], [__METHOD__]); + } + + /** + * Refresh page. + * + * @return void + */ + public function refresh() + { + $this->driver->refresh(); + } + + /** + * Reopen browser. + * + * @return void + */ + public function reopen() + { + $this->eventManager->dispatchEvent(['reopen'], [__METHOD__]); + if ($this->driver->getSessionId()) { + $this->driver->stop(); + } + if ($sessionStrategy = $this->configuration->get('server/0/item/selenium/sessionStrategy')) { + $this->driver->setSessionStrategy($sessionStrategy); + } else { + $this->driver->setSessionStrategy('isolated'); + } + $this->init(); + } + + /** + * Change the focus to a frame in the page by locator. + * + * @param Locator|null $locator + * @return void + * @throws \Exception + */ + public function switchToFrame(Locator $locator = null) + { + if ($locator) { + $this->eventManager->dispatchEvent(['switch_to_frame'], [(string)$locator]); + try { + $element = $this->findElement($locator); + } catch (\Exception $e) { + throw new \Exception( + sprintf( + 'Error occurred during switch to frame! Message: "%s". Locator: "%s".', + $e->getMessage(), + $locator + ) + ); + } + } else { + $this->eventManager->dispatchEvent(['switch_to_frame'], ['Switch to main window']); + $element = null; + } + + $this->driver->frame($element); + } + + /** + * Close the current window. + * + * @return void + */ + public function closeWindow() + { + $windowHandles = $this->driver->windowHandles(); + if (count($windowHandles) > 1) { + $this->driver->window(end($windowHandles)); + $this->driver->closeWindow(); + $this->driver->window(reset($windowHandles)); + } else { + $this->driver->closeWindow(); + } + } + + /** + * Select window by its name. + * + * @return void + */ + public function selectWindow() + { + $windowHandles = $this->driver->windowHandles(); + $this->driver->window(end($windowHandles)); + } + + /** + * Get page title text. + * + * @return string + */ + public function getTitle() + { + return $this->driver->title(); + } + + /** + * Press OK on an alert or confirm a dialog. + * + * @return void + */ + public function acceptAlert() + { + //$this->_driver->acceptAlert(); Temporary fix for selenium issue 3544 + $this->waitForOperationSuccess('acceptAlert'); + $this->eventManager->dispatchEvent(['accept_alert_after'], [__METHOD__]); + } + + /** + * Press Cancel on alert or does not confirm a dialog. + * + * @return void + */ + public function dismissAlert() + { + //$this->_driver->dismissAlert(); Temporary fix for selenium issue 3544 + $this->waitForOperationSuccess('dismissAlert'); + $this->eventManager->dispatchEvent(['dismiss_alert_after'], [__METHOD__]); + } + + /** + * @todo Temporary fix for selenium issue 3544 + * https://code.google.com/p/selenium/issues/detail?id=3544 + * + * @param string $operation + */ + protected function waitForOperationSuccess($operation) + { + $driver = $this->driver; + $this->waitUntil( + function () use ($driver, $operation) { + try { + $driver->$operation(); + } catch (\PHPUnit_Extensions_Selenium2TestCase_WebDriverException $exception) { + return null; + } + return true; + } + ); + } + + /** + * Get the alert dialog text. + * + * @return string + */ + public function getAlertText() + { + return $this->driver->alertText(); + } + + /** + * Set the text to a prompt popup. + * + * @param string $text + * @return void + */ + public function setAlertText($text) + { + $this->driver->alertText($text); + } + + /** + * Get current page url. + * + * @return string + */ + public function getUrl() + { + try { + if ($this->driver->alertText()) { + return null; + } + } catch (\PHPUnit_Extensions_Selenium2TestCase_WebDriverException $exception) { + return $this->driver->url(); + } + + return $this->driver->url(); + } + + /** + * Get Html page source. + * + * @return string + */ + public function getHtmlSource() + { + return $this->driver->source(); + } + + /** + * Get binary string of image. + * + * @return string + */ + public function getScreenshotData() + { + return $this->driver->currentScreenshot(); + } + + /** + * Set focus on element. + * + * @param ElementInterface $element + * @return void + */ + public function focus(ElementInterface $element) + { + $elementId = $element->getAttribute('id'); + if ($elementId) { + $js = "if (window.jQuery != undefined) jQuery('[id=\"$elementId\"]').focus(); "; + $js .= "var element = document.getElementById('$elementId'); if (element != undefined) element.focus();"; + $this->driver->execute(['script' => $js, 'args' => []]); + } else { + $element->click(); + } + } + + /** + * Trigger change on event. + * + * @param ElementInterface $element + * @return void + */ + protected function triggerChangeEvent(ElementInterface $element) + { + $elementId = $element->getAttribute('id'); + if ($elementId) { + $js = "if (window.jQuery != undefined)"; + $js .= "{jQuery('[id=\"$elementId\"]').change(); jQuery('[id=\"$elementId\"]').keyup();}"; + $js .= "var element = document.getElementById('$elementId'); if (element != undefined) element.focus();"; + $this->driver->execute(['script' => $js, 'args' => []]); + } + } +} diff --git a/dev/tests/functional/lib/Magento/Mtf/Client/Element/SimpleElement.php b/dev/tests/functional/lib/Magento/Mtf/Client/Element/SimpleElement.php new file mode 100644 index 0000000000..5829965174 --- /dev/null +++ b/dev/tests/functional/lib/Magento/Mtf/Client/Element/SimpleElement.php @@ -0,0 +1,308 @@ +driver = $driver; + $this->eventManager = $eventManager; + $this->locator = $locator; + $this->context = $context; + } + + /** + * Drag and drop element to(between) another element(s) + * + * @param ElementInterface $target + * @return void + */ + public function dragAndDrop(ElementInterface $target) + { + $this->driver->dragAndDrop($this, $target); + } + + /** + * Check whether element is visible + * + * @return bool + */ + public function isVisible() + { + return $this->driver->isVisible($this); + } + + /** + * Get content + * + * @return string + */ + public function getText() + { + return $this->driver->getText($this); + } + + /** + * Find element by locator in context of current element + * + * @param string $selector + * @param string $strategy [optional] + * @param null|string $type [optional] + * @return ElementInterface + */ + public function find($selector, $strategy = Locator::SELECTOR_CSS, $type = null) + { + return $this->driver->find($selector, $strategy, $type, $this); + } + + /** + * Get all elements by locator + * + * @param string $selector + * @param string $strategy + * @param null|string $type + * @return ElementInterface[] + */ + public function getElements($selector, $strategy = Locator::SELECTOR_CSS, $type = null) + { + return $this->driver->getElements($this, $selector, $strategy, $type); + } + + /** + * Wait until callback isn't null or timeout occurs + * + * @param callable $callback + * @return mixed + */ + public function waitUntil($callback) + { + return $this->driver->waitUntil($callback); + } + + /** + * Click + * + * @return void + */ + public function click() + { + $this->driver->click($this); + } + + /** + * Send keys + * + * @param array $keys + * @return void + */ + public function keys(array $keys) + { + $this->driver->keys($this, $keys); + } + + /** + * Check whether element is enabled + * + * @return bool + */ + public function isDisabled() + { + return $this->driver->isDisabled($this); + } + + /** + * Check whether element is present in the DOM. + * + * @return bool + */ + public function isPresent() + { + return $this->driver->isPresent($this); + } + + /** + * Check whether element is selected + * + * @return bool + */ + public function isSelected() + { + return $this->driver->isSelected($this); + } + + /** + * Set the value + * + * @param string|array $value + * @return void + */ + public function setValue($value) + { + $this->driver->setValue($this, $value); + } + + /** + * Get the value + * + * @return string|array + */ + public function getValue() + { + return $this->driver->getValue($this); + } + + /** + * Get the value of a the given attribute of the element + * + * @param string $name + * @return string + */ + public function getAttribute($name) + { + return $this->driver->getAttribute($this, $name); + } + + /** + * Double click + * + * @return void + */ + public function doubleClick() + { + $this->driver->doubleClick($this); + } + + /** + * Right click + * + * @return void + */ + public function rightClick() + { + $this->driver->rightClick($this); + } + + /** + * Get absolute selector (for DBG) + * + * @return string + */ + public function getAbsoluteSelector() + { + $selectors = []; + $selectors[] = $this->getLocator(); + $element = $this; + while($element = $element->getContext()) { + $selectors[] = $element->getLocator(); + } + + return implode(' -> ', array_reverse($selectors)); + } + + /** + * Get element locator + * + * @return Locator + */ + public function getLocator() + { + return $this->locator; + } + + /** + * Get context element + * + * @return ElementInterface|null + */ + public function getContext() + { + return $this->context; + } + + /** + * Hover mouse over an element. + * + * @return void + */ + public function hover() + { + $this->driver->hover($this); + } +} diff --git a/dev/tests/functional/tests/app/Mage/Adminhtml/Test/Block/Sales/Order/Create/Payment.php b/dev/tests/functional/tests/app/Mage/Adminhtml/Test/Block/Sales/Order/Create/Payment.php index 30eb174763..f4528819aa 100644 --- a/dev/tests/functional/tests/app/Mage/Adminhtml/Test/Block/Sales/Order/Create/Payment.php +++ b/dev/tests/functional/tests/app/Mage/Adminhtml/Test/Block/Sales/Order/Create/Payment.php @@ -58,8 +58,10 @@ class Payment extends Block public function selectPaymentMethod(array $paymentCode) { $paymentInput = $this->_rootElement->find(sprintf($this->paymentMethod, $paymentCode['method'])); - if ($paymentInput->isVisible()) { - $paymentInput->click(); + if ($paymentInput->isPresent()) { + if ($paymentInput->isVisible()) { + $paymentInput->click(); + } $this->getTemplateBlock()->waitLoader(); } else { throw new \Exception("{$paymentCode['method']} method is not visible."); diff --git a/dev/tests/functional/tests/app/Mage/Paypal/Test/Block/NewLogin.php b/dev/tests/functional/tests/app/Mage/Paypal/Test/Block/NewLogin.php index 02d8494d40..608bcfc2e6 100644 --- a/dev/tests/functional/tests/app/Mage/Paypal/Test/Block/NewLogin.php +++ b/dev/tests/functional/tests/app/Mage/Paypal/Test/Block/NewLogin.php @@ -67,10 +67,12 @@ public function fill(FixtureInterface $customer, Element $element = null) $this->clickToElement($this->startLoginButton); $this->_rootElement = $this->browser->find('.main'); parent::fill($customer, $this->switchOnPayPalFrame($element)); - $this->clickToElement($this->nextButton); $path = glob(MTF_TESTS_PATH . preg_replace('/^\w+\/\w+/', '*/*', str_replace('\\', '/', get_class($this))) . 'Password.xml'); $this->mapping = $this->mapper->read(reset($path))['fields']; + if (!$this->browser->find($this->mapping['password']['selector'])->isVisible()) { + $this->clickToElement($this->nextButton); + } parent::fill($customer, $this->switchOnPayPalFrame($element)); return $this; diff --git a/downloader/Maged/Controller.php b/downloader/Maged/Controller.php index 63870088ce..bcfb0081ca 100644 --- a/downloader/Maged/Controller.php +++ b/downloader/Maged/Controller.php @@ -813,15 +813,17 @@ protected function _addDomainPolicyHeader() */ public function dispatch() { - $baseUrl = Mage::getBaseUrl( - Mage_Core_Model_Store::URL_TYPE_LINK, Mage::getSingleton('adminhtml/url')->getSecure() - ); - if (strpos($baseUrl, 'https') === 0) { - $request = Mage::app()->getRequest(); - if (!$request->isSecure()) { - Mage::app()->getFrontController()->getResponse() - ->setRedirect(rtrim($baseUrl, '/') . $request->getRequestUri(), 301)->sendResponse(); - exit; + if (class_exists('Mage')) { + $baseUrl = Mage::getBaseUrl( + Mage_Core_Model_Store::URL_TYPE_LINK, Mage::getSingleton('adminhtml/url')->getSecure() + ); + if (strpos($baseUrl, 'https') === 0) { + $request = Mage::app()->getRequest(); + if (!$request->isSecure()) { + Mage::app()->getFrontController()->getResponse() + ->setRedirect(rtrim($baseUrl, '/') . $request->getRequestUri(), 301)->sendResponse(); + exit; + } } } @@ -1071,8 +1073,8 @@ public static function getVersionInfo() return array( 'major' => '1', 'minor' => '9', - 'revision' => '3', - 'patch' => '10', + 'revision' => '4', + 'patch' => '0', 'stability' => '', 'number' => '', ); diff --git a/js/lib/jquery/jquery-1.12.0.min.js b/js/lib/jquery/jquery-1.12.0.min.js deleted file mode 100644 index 6c60672fc5..0000000000 --- a/js/lib/jquery/jquery-1.12.0.min.js +++ /dev/null @@ -1,5 +0,0 @@ -/*! jQuery v1.12.0 | (c) jQuery Foundation | jquery.org/license */ -!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="1.12.0",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(!l.ownFirst)for(b in a)return k.call(a,b);for(b in a);return void 0===b||k.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(h)return h.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=e.call(arguments,2),d=function(){return a.apply(b||this,c.concat(e.call(arguments)))},d.guid=a.guid=a.guid||n.guid++,d):void 0},now:function(){return+new Date},support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}if(f=d.getElementById(e[2]),f&&f.parentNode){if(f.id!==e[2])return A.find(a);this.length=1,this[0]=f}return this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||(e=n.uniqueSort(e)),D.test(a)&&(e=e.reverse())),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=!0,c||j.disable(),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.addEventListener?(d.removeEventListener("DOMContentLoaded",K),a.removeEventListener("load",K)):(d.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(d.addEventListener||"load"===a.event.type||"complete"===d.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===d.readyState)a.setTimeout(n.ready);else if(d.addEventListener)d.addEventListener("DOMContentLoaded",K),a.addEventListener("load",K);else{d.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&d.documentElement}catch(e){}c&&c.doScroll&&!function f(){if(!n.isReady){try{c.doScroll("left")}catch(b){return a.setTimeout(f,50)}J(),n.ready()}}()}return I.promise(b)},n.ready.promise();var L;for(L in n(l))break;l.ownFirst="0"===L,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c,e;c=d.getElementsByTagName("body")[0],c&&c.style&&(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",l.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(e))}),function(){var a=d.createElement("div");l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}a=null}();var M=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b},N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1; -return!0}function R(a,b,d,e){if(M(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f}}function S(a,b,c){if(M(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=void 0)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},Z=/^(?:checkbox|radio)$/i,$=/<([\w:-]+)/,_=/^$|\/(?:java|ecma)script/i,aa=/^\s+/,ba="abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video";function ca(a){var b=ba.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}!function(){var a=d.createElement("div"),b=d.createDocumentFragment(),c=d.createElement("input");a.innerHTML="
    a",l.leadingWhitespace=3===a.firstChild.nodeType,l.tbody=!a.getElementsByTagName("tbody").length,l.htmlSerialize=!!a.getElementsByTagName("link").length,l.html5Clone="<:nav>"!==d.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,b.appendChild(c),l.appendChecked=c.checked,a.innerHTML="",l.noCloneChecked=!!a.cloneNode(!0).lastChild.defaultValue,b.appendChild(a),c=d.createElement("input"),c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),a.appendChild(c),l.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!!a.addEventListener,a[n.expando]=1,l.attributes=!a.getAttribute(n.expando)}();var da={option:[1,""],legend:[1,"
    ","
    "],area:[1,"",""],param:[1,"",""],thead:[1,"","
    "],tr:[2,"","
    "],col:[2,"","
    "],td:[3,"","
    "],_default:l.htmlSerialize?[0,"",""]:[1,"X
    ","
    "]};da.optgroup=da.option,da.tbody=da.tfoot=da.colgroup=da.caption=da.thead,da.th=da.td;function ea(a,b){var c,d,e=0,f="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,ea(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function fa(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}var ga=/<|&#?\w+;/,ha=/r;r++)if(g=a[r],g||0===g)if("object"===n.type(g))n.merge(q,g.nodeType?[g]:g);else if(ga.test(g)){i=i||p.appendChild(b.createElement("div")),j=($.exec(g)||["",""])[1].toLowerCase(),m=da[j]||da._default,i.innerHTML=m[1]+n.htmlPrefilter(g)+m[2],f=m[0];while(f--)i=i.lastChild;if(!l.leadingWhitespace&&aa.test(g)&&q.push(b.createTextNode(aa.exec(g)[0])),!l.tbody){g="table"!==j||ha.test(g)?""!==m[1]||ha.test(g)?0:i:i.firstChild,f=g&&g.childNodes.length;while(f--)n.nodeName(k=g.childNodes[f],"tbody")&&!k.childNodes.length&&g.removeChild(k)}n.merge(q,i.childNodes),i.textContent="";while(i.firstChild)i.removeChild(i.firstChild);i=p.lastChild}else q.push(b.createTextNode(g));i&&p.removeChild(i),l.appendChecked||n.grep(ea(q,"input"),ia),r=0;while(g=q[r++])if(d&&n.inArray(g,d)>-1)e&&e.push(g);else if(h=n.contains(g.ownerDocument,g),i=ea(p.appendChild(g),"script"),h&&fa(i),c){f=0;while(g=i[f++])_.test(g.type||"")&&c.push(g)}return i=null,p}!function(){var b,c,e=d.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b]=c in a)||(e.setAttribute(c,"t"),l[b]=e.attributes[c].expando===!1);e=null}();var ka=/^(?:input|select|textarea)$/i,la=/^key/,ma=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,na=/^(?:focusinfocus|focusoutblur)$/,oa=/^([^.]*)(?:\.(.+)|)/;function pa(){return!0}function qa(){return!1}function ra(){try{return d.activeElement}catch(a){}}function sa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)sa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=qa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return"undefined"==typeof n||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(G)||[""],h=b.length;while(h--)f=oa.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=oa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(i=m=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!na.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),h=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),l=n.event.special[q]||{},f||!l.trigger||l.trigger.apply(e,c)!==!1)){if(!f&&!l.noBubble&&!n.isWindow(e)){for(j=l.delegateType||q,na.test(j+q)||(i=i.parentNode);i;i=i.parentNode)p.push(i),m=i;m===(e.ownerDocument||d)&&p.push(m.defaultView||m.parentWindow||a)}o=0;while((i=p[o++])&&!b.isPropagationStopped())b.type=o>1?j:l.bindType||q,g=(n._data(i,"events")||{})[b.type]&&n._data(i,"handle"),g&&g.apply(i,c),g=h&&i[h],g&&g.apply&&M(i)&&(b.result=g.apply(i,c),b.result===!1&&b.preventDefault());if(b.type=q,!f&&!b.isDefaultPrevented()&&(!l._default||l._default.apply(p.pop(),c)===!1)&&M(e)&&h&&e[q]&&!n.isWindow(e)){m=e[h],m&&(e[h]=null),n.event.triggered=q;try{e[q]()}catch(s){}n.event.triggered=void 0,m&&(e[h]=m)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.rnamespace||a.rnamespace.test(g.namespace))&&(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]","i"),va=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,wa=/\s*$/g,Aa=ca(d),Ba=Aa.appendChild(d.createElement("div"));function Ca(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function Da(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function Ea(a){var b=ya.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Ga(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(Da(b).text=a.text,Ea(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&Z.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}function Ha(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&xa.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(o&&(k=ja(b,a[0].ownerDocument,!1,a,d),e=k.firstChild,1===k.childNodes.length&&(k=e),e||d)){for(i=n.map(ea(k,"script"),Da),h=i.length;o>m;m++)g=k,m!==p&&(g=n.clone(g,!0,!0),h&&n.merge(i,ea(g,"script"))),c.call(a[m],g,m);if(h)for(j=i[i.length-1].ownerDocument,n.map(i,Ea),m=0;h>m;m++)g=i[m],_.test(g.type||"")&&!n._data(g,"globalEval")&&n.contains(j,g)&&(g.src?n._evalUrl&&n._evalUrl(g.src):n.globalEval((g.text||g.textContent||g.innerHTML||"").replace(za,"")));k=e=null}return a}function Ia(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(ea(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&fa(ea(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(va,"<$1>")},clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!ua.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(Ba.innerHTML=a.outerHTML,Ba.removeChild(f=Ba.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=ea(f),h=ea(a),g=0;null!=(e=h[g]);++g)d[g]&&Ga(e,d[g]);if(b)if(c)for(h=h||ea(a),d=d||ea(f),g=0;null!=(e=h[g]);g++)Fa(e,d[g]);else Fa(a,f);return d=ea(f,"script"),d.length>0&&fa(d,!i&&ea(a,"script")),d=h=e=null,f},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.attributes,m=n.event.special;null!=(d=a[h]);h++)if((b||M(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k||"undefined"==typeof d.removeAttribute?d[i]=void 0:d.removeAttribute(i),c.push(f))}}}),n.fn.extend({domManip:Ha,detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return Y(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||d).createTextNode(a))},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(ea(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return Y(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(ta,""):void 0;if("string"==typeof a&&!wa.test(a)&&(l.htmlSerialize||!ua.test(a))&&(l.leadingWhitespace||!aa.test(a))&&!da[($.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ea(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(ea(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],f=n(a),h=f.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(f[d])[b](c),g.apply(e,c.get());return this.pushStack(e)}});var Ja,Ka={HTML:"block",BODY:"block"};function La(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function Ma(a){var b=d,c=Ka[a];return c||(c=La(a,b),"none"!==c&&c||(Ja=(Ja||n("