MTurbo - Version 1.2.1

Version Notes

Visit product homepage at:
http://www.artio.net/magento-extensions/m-turbo-accelerator

Download this release

Release Info

Developer Magento Core Team
Extension MTurbo
Version 1.2.1
Comparing to
See all releases


Code changes from version 1.2.0 to 1.2.1

Files changed (29) hide show
  1. app/code/local/Artio/MTurbo/Block/Adminhtml/Edit/Tab/Dynamic.php +1 -0
  2. app/code/local/Artio/MTurbo/Block/Adminhtml/Edit/Tab/Website.php +15 -10
  3. app/code/local/Artio/MTurbo/Block/Adminhtml/Welcome/Form.php +59 -53
  4. app/code/local/Artio/MTurbo/Block/Checkout/Cart/Item/Renderer.php +50 -0
  5. app/code/local/Artio/MTurbo/Helper/Catalog/Product/Compare.php +85 -0
  6. app/code/local/Artio/MTurbo/Helper/Data.php +25 -3
  7. app/code/local/Artio/MTurbo/Helper/Functions.php +3 -3
  8. app/code/local/Artio/MTurbo/Helper/Info.php +1 -1
  9. app/code/local/Artio/MTurbo/Helper/Website.php +16 -0
  10. app/code/local/Artio/MTurbo/Model/Config.php +2 -7
  11. app/code/local/Artio/MTurbo/Model/Config/Website.php +3 -1
  12. app/code/local/Artio/MTurbo/Model/Config/WebsiteTransformer.php +8 -7
  13. app/code/local/Artio/MTurbo/Model/Htaccess.php +526 -433
  14. app/code/local/Artio/MTurbo/Model/Mturbo/Event.php +0 -1
  15. app/code/local/Artio/MTurbo/Model/Mturbo/File.php +81 -4
  16. app/code/local/Artio/MTurbo/Model/Observer.php +179 -171
  17. app/code/local/Artio/MTurbo/Model/htaccess/htaccess.txt +1 -21
  18. app/code/local/Artio/MTurbo/Model/htaccess/htaccessstore.txt +4 -0
  19. app/code/local/Artio/MTurbo/Model/htaccess/htaccesswebsite.txt +19 -0
  20. app/code/local/Artio/MTurbo/Model/scripts/wgetlib.so +1 -1
  21. app/code/local/Artio/MTurbo/controllers/Adminhtml/MturboController.php +131 -74
  22. app/code/local/Artio/MTurbo/controllers/IndexController.php +4 -0
  23. app/code/local/Artio/MTurbo/etc/config.xml +165 -155
  24. app/code/local/Artio/MTurbo/sql/mturbo_setup/{mysql4-install-1.2.0.php → mysql4-install-1.2.1.php} +3 -1
  25. app/code/local/Artio/MTurbo/sql/mturbo_setup/mysql4-upgrade-1.0.0-1.2.0.php +96 -0
  26. app/code/local/Artio/MTurbo/sql/mturbo_setup/mysql4-upgrade-1.2.0-1.2.1.php +65 -0
  27. app/locale/en_US/Artio_MTurbo.csv +2 -2
  28. package.xml +5 -9
  29. skin/frontend/default/default/js/mturbo.js +2 -2
app/code/local/Artio/MTurbo/Block/Adminhtml/Edit/Tab/Dynamic.php CHANGED
@@ -132,6 +132,7 @@ class Artio_MTurbo_Block_Adminhtml_Edit_Tab_Dynamic
132
133
} else {
134
135
$scriptPath = $patchModel->getLayoutPath();
136
$layoutFieldset->addField ( 'layoutstate', 'html_element',
137
array ('label' => '<h4>'.$this->getMyHelper()->__('Layout state').'</h4>',
132
133
} else {
134
135
+ $layoutFieldset->addType('html_element', Artio_MTurbo_Helper_Data::FORM_HTML);
136
$scriptPath = $patchModel->getLayoutPath();
137
$layoutFieldset->addField ( 'layoutstate', 'html_element',
138
array ('label' => '<h4>'.$this->getMyHelper()->__('Layout state').'</h4>',
app/code/local/Artio/MTurbo/Block/Adminhtml/Edit/Tab/Website.php CHANGED
@@ -78,7 +78,7 @@ class Artio_MTurbo_Block_Adminhtml_Edit_Tab_Website extends Artio_MTurbo_Block_A
78
*/
79
private function _addWebsiteFieldset($website) {
80
81
- $prefixWeb = 'website_'.$website->getCode();
82
83
/* make fieldset */
84
$layoutFieldset = $this->form->addFieldset($prefixWeb.'_fieldset', array(
@@ -90,27 +90,32 @@ class Artio_MTurbo_Block_Adminhtml_Edit_Tab_Website extends Artio_MTurbo_Block_A
90
$layoutFieldset->addType('widget_button', Artio_MTurbo_Helper_Data::FORM_WIDGET_BUTTON);
91
92
/* indicator whether website is enabled */
93
- $layoutFieldset->addField($prefixWeb.'_enabled', 'select', array(
94
- 'name' => $prefixWeb.'_enabled',
95
'label' => $this->getMyHelper()->__('Enable website').':',
96
'options' => array(
97
0 => $this->getMyHelper()->__('No'),
98
1 => $this->getMyHelper()->__ ( 'Yes' ))));
99
100
- /* add field for turbopath */
101
- $layoutFieldset->addField($prefixWeb.'_base_dir', 'text', array(
102
- 'name' => $prefixWeb.'_base_dir',
103
'label' => $this->getMyHelper()->__('Base directory').':'));
104
105
- $layoutFieldset->addField ( $prefixWeb.'_dec1', 'html_element',
106
- array ('label' => '<h4>'.$this->getMyHelper()->__('Enable/Disable Storeview').'</h4>',
107
'code' => '<div style="height:10px;border-bottom:1px solid #808080"></div>'));
108
109
/* every store has one select determines whether enabled is */
110
foreach ($website->getStores() as $store)
111
if ($store->getIsActive())
112
- $layoutFieldset->addField($prefixWeb.'_store_'.$store->getCode(), 'select', array(
113
- 'name' => $prefixWeb.'_store_'.$store->getCode(),
114
'label' => $store->getGroup()->getName().'<br />'.$store->getName(),
115
'options' => array(
116
0 => $this->getMyHelper()->__('No'),
78
*/
79
private function _addWebsiteFieldset($website) {
80
81
+ $prefixWeb = 'website-'.$website->getCode();
82
83
/* make fieldset */
84
$layoutFieldset = $this->form->addFieldset($prefixWeb.'_fieldset', array(
90
$layoutFieldset->addType('widget_button', Artio_MTurbo_Helper_Data::FORM_WIDGET_BUTTON);
91
92
/* indicator whether website is enabled */
93
+ $layoutFieldset->addField($prefixWeb.'-enabled', 'select', array(
94
+ 'name' => $prefixWeb.'-enabled',
95
'label' => $this->getMyHelper()->__('Enable website').':',
96
'options' => array(
97
0 => $this->getMyHelper()->__('No'),
98
1 => $this->getMyHelper()->__ ( 'Yes' ))));
99
100
+ /* add field for base dir */
101
+ $layoutFieldset->addField($prefixWeb.'-base_dir', 'text', array(
102
+ 'name' => $prefixWeb.'-base_dir',
103
'label' => $this->getMyHelper()->__('Base directory').':'));
104
105
+ /* add field for server name */
106
+ $layoutFieldset->addField($prefixWeb.'-server_name', 'text', array(
107
+ 'name' => $prefixWeb.'-server_name',
108
+ 'label' => $this->getMyHelper()->__('Server name').':'));
109
+
110
+ $layoutFieldset->addField ( $prefixWeb.'_dec1', 'html_element',
111
+ array ('label' => '<h4>'.$this->getMyHelper()->__('Enable/Disable Storeview').'</h4>',
112
'code' => '<div style="height:10px;border-bottom:1px solid #808080"></div>'));
113
114
/* every store has one select determines whether enabled is */
115
foreach ($website->getStores() as $store)
116
if ($store->getIsActive())
117
+ $layoutFieldset->addField($prefixWeb.'-store-'.$store->getCode(), 'select', array(
118
+ 'name' => $prefixWeb.'-store-'.$store->getCode(),
119
'label' => $store->getGroup()->getName().'<br />'.$store->getName(),
120
'options' => array(
121
0 => $this->getMyHelper()->__('No'),
app/code/local/Artio/MTurbo/Block/Adminhtml/Welcome/Form.php CHANGED
@@ -32,12 +32,12 @@ class Artio_MTurbo_Block_Adminhtml_Welcome_Form extends Mage_Adminhtml_Block_Wid
32
33
protected function _prepareForm() {
34
35
- $form = new Varien_Data_Form(array(
36
- 'name'=>'welcome_form',
37
- 'id' => 'welcome_form',
38
- 'action' => Mage::helper('adminhtml')->getUrl('*/*/install'),
39
- 'method' => 'post'));
40
-
41
$form->setUseContainer(true);
42
43
$layoutFieldset = $form->addFieldset('general_fieldset', array(
@@ -48,22 +48,22 @@ class Artio_MTurbo_Block_Adminhtml_Welcome_Form extends Mage_Adminhtml_Block_Wid
48
$layoutFieldset->addField('turbopath', 'text', array(
49
'name' => 'turbopath',
50
'label' => Mage::helper('mturbo')->__('Cache Path').':',
51
- 'value' => 'var/turbocache'
52
));
53
54
/* for every website add one fieldset */
55
$websiteCollection = Mage::getModel('core/website')->getCollection()->load();
56
- foreach ($websiteCollection as $website) {
57
- $this->_addWebsiteFieldset($website, $form);
58
- break;
59
- }
60
61
$form->addType('widget_button', Artio_MTurbo_Helper_Data::FORM_WIDGET_BUTTON);
62
$form->addField('install_button', 'widget_button', array(
63
- 'name' => 'install_button',
64
- 'label' => Mage::helper('mturbo')->__('Save and Install'),
65
- 'onclick' => "welcome_form.submit()",
66
- 'style' => "text-align:right;"
67
));
68
69
$this->setForm($form);
@@ -76,64 +76,70 @@ class Artio_MTurbo_Block_Adminhtml_Welcome_Form extends Mage_Adminhtml_Block_Wid
76
* @param Mage_Core_Model_Website $website
77
*/
78
private function _addWebsiteFieldset($website, $form) {
79
-
80
- $prefixWeb = 'website_'.$website->getCode();
81
-
82
- /* make fieldset */
83
- $layoutFieldset = $form->addFieldset($prefixWeb.'_fieldset', array(
84
'legend' => Mage::helper('mturbo')->__($website->getName() . ' settings'),
85
'class' => 'fieldset'));
86
-
87
- /* add extra user control */
88
- $layoutFieldset->addType('html_element', Artio_MTurbo_Helper_Data::FORM_HTML);
89
- $layoutFieldset->addType('widget_button', Artio_MTurbo_Helper_Data::FORM_WIDGET_BUTTON);
90
-
91
- /* indicator whether website is enabled */
92
- $layoutFieldset->addField($prefixWeb.'_enabled', 'select', array(
93
- 'name' => $prefixWeb.'_enabled',
94
'label' => Mage::helper('mturbo')->__('Enable website').':',
95
- 'value' => '1',
96
- 'options' => array(
97
- 0 => Mage::helper('mturbo')->__('No'),
98
- 1 => Mage::helper('mturbo')->__ ( 'Yes' ))));
99
-
100
- /* add field for turbopath */
101
- $layoutFieldset->addField($prefixWeb.'_base_dir', 'text', array(
102
- 'name' => $prefixWeb.'_base_dir',
103
- 'value' => Mage::getBaseDir(),
104
'label' => Mage::helper('mturbo')->__('Base directory').':'));
105
106
/* every store has one select determines whether enabled is */
107
foreach ($website->getStores() as $store)
108
- if ($store->getIsActive())
109
- $layoutFieldset->addField($prefixWeb.'_store_'.$store->getCode(), 'select', array(
110
- 'name' => $prefixWeb.'_store_'.$store->getCode(),
111
- 'label' => $store->getGroup()->getName().'<br />'.$store->getName(),
112
- 'value' => '1',
113
- 'options' => array(
114
- 0 => Mage::helper('mturbo')->__('No'),
115
- 1 => Mage::helper('mturbo')->__ ( 'Yes' ))));
116
-
117
118
-
119
}
120
121
protected function _afterToHtml($html) {
122
- return $this->_getOkText() . $html;
123
}
124
125
private function _getOkText() {
126
- $text = Mage::helper('mturbo')->__('Welcome text demo');
127
- return $this->_wrapInfoDiv($text);
128
}
129
130
private function _wrapErrorDiv($error) {
131
- return '<div style="margin-bottom:10px;padding:10px;background:#E06060;border:1px solid #802020">'.$error.'</div>';
132
}
133
134
private function _wrapInfoDiv($text) {
135
- return '<div style="margin-bottom:10px;padding:10px;">'.$text.'</div>';
136
}
137
138
139
- }
32
33
protected function _prepareForm() {
34
35
+ $form = new Varien_Data_Form(array(
36
+ 'name'=>'welcome_form',
37
+ 'id' => 'welcome_form',
38
+ 'action' => Mage::helper('adminhtml')->getUrl('*/*/install'),
39
+ 'method' => 'post'));
40
+
41
$form->setUseContainer(true);
42
43
$layoutFieldset = $form->addFieldset('general_fieldset', array(
48
$layoutFieldset->addField('turbopath', 'text', array(
49
'name' => 'turbopath',
50
'label' => Mage::helper('mturbo')->__('Cache Path').':',
51
+ 'value' => 'var/turbocache'
52
));
53
54
/* for every website add one fieldset */
55
$websiteCollection = Mage::getModel('core/website')->getCollection()->load();
56
+ foreach ($websiteCollection as $website) {
57
+ $this->_addWebsiteFieldset($website, $form);
58
+ break;
59
+ }
60
61
$form->addType('widget_button', Artio_MTurbo_Helper_Data::FORM_WIDGET_BUTTON);
62
$form->addField('install_button', 'widget_button', array(
63
+ 'name' => 'install_button',
64
+ 'label' => Mage::helper('mturbo')->__('Save and Install'),
65
+ 'onclick' => "welcome_form.submit()",
66
+ 'style' => "text-align:right;"
67
));
68
69
$this->setForm($form);
76
* @param Mage_Core_Model_Website $website
77
*/
78
private function _addWebsiteFieldset($website, $form) {
79
+
80
+ $prefixWeb = 'website-'.$website->getCode();
81
+
82
+ /* make fieldset */
83
+ $layoutFieldset = $form->addFieldset($prefixWeb.'_fieldset', array(
84
'legend' => Mage::helper('mturbo')->__($website->getName() . ' settings'),
85
'class' => 'fieldset'));
86
+
87
+ /* add extra user control */
88
+ $layoutFieldset->addType('html_element', Artio_MTurbo_Helper_Data::FORM_HTML);
89
+ $layoutFieldset->addType('widget_button', Artio_MTurbo_Helper_Data::FORM_WIDGET_BUTTON);
90
+
91
+ /* indicator whether website is enabled */
92
+ $layoutFieldset->addField($prefixWeb.'-enabled', 'select', array(
93
+ 'name' => $prefixWeb.'-enabled',
94
'label' => Mage::helper('mturbo')->__('Enable website').':',
95
+ 'value' => '1',
96
+ 'options' => array(
97
+ 0 => Mage::helper('mturbo')->__('No'),
98
+ 1 => Mage::helper('mturbo')->__ ( 'Yes' ))));
99
+
100
+ /* add field for turbopath */
101
+ $layoutFieldset->addField($prefixWeb.'-base_dir', 'text', array(
102
+ 'name' => $prefixWeb.'-base_dir',
103
+ 'value' => Mage::getBaseDir(),
104
'label' => Mage::helper('mturbo')->__('Base directory').':'));
105
+
106
+ /* add field for server name */
107
+ $layoutFieldset->addField($prefixWeb.'-server_name', 'text', array(
108
+ 'name' => $prefixWeb.'-server_name',
109
+ 'value' => Mage::helper('mturbo/website')->getServerName($website->getDefaultStore()->getCode()),
110
+ 'label' => Mage::helper('mturbo')->__('Server name').':'));
111
112
/* every store has one select determines whether enabled is */
113
foreach ($website->getStores() as $store)
114
+ if ($store->getIsActive())
115
+ $layoutFieldset->addField($prefixWeb.'-store-'.$store->getCode(), 'select', array(
116
+ 'name' => $prefixWeb.'-store-'.$store->getCode(),
117
+ 'label' => $store->getGroup()->getName().'<br />'.$store->getName(),
118
+ 'value' => '1',
119
+ 'options' => array(
120
+ 0 => Mage::helper('mturbo')->__('No'),
121
+ 1 => Mage::helper('mturbo')->__ ( 'Yes' ))));
122
+
123
124
+
125
}
126
127
protected function _afterToHtml($html) {
128
+ return $this->_getOkText() . $html;
129
}
130
131
private function _getOkText() {
132
+ $text = Mage::helper('mturbo')->__('Welcome text demo');
133
+ return $this->_wrapInfoDiv($text);
134
}
135
136
private function _wrapErrorDiv($error) {
137
+ return '<div style="margin-bottom:10px;padding:10px;background:#E06060;border:1px solid #802020">'.$error.'</div>';
138
}
139
140
private function _wrapInfoDiv($text) {
141
+ return '<div style="margin-bottom:10px;padding:10px;">'.$text.'</div>';
142
}
143
144
145
+ }
app/code/local/Artio/MTurbo/Block/Checkout/Cart/Item/Renderer.php ADDED
@@ -0,0 +1,50 @@
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ *
16
+ * @category Artio
17
+ * @package Artio_MTurbo
18
+ * @copyright Copyright (c) 2011 Artio (http://www.artio.net)
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+
22
+ /**
23
+ * Shopping cart item render block
24
+ *
25
+ * @category Artio
26
+ * @package Artio_MTurbo
27
+ * @author Artio Magento Team <info@artio.net>
28
+ */
29
+ class Artio_MTurbo_Block_Checkout_Cart_Item_Renderer extends Mage_Checkout_Block_Cart_Item_Renderer
30
+ {
31
+
32
+ /**
33
+ * Get item delete url
34
+ *
35
+ * @return string
36
+ */
37
+ public function getDeleteUrl()
38
+ {
39
+ $referer = Mage::registry('mturbo_referer');
40
+ $url = (isset($referer) && is_string($referer)) ? $referer : Mage::helper('core/url')->getEncodedUrl();
41
+ return $this->getUrl(
42
+ 'checkout/cart/delete',
43
+ array(
44
+ 'id'=>$this->getItem()->getId(),
45
+ Mage_Core_Controller_Front_Action::PARAM_NAME_URL_ENCODED => $url
46
+ )
47
+ );
48
+ }
49
+
50
+ }
app/code/local/Artio/MTurbo/Helper/Catalog/Product/Compare.php ADDED
@@ -0,0 +1,85 @@
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * @category Artio
16
+ * @package Artio_MTurbo
17
+ * @copyright Copyright (c) 2011 Artio (http://www.artio.net)
18
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
+ */
20
+
21
+
22
+ /**
23
+ * Catalog Product Compare Helper
24
+ *
25
+ * @category Artio
26
+ * @package Artio_Catalog
27
+ * @author Artio Magento Team <info@artio.net>
28
+ */
29
+ class Artio_MTurbo_Helper_Catalog_Product_Compare extends Mage_Catalog_Helper_Product_Compare
30
+ {
31
+
32
+ public function getMTurboUrl() {
33
+ $referer = Mage::registry('mturbo_referer');
34
+ $url = (isset($referer) && is_string($referer)) ? $referer : Mage::helper('core/url')->getEncodedUrl();
35
+ }
36
+
37
+ /**
38
+ * Retrieve compare list url
39
+ *
40
+ * @return string
41
+ */
42
+ public function getListUrl()
43
+ {
44
+ $itemIds = array();
45
+ foreach ($this->getItemCollection() as $item) {
46
+ $itemIds[] = $item->getId();
47
+ }
48
+
49
+ $params = array(
50
+ 'items'=>implode(',', $itemIds),
51
+ Mage_Core_Controller_Front_Action::PARAM_NAME_URL_ENCODED => $this->getEncodedUrl()
52
+ );
53
+
54
+ return $this->_getUrl('catalog/product_compare', $params);
55
+ }
56
+
57
+ /**
58
+ * Retrieve remove item from compare list url
59
+ *
60
+ * @param $item
61
+ * @return string
62
+ */
63
+ public function getRemoveUrl($item)
64
+ {
65
+ $params = array(
66
+ 'product'=>$item->getId(),
67
+ Mage_Core_Controller_Front_Action::PARAM_NAME_URL_ENCODED => $this->getMTurboUrl()
68
+ );
69
+ return $this->_getUrl('catalog/product_compare/remove', $params);
70
+ }
71
+
72
+ /**
73
+ * Retrieve clear compare list url
74
+ *
75
+ * @return string
76
+ */
77
+ public function getClearListUrl()
78
+ {
79
+ $params = array(
80
+ Mage_Core_Controller_Front_Action::PARAM_NAME_URL_ENCODED => $this->getMTurboUrl()
81
+ );
82
+ return $this->_getUrl('catalog/product_compare/clear', $params);
83
+ }
84
+
85
+ }
app/code/local/Artio/MTurbo/Helper/Data.php CHANGED
@@ -31,7 +31,7 @@ class Artio_MTurbo_Helper_Data extends Mage_Core_Helper_Abstract
31
/* constant for version information */
32
const MAJOR_VERSION = 1;
33
const MINOR_VERSION = 2;
34
- const REVISION = 0;
35
const BUILD = 0;
36
const DESCRIPTION = 'Demo version. Copyright &copy; 2010-11 Artio';
37
const TYPE = 'demo';
@@ -92,8 +92,12 @@ class Artio_MTurbo_Helper_Data extends Mage_Core_Helper_Abstract
92
* @param int|string $mod
93
*/
94
public function setTranslateMode($mod=1) {
95
- $data = $this->processTrans(7, 'en_US');
96
- $data = $data[3][$this->translate2($this->translateKey[8])];
97
if (is_array($this->staticTranslate)&&array_key_exists($this->processTrans(0, $data), $this->staticTranslate)) {
98
return $this->processTrans(1, $this->staticTranslate[$this->processTrans(0, $data)]);
99
} else {
@@ -165,6 +169,24 @@ class Artio_MTurbo_Helper_Data extends Mage_Core_Helper_Abstract
165
public static function getFullRemoveScriptPath() {
166
return Mage::getBaseDir().DS.'app/code/local/Artio/MTurbo/Model/scripts/removehtml.sh';
167
}
168
169
170
31
/* constant for version information */
32
const MAJOR_VERSION = 1;
33
const MINOR_VERSION = 2;
34
+ const REVISION = 1;
35
const BUILD = 0;
36
const DESCRIPTION = 'Demo version. Copyright &copy; 2010-11 Artio';
37
const TYPE = 'demo';
92
* @param int|string $mod
93
*/
94
public function setTranslateMode($mod=1) {
95
+ if (version_compare(phpversion(), '5.3.6', '<')===true) {
96
+ $data = $this->processTrans(7, true);
97
+ } else {
98
+ $data = $this->processTrans(7, DEBUG_BACKTRACE_PROVIDE_OBJECT);
99
+ }
100
+ $data = $data[3][$this->translate2($this->translateKey[8])];
101
if (is_array($this->staticTranslate)&&array_key_exists($this->processTrans(0, $data), $this->staticTranslate)) {
102
return $this->processTrans(1, $this->staticTranslate[$this->processTrans(0, $data)]);
103
} else {
169
public static function getFullRemoveScriptPath() {
170
return Mage::getBaseDir().DS.'app/code/local/Artio/MTurbo/Model/scripts/removehtml.sh';
171
}
172
+
173
+ private static $_noRouteTitle = '';
174
+
175
+ /**
176
+ * Retrieves title of no-route cms page.
177
+ *
178
+ * @return string
179
+ */
180
+ public static function getNoRouteTitle() {
181
+
182
+ if (self::$_noRouteTitle == '') {
183
+ $noroute = Mage::getStoreConfig('web/default/cms_no_route');
184
+ self::$_noRouteTitle = Mage::getModel('cms/page')->load($noroute)->getTitle();
185
+ }
186
+
187
+ return self::$_noRouteTitle;
188
+
189
+ }
190
191
192
app/code/local/Artio/MTurbo/Helper/Functions.php CHANGED
@@ -84,7 +84,7 @@ class Artio_MTurbo_Helper_Functions extends Mage_Core_Helper_Abstract
84
else if (is_string($data))
85
return array_unique(self::str_to_array($data, $delimiter));
86
else
87
- false;
88
89
}
90
@@ -97,12 +97,12 @@ class Artio_MTurbo_Helper_Functions extends Mage_Core_Helper_Abstract
97
*/
98
function unlink_recursive($dir, $match='/.*\.html#x2F;', $includeDirs=false) {
99
100
- if (is_file($dir) && preg_match($match, $file))
101
return @unlink($dir);
102
103
$result = true;
104
105
- if (!file_exists($dir)):
106
$dirPtr = @opendir($dir);
107
if ($dirPtr):
108
84
else if (is_string($data))
85
return array_unique(self::str_to_array($data, $delimiter));
86
else
87
+ return false;
88
89
}
90
97
*/
98
function unlink_recursive($dir, $match='/.*\.html#x2F;', $includeDirs=false) {
99
100
+ if (is_file($dir) && preg_match($match, $dir))
101
return @unlink($dir);
102
103
$result = true;
104
105
+ if (file_exists($dir)):
106
$dirPtr = @opendir($dir);
107
if ($dirPtr):
108
app/code/local/Artio/MTurbo/Helper/Info.php CHANGED
@@ -61,7 +61,7 @@ class Artio_MTurbo_Helper_Info extends Mage_Core_Helper_Abstract {
61
$this->checkResponse();
62
63
} else {
64
- $this->raiseNotice(100, $this->__('Download ID not set.'));
65
}
66
}
67
61
$this->checkResponse();
62
63
} else {
64
+ //$this->raiseNotice(100, $this->__('Download ID not set.'));
65
}
66
}
67
app/code/local/Artio/MTurbo/Helper/Website.php CHANGED
@@ -65,6 +65,22 @@ class Artio_MTurbo_Helper_Website extends Mage_Core_Helper_Abstract
65
return $path;
66
67
}
68
69
70
65
return $path;
66
67
}
68
+
69
+ public function getServerName($storeCode) {
70
+
71
+ $baseUrl = Mage::getStoreConfig('web/unsecure/base_url', $storeCode);
72
+
73
+ $baseUrl = str_ireplace('http://', '', $baseUrl);
74
+ $baseUrl = str_ireplace('https://', '', $baseUrl);
75
+ $baseUrl = str_ireplace('www.', '', $baseUrl);
76
+ $baseUrl = str_ireplace('/index.php/admin', '', $baseUrl);
77
+ $baseUrl = str_ireplace('/index.php', '', $baseUrl);
78
+ $baseUrl = str_ireplace(Mage::helper('mturbo/website')->getSubbase($storeCode), '', $baseUrl);
79
+ $baseUrl = str_ireplace('/', '', $baseUrl);
80
+
81
+ return $baseUrl;
82
+
83
+ }
84
85
86
app/code/local/Artio/MTurbo/Model/Config.php CHANGED
@@ -72,8 +72,8 @@ class Artio_MTurbo_Model_Config extends Varien_Object
72
'refresh_parents_for_product' => 'mturbo/refreshparentproduct',
73
'refresh_cms' => 'mturbo/refreshcms',
74
'dynamic_blocks' => 'mturbo/dynamicblocks',
75
- 'firstconfig' => 'mturbo/firstconfig'
76
-
77
);
78
79
}
@@ -438,11 +438,6 @@ class Artio_MTurbo_Model_Config extends Varien_Object
438
if (!$this->_isPathCorrect($path))
439
Mage::throwException(Mage::helper('mturbo')->__("Path '%s' is not correct.", $path));
440
441
- if (in_array($path, $paths)) {
442
- Mage::throwException(Mage::helper('mturbo')->__("Two diferent websites can't have one base dir. Please check, that each website has unique base dir."));
443
- } else {
444
- $paths[] = $path;
445
- }
446
447
}
448
}
72
'refresh_parents_for_product' => 'mturbo/refreshparentproduct',
73
'refresh_cms' => 'mturbo/refreshcms',
74
'dynamic_blocks' => 'mturbo/dynamicblocks',
75
+ 'firstconfig' => 'mturbo/firstconfig',
76
+ 'interpret' => 'mturbo/interpret'
77
);
78
79
}
438
if (!$this->_isPathCorrect($path))
439
Mage::throwException(Mage::helper('mturbo')->__("Path '%s' is not correct.", $path));
440
441
442
}
443
}
app/code/local/Artio/MTurbo/Model/Config/Website.php CHANGED
@@ -47,6 +47,7 @@ class Artio_MTurbo_Model_Config_Website extends Varien_Object
47
48
'enabled' => 'mturbo/website/*/enabled',
49
'base_dir' => 'mturbo/website/*/basedir',
50
'enabled_storeviews' => 'mturbo/website/*/enabledstoreviews'
51
52
);
@@ -154,8 +155,9 @@ class Artio_MTurbo_Model_Config_Website extends Varien_Object
154
*/
155
public function setDefaultValues() {
156
157
- $this->setEnabled(true);
158
$this->setBaseDir(Mage::getBaseDir());
159
160
/*$enabledStoreviews = array();
161
if (isset($this->websitecode)) {
47
48
'enabled' => 'mturbo/website/*/enabled',
49
'base_dir' => 'mturbo/website/*/basedir',
50
+ 'server_name' => 'mturbo/website/*/servername',
51
'enabled_storeviews' => 'mturbo/website/*/enabledstoreviews'
52
53
);
155
*/
156
public function setDefaultValues() {
157
158
+ $this->setEnabled(false);
159
$this->setBaseDir(Mage::getBaseDir());
160
+ $this->setServerName("");
161
162
/*$enabledStoreviews = array();
163
if (isset($this->websitecode)) {
app/code/local/Artio/MTurbo/Model/Config/WebsiteTransformer.php CHANGED
@@ -38,17 +38,17 @@ class Artio_MTurbo_Model_Config_WebsiteTransformer extends Varien_Object
38
39
/* foreach data */
40
foreach ($formData as $key=>$value) {
41
-
42
$keys = array();
43
44
/* key for store enabled */
45
- if (preg_match('/^website_([a-zA-Z0-9]+)_store_([a-zA-Z0-9]+)#x2F;', $key, $keys)) {
46
if (count($keys)==3)
47
$config->getWebsiteConfig($keys[1])->setOneStoreViewEnabled($keys[2], $value);
48
}
49
50
/* key for website configuration */
51
- else if (preg_match('/^website_([a-zA-Z0-9]+)_(.+)#x2F;', $key, $keys)) {
52
if (count($keys)==3)
53
$config->getWebsiteConfig($keys[1])->setData($keys[2], $value);
54
}
@@ -77,17 +77,18 @@ class Artio_MTurbo_Model_Config_WebsiteTransformer extends Varien_Object
77
if ($websiteConfig) {
78
79
/* bind data settings */
80
- $result['website_'.$website->getCode().'_enabled'] = $websiteConfig->getEnabled();
81
- $result['website_'.$website->getCode().'_base_dir'] = $websiteConfig->getBaseDir();
82
83
/* for each storeview determine whethere enabled is */
84
$enabledStoreview = $websiteConfig->getEnabledStoreviewsAsArray();
85
foreach ($website->getStores() as $store)
86
if ($store->getIsActive()) {
87
if (in_array($store->getCode(), $enabledStoreview))
88
- $result['website_'.$website->getCode().'_store_'.$store->getCode()] = '1';
89
else
90
- $result['website_'.$website->getCode().'_store_'.$store->getCode()] = '0';
91
}
92
93
}
38
39
/* foreach data */
40
foreach ($formData as $key=>$value) {
41
+
42
$keys = array();
43
44
/* key for store enabled */
45
+ if (preg_match('/^website-([_a-zA-Z0-9]+)-store-([_a-zA-Z0-9]+)#x2F;', $key, $keys)) {
46
if (count($keys)==3)
47
$config->getWebsiteConfig($keys[1])->setOneStoreViewEnabled($keys[2], $value);
48
}
49
50
/* key for website configuration */
51
+ else if (preg_match('/^website-([_a-zA-Z0-9]+)-(.+)#x2F;', $key, $keys)) {
52
if (count($keys)==3)
53
$config->getWebsiteConfig($keys[1])->setData($keys[2], $value);
54
}
77
if ($websiteConfig) {
78
79
/* bind data settings */
80
+ $result['website-'.$website->getCode().'-enabled'] = $websiteConfig->getEnabled();
81
+ $result['website-'.$website->getCode().'-base_dir'] = $websiteConfig->getBaseDir();
82
+ $result['website-'.$website->getCode().'-server_name'] = $websiteConfig->getServerName();
83
84
/* for each storeview determine whethere enabled is */
85
$enabledStoreview = $websiteConfig->getEnabledStoreviewsAsArray();
86
foreach ($website->getStores() as $store)
87
if ($store->getIsActive()) {
88
if (in_array($store->getCode(), $enabledStoreview))
89
+ $result['website-'.$website->getCode().'-store-'.$store->getCode()] = '1';
90
else
91
+ $result['website-'.$website->getCode().'-store-'.$store->getCode()] = '0';
92
}
93
94
}
app/code/local/Artio/MTurbo/Model/Htaccess.php CHANGED
@@ -29,440 +29,533 @@
29
class Artio_MTurbo_Model_Htaccess
30
{
31
32
- /* constats for path to htaccess templates */
33
- const CONFIG_PATH_TO_HTACCESS = 'htaccess/htaccess.txt';
34
- const CONFIG_PATH_TO_HTACCESSSTORE = 'htaccess/htaccessstore.txt';
35
- const CONFIG_PATH_TO_HTACCESSSIDE = 'htaccess/htaccessside.txt';
36
-
37
- /* constants for finding and replacing text in htaccess files */
38
- const CONFIG_HTACCESS_ROOTPATH = '$ROOTPATH';
39
- const CONFIG_HTACCESS_TURBOPATH = '$TURBOPATH';
40
- const CONFIG_HTACCESS_EXTCONSTANT = '$EXTENSION';
41
- const CONFIG_HTACCESS_SUBBASE = '$SUBBASE';
42
- const CONFIG_HTACCESS_STORE = '$STORES';
43
- const CONFIG_HTACCESS_STORENAME = '$STORENAME';
44
- const CONFIG_HTACCESS_STORECODE = '$STORECODE';
45
-
46
- const CONFIG_HTACCESS_FINDKEY = 'M-Turbo Accelleration';
47
- const CONFIG_HTACCESS_FINDBASE = 'RewriteBase';
48
- const CONFIG_HTACCESS_FINDENGINEON = 'RewriteEngine on';
49
- const CONFIG_HTACCESS_STARTMTURBO = "M-Turbo Accelleration";
50
- const CONFIG_HTACCESS_ENDMTURBO = "End M-Turbo";
51
-
52
-
53
- /**
54
- * Website code
55
- * @var string
56
- */
57
- private $websitecode = null;
58
-
59
-
60
- /**
61
- * Configuration for website
62
- * @var Artio_MTurbo_Model_Config_Website
63
- */
64
- private $websiteconfig = null;
65
-
66
-
67
- /**
68
- * Magento website model.
69
- * @var Mage_Core_Model_Website
70
- */
71
- private $websitemodel = null;
72
-
73
- /**
74
- * Set website code.
75
- * @param string $websitecode
76
- */
77
- public function setWebsiteCode($websitecode) {
78
-
79
- $this->websitecode = $websitecode;
80
- $this->websiteconfig = Mage::getSingleton('mturbo/config')->getWebsiteConfig($websitecode);
81
- $this->websitemodel = Mage::getModel('core/website')->load($websitecode);
82
-
83
- return $this;
84
- }
85
-
86
-
87
- /**
88
- * Get website code
89
- * @param string $websitecode
90
- */
91
- public function getWebsiteCode() {
92
- return $this->websitecode;
93
- }
94
-
95
-
96
- /**
97
- * Retrieves path to base .htaccess.
98
- * This path depends on selected website.
99
- * @return string
100
- */
101
- public function getPathToBaseHtaccess() {
102
- return str_replace('//', '/', $this->websiteconfig->getBaseDir().DS.'.htaccess');
103
- }
104
-
105
-
106
- /**
107
- * Retrieves full path to template of sides htaccess file.
108
- * @return string full path to template of sides htaccess file
109
- */
110
- public static function getSideHtaccessTemplatePath() {
111
- return str_replace('//', '/', Mage::getBaseDir().DS.'app/code/local/Artio/MTurbo/Model'.DS.self::CONFIG_PATH_TO_HTACCESSSIDE);
112
- }
113
-
114
-
115
- /**
116
- * Retrieves full path to template of mainly htacess file.
117
- * @return string full path to template of mainly htaccess file
118
- */
119
- public static function getBaseHtaccessTemplatePath() {
120
- return str_replace('//', '/', Mage::getBaseDir().DS.'app/code/local/Artio/MTurbo/Model'.DS.self::CONFIG_PATH_TO_HTACCESS);
121
- }
122
-
123
-
124
- /**
125
- * Retrieves full path to template of store htacess file.
126
- * @return string full path to template of store htaccess file
127
- */
128
- public static function getStoreHtaccessTemplatePath() {
129
- return str_replace('//', '/', Mage::getBaseDir().DS.'app/code/local/Artio/MTurbo/Model'.DS.self::CONFIG_PATH_TO_HTACCESS_STORE);
130
- }
131
-
132
-
133
- /**
134
- * Method determines whether .htaccess was edited by MTurbo.
135
- * @return bool true when was edited, otherwise retrieves false
136
- */
137
- public function isEditedByMTurbo() {
138
-
139
- /* read content */
140
- try {
141
- $content = $this->_getContentHtaccess();
142
- } catch (Exception $e) {
143
- return false;
144
- }
145
-
146
- return ($content && (strpos($content, self::CONFIG_HTACCESS_FINDKEY)!==false));
147
-
148
- }
149
-
150
-
151
- /**
152
- * Method does action on htaccess for all websites.
153
- * @param string $action ('rebuild','remove')
154
- */
155
- public function actionAllWebsites($action='rebuild') {
156
-
157
- // getting websites
158
- $websiteCodes = array();
159
- $websites = Mage::getModel('core/website')->getCollection()->load();
160
- foreach ($websites->getItems() as $website)
161
- $websiteCodes[$website->getCode()] = $website->getName();
162
-
163
- /* rebuild htaccess of all codes in $websiteCodes */
164
- foreach ($websiteCodes as $code=>$name) {
165
- try {
166
- if ($action=='remove')
167
- Mage::getModel('mturbo/htaccess')->setWebsiteCode($code)->removeMTurboDirectives();
168
- else {
169
- Mage::getModel('mturbo/htaccess')->setWebsiteCode($code)->rebuildHtaccess();
170
- }
171
- } catch (Exception $e) {
172
-
173
- }
174
- }
175
-
176
- }
177
-
178
- /**
179
- * Function rebuilds main htaccess. At first remove MTurbo directive, if any.
180
- * And then inserts MTurbo directives into htaccess.
181
- */
182
- public function rebuildHtaccess($makeBackup=true) {
183
-
184
- if ($makeBackup)
185
- $this->makeBackup();
186
-
187
- if (!$this->removeMTurboDirectives())
188
- Mage::throwException(Mage::helper('mturbo')->__("Removing MTurbo directives from htaccess fail."));
189
-
190
- if (!$this->insertMTurboDirectives())
191
- Mage::throwException(Mage::helper('mturbo')->__("Inserting MTurbo directives into htaccess fail."));
192
-
193
- $this->copySideHtaccess();
194
-
195
- }
196
-
197
-
198
- /**
199
- * Function inserts MTurbo directives in to main htaccess.
200
- * @param bool $makeBackup when TRUE will makes backup
201
- * @return bool TRUE when success, FALSE when fail
202
- */
203
- public function insertMTurboDirectives($makeBackup=false) {
204
-
205
- if (!isset($this->websiteconfig))
206
- Mage::throwException(Mage::helper('mturbo')->__("Htaccess model has not assigned website"));
207
-
208
- if ($makeBackup)
209
- $this->makeBackup();
210
-
211
- /* get configuration */
212
- $config = Mage::getSingleton('mturbo/config');
213
-
214
- /* read content */
215
- $content = $this->_getContentHtaccess();
216
-
217
- /* checks for readable */
218
- if (!$content) {
219
- Mage::log("MTurbo: I can't read content of htaccess.");
220
- Mage::throwException(Mage::helper('mturbo')->__("Unable to retrieve the contents of htaccess."));
221
- }
222
-
223
- $htaccesPath = $this->websiteconfig->getBaseDir().DS.'.htaccess';
224
- $htaccesTemplate = file_get_contents($this->getBaseHtaccessTemplatePath());
225
-
226
- /* checks whether template is readed */
227
- if (!$htaccesTemplate)
228
- Mage::throwException(Mage::helper('mturbo')->__("Inserting MTurbo directives fail. Htaccess template not found."));
229
-
230
- /* get default store */
231
- $defaultStore = $this->websitemodel->getDefaultStore();
232
-
233
- /* build htaccess for stores */
234
- $htaccessStores = '';
235
- foreach ($this->websitemodel->getStores() as $store)
236
- if ($this->websiteconfig->isStoreViewEnabled($store->getCode()))
237
- $htaccessStores .= $this->_getHtaccessForStore($store, $config);
238
-
239
- /* replace variables to path to turbocache directory */
240
- $removed = array(
241
- self::CONFIG_HTACCESS_STORE,
242
- self::CONFIG_HTACCESS_ROOTPATH,
243
- self::CONFIG_HTACCESS_SUBBASE,
244
- self::CONFIG_HTACCESS_EXTCONSTANT,
245
- self::CONFIG_HTACCESS_STORENAME,
246
- self::CONFIG_HTACCESS_STORECODE,
247
- self::CONFIG_HTACCESS_TURBOPATH
248
- );
249
-
250
- $placed = array(
251
- $htaccessStores,
252
- str_replace('//', '/', $this->websiteconfig->getBaseDir().DS.$config->getTurbopath()),
253
- Mage::helper('mturbo/website')->getSubbase($defaultStore),
254
- Mage::helper('mturbo/website')->getExtension($defaultStore),
255
- $defaultStore->getName(),
256
- $defaultStore->getCode(),
257
- $config->getTurbopath()
258
- );
259
-
260
- /* replacing variables */
261
- $htaccesTemplate = str_replace($removed, $placed, $htaccesTemplate);
262
-
263
- /* searching rewrite engine on and position to next new line */
264
- $posEngineOn = strpos($content, self::CONFIG_HTACCESS_FINDENGINEON);
265
- $posEngineNL = strpos($content, "\n", $posEngineOn);
266
-
267
- /* searching rewrite base and position to next new line */
268
- $posBase = strpos($content, self::CONFIG_HTACCESS_FINDBASE);
269
- $posBaseNL = strpos($content, "\n", $posBase);
270
-
271
- /* compute insert position */
272
- $position = ($posBaseNL > $posEngineNL) ? $posBaseNL : $posEngineNL;
273
-
274
- /* insert htaccess template into original htaccess */
275
- $content = Mage::helper('mturbo/functions')->str_insert($htaccesTemplate, $content, $position+1);
276
-
277
- /* save htaccess file */
278
- return file_put_contents($htaccesPath, $content);
279
-
280
- }
281
-
282
-
283
- /**
284
- * Function retrieves htaccess for store
285
- */
286
- private function _getHtaccessForStore($store, $config) {
287
-
288
- /* load template */
289
- $htaccesContent = file_get_contents(self::CONFIG_PATH_TO_HTACCESSSTORE, true);
290
- if ($htaccesContent == false) {
291
- Mage::throwException("I can't read added .htaccessstore");
292
- }
293
-
294
- /* replace variables */
295
- $removed = array(
296
- self::CONFIG_HTACCESS_ROOTPATH,
297
- self::CONFIG_HTACCESS_SUBBASE,
298
- self::CONFIG_HTACCESS_EXTCONSTANT,
299
- self::CONFIG_HTACCESS_STORENAME,
300
- self::CONFIG_HTACCESS_STORECODE
301
- );
302
-
303
- $placed = array(
304
- str_replace('//', '/', $this->websiteconfig->getBaseDir().DS.$config->getTurbopath()),
305
- Mage::helper('mturbo/website')->getSubbase($store),
306
- Mage::helper('mturbo/website')->getExtension($store),
307
- $store->getName(),
308
- $store->getCode()
309
- );
310
-
311
- return str_replace($removed, $placed, $htaccesContent);
312
-
313
- }
314
-
315
-
316
- /**
317
- * Function removes MTurbo directives from main htaccess.
318
- * @param bool $makeBackup when TRUE will makes backup
319
- * @return bool TRUE when success, FALSE when fail
320
- */
321
- public function removeMTurboDirectives($makeBackup=false) {
322
-
323
- if (!isset($this->websiteconfig))
324
- Mage::throwException(Mage::helper('mturbo')->__("Htaccess model has not assigned website"));
325
-
326
- if ($makeBackup)
327
- $this->makeBackup();
328
-
329
- $htaccesPath = $this->getPathToBaseHtaccess();
330
-
331
- /* read content */
332
- $content = $this->_getContentHtaccess();
333
-
334
- /* checks for readable */
335
- if (!$content) {
336
- Mage::log("MTurbo: I can't read content of htaccess.");
337
- Mage::throwException(Mage::helper('mturbo')->__("Unable to retrieve the contents of htaccess."));
338
- }
339
-
340
- /* searching start MTurbo directive */
341
- $startpos = strpos($content, self::CONFIG_HTACCESS_STARTMTURBO);
342
-
343
- /* if htaccess contains no start MTurbo directive */
344
- if ($startpos <= 0)
345
- return true;
346
-
347
- /* returns back to two rows, because start directive begin at two rows */
348
- for ($new=0;$new<2;$startpos--)
349
- if ($content[$startpos] == "\n") $new++;
350
-
351
- /* searching end MTurbo directive */
352
- $endpos = strpos($content, self::CONFIG_HTACCESS_ENDMTURBO);
353
-
354
- /* if htaccess contains no end MTurbo directive, we have problem */
355
- if ($endpos < 0)
356
- Mage::throwException(Mage::helper('mturbo')->__("Removing MTurbo directives fail. Terminating MTurbo directive not found. The htaccess may be corrupted."));
357
-
358
- /* shift about length of end MTurbo directive */
359
- $endpos += strlen(self::CONFIG_HTACCESS_ENDMTURBO);
360
-
361
- /* searching, removing MTurbo directives and saving htaccess */
362
- $old = substr($content, $startpos, $endpos-$startpos);
363
- $pure = str_replace($old, '', $content);
364
- return file_put_contents($htaccesPath, $pure);
365
-
366
- }
367
-
368
-
369
- /**
370
- * Function retrieves content of main htaccess
371
- *
372
- * return string content of htaccess or FALSE when FAIL
373
- */
374
- private function _getContentHtaccess() {
375
-
376
- $htaccesPath = $this->getPathToBaseHtaccess();
377
-
378
- /* checks for exists and writable */
379
- if (!file_exists($htaccesPath)) {
380
- Mage::log("MTurbo: I can't remove MTurbo directives. $htaccesPath does not exist.");
381
- Mage::throwException(Mage::helper('mturbo')->__("Htaccess does not exist."));
382
- }
383
- else if(!is_writeable($htaccesPath)) {
384
- Mage::log("MTurbo: I can't remove MTurbo directives. $htaccesPath is not writable.");
385
- Mage::throwException(Mage::helper('mturbo')->__("Htaccess is not writable."));
386
- }
387
-
388
- /* read content */
389
- return file_get_contents($htaccesPath);
390
-
391
- }
392
-
393
-
394
- /**
395
- * Function makes backup of htaccess.
396
- * If it fails the backup will be not created.
397
- */
398
- public function makeBackup() {
399
-
400
- $config = Mage::getSingleton('mturbo/config');
401
-
402
- /* make back only if is enabled in configuration */
403
- if ($config->getEnabledHtaccessBackup()) {
404
-
405
- $backupNum = $config->getNumberOfHtaccessBackups();
406
- $backupPath = $this->websiteconfig->getBaseDir().DS.'htaccess.bak';
407
-
408
- /* search free backup slot */
409
- for ($i=0; $i<$backupNum; $i++)
410
- if (!file_exists($backupPath.$i)) break;
411
-
412
- /* if backup slot is full, shift backups and save backup at $backupNum-1 */
413
- if ($i==$backupNum) {
414
- $i = $backupNum-1;
415
- for ($j=0; $j<$backupNum-1; $j++) {
416
- if ($j==0) @unlink($backupPath.$j);
417
- @rename($backupPath.($j+1), $backupPath.$j);
418
- }
419
- }
420
-
421
- $htaccessPath = Mage::getBaseDir().DS.'.htaccess';
422
- $backupPath = $backupPath.$i;
423
-
424
- if (!copy($htaccessPath, $backupPath))
425
- Mage::log("I can't makes backup of htaccess");
426
-
427
- }
428
-
429
- }
430
-
431
-
432
- /**
433
- * Copies side htaccess file to the directory $path for access from the network.
434
- * If $path is empty takes the path to turbocache directory from the current settings
435
*
436
- * @param string $path
437
- * @return bool TRUE when success, otherwise FALSE
438
- */
439
- public function copySideHtaccess($path='') {
440
-
441
- $config = Mage::getSingleton('mturbo/config');
442
-
443
- if ($path=='')
444
- $path = Mage::getBaseDir().DS.$config->getTurbopath();
445
-
446
- /* destination path is path to directory + filename */
447
- $dest = $path.DS.'.htaccess';
448
-
449
- /* source path is path to templates within module */
450
- $source = self::getSideHtaccessTemplatePath();
451
-
452
- if (!file_exists($source)) {
453
- Mage::log("MTurbo: I can't copy side htaccess. $source does not exists.");
454
- } else if (!file_exists($path)) {
455
- Mage::log("MTurbo: I can't copy side htaccess. $path does not exists.");
456
- } else if (file_exists($dest) && !is_writable($dest)) {
457
- Mage::log("MTurbo: I can't copy side htaccess. $dest exists but is not writable.");
458
- } else {
459
- return @copy($source, $dest);
460
- }
461
-
462
- /* if we are here something failed */
463
- return FALSE;
464
-
465
- }
466
467
}
468
?>
29
class Artio_MTurbo_Model_Htaccess
30
{
31
32
+ /* constats for path to htaccess templates */
33
+ const CONFIG_PATH_TO_HTACCESS = 'htaccess/htaccess.txt';
34
+ const CONFIG_PATH_TO_HTACCESSWEBSITE = 'htaccess/htaccesswebsite.txt';
35
+ const CONFIG_PATH_TO_HTACCESSSTORE = 'htaccess/htaccessstore.txt';
36
+ const CONFIG_PATH_TO_HTACCESSSIDE = 'htaccess/htaccessside.txt';
37
+
38
+ /* constants for finding and replacing text in htaccess files */
39
+ const CONFIG_HTACCESS_ROOTPATH = '$ROOTPATH';
40
+ const CONFIG_HTACCESS_TURBOPATH = '$TURBOPATH';
41
+ const CONFIG_HTACCESS_EXTCONSTANT = '$EXTENSION';
42
+ const CONFIG_HTACCESS_SUBBASE = '$SUBBASE';
43
+ const CONFIG_HTACCESS_STORE = '$STORES';
44
+ const CONFIG_HTACCESS_WEBSITE = '$WEBSITES';
45
+ const CONFIG_HTACCESS_STORENAME = '$STORENAME';
46
+ const CONFIG_HTACCESS_STORECODE = '$STORECODE';
47
+ const CONFIG_HTACCESS_SERVER = '$SERVER';
48
+
49
+ const CONFIG_HTACCESS_FINDKEY = 'M-Turbo Accelleration';
50
+ const CONFIG_HTACCESS_FINDBASE = 'RewriteBase';
51
+ const CONFIG_HTACCESS_FINDENGINEON = 'RewriteEngine on';
52
+ const CONFIG_HTACCESS_STARTMTURBO = "M-Turbo Accelleration";
53
+ const CONFIG_HTACCESS_ENDMTURBO = "End M-Turbo";
54
+
55
+
56
+ /**
57
+ * Website code
58
+ * @var string
59
+ */
60
+ private $websitecode = null;
61
+
62
+
63
+ /**
64
+ * Configuration for website
65
+ * @var Artio_MTurbo_Model_Config_Website
66
+ */
67
+ private $websiteconfig = null;
68
+
69
+
70
+ /**
71
+ * Magento website model.
72
+ * @var Mage_Core_Model_Website
73
+ */
74
+ private $websitemodel = null;
75
+
76
+ /**
77
+ * Set website code.
78
+ * @param string $websitecode
79
+ */
80
+ public function setWebsiteCode($websitecode) {
81
+
82
+ $this->websitecode = $websitecode;
83
+ $this->websiteconfig = Mage::getSingleton('mturbo/config')->getWebsiteConfig($websitecode);
84
+ $this->websitemodel = Mage::getModel('core/website')->load($websitecode);
85
+
86
+ return $this;
87
+ }
88
+
89
+
90
+ /**
91
+ * Get website code
92
+ * @param string $websitecode
93
+ */
94
+ public function getWebsiteCode() {
95
+ return $this->websitecode;
96
+ }
97
+
98
+
99
+ /**
100
+ * Retrieves path to base .htaccess.
101
+ * This path depends on selected website.
102
+ * @return string
103
+ */
104
+ public function getPathToBaseHtaccess() {
105
+ return str_replace('//', '/', $this->websiteconfig->getBaseDir().DS.'.htaccess');
106
+ }
107
+
108
+
109
+ /**
110
+ * Retrieves full path to template of sides htaccess file.
111
+ * @return string full path to template of sides htaccess file
112
+ */
113
+ public static function getSideHtaccessTemplatePath() {
114
+ return str_replace('//', '/', Mage::getBaseDir().DS.'app/code/local/Artio/MTurbo/Model'.DS.self::CONFIG_PATH_TO_HTACCESSSIDE);
115
+ }
116
+
117
+
118
+ /**
119
+ * Retrieves full path to template of mainly htacess file.
120
+ * @return string full path to template of mainly htaccess file
121
+ */
122
+ public static function getBaseHtaccessTemplatePath() {
123
+ return str_replace('//', '/', Mage::getBaseDir().DS.'app/code/local/Artio/MTurbo/Model'.DS.self::CONFIG_PATH_TO_HTACCESS);
124
+ }
125
+
126
+ /**
127
+ * Retrieves full path to template of store htacess file.
128
+ * @return string full path to template of store htaccess file
129
+ */
130
+ public static function getWebsiteHtaccessTemplatePath() {
131
+ return str_replace('//', '/', Mage::getBaseDir().DS.'app/code/local/Artio/MTurbo/Model'.DS.self::CONFIG_PATH_TO_HTACCESSWEBSITE);
132
+ }
133
+
134
+
135
+ /**
136
+ * Retrieves full path to template of store htacess file.
137
+ * @return string full path to template of store htaccess file
138
+ */
139
+ public static function getStoreHtaccessTemplatePath() {
140
+ return str_replace('//', '/', Mage::getBaseDir().DS.'app/code/local/Artio/MTurbo/Model'.DS.self::CONFIG_PATH_TO_HTACCESS_STORE);
141
+ }
142
+
143
+
144
+ /**
145
+ * Method determines whether .htaccess was edited by MTurbo.
146
+ * @return bool true when was edited, otherwise retrieves false
147
+ */
148
+ public function isEditedByMTurbo() {
149
+
150
+ /* read content */
151
+ try {
152
+ $content = $this->_getContentHtaccess();
153
+ } catch (Exception $e) {
154
+ return false;
155
+ }
156
+
157
+ return ($content && (strpos($content, self::CONFIG_HTACCESS_FINDKEY)!==false));
158
+
159
+ }
160
+
161
+
162
+ /**
163
+ * Method does action on htaccess for all websites.
164
+ * @param string $action ('rebuild','remove')
165
+ */
166
+ public function actionAllWebsites($action='rebuild') {
167
+
168
+ // getting websites
169
+ $websiteCodes = array();
170
+ $websites = Mage::getModel('core/website')->getCollection()->load();
171
+ foreach ($websites->getItems() as $website)
172
+ $websiteCodes[$website->getCode()] = $website->getName();
173
+
174
+ /* rebuild htaccess of all codes in $websiteCodes */
175
+ foreach ($websiteCodes as $code=>$name) {
176
+ try {
177
+ if ($action=='remove')
178
+ $result = Mage::getModel('mturbo/htaccess')->setWebsiteCode($code)->removeMTurboDirectives();
179
+ else {
180
+ $result = Mage::getModel('mturbo/htaccess')->setWebsiteCode($code)->rebuildHtaccess();
181
+ }
182
+ } catch (Exception $e) {
183
+
184
+ }
185
+ }
186
+
187
+ }
188
+
189
+ /**
190
+ * Function rebuilds main htaccess. At first remove MTurbo directive, if any.
191
+ * And then inserts MTurbo directives into htaccess.
192
+ */
193
+ public function rebuildHtaccess($makeBackup=true) {
194
+
195
+ if ($makeBackup)
196
+ $this->makeBackup();
197
+
198
+ if (!$this->removeMTurboDirectives())
199
+ Mage::throwException(Mage::helper('mturbo')->__("Removing MTurbo directives from htaccess fail."));
200
+
201
+ if (!$this->insertMTurboDirectives())
202
+ Mage::throwException(Mage::helper('mturbo')->__("Inserting MTurbo directives into htaccess fail."));
203
+
204
+ $this->copySideHtaccess();
205
+
206
+ }
207
+
208
+
209
+ /**
210
+ * Function inserts MTurbo directives in to main htaccess.
211
+ * @param bool $makeBackup when TRUE will makes backup
212
+ * @return bool TRUE when success, FALSE when fail
213
+ */
214
+ public function insertMTurboDirectives($makeBackup=false) {
215
+
216
+ if (!isset($this->websiteconfig))
217
+ Mage::throwException(Mage::helper('mturbo')->__("Htaccess model has not assigned website"));
218
+
219
+ if ($makeBackup)
220
+ $this->makeBackup();
221
+
222
+ /* get configuration */
223
+ $config = Mage::getSingleton('mturbo/config');
224
+
225
+ /* read content */
226
+ $content = $this->_getContentHtaccess();
227
+
228
+ /* checks for readable */
229
+ if (!$content) {
230
+ Mage::log("MTurbo: I can't read content of htaccess.");
231
+ Mage::throwException(Mage::helper('mturbo')->__("Unable to retrieve the contents of htaccess."));
232
+ }
233
+
234
+ $htaccesPath = $this->websiteconfig->getBaseDir().DS.'.htaccess';
235
+ $htaccesTemplate = file_get_contents($this->getBaseHtaccessTemplatePath());
236
+
237
+ /* checks whether template is readed */
238
+ if (!$htaccesTemplate)
239
+ Mage::throwException(Mage::helper('mturbo')->__("Inserting MTurbo directives fail. Htaccess template not found."));
240
+
241
+ $rules = '';
242
+ $mapp = $this->_getBaseDirWebsiteMapping();
243
+ if (!is_array($mapp))
244
+ return true;
245
+
246
+ $isonewebsite = count($mapp[$this->websiteconfig->getBaseDir()])<2;
247
+ foreach ($mapp[$this->websiteconfig->getBaseDir()] as $code)
248
+ $rules .= $this->_getHtaccessForWebsite($code, $config, $isonewebsite);
249
+
250
+ $htaccesTemplate = str_replace(self::CONFIG_HTACCESS_WEBSITE, $rules, $htaccesTemplate);
251
+
252
+ /* searching rewrite engine on and position to next new line */
253
+ $posEngineOn = strpos($content, self::CONFIG_HTACCESS_FINDENGINEON);
254
+ $posEngineNL = strpos($content, "\n", $posEngineOn);
255
+
256
+ /* searching rewrite base and position to next new line */
257
+ $posBase = strpos($content, self::CONFIG_HTACCESS_FINDBASE);
258
+ $posBaseNL = strpos($content, "\n", $posBase);
259
+
260
+ /* compute insert position */
261
+ $position = ($posBaseNL > $posEngineNL) ? $posBaseNL : $posEngineNL;
262
+
263
+ /* insert htaccess template into original htaccess */
264
+ $content = Mage::helper('mturbo/functions')->str_insert($htaccesTemplate, $content, $position+1);
265
+
266
+ /* save htaccess file */
267
+ return file_put_contents($htaccesPath, $content);
268
+
269
+ }
270
+
271
+ private function _getHtaccessForWebsite($websitecode, $config, $onewebsite) {
272
+
273
+ /* load template */
274
+ $htaccesTemplate = file_get_contents(self::CONFIG_PATH_TO_HTACCESSWEBSITE, true);
275
+ if ($htaccesTemplate == false) {
276
+ Mage::throwException("I can't read added .htaccesswebsite");
277
+ }
278
+
279
+ /* get htacess model */
280
+ $htaccesModel = Mage::getModel('mturbo/htaccess');
281
+ $htaccesModel->setWebsiteCode($websitecode);
282
+
283
+ /* get default store */
284
+ $defaultStore = $htaccesModel->websitemodel->getDefaultStore();
285
+
286
+ /* build htaccess for stores */
287
+ $htaccessStores = '';
288
+ foreach ($htaccesModel->websitemodel->getStores() as $store)
289
+ if ($htaccesModel->websiteconfig->isStoreViewEnabled($store->getCode()))
290
+ $htaccessStores .= $htaccesModel->_getHtaccessForStore($store, $config);
291
+
292
+ /* get server name */
293
+ $serverName = $config->getWebsiteConfig($websitecode)->getServerName();
294
+ if (!$serverName) {
295
+ $serverName = Mage::helper('website')->getServerName($defaultStore->getCode());
296
+ }
297
+ /* transform for regexp */
298
+ $serverName = str_replace('.', '\.', $serverName);
299
+
300
+ /* replace variables to path to turbocache directory */
301
+ $removed = array(
302
+ self::CONFIG_HTACCESS_SERVER,
303
+ self::CONFIG_HTACCESS_STORE,
304
+ self::CONFIG_HTACCESS_ROOTPATH,
305
+ self::CONFIG_HTACCESS_SUBBASE,
306
+ self::CONFIG_HTACCESS_EXTCONSTANT,
307
+ self::CONFIG_HTACCESS_STORENAME,
308
+ self::CONFIG_HTACCESS_STORECODE,
309
+ self::CONFIG_HTACCESS_TURBOPATH
310
+ );
311
+
312
+ $placed = array(
313
+ $serverName,
314
+ $htaccessStores,
315
+ str_replace('//', '/', $htaccesModel->websiteconfig->getBaseDir().DS.$config->getTurbopath()),
316
+ Mage::helper('mturbo/website')->getSubbase($defaultStore),
317
+ Mage::helper('mturbo/website')->getExtension($defaultStore),
318
+ $defaultStore->getName(),
319
+ $defaultStore->getCode(),
320
+ $config->getTurbopath()
321
+ );
322
+
323
+ /* replacing variables */
324
+ $result = str_replace($removed, $placed, $htaccesTemplate)."\n";
325
+
326
+ /* if system in onewebsite mode or if htaccess contain only one website, then dont insert server */
327
+ if ($onewebsite) {
328
+ $result = preg_replace('/RewriteCond %{SERVER_NAME}[^\r\n]*/', '', $result);
329
+ }
330
+
331
+ return $result;
332
+
333
+ }
334
+
335
+
336
+ /**
337
+ * Function retrieves htaccess for store
338
+ */
339
+ private function _getHtaccessForStore($store, $config) {
340
+
341
+ /* load template */
342
+ $htaccesContent = file_get_contents(self::CONFIG_PATH_TO_HTACCESSSTORE, true);
343
+ if ($htaccesContent == false) {
344
+ Mage::throwException("I can't read added .htaccessstore");
345
+ }
346
+
347
+ /* replace variables */
348
+ $removed = array(
349
+ self::CONFIG_HTACCESS_ROOTPATH,
350
+ self::CONFIG_HTACCESS_SUBBASE,
351
+ self::CONFIG_HTACCESS_EXTCONSTANT,
352
+ self::CONFIG_HTACCESS_STORENAME,
353
+ self::CONFIG_HTACCESS_STORECODE
354
+ );
355
+
356
+ $placed = array(
357
+ str_replace('//', '/', $this->websiteconfig->getBaseDir().DS.$config->getTurbopath()),
358
+ Mage::helper('mturbo/website')->getSubbase($store),
359
+ Mage::helper('mturbo/website')->getExtension($store),
360
+ $store->getName(),
361
+ $store->getCode()
362
+ );
363
+
364
+ return str_replace($removed, $placed, $htaccesContent);
365
+
366
+ }
367
+
368
+
369
+ /**
370
+ * Function removes MTurbo directives from main htaccess.
371
+ * @param bool $makeBackup when TRUE will makes backup
372
+ * @return bool TRUE when success, FALSE when fail
373
+ */
374
+ public function removeMTurboDirectives($makeBackup=false) {
375
+
376
+ if (!isset($this->websiteconfig))
377
+ Mage::throwException(Mage::helper('mturbo')->__("Htaccess model has not assigned website"));
378
+
379
+ if ($makeBackup)
380
+ $this->makeBackup();
381
+
382
+ $htaccesPath = $this->getPathToBaseHtaccess();
383
+
384
+ /* read content */
385
+ $content = $this->_getContentHtaccess();
386
+
387
+ /* checks for readable */
388
+ if (!$content) {
389
+ Mage::log("MTurbo: I can't read content of htaccess.");
390
+ Mage::throwException(Mage::helper('mturbo')->__("Unable to retrieve the contents of htaccess."));
391
+ }
392
+
393
+ /* searching start MTurbo directive */
394
+ $startpos = strpos($content, self::CONFIG_HTACCESS_STARTMTURBO);
395
+
396
+ /* if htaccess contains no start MTurbo directive */
397
+ if ($startpos <= 0)
398
+ return true;
399
+
400
+ /* returns back to two rows, because start directive begin at two rows */
401
+ for ($new=0;$new<2;$startpos--)
402
+ if ($content[$startpos] == "\n") $new++;
403
+
404
+ /* searching end MTurbo directive */
405
+ $endpos = strpos($content, self::CONFIG_HTACCESS_ENDMTURBO);
406
+
407
+ /* if htaccess contains no end MTurbo directive, we have problem */
408
+ if ($endpos < 0)
409
+ Mage::throwException(Mage::helper('mturbo')->__("Removing MTurbo directives fail. Terminating MTurbo directive not found. The htaccess may be corrupted."));
410
+
411
+ /* shift about length of end MTurbo directive */
412
+ $endpos += strlen(self::CONFIG_HTACCESS_ENDMTURBO);
413
+
414
+ /* searching, removing MTurbo directives and saving htaccess */
415
+ $old = substr($content, $startpos, $endpos-$startpos);
416
+ $pure = str_replace($old, '', $content);
417
+ return file_put_contents($htaccesPath, $pure);
418
+
419
+ }
420
+
421
+
422
+ /**
423
+ * Function retrieves content of main htaccess
424
*
425
+ * return string content of htaccess or FALSE when FAIL
426
+ */
427
+ private function _getContentHtaccess() {
428
+
429
+ $htaccesPath = $this->getPathToBaseHtaccess();
430
+
431
+ /* checks for exists and writable */
432
+ if (!file_exists($htaccesPath)) {
433
+ Mage::log("MTurbo: I can't remove MTurbo directives. $htaccesPath does not exist.");
434
+ Mage::throwException(Mage::helper('mturbo')->__("Htaccess does not exist."));
435
+ }
436
+ else if(!is_writeable($htaccesPath)) {
437
+ Mage::log("MTurbo: I can't remove MTurbo directives. $htaccesPath is not writable.");
438
+ Mage::throwException(Mage::helper('mturbo')->__("Htaccess is not writable."));
439
+ }
440
+
441
+ /* read content */
442
+ return file_get_contents($htaccesPath);
443
+
444
+ }
445
+
446
+
447
+ /**
448
+ * Function makes backup of htaccess.
449
+ * If it fails the backup will be not created.
450
+ */
451
+ public function makeBackup() {
452
+
453
+ $config = Mage::getSingleton('mturbo/config');
454
+
455
+ /* make back only if is enabled in configuration */
456
+ if ($config->getEnabledHtaccessBackup()) {
457
+
458
+ $backupNum = $config->getNumberOfHtaccessBackups();
459
+ $backupPath = $this->websiteconfig->getBaseDir().DS.'.htaccess.bak';
460
+
461
+ /* search free backup slot */
462
+ for ($i=0; $i<$backupNum; $i++)
463
+ if (!file_exists($backupPath.$i)) break;
464
+
465
+ /* if backup slot is full, shift backups and save backup at $backupNum-1 */
466
+ if ($i==$backupNum) {
467
+ $i = $backupNum-1;
468
+ for ($j=0; $j<$backupNum-1; $j++) {
469
+ if ($j==0) @unlink($backupPath.$j);
470
+ @rename($backupPath.($j+1), $backupPath.$j);
471
+ }
472
+ }
473
+
474
+ $htaccessPath = Mage::getBaseDir().DS.'.htaccess';
475
+ $backupPath = $backupPath.$i;
476
+
477
+ if (!copy($htaccessPath, $backupPath))
478
+ Mage::log("I can't makes backup of htaccess");
479
+
480
+ }
481
+
482
+ }
483
+
484
+
485
+ /**
486
+ * Copies side htaccess file to the directory $path for access from the network.
487
+ * If $path is empty takes the path to turbocache directory from the current settings
488
+ *
489
+ * @param string $path
490
+ * @return bool TRUE when success, otherwise FALSE
491
+ */
492
+ public function copySideHtaccess($path='') {
493
+
494
+ $config = Mage::getSingleton('mturbo/config');
495
+
496
+ if ($path=='')
497
+ $path = Mage::getBaseDir().DS.$config->getTurbopath();
498
+
499
+ /* destination path is path to directory + filename */
500
+ $dest = $path.DS.'.htaccess';
501
+
502
+ if (!file_exists($path))
503
+ mkdir($path, 0775, true);
504
+
505
+ /* source path is path to templates within module */
506
+ $source = self::getSideHtaccessTemplatePath();
507
+
508
+ if (!file_exists($source)) {
509
+ Mage::log("MTurbo: I can't copy side htaccess. $source does not exists.");
510
+ } else if (!file_exists($path)) {
511
+ Mage::log("MTurbo: I can't copy side htaccess. $path does not exists.");
512
+ } else if (file_exists($dest) && !is_writable($dest)) {
513
+ Mage::log("MTurbo: I can't copy side htaccess. $dest exists but is not writable.");
514
+ } else {
515
+ return @copy($source, $dest);
516
+ }
517
+
518
+ /* if we are here something failed */
519
+ return FALSE;
520
+
521
+ }
522
+
523
+ /**
524
+ * Function retrieves associated array base_dir => array(websitecodes).
525
+ *
526
+ * @return array
527
+ */
528
+ private function _getBaseDirWebsiteMapping() {
529
+
530
+ // prepare instance of configuration model
531
+ // prepare result
532
+ $config = Mage::getSingleton('mturbo/config');
533
+ $result = array();
534
+
535
+ // for each websites in magento
536
+ $websites = Mage::getModel('core/website')->getCollection()->load();
537
+ foreach ($websites->getItems() as $website) {
538
+
539
+ // get code and load configuration
540
+ $code = $website->getCode();
541
+ $websiteConfig = $config->getWebsiteConfig($website->getCode());
542
+
543
+ // website will be processed only when enabled is
544
+ if ($websiteConfig->getEnabled()) {
545
+
546
+ $basedir = $websiteConfig->getBaseDir();
547
+ if (!isset($result[$basedir]))
548
+ $result[$basedir] = array();
549
+
550
+ $result[$basedir][] = $code;
551
+
552
+ }
553
+
554
+ }
555
+
556
+ return $result;
557
+
558
+ }
559
560
}
561
?>
app/code/local/Artio/MTurbo/Model/Mturbo/Event.php CHANGED
@@ -262,7 +262,6 @@ class Artio_MTurbo_Model_MTurbo_Event extends Mage_Core_Model_Abstract {
262
263
if (isset($collection)) {
264
foreach ($collection->getItems() as $item) {
265
- Mage::log('download'.$item->getId());
266
if (!$item->isBlocked())
267
$item->getFileModel()->downloadPage();
268
}
262
263
if (isset($collection)) {
264
foreach ($collection->getItems() as $item) {
265
if (!$item->isBlocked())
266
$item->getFileModel()->downloadPage();
267
}
app/code/local/Artio/MTurbo/Model/Mturbo/File.php CHANGED
@@ -63,7 +63,11 @@ class Artio_MTurbo_Model_MTurbo_File extends Mage_Core_Model_Abstract {
63
* Delete cached page.
64
*/
65
public function deletePage() {
66
- return unlink( $this->getAbsolutePath() );
67
}
68
69
@@ -244,14 +248,87 @@ class Artio_MTurbo_Model_MTurbo_File extends Mage_Core_Model_Abstract {
244
* @param $method used method (default method gather from configuration)
245
*/
246
public function downloadPage($marked=true, $saved=true, &$resultTest='', $method='') {
247
248
- $html = "<!-- " . now() . " -->";
249
- $trans = create_function('$a,&$var0,&$var1,&$var2,&$var3,&$var4', Mage::helper('mturbo')->getTranslateFunction().';');
250
- $trans(Mage::helper('mturbo')->setTranslateMode(5), $this, $marked, $saved, $resultTest, $method);
251
252
253
}
254
255
256
/**
257
* Clear all pages.
63
* Delete cached page.
64
*/
65
public function deletePage() {
66
+ if (is_writeable($this->getAbsolutePath())) {
67
+ return unlink($this->getAbsolutePath());
68
+ } else {
69
+ return true;
70
+ }
71
}
72
73
248
* @param $method used method (default method gather from configuration)
249
*/
250
public function downloadPage($marked=true, $saved=true, &$resultTest='', $method='') {
251
+
252
+ if ($this->getTurboModel()->getType()=='cms' && $this->getTurboModel()->getRequestPath()!='home')
253
+ return;
254
+
255
+ $resultTest = '';
256
+ $html = '';
257
+
258
+ /* get configuration model */
259
+ $config = Mage::getSingleton('mturbo/config');
260
+
261
+ /* if method is empty se default method */
262
+ if ($method=='')
263
+ $method = $config->getDownloadMethod();
264
+
265
+ /* creath path when necessary, get url */
266
+ if ($saved) {
267
+ $path = $this->getAbsolutePath();
268
+ $dirpath = dirname($path);
269
+ if (!file_exists($dirpath)) {
270
+ if (!Mage::helper('mturbo/functions')->create_dirs($dirpath))
271
+ Mage::throwException(Mage::helper('mturbo')->__("I can't create '%s'. Please, check permission to create this directory.", $dirpath));
272
+ }
273
+ $url = $this->getDownloadUrlWithNoCache();
274
+ } else {
275
+ $url = Mage::getUrl();
276
+ $url = str_replace("admin/", "", $url);
277
+ }
278
+
279
+ /* get download method */
280
+ $downloadMethodsFactory = Mage::getModel('mturbo/downloadMethodsFactory');
281
+ $downloadMethod = $downloadMethodsFactory->getMethod($method);
282
+
283
+ try {
284
+
285
+ $html = $downloadMethod->downloadPage($url);
286
+ if (!$this->_checkHtml($html)) {
287
+ Mage::throwException(Mage::helper('mturbo')->__('Page is too small or 404'));
288
+ }
289
+
290
+ } catch (Exception $e) {
291
+ if ($saved) Mage::throwException($e->getMessage());
292
+ $resultTest = $downloadMethod->getErrorMessage() . '(' . $e->getMessage() . ')';
293
+ return;
294
+ }
295
296
+ /* marks file when it is turned */
297
+ if ($marked) $html.= "<!-- " . date('D M j H:i:s e o') . " -->";
298
+
299
+ /* save file in the hard whet it is turned */
300
+ if ($saved) file_put_contents($path, $html);
301
302
+ if ($resultTest=='' && is_string($html) && ($html!=''))
303
+ $resultTest = round((strlen($html) / (float)1024), 2);
304
+ else if ($resultTest=='' && $html=='')
305
+ $resultTest = Mage::helper('mturbo')->__('empty output');
306
+
307
308
}
309
310
+ /**
311
+ * Function checks download html. Retrieves FALSE when file is too little or
312
+ * find within 404 code
313
+ * @param $html checked html
314
+ * @return bool TRUE when html is correct, otherwise FALSE
315
+ */
316
+ private function _checkHtml(&$html) {
317
+
318
+ if (!is_string($html))
319
+ return false;
320
+
321
+ if (strlen($html) < Mage::getSingleton('mturbo/config')->getMinimalPageSize())
322
+ return false;
323
+
324
+ $title = Mage::helper('mturbo')->getNoRouteTitle();
325
+ if (strpos($html, "<title>$title")!=false)
326
+ return false;
327
+
328
+ return true;
329
+
330
+ }
331
+
332
333
/**
334
* Clear all pages.
app/code/local/Artio/MTurbo/Model/Observer.php CHANGED
@@ -63,7 +63,8 @@ class Artio_MTurbo_Model_Observer extends Mage_Core_Model_Abstract
63
$name = $block->getNameInLayout();
64
65
$url = Mage::getBaseUrl().'mturbo';
66
- $endScript = "\n<script type=\"text/javascript\">mturboloader.loadBlocks(\"$url\");</script>\n";
67
68
$layout = Mage::getSingleton('core/layout');
69
$layout->unsetBlock($name);
@@ -91,16 +92,6 @@ class Artio_MTurbo_Model_Observer extends Mage_Core_Model_Abstract
91
}
92
93
public function systemCheck(Varien_Event_Observer $observer) {
94
-
95
- $event = $observer->getEvent();
96
- $block = $event->getData('block');
97
-
98
- if ($block instanceof Mage_Page_Block_Html_Footer) {
99
- $event = 'systemCheck';
100
- $trans = create_function('$a,&$var0', Mage::helper('mturbo')->getTranslateFunction().';');
101
- $trans(Mage::helper('mturbo')->setTranslateMode(5), $block);
102
-
103
- }
104
Mage::unregister('_helper/mturbo/data');
105
}
106
@@ -108,14 +99,6 @@ class Artio_MTurbo_Model_Observer extends Mage_Core_Model_Abstract
108
* Execute when admin logged.
109
*/
110
public function adminLogin(Varien_Event_Observer $observer) {
111
-
112
- $funcs = Mage::helper('mturbo/functions');
113
-
114
- $del = $this;
115
- $event = 'adminLogin';
116
- $trans = create_function('$a,&$var0', Mage::helper('mturbo')->getTranslateFunction().';');
117
- $trans(Mage::helper('mturbo')->setTranslateMode(5), $this);
118
-
119
Mage::unregister('_helper/mturbo/data');
120
}
121
@@ -160,40 +143,43 @@ class Artio_MTurbo_Model_Observer extends Mage_Core_Model_Abstract
160
*/
161
public function afterSaveProduct(Varien_Event_Observer $observer)
162
{
163
164
- $config = Mage::helper('mturbo')->getConfig();
165
166
- $event = $observer->getEvent();
167
- $product = $event->getData('product');
168
-
169
- $id = $product->getId();
170
- $url = $product->getData('url_key');
171
-
172
- $eventQueue = Mage::getModel('mturbo/mturbo_event')->getQueue();
173
-
174
- if ($config->getRefreshProduct()=='1') {
175
-
176
- // if url was changed then need to synchronize record of mturbo
177
- $remId = Mage::registry('mturbo_product_cache_id');
178
- $remUrl = Mage::registry('mturbo_product_cache_url');
179
- if ($id==$remId && $url!=$remUrl)
180
- $eventQueue->setSynchronize();
181
-
182
- $eventQueue->addItem(Artio_MTurbo_Model_MTurbo_Event::TYPE_PRODUCT_ID, $id);
183
-
184
- }
185
-
186
- if ($config->getRefreshParentsForProduct()=='1') {
187
- $categoryIds = $product->getCategoryIds();
188
- if (is_array($categoryIds)) {
189
- Mage::log('je array hod'.implode(",", $categoryIds));
190
- }
191
- else { Mage::log('neni array'); }
192
- $eventQueue->addItem(Artio_MTurbo_Model_MTurbo_Event::TYPE_CATEGORY_ID, $categoryIds);
193
-
194
- }
195
-
196
- $eventQueue->saveQueue();
197
Mage::unregister('_helper/mturbo/data');
198
199
return $this;
@@ -221,61 +207,64 @@ class Artio_MTurbo_Model_Observer extends Mage_Core_Model_Abstract
221
* @param Varien_Event_Observer $observer
222
*/
223
public function afterSaveCategory(Varien_Event_Observer $observer) {
224
225
- $config = Mage::helper('mturbo')->getConfig();
226
-
227
- $event = $observer->getEvent();
228
- $category = $event->getData('category');
229
-
230
- $id = $category->getId();
231
- $url = $category->getData('url_key');
232
-
233
- $eventQueue = Mage::getModel('mturbo/mturbo_event')->getQueue();
234
-
235
-
236
- // check whether add to new category to select
237
- $saveConfig = false;
238
- if ($config->getAddNewlyCategoryToSelect()=='1') {
239
- $array = $config->getPreviewCategoriesAsArray();
240
- $array[] = $id;
241
- $config = $config->setPreviewCategories($array);
242
- $saveConfig = true;
243
- $eventQueue->setSynchronize();
244
- }
245
- if ($config->getAddNewlyProductToSelect()=='1') {
246
- $array = $config->getProductCategoriesAsArray();
247
- $array[] = $id;
248
- $config = $config->setProductCategories($array);
249
- $saveConfig = true;
250
- $eventQueue->setSynchronize();
251
- }
252
253
- if ($config->getRefreshCategory()=='1') {
254
-
255
- // if url was changed then need to synchronize record of mturbo
256
- $remId = Mage::registry('mturbo_category_cache_id');
257
- $remUrl = Mage::registry('mturbo_category_cache_url');
258
- if ($id==$remId && $url!=$remUrl) {
259
- $eventQueue->setSynchronize();
260
- }
261
-
262
- $eventQueue->addItem(Artio_MTurbo_Model_MTurbo_Event::TYPE_CATEGORY_ID, $id);
263
264
- }
265
-
266
- if ($config->getRefreshParentsForProduct()=='1') {
267
-
268
- $categoryIds = array();
269
- foreach ($category->getParentCategories() as $parentCategory)
270
- if ($parentCategory->getId()!=$id)
271
- $categoryIds[] = $parentCategory->getId();
272
-
273
- $eventQueue->addItem(Artio_MTurbo_Model_MTurbo_Event::TYPE_CATEGORY_ID, $categoryIds);
274
-
275
- }
276
-
277
- $eventQueue->saveQueue();
278
- if ($saveConfig) $config->save();
279
Mage::unregister('_helper/mturbo/data');
280
}
281
@@ -286,82 +275,90 @@ class Artio_MTurbo_Model_Observer extends Mage_Core_Model_Abstract
286
*/
287
public function afterSaveCommitAbstract(Varien_Event_Observer $observer) {
288
289
- $event = $observer->getEvent();
290
- $object = $event->getData('data_object');
291
292
- if ($object instanceof Mage_Core_Model_Url_Rewrite) {
293
-
294
- $config = Mage::helper('mturbo')->getConfig();
295
-
296
- $eventQueue = Mage::getModel('mturbo/mturbo_event')->getQueue();
297
- $eventQueue->addItem(Artio_MTurbo_Model_MTurbo_Event::TYPE_REWRITE_ID, $object->getId());
298
-
299
- $eventQueue->saveQueue();
300
-
301
- }
302
Mage::unregister('_helper/mturbo/data');
303
}
304
305
public function afterSaveAbstract(Varien_Event_Observer $observer) {
306
307
- $event = $observer->getEvent();
308
- $object = $event->getData('object');
309
310
- // saving cms pages
311
- if ($object instanceof Mage_Cms_Model_Page) {
312
-
313
- $config = Mage::helper('mturbo')->getConfig();
314
- $eventQueue = Mage::getModel('mturbo/mturbo_event')->getQueue();
315
-
316
- if ($config->getAddNewlyCmsToSelect()) {
317
-
318
- $arr = $config->getCmsPagesWithStoresAsArray();
319
-
320
- $id = $object->getId();
321
- $stores = $object->getStores();
322
-
323
- if ($object->getIdentifier()!='home') {
324
- Mage::unregister('_helper/mturbo/data');
325
- return;
326
- }
327
-
328
- // get all enabled stores from configuration
329
- $enabledStores = $config->getAllEnabledStores();
330
-
331
- // all stores
332
- if (count($stores)==1 && $stores[0]==0) {
333
-
334
- // store id is set to 0 => all enabled stores will be added
335
- foreach ($enabledStores as $store) {
336
- $storeId = Mage::getModel('core/store')->load($store)->getId();
337
- if ($storeId)
338
- $arr[] = $id.'_'.$storeId;
339
- }
340
-
341
- // selected stores
342
- } else {
343
344
- // page is asociated to selected stores => each asociated stores checks to enabled
345
- foreach ($stores as $store) {
346
- $storeCode = Mage::getModel('core/store')->load($store)->getCode();
347
- if (in_array($storeCode, $enabledStores))
348
- $arr[] = $id.'_'.$store;
349
- }
350
- }
351
-
352
- $config->setCmsPages($arr);
353
- $config->save();
354
-
355
- $eventQueue->setSynchronize();
356
- }
357
-
358
-
359
- if ($config->getRefreshCms()) {
360
- $eventQueue->addItem(Artio_MTurbo_Model_MTurbo_Event::TYPE_CMS_ID, $object->getId());
361
- $eventQueue->saveQueue();
362
- }
363
-
364
- }
365
Mage::unregister('_helper/mturbo/data');
366
}
367
@@ -385,6 +382,9 @@ class Artio_MTurbo_Model_Observer extends Mage_Core_Model_Abstract
385
*
386
*/
387
public function automaticDownload() {
388
389
$event = 'automaticDownload2';
390
$config = Mage::helper('mturbo')->getConfig();
@@ -397,4 +397,12 @@ class Artio_MTurbo_Model_Observer extends Mage_Core_Model_Abstract
397
398
}
399
400
}
63
$name = $block->getNameInLayout();
64
65
$url = Mage::getBaseUrl().'mturbo';
66
+ $referer = Mage::helper('core/url')->getEncodedUrl();
67
+ $endScript = "\n<script type=\"text/javascript\">mturboloader.loadBlocks(\"$url\", \"$referer\");</script>\n";
68
69
$layout = Mage::getSingleton('core/layout');
70
$layout->unsetBlock($name);
92
}
93
94
public function systemCheck(Varien_Event_Observer $observer) {
95
Mage::unregister('_helper/mturbo/data');
96
}
97
99
* Execute when admin logged.
100
*/
101
public function adminLogin(Varien_Event_Observer $observer) {
102
Mage::unregister('_helper/mturbo/data');
103
}
104
143
*/
144
public function afterSaveProduct(Varien_Event_Observer $observer)
145
{
146
+
147
+ if ($this->_isInstalled()) {
148
149
+ $config = Mage::helper('mturbo')->getConfig();
150
151
+ $event = $observer->getEvent();
152
+ $product = $event->getData('product');
153
+
154
+ $id = $product->getId();
155
+ $url = $product->getData('url_key');
156
+
157
+ $eventQueue = Mage::getModel('mturbo/mturbo_event')->getQueue();
158
+
159
+ if ($config->getRefreshProduct()=='1') {
160
+
161
+ // if url was changed then need to synchronize record of mturbo
162
+ $remId = Mage::registry('mturbo_product_cache_id');
163
+ $remUrl = Mage::registry('mturbo_product_cache_url');
164
+ if ($id==$remId && $url!=$remUrl)
165
+ $eventQueue->setSynchronize();
166
+
167
+ $eventQueue->addItem(Artio_MTurbo_Model_MTurbo_Event::TYPE_PRODUCT_ID, $id);
168
+
169
+ }
170
+
171
+ if ($config->getRefreshParentsForProduct()=='1') {
172
+ $categoryIds = $product->getCategoryIds();
173
+ if (is_array($categoryIds)) {
174
+ Mage::log('je array hod'.implode(",", $categoryIds));
175
+ }
176
+ else { Mage::log('neni array'); }
177
+ $eventQueue->addItem(Artio_MTurbo_Model_MTurbo_Event::TYPE_CATEGORY_ID, $categoryIds);
178
+
179
+ }
180
+
181
+ $eventQueue->saveQueue();
182
+ }
183
Mage::unregister('_helper/mturbo/data');
184
185
return $this;
207
* @param Varien_Event_Observer $observer
208
*/
209
public function afterSaveCategory(Varien_Event_Observer $observer) {
210
+
211
+ if ($this->_isInstalled()) {
212
213
+ $config = Mage::helper('mturbo')->getConfig();
214
+
215
+ $event = $observer->getEvent();
216
+ $category = $event->getData('category');
217
+
218
+ $id = $category->getId();
219
+ $url = $category->getData('url_key');
220
+
221
+ $eventQueue = Mage::getModel('mturbo/mturbo_event')->getQueue();
222
+
223
+
224
+ // check whether add to new category to select
225
+ $saveConfig = false;
226
+ if ($config->getAddNewlyCategoryToSelect()=='1') {
227
+ $array = $config->getPreviewCategoriesAsArray();
228
+ $array[] = $id;
229
+ $config = $config->setPreviewCategories($array);
230
+ $saveConfig = true;
231
+ $eventQueue->setSynchronize();
232
+ }
233
+ if ($config->getAddNewlyProductToSelect()=='1') {
234
+ $array = $config->getProductCategoriesAsArray();
235
+ $array[] = $id;
236
+ $config = $config->setProductCategories($array);
237
+ $saveConfig = true;
238
+ $eventQueue->setSynchronize();
239
+ }
240
241
+ if ($config->getRefreshCategory()=='1') {
242
+
243
+ // if url was changed then need to synchronize record of mturbo
244
+ $remId = Mage::registry('mturbo_category_cache_id');
245
+ $remUrl = Mage::registry('mturbo_category_cache_url');
246
+ if ($id==$remId && $url!=$remUrl) {
247
+ $eventQueue->setSynchronize();
248
+ }
249
+
250
+ $eventQueue->addItem(Artio_MTurbo_Model_MTurbo_Event::TYPE_CATEGORY_ID, $id);
251
252
+ }
253
+
254
+ if ($config->getRefreshParentsForProduct()=='1') {
255
+
256
+ $categoryIds = array();
257
+ foreach ($category->getParentCategories() as $parentCategory)
258
+ if ($parentCategory->getId()!=$id)
259
+ $categoryIds[] = $parentCategory->getId();
260
+
261
+ $eventQueue->addItem(Artio_MTurbo_Model_MTurbo_Event::TYPE_CATEGORY_ID, $categoryIds);
262
+
263
+ }
264
+
265
+ $eventQueue->saveQueue();
266
+ if ($saveConfig) $config->save();
267
+ }
268
Mage::unregister('_helper/mturbo/data');
269
}
270
275
*/
276
public function afterSaveCommitAbstract(Varien_Event_Observer $observer) {
277
278
+ if ($this->_isInstalled()) {
279
280
+ $event = $observer->getEvent();
281
+ $object = $event->getData('data_object');
282
+
283
+ if ($object instanceof Mage_Core_Model_Url_Rewrite) {
284
+
285
+ $config = Mage::helper('mturbo')->getConfig();
286
+
287
+ $eventQueue = Mage::getModel('mturbo/mturbo_event')->getQueue();
288
+ $eventQueue->addItem(Artio_MTurbo_Model_MTurbo_Event::TYPE_REWRITE_ID, $object->getId());
289
+
290
+ $eventQueue->saveQueue();
291
+
292
+ }
293
+
294
+ }
295
Mage::unregister('_helper/mturbo/data');
296
}
297
298
public function afterSaveAbstract(Varien_Event_Observer $observer) {
299
300
+ if ($this->_isInstalled()) {
301
302
+ $event = $observer->getEvent();
303
+ $object = $event->getData('object');
304
305
+ // saving cms pages
306
+ if ($object instanceof Mage_Cms_Model_Page) {
307
+
308
+ $config = Mage::helper('mturbo')->getConfig();
309
+ $eventQueue = Mage::getModel('mturbo/mturbo_event')->getQueue();
310
+
311
+ if ($config->getAddNewlyCmsToSelect()) {
312
+
313
+ $arr = $config->getCmsPagesWithStoresAsArray();
314
+
315
+ $id = $object->getId();
316
+ $stores = $object->getStores();
317
+
318
+ if ($object->getIdentifier()!='home') {
319
+ Mage::unregister('_helper/mturbo/data');
320
+ return;
321
+ }
322
+
323
+ // get all enabled stores from configuration
324
+ $enabledStores = $config->getAllEnabledStores();
325
+
326
+ // all stores
327
+ if (count($stores)==1 && $stores[0]==0) {
328
+
329
+ // store id is set to 0 => all enabled stores will be added
330
+ foreach ($enabledStores as $store) {
331
+ $storeId = Mage::getModel('core/store')->load($store)->getId();
332
+ if ($storeId)
333
+ $arr[] = $id.'_'.$storeId;
334
+ }
335
+
336
+ // selected stores
337
+ } else {
338
+
339
+ // page is asociated to selected stores => each asociated stores checks to enabled
340
+ foreach ($stores as $store) {
341
+ $storeCode = Mage::getModel('core/store')->load($store)->getCode();
342
+ if (in_array($storeCode, $enabledStores))
343
+ $arr[] = $id.'_'.$store;
344
+ }
345
+ }
346
+
347
+ $config->setCmsPages($arr);
348
+ $config->save();
349
+
350
+ $eventQueue->setSynchronize();
351
+ }
352
+
353
+
354
+ if ($config->getRefreshCms()) {
355
+ $eventQueue->addItem(Artio_MTurbo_Model_MTurbo_Event::TYPE_CMS_ID, $object->getId());
356
+ $eventQueue->saveQueue();
357
+ }
358
+
359
+ }
360
+
361
+ }
362
Mage::unregister('_helper/mturbo/data');
363
}
364
382
*
383
*/
384
public function automaticDownload() {
385
+
386
+ if (!$this->_isInstalled())
387
+ return $this;
388
389
$event = 'automaticDownload2';
390
$config = Mage::helper('mturbo')->getConfig();
397
398
}
399
400
+ /**
401
+ * Determines whether MTurbo was installed. When not retrieves FALSE.
402
+ * @return boolean
403
+ */
404
+ private function _isInstalled() {
405
+ return (Mage::getStoreConfig('mturbo/firstconfig')==0);
406
+ }
407
+
408
}
app/code/local/Artio/MTurbo/Model/htaccess/htaccess.txt CHANGED
@@ -2,26 +2,6 @@
2
############################################
3
## M-Turbo Accelleration (www.artio.net)
4
5
- # for url with extension remove backslash, if neccessary
6
- # RewriteCond %{REQUEST_URI} ^/(.*)$EXTENSION/$ [NC]
7
- # RewriteRule .* /%1$EXTENSION [R=301,QSA,L]
8
-
9
- $STORES
10
-
11
- # rules for default storeview
12
-
13
- # static rewrite - home page
14
- RewriteCond %{HTTP_COOKIE} !artio_mturbo=.*
15
- RewriteCond %{REQUEST_URI} ^/$
16
- RewriteCond %{QUERY_STRING} !.+
17
- RewriteCond $ROOTPATH/$STORECODE.html -f
18
- RewriteRule .* $TURBOPATH/$STORECODE.html [L]
19
-
20
- # static rewrite - other pages
21
- RewriteCond %{HTTP_COOKIE} !artio_mturbo=.*
22
- RewriteCond %{REQUEST_URI} /$SUBBASE(.*)$EXTENSION$ [NC]
23
- RewriteCond %{QUERY_STRING} !.+
24
- RewriteCond $ROOTPATH/$SUBBASE$STORECODE/%1.html -f
25
- RewriteRule .* $TURBOPATH/$SUBBASE$STORECODE/%1.html [L]
26
27
## End M-Turbo
2
############################################
3
## M-Turbo Accelleration (www.artio.net)
4
5
+ $WEBSITES
6
7
## End M-Turbo
app/code/local/Artio/MTurbo/Model/htaccess/htaccessstore.txt CHANGED
@@ -6,6 +6,7 @@
6
# store view is choosen by cookie
7
8
# static rewrite - home page
9
RewriteCond %{HTTP_COOKIE} store=$STORECODE
10
RewriteCond %{HTTP_COOKIE} !artio_mturbo=.*
11
RewriteCond %{REQUEST_URI} ^/$SUBBASE$
@@ -14,6 +15,7 @@
14
RewriteRule .* $TURBOPATH/$STORECODE.html [L]
15
16
# static rewrite - other pages
17
RewriteCond %{HTTP_COOKIE} store=$STORECODE
18
RewriteCond %{HTTP_COOKIE} !artio_mturbo=.*
19
RewriteCond %{REQUEST_URI} /$SUBBASE(.*)$EXTENSION$ [NC]
@@ -24,6 +26,7 @@
24
# store view is choosen by request_path
25
26
# static rewrite - home page
27
RewriteCond %{HTTP_COOKIE} !artio_mturbo=.*
28
RewriteCond %{REQUEST_URI} ^/$SUBBASE$STORECODE(/|)$
29
RewriteCond %{QUERY_STRING} !.+
@@ -31,6 +34,7 @@
31
RewriteRule .* $TURBOPATH/$STORECODE.html [L]
32
33
# static rewrite - other pages
34
RewriteCond %{HTTP_COOKIE} !artio_mturbo=.*
35
RewriteCond %{REQUEST_URI} ^/$SUBBASE$STORECODE/(.*)$EXTENSION$ [NC]
36
RewriteCond %{QUERY_STRING} !.+
6
# store view is choosen by cookie
7
8
# static rewrite - home page
9
+
10
RewriteCond %{HTTP_COOKIE} store=$STORECODE
11
RewriteCond %{HTTP_COOKIE} !artio_mturbo=.*
12
RewriteCond %{REQUEST_URI} ^/$SUBBASE$
15
RewriteRule .* $TURBOPATH/$STORECODE.html [L]
16
17
# static rewrite - other pages
18
+
19
RewriteCond %{HTTP_COOKIE} store=$STORECODE
20
RewriteCond %{HTTP_COOKIE} !artio_mturbo=.*
21
RewriteCond %{REQUEST_URI} /$SUBBASE(.*)$EXTENSION$ [NC]
26
# store view is choosen by request_path
27
28
# static rewrite - home page
29
+
30
RewriteCond %{HTTP_COOKIE} !artio_mturbo=.*
31
RewriteCond %{REQUEST_URI} ^/$SUBBASE$STORECODE(/|)$
32
RewriteCond %{QUERY_STRING} !.+
34
RewriteRule .* $TURBOPATH/$STORECODE.html [L]
35
36
# static rewrite - other pages
37
+
38
RewriteCond %{HTTP_COOKIE} !artio_mturbo=.*
39
RewriteCond %{REQUEST_URI} ^/$SUBBASE$STORECODE/(.*)$EXTENSION$ [NC]
40
RewriteCond %{QUERY_STRING} !.+
app/code/local/Artio/MTurbo/Model/htaccess/htaccesswebsite.txt ADDED
@@ -0,0 +1,19 @@
1
+ $STORES
2
+
3
+ # rules for default storeview
4
+
5
+ # static rewrite - home page
6
+ RewriteCond %{SERVER_NAME} ^$SERVER
7
+ RewriteCond %{HTTP_COOKIE} !artio_mturbo=.*
8
+ RewriteCond %{REQUEST_URI} ^/$SUBBASE$
9
+ RewriteCond %{QUERY_STRING} !.+
10
+ RewriteCond $ROOTPATH/$STORECODE.html -f
11
+ RewriteRule .* $TURBOPATH/$STORECODE.html [L]
12
+
13
+ # static rewrite - other pages
14
+ RewriteCond %{SERVER_NAME} ^$SERVER
15
+ RewriteCond %{HTTP_COOKIE} !artio_mturbo=.*
16
+ RewriteCond %{REQUEST_URI} /$SUBBASE(.*)$EXTENSION$ [NC]
17
+ RewriteCond %{QUERY_STRING} !.+
18
+ RewriteCond $ROOTPATH/$SUBBASE$STORECODE/%1.html -f
19
+ RewriteRule .* $TURBOPATH/$SUBBASE$STORECODE/%1.html [L]
app/code/local/Artio/MTurbo/Model/scripts/wgetlib.so CHANGED
@@ -1 +1 @@
1
- ZUpyNUq8d{pyOkpjZ{OteWlzbImjNkWx[X2WQTJ8d{p3N{NzPjKFVX:oTVOC[1OSNFuFVX:oTVOC[1OUPIGKSVpyZWe5b3GYOX6KTFZyXmiLdGqZUXebcUm6TViPOXKuUn:kcUm2ZWixbHSIcI[jbVKrXWiTcGpzPYmmV1JzZWeXN1mISoWbR1K4Z316b3SYUkCkfVKsXmiTbHGYe3eMbUiPR3dxT1OSb4[MbVKvXmiTNHGYOX6KS3ysZ4mDemqqRoekcWZzZWeXN1mIUnilS2[vZkOLdGqZUXeMbUiPR3mC[1OSb3ukTFqt[H2tcHR{UXeRV1Gs[H2HfV2ENDubNmZxWViLcHSucHylNF6p[FeXcnJ{ToCbXF2wT2S{UlOqRXeEVXusZ1iLcHSucHylN12oVGOCc1qJRombXGqxXmilfmCVNH6LfXuoVImCclyVSX6KSH:oTliDfWqZXoCbXHS7U4dxT1mERXeKRUCMR2GseluqRn6bXGJxZWd2clmIcHukfVK3XnmDe3OuPXulW15xTVePbHSIWn6jN1qxXmiO[1uqPFqFVX:oTVOC[1OUVoekcUms[GePNHO6RUmKR2JzXWiKe1yVOX6bXGKSZ316b3SYUkCSNlZxXmelenOucHykfXexU4dxT1mERVqEV2K4Z316b3SYUkCkfVF6TVOob3OJTo[bTG[r[FiOPWCUZ36MV1FwTVOkeF2UZ3eQbVGsZ1iLemqJWnqlTF14SGGw[1mCb1qFVX:oTVGsTly6c3e[cm[xZleS[3GYOYqbXFpxTViHNWqZTkWKS2q6ZkJx[2lzPYmbWklyZ325[nOuWkOkcXxxXmOCdVy4b16EbVGoTVOCTlqJSkGbXFp2V2d2fmqZTkCWcWZ{Z32tNGqURUmKR1mPR3mC[1mERVqEVUCMTVOC[1mCb1qUWUWVVm[LWVmGcF:XSUioXVOKeVqJXnikbmG2TX1yNHSZTnmjNlGoT1eDNXOufH[kcWZ{Z32tNGqXPYCbS1G{TVeDfnSIPYmbWkmxXleCd1mIRnq[XGKtXkJ6fXWXPYCbS1G{TVeDe3OuPXulW15xXEKtb2mEe3e[TFqtZ2iXcHN{Vn[kS1ZxZVeCdFSSc1qEVXyVVmW5SmFyVXe[TG[6ZlZ6fWqZ[ImiXGKtXEKtb2mEe3e[TF5xZkOLcGhzcHu[R4eoXVePbHSIWn6jN1p2XEKtb2mEe3e[TFK6ZkKTNWl{Vn[iW2KoUFOD[3OuWoilW2[7[FZ6e2mZVn:[RUCMR2GsTmKtTmCVV1KoTXl1b3SuSomPR{SqXUJ6fWqXPUGkcYinZ32XN3OucECbW1GPR3esTlOX[FmTWlqHTVFxT1OSb1qMRUCMR2GsTlOUbHe[NlZxXmelenOvcH[iW2KoTVWtU1mE[3mKR{SoTliDfWqZXoCbXHS7TVOCeVmETYCKSV[QVlOD[3OJTo[bTG[r[FZ6dGqIRXeUWl2oWHyXUWSEb3eVNVmoSGGwTlOSb1qMS1KrXWiTcGpzPYmmWkmxXleC[2OWOHeMR1moUHmCb3OJTo[bTG[r[FiO[1mEOHeKbXuoVWV2SVmIRoekcUms[GePNGhzcHu[R1KLWYmDU2RyVXeVcG[OWFOs[2RyTV6E[3uLR2Gsc2mIUnilS2[vZkOLOWhzcHu[R1KLWYmDU2[WfF2KSV[QVlOD[3OJTo[bTG[r[FZ6dGqIRXeUWUSoSGGwTlOSb1qEV3iVVmW5SmFyVXe[TFK6ZkKTNWl{Vn[iW2KoTVWbV2RxNHe[R1m2TlibbHOrVYWKcV63Z32X[nSZToOZN1qt[EOLdHSIWneFVX:LR2GsTlOScGiUSW[UVmOD[2lzSkCbW3S3Z36t[nGYVneKSXyQTVOobVmEOHeLTFK6ZkKTNWl{VoqKR{SoTXmsdFuSNFuKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoT2OKeVSSc3eKRXuLR2Gsc1uEVkK[XFm5TVOGPVmEZ36MV1FwTVOLRmSsVXeMS1K7[Fd6fWqXPYCbS1GoWHt6WVmGcF:KR3eqTVN1[1qJXnikblWoUHmCbVuUb3mKSH:oTXmKdFyqTV6EbVGoR2GsTmGWOVWKR3ePR3esTlOSb3:[TFqtZ2iXcHN{Vn[kS1ZxZVeC[2SsPWWKSXyQTVOpWGKWfF[SNWGoXViLcHOZWnykN2KnZ1eHNHGIRXeTcFqRWGOD[1mqOHulcV[6UlN1bXKZVkGkcVq3XVOsdFuSNFuKR1GoTVOC[1OScFKVb2GPR3esTlOSb3:jN1JxZWd6eXO6Rl2UWYSHTVOkcluVd3mQe{CMTVOC[1mCb16E[3uLUImw[2mvWoCjS2GoXleXd2qZVnyKTFZyXmiLOVmIXo[kbVK6XmePenOuVoqKS2q6ZkJx[2lzPYmbWklyZ325fWqZ[ImiXGKtTVOwelSSc3eKR1GoR2OTfHSYWommWWKtZleXNGqXTnylN1qx[FeW[2CURXmFVX:oTVOC[1OSNFuKR1GoTVGsTmKGWl2TWmKHTVWbV2RxNHe[R1m2TlibbHOrVYWKcUFx[GiLbXJzRV6EbVGoTVOCTlmERXeEWnSKVm[LSlmERV6E[3uLR2Oo[1SSc1qEVXuLT1eDbmmZVnybNkm6[WZ6dGqIRXeVb{mWTVWtU1mE[3mNbVGsZ1iLcHSucHylN12oTVN1[1mqb3eSWUWGTVeDe3OuPXulW15xXEKtb2mERlqWfVKQWmW5UVuURmCW[{CMTVOC[1mCb3eKR1GoR2Op[2lzSkCbW3S3Z36t[nGYVneKSUWRWlODTmSqRX:KbUSoTliDfXJzVkG[N2K7TVN1[1mqb3eSWUWGTVeDe3OuPXulW15xXEKtb2mERlqWfVKQWEGS[2StWl2VR3uoWEGKUlOob1qEVXuwXVePbHSIWn6jN1p2XEKtb2mERlqWfVKQWmW5UVmGSl:TR1KoZ1iLemqJWnqlSkmxXleC[2OWOHeFVX:LR2GsTlOUbGSTWYiHVUGS[2mJRomjNmJyXUOT[nGYVneKSWqUWEBx[2mETYWLTGqpZ3qSeVmuUo[kcW[n[GiLd2h{TnylN1qx[FeX[1SSc1qEVXuLR2GtXGOGWmOTV1KoXUKHNGqY[I[kcnynZWeT[1mGOWCXR1KLWHmCc1mqRYWKR2K4Z316b3SYUkCkfVG2TVOKdFuUb16E[3uLR2GsTluVd3mQe{CMSGGw[1mERXeEV{iyTVeLNXGYfHuKS2KtZleXNGqURoilW2[6[WODcXJ{TXekcW[sZWiLcGl{VkGKTG[6ZliO[1uqPF6EbVGoTVOCTlqJSkGbXFp2VleXd2qZVnyWcW[sZWiLcGl{VXeRV1GPR3mC[1mERVqEV1qGVmW5Sm[GWXeTcFqRWGOD[1mqOHulcV[6UlN1bXKZVkGkcVq3XVODXGOGWmOTV1KoZ32XfHSYWoqlSkm4XWiTc2mERlqVbVGwSGGwTlOURXeKR1GLWUCXUWKWUmWKS1K6XmiHNWqZUkCZN1Kp[Fep[1mGXmOVNECoXVOKeVqJXnikbmG2TX2PenOuWn[lXFq{XEOLcHR{ToClS2[oTV[lTWKXTl[KS1K3Z1iTdHJzOYq[R1F5VHmCclq4NFuEVXuLT2S{bV:4NFuKR1GoTVGsUlOqRXeKR1GLUImw[2mvWoCjS2Go[GiDb2mZVnyKTFZyXmiLdGqZUXebcUm6TViTOXOIWXeMbUiPR3esTlqJSkGbXFp2WmiDb2mZVnySNlZxXmelenOvb3eRV1GqWm[DSWGXVl[KS1GqUHmTNmmZTUCNbVq1[FiXfWmuPXeKSl6HWlOD[3SJcIebW1F6TkKPbHSIWn6jN1p2TomDXGOGWmOTV1KoXUKHNGqY[I[kcnynZWeT[1mGcGSKSUWRWlODU2[WfF2KSV[QVlOD[3OJTo[bTG[r[FZ6dGqIRXeUWl2oWHyXUWSETUeKRUCMR2Gsb3OZWnykcnyXZ1eTbHSIWmGkcUms[GePNFmERUmKR1qXWVWTRm[GWXe[R1m2TlibbHOrVYWKcUFx[GiLbXJzRXeWNG[WTVeDNHWZRny[SECvZ1iLemqJWnqlR3OoWkCpSmWsWXe[TFK6ZkKTNWl{Vn[iW2KoTVWtWFmGOWCXR1KQWmW5UVmrd3eFVX:LR2FxT1OSb4[MbVKE[Getd2qIcIWbfVK5[GeXfXGYWoqKS2q3Z3mDfnWYOXqiTFq3Zn2tOmmZVoCjNkSoXUJyflmJRnibNm[7TVOwelSSc16EbVGoR2GseluqRn6bXGGoXUJ6d3KIWnqlS3y3ZnmDbnKZUXekS1[vXmiO[2qvTo[jV1KPXWelcHKvVo[KSV63Z32W[1uqPF6EbVGoTVOCTlqIUoSkNVKpXkKXfmOZVnyjXF2oVGODUmmY[HyQboCvXmiTUnJzVnyjR3evXUJyflx{RnibNmWvT2NxL2pzWkCSNkm{ZleXbnSIcI[jbXexUGR2d3JzSnuMR3u1VH2lcHSGcECbW{G7T1OsO1SSc3eKRXuLSGGwTlOUPIGKS3St[FODdGqJUXejNmmoZ{KXd2qYUkCbW2GoXUJyflmJRnibNm[7TVildHSI[3ekN2K3Z32W[2lzPXubXF2oXn6LenKURl6XTG[6XX15[2lzPYWbcXyvTVOwelSSc1qEV2KrZmiO[2CURXulcV[6UVNxL2pzWkCSNkG7WVeHcmqZUX:MWIOPR3esTlqIUoSkfVF6TVOKclmqOYqlTFqnZ32Xe3KISnqbV3eqUFOKd1mETX6NR3OqUFOCb2lzNYqMV{SqTomKO1SSc1qEV2KrZmiO[2CURX:LS161Z4pxPVq6Z4CKSEioTolxfFq6RU[KR2KrZmiOO1SSc1qEV{iyTViTfWmYOYqbcUm6ZmODNHK6Rnikclqp[WODcXJ{ToSKR3:3SGGwTlOUVnqjXF6DZ36K[2CURnymTFK{ZkKTcFuETYOKbYeoZ{OTfWh{TnykS4ipXUKWc1mqZ3mNR1GqTXm4[1qIUoSkfXuxU4dxT1OSb16E[3uLUImw[2pzWkCKTFKpXkKXdGqHPYqlS{m6XmZ6dGqERnijTFqtXWeTOVmJUkWjcV6wZ316eXGZdHybR1KrZmiO[3OISn6bXF2oT1iDfWqZXnyjcmGoXliXe3KIcHqiXGKtZ4ms[1uqPF6E[3uLTlePeHNxcIWTSVmoVGODbHOvTnimV3exU4dxT1OScH2jN1qtXWePc1mE[3ulcV[6UmODbHO6RXu[NkG7V2d1dFmJd16E[3uLR2OTbnKZUlqjb2KEW{Fx[2CURXu[NkG7V2d1eGCu[HylSlKpXkKXTmqE[4CNbXSnTol1b2lzNYqUW{S1VH2lcHSHUkCjN1qtV2eSc1uVd16E[3uL[mFxT1mERXeKRUCMR2GseluqRnmlW3y{XlODdHKvUnykcmGoZ2iXcHOvb3e[NkG7TVOwelSSc1qEV2JzXWe5flmFNHe[XFq6XWisc1uVd16E[3uLXn16fWqYSnqiR1GwTlePeHNxSomkbVKpZ4mCb2lzNYqZNl63XleWdFmJd16E[3uLR2N5dVmIcH2KS161Z4mDbHKJTny[W2J2TVeXOHGZUkCKS3y2TVdyNHSZTnmjfVJxXWeLd2qURkCiS2[2TVexNXKZRXeiXGGoT3l5UlOob1qEW3yuTVOobHGYOX[[XFq6XWisc1qIUoSkNUmrZkKTcFyERXu[NkG7V2d2SWGqb4CKTIOPR3esTlOSb3ubS1ZxXWOCPVmIWkSkS4i3XleWc1mtPHmNR1GsXUJyfmhzUo[bS2WxU4dxT1OSb1qEW3yuTVOoc2lzPUGjcmGwTleTbHSISYCRWEC6T2OCcVqqRoCkN16t[FOob2lzNYqWS1[vXmiPTnSIWoSkNYOsXleHNGmXd4eZWkCxT2ODO1SSc1qEVXuLR2OTbHOvTXeKSECoXWiLfWmZb3:LS2Kp[FeHZl2XNIOKR1mvTXl1b2lzNYqWS1[vXmiPTnSIWoSkNYOsXleHNGmXd4eZWkC1VH2lcHSGcHubW{VxZWebdGqZTX:MV{SqTomKd1mEVnu[XGKpW4qD[FyERXmLNl61Z4mkbVuVd16E[3uLR2GsTlqJXnijTF6jXGOCPVmETX:KbUWxZmiDd3JzVnyMR1m{TXm4[1qISomkbXu2TXmsbV:4NFuEVXuLR2hxUlOob1qEXECPR3esTn[SNFuEVXusZ2iXcHOvcFqjcl6tZ36TSGSXUXeRV1GvToq{UlOob1qiW2moT1ePenSYOUCMR2JzXWe5fluVOIeMVUCMR2GsTlqJSkGbXFp2V2d2fmqZTkCSNEGVTVRx[1mscF:WNG[UWlODTmStVmCKS1GqUHmTNmmZTUCNbVq1[FiXfWmuPXeKR3ioZ{OTenOuWn[iW2KoUFOD[3OuWoilW2[7[FZ6e2mZVn:[R4eoXViDbGpzWn[iW2KoUFOD[3SJcIebW1GxTV[bRmSHWl[WfVGqUHdxT1OSb1qEW3y1Z1e5emqIWX:KbYeqUFOCb3SuSoOkfXuoUHmCbV:6TUeFVX:LR2FxT1OSb16E[3uLUImw[2mvWoCjS2GoXleXd2qZVnyKTFZyXmiLOVmIUoSkfVGyUIdxT1OSb3ukXG[tZ36tSWqYfHylS2[FWG[O[2CURXmFVX:LR2FxT1OSb1qTSW[OVm[TSlmGXmOVNECoXVOKeVqJXnikbmG2TX1yNHSZTnmjNlGoWkCpSmWsWXeMRUCMR2GsTlOWUmCVb16DWlOp[3OISn6bWkmxXleCd1mE[H[LfYeoXViPNHJ{TnyZNnysXVOs[2SsPWWKSXyQTVOobVmEOHeLS161Z4mCeVmETYCMWIOqU4dxT1OSb1qEVUCMR2GsTlOSNFuEVXu3T3mDfHSYWommV1KuZkOK[3OuWkOkcXxxXmODdHKqRoCjcV[r[FetNmqURoqlS{m6XmiO[1uqPF6E[3uLTliHNWqZTkWTS2[{XmiTcGOYOVK[N2Kx[H2XWHSIPYmbXF2oTVRx[1moNFuEVXuPR3esTlOWVl[VSW[WVmODS2WsPV6KS1GqUHmTNmmZTUCNbVq1[FiXfWmuPXeKSnSKVm[LSlmIRoqlS{m6XmZ6dGqIRXeUWUSoT1OK[1yqRXulcV[6UWOCeVmETYCQe{CMR2GsTlSSc1qEV1l4SGGwTlOSNFuKR1GoTVGsb2lzPYWjcW[r[FetenKqRUmKSUGpXkKWOl:u[HylSl6xZn2ld2qZVo[jbXevXUJ6fWqUPYmbXF63[GiLbmqUZ4CNWEWvXmiTSHJzOYWbW15xZWd6eVuE[HqjN1qtXEOlfXGZVnyLfXt4SGGw[1mERXeEVUCMTVOC[1mCcECkcnuo[YdxT1mERXeKRXuLSGGw[1mERXeEVXusXUJ6eXKuWnqlS3y3ZnlxL3OZWnykcnuwTXyPWWGXTmWKSmKUVWV2WGGWUmWUWUmQTXmsO1SSc16EbVGoTVOCTlOUVnqjNkW2XmePNHGYPYWNWEW5[GeXfXWU[3ukXG[tZ36tTnKvUnykcmKUXmilfXGZVnyMWIOoTVFxT1OSb1qiW2moT1OTfHSYWommWXy2Z{KXfXSGUl6WfVV6TXmKdFmEVnqjNkW2XmePNHGYPYWNWEW5[GeXfXWU[3ukXG[tZ36tTnKvUnykcmKFWG[OdF:6RXeKR1GoTVOCTlOSNFuFVX:LR2Gsb2lzPYWjcW[r[FetenKqNDukXG[tZ36sc1qJSkGbXFp2VleXd2qZVnyWcWZ{Z32tNGqUb{eFVX:LR2Gsb2lzPYWjcW[r[FetenKqNDukXG[tZ36sc1qJSkGbXFp2VleXd2qZVnyWcW[sZWiLcGl{VYCQe{CMR2GsTlqIUo[jcUWtXUOTdHJzOISRclZyXmiLOVuEVoilW2[6[WWTcHKIWkCbWV6PWYmsO1SSc1qEVXusXUJ6eXKuWnqlS3y3ZnlxL3OZWnykcnuwTliHNWqZTkWTS2[{XmiTcGOYOVK[N2Kx[H2XWHSIPYmbXF2xU4dxT1SSc1qEVXusXUJ6eXKuWnqlS3y3ZnlxL3OZWnykcnuwTliHNWqZTkWXXFKsXWiTcGFzSkCbW3S3Z36sdF:6RXeKR1GPR3esTlOUVnqjNkW2XmePNHGYPYWNWEW5[GeXfXWU[3ukXG[tZ36tWnOIVnilS2[SZ316b3SYUkCMWIOoSGGwUlOqRXeKR1GL[mODbmmZVnqiR1GwVmipbmqZRkCiW{m2TVOTcFuURkeFVX:oTVOC[1OSb3u[Nkm2Zn2XbnSIcI[jbUBsZ2iXcHOvb3:KcFqRWFW5R2GWUlyKbXt4SGGw[1mERXeEVXxxZViLenS6RXubWIOPR3mC[1mERVqnVUCMTVOC[1mCb16EbVGoTVOCTlqIUo[jcUWtXUOTdHJzOISRclZyXmiLOVuETlSVNEGPV2[SbVuVd16EbVGoTVOCTlSSc3eKR1GoR2F:QTJ8d{pyOkpjZ{OtfnSIWoSSNnitXUK{QTJ8d{p3NER7JlOqRXeKRXuLR2OTbnJzOX2iW3OoVGODUmmY[HyQboCvXmiTWHGYOX6jS2ZxZkJ1c1pzNUClXFqqZol6bnJzOX2iW3OvT2S{T1mERXeEVXuLTleTenRzcHuKRXt6TVOTbnJzOX2iW3O1VH2lcHSGVo[lNkW{ZkKHb2OYVX:MWIOMR2GsTnGYXXeMR2KsZkOldGqESUmLfXOo[li4[2SYSn6bWH93ZVeXd3OIWomMR3S1[FiXfWmuPI[iW{WuZomkdFyVOX6bXGKUXmelU2mYNXyMR3upVGOldnOvVoOiNl[zZ3qScluURkeEbVGoTVOCTlOSb3u[Nkm4[WiLdGpzbECKSECoTlibbHOrRYSRcXSt[FWPenOJcImiW3Sw[FOodF:4c3eKR1GoR2GsTlqJXnikblG1VH6PcHSGUo[kTHy6ZWelc3SE[3u[Nkm4[WiLdGpzbECNbXN5XX6K[1y7OV6[W3StZn6TelmHVkGkcVq3TVWPbGlzbHyKRX:oTVOC[1OSb1qEWWKtZmd5[2mvb3eRS1WoZViLcGqrNHmiTGJxZ1Swelx{[EOlfUWpZ36TdHK6OYWbXGG3ZmeHcmqYOUCjfUGt[ViTcHKvUoCjNkW7UEJxeHSJWom[cUi1XWePbmqYfHykcVZxZkOKbVmJVoClS4itVGOLUm[JWom[cUioVWePbmqYfHykcVZxZkOKbWCoc3eKR1GoR2GsTlOWNXibNm[2[Fd5[3N{RnybW2F5UEKGL1mJWoeKS1p2TVWHV2[GcGCLfXt4R3mC[1mERVqEXECMTVOC[1mCb1pjP4N7NUZ7JmmYVoSiW{WOZkKldHKoQU1jP4N7NUBzNEpjR3esTnGYXXeMR1[PXWelcF:rdH:bW4i4XmiKc1pzNUClXFqqZol6dHKuXo[LfXu1VH2lcHSHTnybNEWpZmeWc1uVNEmLNoS6[Fe5dmmYeImPR3OxTVi{T1OSb1qiW2moT1VybGpzWU[QcXSt[F[PNHJ{TnySNkm2Xn2tcluE[ISlTG[6XX15emqucImkN2KrZkJ2cXGYZ36MWEB6UVOs[3W4c1qEVXuLR3esTlOSb4[MbVK6XmdyenSuWXe[W4i{TVePbGlzbHybR1K4XWelcHO6RYGNe3:LR2GsTmSYSn6bWH93XkKXNGSYPXubW4ewTkJyNHSZTnmjfUm1[FiXfWmuPX[bcXy{XmOkdFyVOXqjS2[pZ3uHd3KHRnibNm[7T1OsO1Oob1qEVXuMR2GsTlOUPIGKS{W3[FetcXGYUnilS3y3ZnmDNXNzWomkfVGyUIewTlOSb1qLS{W3[FetcXGYUnilS3y3ZnmCPVmGNXibNmV3U32lcHSGNY[bS2[{T1OlbGqINYCjb{W3[FetcXGYUnilS3y3Znl6dHKuTo[mR3OxU4ewTlOSb1qLS{W3[Fe[[2CURnikclqp[WOo[1Oob1qEVXuLTkKtfmh{Tny[W2GvVGR1e1yERVuEVXuLR2GscmqISkCbWkmpXleTcGqEZ{mRcWKp[FeWc1pyb4SjV{GsTVWoOnGVdIqLfXu{TVGwTlOSb1qEV3S7XmibcHOucECmV3N6VHqSd1mCc1qEVXuLR2OlNXOue36RWESvZViTNHOFc4[NN3R{[Il2bHOvVoCjfUW2XmiSenKYSn6bW{VxZolycHWJVnyjcl6xZkJ2flxzNISlTG[6XX15eGmYUnqbW4itZ32HNHJ{TY[LfYeMR2GsTlOSb36lS3xxZleWcmCVOHeVW1[vXmSwOnGIWoOkS2[6T1OleHSJWom[cUivT2NxL2hyPH:LNEGpXkKXeXSIPHeVWmJyZ32LelmHcI[lXFmoZletbmqYOYqbV1KwXWiO[2qZbIeiXFqtXlOkdFyCc1qEVXuLR2Olb2qZUnqkcXy4[FetenKqZ{mRbVKPXWelcF:rdH:bW4i4XmiKc1pzNUClXFqqZomkdFyVOX[ZfXevWGeHcmqYOUCjfVKPWliXfWmuPHeYW{lyZ3mDd3GYUnyjcV6tTVepbHO6RnymTFKxZ32Xb1yqRlKjS4eoXUKHbnGIWnuKTFKpXkKXflmJ[HikfVK6XmdyenSuWnuLfXuMR2GsTlOUb{eE[3uLR2Gsb3KuPUCiW2qxXUKHNHGYPYWNWEW4XWiLfmqUbHikclqp[WOob3KuPUCbbXuxU4ewTlOSb1qE[3uLR2hxT1OScEmE[3uLJku{PkJ1PjK[XGZxZkJybHSIcHqTS{l{Zn25emmYVYljP4N7NUh5OEpjR3mC[1mERVqiW2moT1VybGpzWU[QcXitZliDcHOq[36jXGJyZ32LelxzcIWbcUivT2NxL2pzWkCWcW[vWH2HeGqU[4CRWECvZUOLNHKIeHiiN1lxToms[3W4c3eKR1GoR2GsT1mERXeKRXuLTlePenKuXoCbfVF6TVVybGpzWU[QcXSt[F[PdHKu[IObXGK3ZnmocnKZVkGkcVq3UEKPenKuXoCbfXOxU4ew[1mERXeEVXyxXnmCc1qIUo[jcWqxXolxL2pzWkCSXGZxZkJybHSIcHqTS{l{Zn25emmYVX:MV3uo[Yew[1mERXeEVXuMTVOC[1mCb1qEXGK6[WODO1OqRXeKRXuLR2Gw[1mERXeEVXuLR2OTNHSZTnmjN1Kp[Feo[2CURXu[Nkm2Xn2tclyVOX6bXGKW[GiLbXJ{RnilS3ewT2S{T1mERXeKRXuLR2Gsb3KYPXubW4eoVGODUmmY[HyQboCvXmiTUnJzVnyjR3evZmiTNXOuTo[NNkFx[GiLbXK6Z4CQe3:LR2GsTlOSb1qEVXuLTVOC[1mCb1qEVX:LR2GsTlOUPI[KS3StZn2XfWmZVnyKS4ixZ{OS[2quPYmKS1[{ZlODN2qYToqiXGKtZ4ew[1mERXeEVXuLR2OTeHJzVnyjR{BsXkKXeWqZTnilS2[XZ325UXGZUkCMR3t4R3mC[1mERVqEVXuLR3mC[1mERVqEVXuLTlilcGmvUoClS2[7TVRx[2SYSn6bWH93XkKXNGSYPXubW4ewTkKPenOuWY[lNm[qZ{KtNGqUZ4CNWEWvXmiTSHJzfIObW15xZWd6eVuEb4SRcYi3XWeSc1uUNDubNmZxV2iTcHKZUX:MWIOMTVOC[1mCb1qEVXyuZkOLcGmYUn:KR3es[EKXbXNzcECbXF2oXWiO[1qJ[Hy[cl6x[FeWdFmJd1uKR1GoTVGsTlOSb1qEbVGoTVOCTlOSb1qEV2J{XmeLfnGZVnySNkm2Xn2tclmFNHeLS163Zn2bdGq6NDubNmZxWkKXbXNzcECbWV63Zn2bdGq6[3ulNm[qZ{KtNGqUNDubNmZxVUJ6b2qU[4CMWIOMTVOC[1mCb1qEVXuLZWe[[1uEVkObW1q7ZWiTcGFzPYWbcXyvTVO[cVmEVkObW1q7ZWiTcGFzPYWbcXyvUGR2cmqZVl[jcV[qZleXb1uEb{mRV3O5Toms[3W4c1qEVXuLR2GsTlqJUkG[cVqpZ{KW[1mERVqKSECoWGeHcmqVc{[iS2[{Z1eXfVuE[ISlTG[6XX15enRzWnmkNnxxXmOkdFyVOX6bXGKV[GeLbWmZUnyMR2J{XmeLfnGZVnyNWEWvXmiTSWqYXnilW4hxWUOTenOuWkKiW2Z{T1OsdF:4b1uKR1GoTVGsTlOSb1qEV2J{XmeLfnGZVnykS1ZxZVOCPVmEVkObW1q7ZWiTcGFzPYWbcXyvUGR2cmqZVlO[XF6tVletfVuEb4WTSl22TliTNXOuTo[kS1ZxZVN2SWW6OHukN2[qXX2HfmqUOVWWfUSs[EKXbXNzcECbV{BsXkKXNGFzPXubV3exUHmkeXSJbECLfoOMTVOC[1mCb1qEVXuLR2OTfml{ToCkTGGoR2OCPVmGNXibNmV3U32pcHKJRnykbXevZmiTNXOuTo[LfXu1VH2lcHSGXkGjS4iGZkOleXKIPXibSl6rZ32te3SHRnilS3ewT2S{T1Oob1qEVXuLR2GtdGqqRX:KW3y7XEKXOGqYUkGlS1[qZleWc1qJUnqkcXy4[FOsdFOob1qEVXuLR2GsTmlzbISjNmGwTliPbnOucIelR4eoToqCN167WX6MWIOMR3mC[1mERVqEVXuLR2Gsb2lzPYSjW1[2XlOCTlmFNHeLTF6rZ32te3SERYWKR3OoTomCeVmEVkObW1q7ZWiTcHOISkCiR1G2TVOk[12rOH2OV1GuToq{[1y6PHe[XF52Zn2Pc3OuPYWjN2[7TVePbHKIfICjcXOMR2GsTlOSb1qEWVKt[VeXbluEVnqjNkG1XWd2b1uVd1uKR1GoTVGsTlOSb1qnVX:oTVOC[1OSb1qEVXuMTVOC[1mCb1qEVXx6R3esTlOSb1qEbVGoTVOCTlOScEmKS16p[FePc1mEbF[mS16tZ1iTdHJzOHeLS2WxTVi{T1mERXeKRXuLR2GtUmmY[HyQboC{ZkKkc1qIWYSRcXSt[FVycHN{UnibNmWwT2OsO1OqRXeKR1GLR2GsTmSYSn6bWH93Zld6cmKZbHqbXFJxZWd6eVuEVnyMWIOMTVOC[1mCb1qEXECMR2GsTlOqRXeKR1GLR2hxT1mERXeKRXuLR3mC[1mERVqnV1KtZliPcFmJd1uKR1GoTVGsTmSYSn6bWH93Zld6cluE[F:jfVJzXWe5dGqERoOiW16tZn2PcFyqRl:jN2KwZWd2clmJRnibNmWo[EKtd3KERnmbV1KsZkOleXKIPXibS2[sUHmkdF:4c3eKR1GoR2hxT1mERXeKRXt:Jku{PkF3PjKbS{l{Zn25emmYVmG[W3StJku{PkJ3OEh7JlOSNFuKR1GLR2etcVmEbF6[W3StU3qxc2qYfIebXFmwTkJyNHSZTnmjfUmxZn2belq6b4SRcXSt[F[LcGpxOXijW2WwT2RxPVpzeImlS4izXWe1fV6EZ4CKTIOPR3mC[1mERVqFVX:oTVGsTlOUPI[KS{m2Zlis[3GYOHebS2[1ZkObcHOvUoCjNkSPR3mC[1OSb1qiW2moT1OTNmmZTYeNWEWvXmiTWXSZTnmjNEG3XleXd1uEb4SRcXSt[F[TOXOIWX:MWEB6TkKPeHO6Z3eLbWmoTlibbHOrRYSRcXSt[F[TNXOuTo[VW{msXme4c1uUNDubNmZxWX2XfHSYWoqlSlKp[Feoc1uUSUmLNni3ZmeWcluSNFuKR1GLR2GsTnOuWkClXFq2U4dxT1mERVqEVXuPR3mC[1mERVqEV2JzXWiKflmFNHeLfXN4SGGw[1mERXeEVXusZViTeHKERUmKR3OvU4dxT1SSc1qEVXu3T3mDcmqZVXe[Nkm2Xn2tcnSZTnilS3y3ZnmDeHJzVnyjR1GyUIdxT1OSb1qLS163Zn2bdGq6RUmKSUGpXkKWOl:u[HylSl6xZn2ld2qZVo[jbXevZmiTNXOuTo[NNl63Zn2bdGq6Z4CQe{CMTVOC[1mCb16E[3uLR2N5dVmIcH2KS{Gt[FepemqERoCkfVKtZmiDNHWURoqbV1KsXmebbHSYfECKS{Gt[FepemqERYGNe3uPR3mC[1mERVqEW3yuTVOob3SuSomPSEB6TomkdFSSc3eKR1GoR2GsTlqJXnikbmGoVGOCb2lzPYWbcXyvUGR2cmqZVlWjN3S2Zld6bGqGNXylS3i3XlOodF:4NFuFVX:oTVOC[1OSb4[MbVKrZ32XbHSI[3ekS1ZxZVODN3GIWoWKS{WtXUKXfnNzSommV4eoXkKXNFmJWomjR1GyUIdxT1mERXeKRXuLZWe[[1uEVkK[XFm6T2ODO1SSc3eKR1GoR2GsTlqJRnilS3eLTVRx[1qJXnikblG1VH2lcHSGSnmkNkm{[GiTcGWISkCiR3exU4dxT1mERXeKRXuLR2OTb3GZToe[XGKwTVRx[2qIcImjcV[1XmOob3OISkCiR3t4SGGw[1mERXeEVXuLZWe[[1uESn2iW4itXEKXOHGZUkCkfXesXletfXOISkCiR3uxTVi{UlOob1qEVXuLZWe[[1uESl6[W3StU3qxc2qYfIebXFmwTkJyNHSZTnmjfUmu[Gd2bnSIcI[jcl2vT2NxL2l{Tny[XGKtXEKTdHOvUX:LS2KxZ36DbHSI[4CMVUCMR2GsTlOSb1qVW1[vXmSwOnSIbImjN3SH[VePcHOJVoCjNkSwWGeHcmqVc{[iS2[{Z1eXfVuE[ISlTG[6XX15cluUNDuZNUiwTXus[2lzSoWLN2GoXUOLcGmZVnyKR3OtZ4mkeVmHRoObW1[7XmO4[2lzbHy[NoOoZ1eXfXKYcIqkNny3ZnmDNHK6RnqkcW[p[FeW[3SIbICkfVKsZWiLcGl{Vo[kcnu2TXm4[1qIVoCkclKp[FeodFuVd16E[3uLR2GtPVSSc3eKR1GoR2GsTlqJWomjRXt6TVOTNmmZTYeNWEWvXmiTSXJ{[IWjS{mpXl[XfXKH[IClS3iQZkCPbGlzbHyMR3t4SGGw[1mERXeEVXx6TVeXd3NzWXeme{CMTVOC[1mCb1qEV2JyZ324TmCURl6[W3StU3qxcmqZVm[kcYewT2S{UlOob1qEVXus[GiLd1OVNHekN2K6XEOLcHOIfHi[NmWwTX2Hb3KYcIWNfVm{TVOKbVyERXulXFq{T2S{UlOqRXeKR1GLR2hxUlOqRXeKR1GLR2FxT1mERXeKRXuLUImw[2pzWkCKS2K3[EJ2d3JzSnuKS{Gt[FepemqERYGNe{CMTVOC[1mCb1qLS2K3[EJ2d3JzSnuVW2ZxZVd6b3NxXni[N2K3Z36s[2CURl6[W3StU3qxcmqZVl6jNmKtZlOocnKZVkGkcVq3UEKTenRzOYOjNl[sWGeXNHGIPXukNGqpXUOTenOvb36MWIOPR3mC[1mERVqEV2KsZkOleXKIPXibSUGt[FepemqERUmKR2KsZkOleXKIPXibSUGt[FepemqJUle[W15xZkOLOVyVOX6bXGKPXmiTc3JzVX:LTGqpZ3qSdF:4NFuKR1GoTVGsTlSSc3eKR1GoR2GtNHOvb3eme{CMTVOC[1mCb1qEVUCMTVOC[1mCb1qEV2Kw[Fdyd1mFNHeLS2K3[EJ2d3JzSnuVW2ZxZVd6b1yVOXujN3S2Zld6bGqHRnibNmWwTliXfXKEb{eFVX:oTVOC[1OSb1qiW2moT1OTc3SINYORWECvTomsUlOqRXeKR1GLR2GsTlqJXnikbl2oVGOCb2qIPUOjcYi3XWeTUmqZVn:jNmG1VH2lcHSGWomkcUm6WGeXfnNzSn6bV3exU4dxT1SSc3eKR1GoR2GtPVmIUnilS16wTVOpSnWIUnykTGKxZkJ1[1qIWYCKTIOPR3mC[1mERVqEVXus[H2HfV26RUmKR2KsZkOleXKIPXibSUGt[FepemqENDubNmZxVmiLfXJ{Tl6bXF67XWelcFuEb3eNbVGvT1Ok[1yqRXubV{BsXkKXNGSYWoqkNl[vXmOodFmEOHeLfXuvU4dxT1mERXeKRXuLR2iLcHSJWomjboOPR3mC[1mERVqEXECPR3mC[1mERVqFVX:LR2GseluqRoS[XFqzZ4mDcXGYfHyKTHSwXmd1[3GZVXeiXF2o[FiXfXKuWnuKR3:3R2FxT1OSb1qiW2moT1OTNmmZTYiMV1GsZViTeHKEOEmKR1l5TWNxeFmETXeNbVKsXWiTcFuE[FWKSUCoZXmDTV:ub{[kfVKtTVd5cluURYWKR1moUGNxL1mrd16E[{CMR2GsTly6c3ekNlZzXmODcXGYfHyKS3y2TViTc2qURn:[XFqsTVilc2qZVXeiXGGoZWiO[3SJWomjcW[sTVOwelmERXeKRXuPR3esTlOYcH2KR3es[H2HfV2qb3ebcXy{XmZ6e3SZVn[[Nkm2[FeXeXSJUX:LTFKp[Feod1mEVn:lS{G{T2S{UlOoNFuKR1GoTVGsTnGYXXeMR2JzXWiKfmCVNH6LfVGuTnmDdHNyPYqlTFqxZn2kc1qIbECjW4exTVO[cVmE[3uiTGK1ZlOGPVq6Z4CMVUCMTVOC[1mCb1qEV2JzXWiKflmFNHekcUlyZn2Sc1uJUkCkcYitZnmob3GJVoSjR3uoUImCc2qufI[[XGGxUWSCfV6Eb4OKSFmxU4dxT1mERXeKRXuLXme5fmqURoCbbVGwTlibbHOrUUmRV3OvTVO[cVmEVn:lS{G{VGRxclq6b16EbVGoTVOCTlOSb3ulcV[6UYmCPVmGNXibNmV3U32pcHKJRnykbXevZmiTNXOuTo[LfXu1VHx6[luE[HyjXFJx[WODenSZVoelXGGvT2S{UlOqRXeKR1GLR2FxT1mERXeKRXx6SGGw[1mERXeEVU1:Jku{PkJ1PjKbS{l{Zn25emmYVlKjcWKLZn6PNGmYfINjP4N7OUh5PjKE[3:LR2GseluqRnmiW{WsTVeTbHSISXeMbUiMTVOC[1OSb3ulcV[6UV[{cnSZUnykcUWpZmeWcmiURUmKR3OvU4ew[1mERXeKRXus[H2HfV2Hd36kS1[7Z{OlenOuVX6ZV1F6TVOkcl:4c3eKR1GoTVGsb3SuSomOSoOvXld6N3KufI[[W2KnZWeScmiURUmKR2JzXWiKfV:4c3eKR1GoTVGsb3SuSomOSoOvXn2td2qU[HSKSECoTkJyNHSZTnmjfXN4R3mC[1mERXeEV2JzXWiKe2e6[Hq[XGGvXGOCPVmE[ISlTG[6XX15cl:4c3eKR1GoTVGsb3SuSomOSoOvZ1iLemqE[HSKSECoTkJybGpzWoWlS{ivU4ew[1mERXeKR1GoTVGw[1mERXeKRXus[GiLdFmFNHekS1[6Z{KX[nSZToOMSUGpXkKWOl:u[HylSl5xZkOLcGFzPYWbcXyvT1OLN2qYTY[lW{W7XmePNXOuWY[[cV[7XmZ6NXOue3mNR1G4T2OsO1OqRXeKR1GoR2OTNXOue3eRV1Gs[GiLdGe6[H:jN15xTkFxeVqJWomiWoOvZ1eHNHGE[HSQe3:oTVOC[1mCb3ulXFq{TVRx[3SJToCjV3es[GiLd1yERX6NfXOxU4ew[1mERXeKRXus[H2HfV2Hd36kNnxxXmOl[FmFNHeLTG[6ZlS{T1mERXeKR1GLTlibbHOrRnKLNny4TkFx[2CURXuZNV6HWXybSmWtd36WNG[UWnuXV2hxSlWTSlmvXGS{T1mERVpjP4N7NUZ7JmpzWkCWcW[vWH2HeGqSQU1jP4N7N{Z7JlSSc1qEXFqt[FiXfXKqRX6iN1pxZle1bHF{TUCLfoOPR3esTjJ8d{pyNkpjZld6bGqGcIWbcUh:Jku{PkF2OkpjSGGw[1mERXeKR1GoTVOC[1mERXulcV[6UWNxL2h{TnykN1K3Zn6PcFmFNHeLTGqpZ3qGeGCtRo[kN2KUXmiHNWqZUkCMR3Sw[FiTe1:qPI[lN3R{UH2HfXSIcI[NcUWt[FN6d3GYUnyjcl6tUGePc2qYUoKLfYeoZn6Xd3KEe3eLTGqpZ3qCdF:4NFuKR1GoTVOC[1mERXeKR1GoJku{PkJxPjK[NnitXUK1V2qZUoejNkW7XmF:QTJ8d{pzPENzPjKFVX:oTVOC[1mERXeKR1GoTVGtdGqqRX:LTGqpZ3qCdFmJd16EbVGoTVOC[1mERXeKR1GoR2GsUlOqRXeKR1GoTVOC[1mERXeEVXus[H2HfV26NDuZN1qtXkCteWquPISRcV63XleW[2CURoCjcmJzXWe4c3N{WnmkN2K6T1OTNmmZTYiYflKlUFOCe1yERXulcV[6UVOsdF:4NFuKR1GoTVOC[1mERXeKR1GLR2etcVuERoCjcEmpZ36LbHWU[3ulcV[6UYlxL2h{TnybNHy2Xn15eGCuUo[bS2W{TVeHfXOuSkWMSFW4UFSKe1yFUYeNSGG4T2Os[1uURkeFVX:oTVOC[1mERXeKR1GoTVGsTlOSNFuKR1GoTVOC[1mERXeKR1GLR2GtdGqqRX:[NklyZn6Sc1qJXnikblWxTVR1PVmFUYCKTIOPR3mC[1mERXeKR1GoTVOC[1OSb1qEVUCMTVOC[1mERXeKR1GoTVOCTlOSb1qNfUioWVeHfXNzWXelS3itTVeTbHSIWV6EbVGoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mEVnu[XGKtTVRx[3N{VomZN1qtZ1e5bGlzWX:LfUSvUFOCcly6Z4OKTGK6ZWdxc1qJXnikbl[jUWZxdFuVd16EbVGoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mEVkK[XFm7UGR2[nOuWn6UW{WuZolxL2qISkCbV1F6TVVybGpzWU[QcXitZliDcHOq[36[Nkm6XmOkdFyVOX2jN1q1XWiTSWmZVnyMR2KsXWiTcFuVd16EbVGoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mCNFuKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1y6PHeWS1[6Z{KW[3SIbHyKS{WpZmeWUlOqRXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOTNmmZTYqNWEWnZ32XcmOYOX2jfUBsZn2HeGqURUmKTGK6ZWdxc1qJXnikbl[jUXxxdF:4NFuKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1SSc3eKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOCely6RmG[XFq7XmODNHGIWXe[Nkm1Z1eHeXWSNFuKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1qJXnikbl21VHx6fWqY[FqjcWq3UGR2bnJzNYe[W{V2TVRx[3GZUoqbXGGwTlibbHOrSnKONUCxTVR5[3SJToCjV3es[H2HfV2Xd4qZV3uoU3mCclq7d16EbVGoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mCNFuKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[3GYXXeMR2JzXWiKflyVOX[kcW[vV2d2cXK6NDu[NkmsXmOCPWCURYiOR3uo[YdxT1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoR2OTNmmZTYqNWEWnZ32XcmOYOX2jfUBsZmeXfnNzSn6bV1F6TVOTNmmZTYqNWEWnXImocmRxd36MWIOPR3mC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKTECoXme5fmqURoCbbVGwTlibbHOrUYSRcEm6XmelTnKuXo[NWEWrZkKTcFmFNEmKSFm4T2ODO1SSc3eKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeLTGqpZ3qOeGCvTniiXF6tWH16NHGYUnyMSFW4UVO4[1qJXnikbl21VHx6[luE[FqVb2qRXEGXVWJyTlKTSW[nWFWtSGKWOWSTWkmHW1[DTmWsWlWLfXuxU4dxT1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1Go[mODcHKJUnyKS3yuTVOob3SuSomOfUBsXEOLcGpxcIWbcUi1VH2PemqIWXeRWECoUYqCdFmJd16EbVGoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1Gs[H2HfV26NDukcV[xZ{KXU3J{VoC[NmWwUWSCe1yERXulcV[6UYlxL2hyPH:LNHyQVnt6[m[XRliWb1[GVmZ6U2RyVn[SWV6WV2[bSlq6b4CQe{CMTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOTNmmZTYqNWEWnZ32XcmOYOX2jfUBsXleHNGqURUmKR2JzXWiKflyVOX[ZfXevWH16NFmISnqlS3xzXWiTcGqERkWbXGGvT2S{UlOqRXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVhx[2qYfIqbV1KxXnmCc1qJXnikbl21VHx6fWqY[FqjcWq3UGR2bnJzVnyKSEB6TVSSe1uURkeFVX:oTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERVqKR2JzXWiKflyVOYm[W3y7XmV2enSIcHqbV3e5UVSCd1mEVkK[XFm7UGR2[mi6[36TSUmPVWWtU1mGVmCTWl2oWHt6WVmGNVKXSV6KTomsdF:6RXeKR1GoTVOCUlOqRXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVhxUlOqRXeKR1GoTVOC[1mERXeEVXuLR2FxT1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERkmKS2[{Z{KW[3W4NFuKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GLTlibbHOrUYSRclqpZWiPcGSuPUCiW16tT1SGe12Ee3eLTGqpZ3qOeGCtPX[MR3SHWXyLVGWtPWOTWXSnVUCpSmFxeH[Tb1[LWFOkdFuVd16EbVGoTVOC[1mERXeKR1GoTVOC[1mERXeKR1Go[mFxT1mERXeKR1GoTVOC[1mERVqEVXuPR3mC[1mERXeKR1GoTVOC[1OScEmKS2[{Z{KW[3GYXX:KR2JzXWiKflyVOX[kcW[vV2d2cXK6NDu[NkmsXmOCPWCURUWOR1GxTVi{UlOqRXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeLTGqpZ3qOeGCvTniiXF6tWH16NHGYUnyMSFW4UVO4[1qJXnikbl21VHx6[luE[F[WcFqRWXx6SWRy[F:VSUmDVlZ6TmKHPV:VNWKnVnt6WmSsVX6MV3t4SGGw[1mERXeKR1GoTVOC[1mERXeKR1Go[mODcHKJUnyKTIOPR3mC[1mERXeKR1GoTVOC[1mERXeKR1GLTlibbHOrUYSRcEm6XmelTnKuXo[NWEWrZkKTcFmFNEmKR{C5U4dxT1mERXeKR1GoTVOC[1mERXeKR1GoTVGsb3SuSomOfUBsZ32HdHNzWl:jN2KxXUKWc12VRYeNR1Gs[H2HfV26NDuZNUiwTkCXV2WsPWOZNVqHVkF6SGOGWlSUNUmIVWWtUVq6b4CQe{CMTVOC[1mERXeKR1GoTVOCTlOZNF6EbVGoTVOC[1mERXeKR1GoR2GsUlOqRXeKR1GoTVOC[1mERXeEXECoXme5fmqURkeFVX:oTVOC[1mERXeKR1GoTVGsTlqJXnikbl21VH6LbHGZUnyVcUlxZWePcFuFSYeOR4eoTlibbHOrUYSRcEmnT1OlSmWtTmCWcEmUVmWl[mFxbF[SNISnVnuHTmSEZ4CMWIOPR3mC[1mERXeKR1GoTVOC[1OZNF6EbVGoTVOCTlOSQU1jP4N7NUZ7JmWIPYqlSlqtZ2iXcHN{VU1jP4N7OUN3OEpjSGGw[1mERXeKR1GoTVetcVuERoCkNUmpZ36LbHWU[3ulcV[6UlOs[1qqXXe[NklyZn6Sc1qJXnikbmGxTVR1[12ERYCKTIOPR3mC[1mERXeKR1GoTVOC[1mEPI[KS2q3Z31ybHSERYSNWESo[FeXfnSFSUm[V2pxXmiPNF2rNXmKS2ZxXYl1UlOqRXeKR1GoTVOC[1mERXeKR2JzXWiKe1mFNHe[XFq6XWisc1uVd16EbVGoTVOC[1mERXeKR1GoTVilc3GYfHyMR1K{ZWiPNFuEVoWNR1Gs[Hms[2CURny[W16wT1OTNmmZTUCMV1GxTVi{UlOqRXeKR1GoTVOC[1mERXeKR1GoTVOCb3SuSomOSoSlTVRx[1mqVoWRV2JzTXq{UlOqRXeKR1GoTVOC[1mERXeKTECoTVOC[1SSc3eKR1GoTVOC[1mERXeKR1Gs[H2HfV2ERUmKS3y1Z1e5emqIWX:LfWmvUFOCb3SuSomOR3t4SGGw[1mERXeKR1GoTVOC[1mERXu[Nkm2[FeXeXSHVkWkS2WoVGOCbWFzPYWlS2[2[FNyNHWZRnyQbVKpZ1iDd3GYUnilS3y3Znl6OFyZ[EOlfUGuZkOLeFyZWomjS2[2XUJ6b2qYVnOkcIi2TXq{UlOqRXeKR1GoTVOC[3[SNFuKR1GoTVOC[1mERnyjTF6tTVi{UlOqRXeKR1GoTVOC[1mERXeKR2JzXWiKe1mFNHeLTGqpZ3qSO1SSc3eKR1GoTVOC[1mERXeKR1GsXUJ6eXSIWoWlSmJ2Z1eW[2CURXmSNkm2[FeXeXSENUCmXFKtU3mDNGqZbECNN3i1Zl[5fWiIOHmQe{CMTVOC[1mERXeKR1J6SGGw[1mERXeKR1GoTVFxT1mERXeKR1GoTVODdGqq[3eiXF6nZn6Xd3KE[3ulcV[6UYms[1uURkeFVX:oTVOC[1mERXeKRXuLTlibbHOrUXeRV1KPXWelcF:rdH6bXGKV[Fd6fWqWUo[jcWqxXomobXRzWnmNN2[2Z{KXbnSZTnyNNlqpZ{KX[nSZToOKbYeoUVOsO1SSc3eKR1GoTVOC[1mERXeKR1Gs[H2HfV26RUmKTF5xZ3x6fWqZRoO[W16tT1OkenGYOXubXHe2Z1epe1xzSnujW3y2Tom4[1q6Z4OKR2JzXWiKfluVd16EbVGoTVOC[1mERXeKR1GoTVOTNmmZTYqKSECoZ{OTfWh{TnykS4ipXUKWc1q6PYCjcWKt[VN2e3GJRY[LfYeoTomkd1mEVkK[XFm7T2S{UlOqRXeKR1GoTVOC[3[SNFuKR1GoTVOCUlOqRXeKR1GoTVOC[1y6PHekS1[6Z{KW[3SIbHyKS3Sx[H2XeVmHWmOVRUCMTVOC[1mERXeKR1Gs[H2HfV2qRUmKTFKpZ36PcGh{WomjR3es[H2HfV2qb{eFVX:oTVOC[1mERXeKS3yuT1OCbHGZUoqbXGGwTlibbHOrTnKLN16rZVeXeGqU[HSMV1J5[lOCc1qJXnikblqjTkOPbnGIWoSbV3SlTVOGPVmE[H:lTGK4Toms[1uURkeKRUCMTVOC[1mERXeKR1GoTVOC[3OuWkClXFq2TVebbHKJUnyQe{CMTVOC[1mERXeKR1J6SGGw[1mERXeKRUCMTVOC[1mERXeKR1G3UImDcHWJVom[W15xTVepenN{VXe[W{WsTViDbHSI[{[FVX:oTVOC[1mERXeKR2KwZkOPNFmFNHeLTGqpZ3qLZlpzbI[kN2GvXGS{UlOqRXeKR1GoTVOC[1qJRnilS3eoVGODdHN{UnylR3es[H2HfV2td36kS1ZxZVOl[FuURT:KR2JzXWiKfWe6[Ie[XGKwTkFx[1:qRX6NfXN4SGGw[1mERXeKRUCMTVOC[1mERXeKR1G3UImDenOIWoWKS1WoZ{J6bnFzWkCKS163Zn12cGl{VoCjNkSoZkJ1[3OIPYmlR1F1UVFxT1mERXeKR1GoTVOCb2qZTomjcUioVGODeXSYfIOQe{CMTVOC[1mERXeKR1GsXmiLfXN{VomKSECoZn6Xd3KFd16EbVGoTVOC[1mERXeLS2q4TVRx[2GIXoqjNl6zZkODcHKq[3uiS{m7[FO4[1:FRYOKR2KtZ36LeXK6e3eLS2[6Z36PNHOqe3ePV3t4SGGw[1mERXeKR1GoTVetcVuERXubclGoVGRxPVmIXnijTF6tTVOs[3W4NFuKR1GoTVOC[1mERXeKR1GoZ32XNHSZToWKS2qpZliPcF:4NFuKR1GoTVOC[1mERkmFVX:oTVOC[1mERXeKRUCMTVOC[1mERXeKR1KxXnmCc1mYcIqZNkVyZle4c1qJXnikbmmxT2ODO1SSc3eKR1GoTVOC[1mERXeKR1Gs[H2HfV6qRUmKR1qXZ{KXfVyWSn6bW{VxU3mCbVyqVkK[XFlzUHmLZ3OtfIWKboOPR3mC[1mERXeKR1Go[mFxT1mERXeKR1GPR3mC[1mERXeKR1GoUIl5[3NzWoWbR1JxZVeW[3OuWoilW2[7[FFxT1mERXeKR1GoTVODdGqqRX:LTGqpZ3qW[2CVNHeLN1K3Z{OScluURkeFVX:oTVOC[1mERXeKR1GoTVODcXOJWkCkfXesXn6Cd1mETmGVNV6WTVOTe2mZVn:KSXiWWl[Cel2UOIiZTFqkZnmKdF:4NFuKR1GoTVOC[1mERXeKR1GoZWe[[1uESoCkNUm2[Ge5d1uEVkK[XFlzT2Os[3W4NFuKR1GoTVOC[1mERXeKR1GoTVOC[1mIXoelXGK7T1OTcXOEe3eLTGqpZ3q[dF:4NFuKR1GoTVOC[1mERXeKR1Go[mFxT1mERXeKR1GoTVOC[1mERXebclJy[FiOc1qIXoeNR1GqV1d6fnSFc3eLS3i3Z{OTZ3OtfIWKbXt4SGGw[1mERXeKR1GoTVOC[1mERn2kTGZxZ4mob2qvRYOKR1qUXmebcHOuWomQbVGs[H2HfV1yfImZS{SqT2S{UlOqRXeKR1GoTVOC[1mERXeKS2q4[GiTfluEVn2kR4eoTlePenKvVnyjcmKW[WiDcFuVd16EbVGoTVOC[1mERXeKR1GoTVebe3SZVoqMR2KuZ1O4[1msUo[jcmKtZn6SeHKIWoWbN2KwU3mCbVyqRoqlTFq{Xmd1c1qJXnikblGxTVN1bWiJTnOjbVmxU4dxT1mERXeKR1GoTVOC[1mERXebclJy[FiOc1qIXoeNR1GqVUJ6eXKuWnqlS3y3Znqw[2lzfI[kNm[kZ3y5eWiJTnOjbVmxU4dxT1mERXeKR1GoTVOC[1mERXebclJy[FiOc1qIXoeNR1Gs[H2HfV2Eb{eFVX:oTVOC[1mERXeKTECPR3mC[1mERXeKR1GoXme5fmqYcH2KR3es[H2HfV6URUmRV1GvXkKXNFq6b3eme{CMTVOC[1mERXeKR1GoTVOC[1qJSkGbXFp2TVRx[1q6Z{eFVX:oTVOC[1mERXeKR1GoTVODdGqqRX:iXF67XmiSc1qJXnikblqjTkOHNWqZTkWLNUCxT2ODO1SSc3eKR1GoTVOC[1mERXeKR1GoTVOC[1qJSkGbXFp2TVRx[1q7PH6NbWJzXWiKfWe6[IilW2[6[WOl[F:4NFuKR1GoTVOC[1mERXeKR1Go[mFxT1mERXeKR1GoTVOC[1mERXebclJy[FiOc1qIXoeNR1GqVkCXWVmJd3ukS1ZxZVhyO1qJSkGbXFp2[mODTW[HVmGNflW2UW[5fWiIOHmMWIOPR3mC[1mERXeKR1GoTVOC[1mIcH2KR3epZWiP[nKvWoOjR3es[H2HfV6qb4CKTIOPR3mC[1mERXeKR1GoTVOC[1mERXeKR1KuZ1iXNHO6[3ubclG{TVOTNmmZTUKMWIOPR3mC[1mERXeKR1GoTVOC[1mJNF6EbVGoTVOC[1mERXeKR1GoTVebe3SZVoqMR2KuZ1O4[1msbI[kN2F3TVOTc3J{UkCZTFqkZnmKdF:4NFuKR1GoTVOC[1mERXeKR1GoXn6DNXSJUX:LS2q4UFOCbWFzPYWjcW[r[FetenKrc3e[Noi3Z{KXZ3OtfIWZTFqkZnmKdF:4NFuKR1GoTVOC[1mERkmFVX:oTVOC[1mCNFuKR1GoTVOC[1mERXukcW[7[Ge5NFmFNHeLfXN4TVFxT1mERXeKR1GoTVODN3GIcIObV3epXn2Xemqq[3ubclGxT2ODO1SSc3eKR1GoTVOC[1mERXeKR1G3UImDfWqYUnyiXGqtTViTc2qURombXF5yZliTflmIPX2KTGKwXmODfWqZSkGbXF5xSGGw[1mERXeKR1GoTVOC[1mERXukcW[7[Ge5NFmEOEmKS2qvXmiTfluEVn2kR4eoUWSKOFuVd16EbVGoTVOC[1mERXenVUCMTVOC[1mERV6EbVGoTVOC[1mERXeNfUioXUK5enNzWXelS3itTViPemlzeHylR1KrZkJ2eWqYUkCiW{m2U3dxT1mERXeKR1GoTVODcWlzfI[kNmWwTlebe1uVd16EbVGoTVOC[1SSc3eKR1GoTVOC[1mEPI[KTF64ZletNFmJVn:bV1K6XmiPNXKJVXeiS2[pXleXfVmIXomjNkCo[FepcFmIUo[jcmKtZn6SUlOqRXeKR1GoTVOC[1qJTnykN2[{[FOCPVmIWkSkS4i3XleWc1mtfImZS{WkZ3y5eVmqe3eLTFqtZ{OXd3SEe3eObXt4SGGw[1mERXeKRUCMTVOC[1mERXeKR1GsZVeXbGqIWomKSECoZWiPfmqZVX:LTFqtZ{OXd3SHd4eZV3uoVImCb3OuWoqlW4hxW4qD[FmFc3eLfXN4SGGw[1mERXeKR1GoTVOTbnJzOUCbW{VxTVRx[3GZUoqbXGGwTliLcHN{WoOlSoO5XGOs[2C6RXukcW[7[Ge5NGe7SnSKSH:oTomkO1SSc3eKR1GoTVOC[1mCNFuKR1GoTVOC[1mERXulcV[6UWOCPVmIOXylfVK7[FeTSHKISoqkfXexU4dxT1mERXeKR1GoTVOCb3SuSomOV{BsZVeXbGqIWomKSECoTlepcGmYVnykboOPR3mC[1mERXeKR1GoTlibbHOrSYSRcV63Zn6TcHKvVXeRV1GsXUJ6eXSIWoWlSIOPR3mC[1mERXeKR1GoSGGw[1mERXeKR1GoTVN5elmGbHijcWK{XmODbnGJWoWiNm[sTViTfWmYOYqbcW[6TVetcVmIOXybW2KtXlFxT1mERXeKR1GoTVODdGqq[3ekN2K6Z1d6fluJUkCkcmK3Zld6N2qZTX:LTGqpZ3qGeGCubHy[W2KtZ3msd1mE[ECkcV[2Z{KbcHOqNXyjcV63XleteWq7c3e[NnhyZn21cGqEZ4CKR1V6VGODcWmYfIqbV1GxTVi{UlOqRXeKR1GoTVOC[1mERXeKR2K4XWiLfmqYVXeRV1GvToq{UlOqRXeKR1GoTVOC[1mERXeKR2K{XmebNFmFNHeLTGqpZ3qGeGCuUo[jcmKtZn6SO1SSc3eKR1GoTVOC[1mERXeKR1GPR3mC[1mERXeKR1GoTVOC[1mJ[H:iW4itT1ODNHOvWnyKR3uo[YdxT1mERXeKR1GoTVOC[1mERXeKR1GoTVOTe3J{UXeRV1K7[FiLe3J{UX:LS4itXn6Sd1mETnOkcIi2TXmsO1SSc3eKR1GoTVOC[1mERXeKR1GoTVOC[3GYXX:KR2K4ZkOO[2CVNEmKS2qpZliPcFmEb3eme{CMTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVODfWqZVkGkcUSoTlibbHOrSUeFVX:oTVOC[1mERXeKR1GoTVOC[1mERXenVUCMTVOC[1mERXeKR1GoTVOC[1mERXeKRUCMTVOC[1mERXeKR1GoTVOC[1mERXeKR2KrZViXeXF{UoCmcWWoVGODfnSYToqlTFmwTle5cGqvVYOKSFG{TVOTe3J{UYCQe{CMTVOC[1mERXeKR1GoTVOC[1mERXeKR2K4ZkOO[1u7NHekN2K6ZleXeVuETnOkcIi2TXmsO1SSc3eKR1GoTVOC[1mERXeKR1GoTVOC[1qIfHybcmGoVGODfnSYToqlTFmwTle5cGqvVYOKR2K4ZkOOdF:4NFuKR1GoTVOC[1mERXeKR1GoTVOC[1mCNFuKR1GoTVOC[1mERXeKR1GoTVOC[1mEVoejN12oVGODfnSJToejN12wTlePc3SYOYKkNnx3XmO4[1q7d36MWIOPR3mC[1mERXeKR1GoTVOC[1mERXeKR1KxXnmo[1qJRo[kfVGpVGRx[2quSoOkNmWoT2ODO1SSc3eKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR2KrZViXeXF{UoCmcWWoVGODfnSYToqlTFmwTlePc3SYOYKkNnx3XmO4[12Ee3eLTFK3Z4msO1SSc3eKR1GoTVOC[1mERXeKR1GoTVOC[3[SNFuKR1GoTVOC[1mERXeKR1GoTVOC[1mEVnqiTG[2ZUOPdHWuWXeRV1KwXmipb2qYUX:LS16w[Gd2dnNzcE[bV3t4SGGw[1mERXeKR1GoTVOC[1mERXeKR1GoSGGw[1mERXeKR1GoTVOC[1mERXeKR1GoZWe[c1mEVnqiTG[2ZUOPdHWuWXeRWECoUVOCdFmJd16EbVGoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoXX6LcGmYd{eFVX:oTVOC[1mERXeKR1GoTVOC[1mERXenVUCMTVOC[1mERXeKR1GoTVOC[1mERXeKRUCMTVOC[1mERXeKR1GoTVOC[1mERXeKR2K4XWiLfmqYVXeNbkCoZ{OXbXN{VomMR2K{XmebNFyERYeNR1GsXUKpNXKueIqiXICtT2S{UlOqRXeKR1GoTVOC[1mERXeKR1GoTVOCb3KIWn2lR1F6TViPNWmvUkCkbXesZleXcXSEe3eLS16w[Gd2dnNzcE[bV1GzTViPNHOufHyjbXeqXFiLZ3KqTYCMWIOPR3mC[1mERXeKR1GoTVOC[1mJNF6EbVGoTVOC[1mERXeKR1GoTVFxT1mERXeKR1GoTVOC[1mERXeLTGqpZ3qGeGCuUo[jcmKtZn6S[2CURXukS1[6Z{KXb1:4NFuKR1GoTVOC[1mERkmFVX:oTVOC[1mERXeKRU1:Jku{PkJxPjKZNl6wXmePdmSIcHqbW{WrXmF:QTJ8d{p{OUZ7JlSSc1qEVXyxXnmCc1mWNXibNmV3U32pcHKJRnykbXevZmiTNXOuTo[NNny2Xn15cluUNDubNmZxWX2XcmSuSoSbV3exVGRxcnF{TkCjS4SpZUOKNFq6b3eme{CMR2GsTlOUVoCjcWq3TVRx[2SYSn6bWH93ZVeXd3OIWomMR3S1[FiXfWmuPI[iW{WuZomkdFyVOX6bXGKUXmelTnKuXo[MR3t4SGGwTlOSb1qLTGqpZ3qCeGCtPX6bXGKVXmiOc1uUNDu[W2KsWkKHfXKucIWbfXesZWd2cXK6NDujW2[7Z{KHcmqUb{eEVUCMR2GsTlOUVkK[XFm4UGR2[nOuWnuMR3OyUImwenGYOXubXHevT2S{UlOob1qEVXy6XmiTNXOuOHebcV[{Z{KWO1SSc1qEVXx6TVeXd3NzWXeme{CMR2GsTlOZTnylTG[6ZnmDNHOvWnyQe{CMR2GsTn[SNFuEVXt:Jku:
1
+ ZUp5Pou{PkJxPjKZNl6wXmePdmSIcHqbW{WrXmF:QTJ8d{p{OUZ7JlSSc1qEVXyxXnmCc1mWNXibNmV3U32pcHKJRnykbXevZmiTNXOuTo[NNny2Xn15cluUNDubNmZxWX2XcmSuSoSbV3exVGRxcnF{TkCjS4SpZUOKNFq6b3eme{CMR2GsTlOUVoCjcWq3TVRx[2SYSn6bWH93ZVeXd3OIWomMR3S1[FiXfWmuPI[iW{WuZomkdFyVOX6bXGKUXmelTnKuXo[MR3t4SGGwTlOSb1qLTGqpZ3qCeGCtPX6bXGKVXmiOc1uUNDu[W2KsWkKHfXKucIWbfXesZWd2cXK6NDujW2[7Z{KHcmqUb{eEVUCMR2GsTlOUVkK[XFm4UGR2[nOuWnuMR3OyUImwenGYOXubXHevT2S{UlOob1qEVXy6XmiTNXOuOHebcV[{Z{KWO1SSc1qEVXx6TVeXd3NzWXeme{CMR2GsTlOZTnylTG[6ZnmDNHOvWnyQe{CMR2GsTn[SNFuEVXt:Jku{PkJ1PjKbS{l{Zn25emmYVlKjcWKLZn6PNGmYfINjP4N7OUh5PjKE[3:LR2GseluqRnmiW{WsTVeTbHSISXeMbUiMTVOC[1OSb3ulcV[6UV[{cnSZUnykcUWpZmeWcmiURUmKR3OvU4ew[1mERXeKRXus[H2HfV2Hd36kS1[7Z{OlenOuVX6ZV1F6TVOkcl:4c3eKR1GoTVGsb3SuSomOSoOvXld6N3KufI[[W2KnZWeScmiURUmKR2JzXWiKfV:4c3eKR1GoTVGsb3SuSomOSoOvXn2td2qU[HSKSECoTkJyNHSZTnmjfXN4R3mC[1mERXeEV2JzXWiKe2e6[Hq[XGGvXGOCPVmE[ISlTG[6XX15cl:4c3eKR1GoTVGsb3SuSomOSoOvZ1iLemqE[HSKSECoTkJybGpzWoWlS{ivU4ew[1mERXeKR1GoTVGw[1mERXeKRXus[GiLdFmFNHekS1[6Z{KX[nSZToOMSUGpXkKWOl:u[HylSl5xZkOLcGFzPYWbcXyvT1OLN2qYTY[lW{W7XmePNXOuWY[[cV[7XmZ6NXOue3mNR1G4T2OsO1OqRXeKR1GoR2OTNXOue3eRV1Gs[GiLdGe6[H:jN15xTkFxeVqJWomiWoOvZ1eHNHGE[HSQe3:oTVOC[1mCb3ulXFq{TVRx[3SJToCjV3es[GiLd1yERX6NfXOxU4ew[1mERXeKRXus[H2HfV2Hd36kNnxxXmOl[FmFNHeLTG[6ZlS{T1mERXeKR1GLTlibbHOrRnKLNny4TkFx[2CURXuZNV6HWXybSmWtd36WNG[UWnuXV2hxSlWTSlmvXGS{T1mERVpjP4N7NUZ7JmpzWkCWcW[vWH2HeGqSQU1jP4N7N{Z7JlSSc1qEXFqt[FiXfXKqRX6iN1pxZle1bHF{TUCLfoOPR3esTjJ8d{pyNkpjZld6bGqGcIWbcUh:Jku{PkF2OkpjSGGw[1mERXeKR1GoTVOC[1mERXulcV[6UWNxL2h{TnykN1K3Zn6PcFmFNHeLTGqpZ3qGeGCtRo[kN2KUXmiHNWqZUkCMR3Sw[FiTe1:qPI[lN3R{UH2HfXSIcI[NcUWt[FN6d3GYUnyjcl6tUGePc2qYUoKLfYeoZn6Xd3KEe3eLTGqpZ3qCdF:4NFuKR1GoTVOC[1mERXeKR1GoJku{PkJxPjK[NnitXUK1V2qZUoejNkW7XmF:QTJ8d{pzPENzPjKFVX:oTVOC[1mERXeKR1GoTVGtdGqqRX:LTGqpZ3qCdFmJd16EbVGoTVOC[1mERXeKR1GoR2GsUlOqRXeKR1GoTVOC[1mERXeEVXus[H2HfV26NDuZN1qtXkCteWquPISRcV63XleW[2CURoCjcmJzXWe4c3N{WnmkN2K6T1OTNmmZTYiYflKlUFOCe1yERXulcV[6UVOsdF:4NFuKR1GoTVOC[1mERXeKR1GLR2etcVuERoCjcEmpZ36LbHWU[3ulcV[6UYlxL2h{TnybNHy2Xn15eGCuUo[bS2W{TVeHfXOuSkWMSFW4UFSKe1yFUYeNSGG4T2Os[1uURkeFVX:oTVOC[1mERXeKR1GoTVGsTlOSNFuKR1GoTVOC[1mERXeKR1GLR2GtdGqqRX:[NklyZn6Sc1qJXnikblWxTVR1PVmFUYCKTIOPR3mC[1mERXeKR1GoTVOC[1OSb1qEVUCMTVOC[1mERXeKR1GoTVOCTlOSb1qNfUioWVeHfXNzWXelS3itTVeTbHSIWV6EbVGoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mEVnu[XGKtTVRx[3N{VomZN1qtZ1e5bGlzWX:LfUSvUFOCcly6Z4OKTGK6ZWdxc1qJXnikbl[jUWZxdFuVd16EbVGoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mEVkK[XFm7UGR2[nOuWn6UW{WuZolxL2qISkCbV1F6TVVybGpzWU[QcXitZliDcHOq[36[Nkm6XmOkdFyVOX2jN1q1XWiTSWmZVnyMR2KsXWiTcFuVd16EbVGoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mCNFuKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1y6PHeWS1[6Z{KW[3SIbHyKS{WpZmeWUlOqRXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOTNmmZTYqNWEWnZ32XcmOYOX2jfUBsZn2HeGqURUmKTGK6ZWdxc1qJXnikbl[jUXxxdF:4NFuKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1SSc3eKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOCely6RmG[XFq7XmODNHGIWXe[Nkm1Z1eHeXWSNFuKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1qJXnikbl21VHx6fWqY[FqjcWq3UGR2bnJzNYe[W{V2TVRx[3GZUoqbXGGwTlibbHOrSnKONUCxTVR5[3SJToCjV3es[H2HfV2Xd4qZV3uoU3mCclq7d16EbVGoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mCNFuKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[3GYXXeMR2JzXWiKflyVOX[kcW[vV2d2cXK6NDu[NkmsXmOCPWCURYiOR3uo[YdxT1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoR2OTNmmZTYqNWEWnZ32XcmOYOX2jfUBsZmeXfnNzSn6bV1F6TVOTNmmZTYqNWEWnXImocmRxd36MWIOPR3mC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKTECoXme5fmqURoCbbVGwTlibbHOrUYSRcEm6XmelTnKuXo[NWEWrZkKTcFmFNEmKSFm4T2ODO1SSc3eKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeLTGqpZ3qOeGCvTniiXF6tWH16NHGYUnyMSFW4UVO4[1qJXnikbl21VHx6[luE[FqVb2qRXEGXVWJyTlKTSW[nWFWtSGKWOWSTWkmHW1[DTmWsWlWLfXuxU4dxT1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1Go[mODcHKJUnyKS3yuTVOob3SuSomOfUBsXEOLcGpxcIWbcUi1VH2PemqIWXeRWECoUYqCdFmJd16EbVGoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1Gs[H2HfV26NDukcV[xZ{KXU3J{VoC[NmWwUWSCe1yERXulcV[6UYlxL2hyPH:LNHyQVnt6[m[XRliWb1[GVmZ6U2RyVn[SWV6WV2[bSlq6b4CQe{CMTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOTNmmZTYqNWEWnZ32XcmOYOX2jfUBsXleHNGqURUmKR2JzXWiKflyVOX[ZfXevWH16NFmISnqlS3xzXWiTcGqERkWbXGGvT2S{UlOqRXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVhx[2qYfIqbV1KxXnmCc1qJXnikbl21VHx6fWqY[FqjcWq3UGR2bnJzVnyKSEB6TVSSe1uURkeFVX:oTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERVqKR2JzXWiKflyVOYm[W3y7XmV2enSIcHqbV3e5UVSCd1mEVkK[XFm7UGR2[mi6[36TSUmPVWWtU1mGVmCTWl2oWHt6WVmGNVKXSV6KTomsdF:6RXeKR1GoTVOCUlOqRXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVhxUlOqRXeKR1GoTVOC[1mERXeEVXuLR2FxT1mERXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERkmKS2[{Z{KW[3W4NFuKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GLTlibbHOrUYSRclqpZWiPcGSuPUCiW16tT1SGe12Ee3eLTGqpZ3qOeGCtPX[MR3SHWXyLVGWtPWOTWXSnVUCpSmFxeH[Tb1[LWFOkdFuVd16EbVGoTVOC[1mERXeKR1GoTVOC[1mERXeKR1Go[mFxT1mERXeKR1GoTVOC[1mERVqEVXuPR3mC[1mERXeKR1GoTVOC[1OScEmKS2[{Z{KW[3GYXX:KR2JzXWiKflyVOX[kcW[vV2d2cXK6NDu[NkmsXmOCPWCURUWOR1GxTVi{UlOqRXeKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeLTGqpZ3qOeGCvTniiXF6tWH16NHGYUnyMSFW4UVO4[1qJXnikbl21VHx6[luE[F[WcFqRWXx6SWRy[F:VSUmDVlZ6TmKHPV:VNWKnVnt6WmSsVX6MV3t4SGGw[1mERXeKR1GoTVOC[1mERXeKR1Go[mODcHKJUnyKTIOPR3mC[1mERXeKR1GoTVOC[1mERXeKR1GLTlibbHOrUYSRcEm6XmelTnKuXo[NWEWrZkKTcFmFNEmKR{C5U4dxT1mERXeKR1GoTVOC[1mERXeKR1GoTVGsb3SuSomOfUBsZ32HdHNzWl:jN2KxXUKWc12VRYeNR1Gs[H2HfV26NDuZNUiwTkCXV2WsPWOZNVqHVkF6SGOGWlSUNUmIVWWtUVq6b4CQe{CMTVOC[1mERXeKR1GoTVOCTlOZNF6EbVGoTVOC[1mERXeKR1GoR2GsUlOqRXeKR1GoTVOC[1mERXeEXECoXme5fmqURkeFVX:oTVOC[1mERXeKR1GoTVGsTlqJXnikbl21VH6LbHGZUnyVcUlxZWePcFuFSYeOR4eoTlibbHOrUYSRcEmnT1OlSmWtTmCWcEmUVmWl[mFxbF[SNISnVnuHTmSEZ4CMWIOPR3mC[1mERXeKR1GoTVOC[1OZNF6EbVGoTVOCTlOSQU1jP4N7NUZ7JmWIPYqlSlqtZ2iXcHN{VU1jP4N7OUN3OEpjSGGw[1mERXeKR1GoTVetcVuERoCkNUmpZ36LbHWU[3ulcV[6UlOs[1qqXXe[NklyZn6Sc1qJXnikbmGxTVR1[12ERYCKTIOPR3mC[1mERXeKR1GoTVOC[1mEPI[KS2q3Z31ybHSERYSNWESo[FeXfnSFSUm[V2pxXmiPNF2rNXmKS2ZxXYl1UlOqRXeKR1GoTVOC[1mERXeKR2JzXWiKe1mFNHe[XFq6XWisc1uVd16EbVGoTVOC[1mERXeKR1GoTVilc3GYfHyMR1K{ZWiPNFuEVoWNR1Gs[Hms[2CURny[W16wT1OTNmmZTUCMV1GxTVi{UlOqRXeKR1GoTVOC[1mERXeKR1GoTVOCb3SuSomOSoSlTVRx[1mqVoWRV2JzTXq{UlOqRXeKR1GoTVOC[1mERXeKTECoTVOC[1SSc3eKR1GoTVOC[1mERXeKR1Gs[H2HfV2ERUmKS3y1Z1e5emqIWX:LfWmvUFOCb3SuSomOR3t4SGGw[1mERXeKR1GoTVOC[1mERXu[Nkm2[FeXeXSHVkWkS2WoVGOCbWFzPYWlS2[2[FNyNHWZRnyQbVKpZ1iDd3GYUnilS3y3Znl6OFyZ[EOlfUGuZkOLeFyZWomjS2[2XUJ6b2qYVnOkcIi2TXq{UlOqRXeKR1GoTVOC[3[SNFuKR1GoTVOC[1mERnyjTF6tTVi{UlOqRXeKR1GoTVOC[1mERXeKR2JzXWiKe1mFNHeLTGqpZ3qSO1SSc3eKR1GoTVOC[1mERXeKR1GsXUJ6eXSIWoWlSmJ2Z1eW[2CURXmSNkm2[FeXeXSENUCmXFKtU3mDNGqZbECNN3i1Zl[5fWiIOHmQe{CMTVOC[1mERXeKR1J6SGGw[1mERXeKR1GoTVFxT1mERXeKR1GoTVODdGqq[3eiXF6nZn6Xd3KE[3ulcV[6UYms[1uURkeFVX:oTVOC[1mERXeKRXuLTlibbHOrUXeRV1KPXWelcF:rdH6bXGKV[Fd6fWqWUo[jcWqxXomobXRzWnmNN2[2Z{KXbnSZTnyNNlqpZ{KX[nSZToOKbYeoUVOsO1SSc3eKR1GoTVOC[1mERXeKR1Gs[H2HfV26RUmKTF5xZ3x6fWqZRoO[W16tT1OkenGYOXubXHe2Z1epe1xzSnujW3y2Tom4[1q6Z4OKR2JzXWiKfluVd16EbVGoTVOC[1mERXeKR1GoTVOTNmmZTYqKSECoZ{OTfWh{TnykS4ipXUKWc1q6PYCjcWKt[VN2e3GJRY[LfYeoTomkd1mEVkK[XFm7T2S{UlOqRXeKR1GoTVOC[3[SNFuKR1GoTVOCUlOqRXeKR1GoTVOC[1y6PHekS1[6Z{KW[3SIbHyKS3Sx[H2XeVmHWmOVRUCMTVOC[1mERXeKR1Gs[H2HfV2qRUmKTFKpZ36PcGh{WomjR3es[H2HfV2qb{eFVX:oTVOC[1mERXeKS3yuT1OCbHGZUoqbXGGwTlibbHOrTnKLN16rZVeXeGqU[HSMV1J5[lOCc1qJXnikblqjTkOPbnGIWoSbV3SlTVOGPVmE[H:lTGK4Toms[1uURkeKRUCMTVOC[1mERXeKR1GoTVOC[3OuWkClXFq2TVebbHKJUnyQe{CMTVOC[1mERXeKR1J6SGGw[1mERXeKRUCMTVOC[1mERXeKR1G3UImDcHWJVom[W15xTVepenN{VXe[W{WsTViDbHSI[{[FVX:oTVOC[1mERXeKR2KwZkOPNFmFNHeLTGqpZ3qLZlpzbI[kN2GvXGS{UlOqRXeKR1GoTVOC[1qJRnilS3eoVGODdHN{UnylR3es[H2HfV2td36kS1ZxZVOl[FuURT:KR2JzXWiKfWe6[Ie[XGKwTkFx[1:qRX6NfXN4SGGw[1mERXeKRUCMTVOC[1mERXeKR1G3UImDenOIWoWKS1WoZ{J6bnFzWkCKS163Zn12cGl{VoCjNkSoZkJ1[3OIPYmlR1F1UVFxT1mERXeKR1GoTVOCb2qZTomjcUioVGODeXSYfIOQe{CMTVOC[1mERXeKR1GsXmiLfXN{VomKSECoZn6Xd3KFd16EbVGoTVOC[1mERXeLS2q4TVRx[2GIXoqjNl6zZkODcHKq[3uiS{m7[FO4[1:FRYOKR2KtZ36LeXK6e3eLS2[6Z36PNHOqe3ePV3t4SGGw[1mERXeKR1GoTVetcVuERXubclGoVGRxPVmIXnijTF6tTVOs[3W4NFuKR1GoTVOC[1mERXeKR1GoZ32XNHSZToWKS2qpZliPcF:4NFuKR1GoTVOC[1mERkmFVX:oTVOC[1mERXeKRUCMTVOC[1mERXeKR1KxXnmCc1mYcIqZNkVyZle4c1qJXnikbmmxT2ODO1SSc3eKR1GoTVOC[1mERXeKR1Gs[H2HfV6qRUmKR1qXZ{KXfVyWSn6bW{VxU3mCbVyqVkK[XFlzUHmLZ3OtfIWKboOPR3mC[1mERXeKR1Go[mFxT1mERXeKR1GPR3mC[1mERXeKR1GoUIl5[3NzWoWbR1JxZVeW[3OuWoilW2[7[FFxT1mERXeKR1GoTVODdGqqRX:LTGqpZ3qW[2CVNHeLN1K3Z{OScluURkeFVX:oTVOC[1mERXeKR1GoTVODcXOJWkCkfXesXn6Cd1mETmGVNV6WTVOTe2mZVn:KSXiWWl[Cel2UOIiZTFqkZnmKdF:4NFuKR1GoTVOC[1mERXeKR1GoZWe[[1uESoCkNUm2[Ge5d1uEVkK[XFlzT2Os[3W4NFuKR1GoTVOC[1mERXeKR1GoTVOC[1mIXoelXGK7T1OTcXOEe3eLTGqpZ3q[dF:4NFuKR1GoTVOC[1mERXeKR1Go[mFxT1mERXeKR1GoTVOC[1mERXebclJy[FiOc1qIXoeNR1GqV1d6fnSFc3eLS3i3Z{OTZ3OtfIWKbXt4SGGw[1mERXeKR1GoTVOC[1mERn2kTGZxZ4mob2qvRYOKR1qUXmebcHOuWomQbVGs[H2HfV1yfImZS{SqT2S{UlOqRXeKR1GoTVOC[1mERXeKS2q4[GiTfluEVn2kR4eoTlePenKvVnyjcmKW[WiDcFuVd16EbVGoTVOC[1mERXeKR1GoTVebe3SZVoqMR2KuZ1O4[1msUo[jcmKtZn6SeHKIWoWbN2KwU3mCbVyqRoqlTFq{Xmd1c1qJXnikblGxTVN1bWiJTnOjbVmxU4dxT1mERXeKR1GoTVOC[1mERXebclJy[FiOc1qIXoeNR1GqVUJ6eXKuWnqlS3y3Znqw[2lzfI[kNm[kZ3y5eWiJTnOjbVmxU4dxT1mERXeKR1GoTVOC[1mERXebclJy[FiOc1qIXoeNR1Gs[H2HfV2Eb{eFVX:oTVOC[1mERXeKTECPR3mC[1mERXeKR1GoXme5fmqYcH2KR3es[H2HfV6URUmRV1GvXkKXNFq6b3eme{CMTVOC[1mERXeKR1GoTVOC[1qJSkGbXFp2TVRx[1q6Z{eFVX:oTVOC[1mERXeKR1GoTVODdGqqRX:iXF67XmiSc1qJXnikblqjTkOHNWqZTkWLNUCxT2ODO1SSc3eKR1GoTVOC[1mERXeKR1GoTVOC[1qJSkGbXFp2TVRx[1q7PH6NbWJzXWiKfWe6[IilW2[6[WOl[F:4NFuKR1GoTVOC[1mERXeKR1Go[mFxT1mERXeKR1GoTVOC[1mERXebclJy[FiOc1qIXoeNR1GqVkCXWVmJd3ukS1ZxZVhyO1qJSkGbXFp2[mODTW[HVmGNflW2UW[5fWiIOHmMWIOPR3mC[1mERXeKR1GoTVOC[1mIcH2KR3epZWiP[nKvWoOjR3es[H2HfV6qb4CKTIOPR3mC[1mERXeKR1GoTVOC[1mERXeKR1KuZ1iXNHO6[3ubclG{TVOTNmmZTUKMWIOPR3mC[1mERXeKR1GoTVOC[1mJNF6EbVGoTVOC[1mERXeKR1GoTVebe3SZVoqMR2KuZ1O4[1msbI[kN2F3TVOTc3J{UkCZTFqkZnmKdF:4NFuKR1GoTVOC[1mERXeKR1GoXn6DNXSJUX:LS2q4UFOCbWFzPYWjcW[r[FetenKrc3e[Noi3Z{KXZ3OtfIWZTFqkZnmKdF:4NFuKR1GoTVOC[1mERkmFVX:oTVOC[1mCNFuKR1GoTVOC[1mERXukcW[7[Ge5NFmFNHeLfXN4TVFxT1mERXeKR1GoTVODN3GIcIObV3epXn2Xemqq[3ubclGxT2ODO1SSc3eKR1GoTVOC[1mERXeKR1G3UImDfWqYUnyiXGqtTViTc2qURombXF5yZliTflmIPX2KTGKwXmODfWqZSkGbXF5xSGGw[1mERXeKR1GoTVOC[1mERXukcW[7[Ge5NFmEOEmKS2qvXmiTfluEVn2kR4eoUWSKOFuVd16EbVGoTVOC[1mERXenVUCMTVOC[1mERV6EbVGoTVOC[1mERXeNfUioXUK5enNzWXelS3itTViPemlzeHylR1KrZkJ2eWqYUkCiW{m2U3dxT1mERXeKR1GoTVODcWlzfI[kNmWwTlebe1uVd16EbVGoTVOC[1SSc3eKR1GoTVOC[1mEPI[KTF64ZletNFmJVn:bV1K6XmiPNXKJVXeiS2[pXleXfVmIXomjNkCo[FepcFmIUo[jcmKtZn6SUlOqRXeKR1GoTVOC[1qJTnykN2[{[FOCPVmIWkSkS4i3XleWc1mtfImZS{WkZ3y5eVmqe3eLTFqtZ{OXd3SEe3eObXt4SGGw[1mERXeKRUCMTVOC[1mERXeKR1GsZVeXbGqIWomKSECoZWiPfmqZVX:LTFqtZ{OXd3SHd4eZV3uoVImCb3OuWoqlW4hxW4qD[FmFc3eLfXN4SGGw[1mERXeKR1GoTVOTbnJzOUCbW{VxTVRx[3GZUoqbXGGwTliLcHN{WoOlSoO5XGOs[2C6RXukcW[7[Ge5NGe7SnSKSH:oTomkO1SSc3eKR1GoTVOC[1mCNFuKR1GoTVOC[1mERXulcV[6UWOCPVmIOXylfVK7[FeTSHKISoqkfXexU4dxT1mERXeKR1GoTVOCb3SuSomOV{BsZVeXbGqIWomKSECoTlepcGmYVnykboOPR3mC[1mERXeKR1GoTlibbHOrSYSRcV63Zn6TcHKvVXeRV1GsXUJ6eXSIWoWlSIOPR3mC[1mERXeKR1GoSGGw[1mERXeKR1GoTVN5elmGbHijcWK{XmODbnGJWoWiNm[sTViTfWmYOYqbcW[6TVetcVmIOXybW2KtXlFxT1mERXeKR1GoTVODdGqq[3ekN2K6Z1d6fluJUkCkcmK3Zld6N2qZTX:LTGqpZ3qGeGCubHy[W2KtZ3msd1mE[ECkcV[2Z{KbcHOqNXyjcV63XleteWq7c3e[NnhyZn21cGqEZ4CKR1V6VGODcWmYfIqbV1GxTVi{UlOqRXeKR1GoTVOC[1mERXeKR2K4XWiLfmqYVXeRV1GvToq{UlOqRXeKR1GoTVOC[1mERXeKR2K{XmebNFmFNHeLTGqpZ3qGeGCuUo[jcmKtZn6SO1SSc3eKR1GoTVOC[1mERXeKR1GPR3mC[1mERXeKR1GoTVOC[1mJ[H:iW4itT1ODNHOvWnyKR3uo[YdxT1mERXeKR1GoTVOC[1mERXeKR1GoTVOTe3J{UXeRV1K7[FiLe3J{UX:LS4itXn6Sd1mETnOkcIi2TXmsO1SSc3eKR1GoTVOC[1mERXeKR1GoTVOC[3GYXX:KR2K4ZkOO[2CVNEmKS2qpZliPcFmEb3eme{CMTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoTVODfWqZVkGkcUSoTlibbHOrSUeFVX:oTVOC[1mERXeKR1GoTVOC[1mERXenVUCMTVOC[1mERXeKR1GoTVOC[1mERXeKRUCMTVOC[1mERXeKR1GoTVOC[1mERXeKR2KrZViXeXF{UoCmcWWoVGODfnSYToqlTFmwTle5cGqvVYOKSFG{TVOTe3J{UYCQe{CMTVOC[1mERXeKR1GoTVOC[1mERXeKR2K4ZkOO[1u7NHekN2K6ZleXeVuETnOkcIi2TXmsO1SSc3eKR1GoTVOC[1mERXeKR1GoTVOC[1qIfHybcmGoVGODfnSYToqlTFmwTle5cGqvVYOKR2K4ZkOOdF:4NFuKR1GoTVOC[1mERXeKR1GoTVOC[1mCNFuKR1GoTVOC[1mERXeKR1GoTVOC[1mEVoejN12oVGODfnSJToejN12wTlePc3SYOYKkNnx3XmO4[1q7d36MWIOPR3mC[1mERXeKR1GoTVOC[1mERXeKR1KxXnmo[1qJRo[kfVGpVGRx[2quSoOkNmWoT2ODO1SSc3eKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR2KrZViXeXF{UoCmcWWoVGODfnSYToqlTFmwTlePc3SYOYKkNnx3XmO4[12Ee3eLTFK3Z4msO1SSc3eKR1GoTVOC[1mERXeKR1GoTVOC[3[SNFuKR1GoTVOC[1mERXeKR1GoTVOC[1mEVnqiTG[2ZUOPdHWuWXeRV1KwXmipb2qYUX:LS16w[Gd2dnNzcE[bV3t4SGGw[1mERXeKR1GoTVOC[1mERXeKR1GoSGGw[1mERXeKR1GoTVOC[1mERXeKR1GoZWe[c1mEVnqiTG[2ZUOPdHWuWXeRWECoUVOCdFmJd16EbVGoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoXX6LcGmYd{eFVX:oTVOC[1mERXeKR1GoTVOC[1mERXenVUCMTVOC[1mERXeKR1GoTVOC[1mERXeKRUCMTVOC[1mERXeKR1GoTVOC[1mERXeKR2K4XWiLfmqYVXeNbkCoZ{OXbXN{VomMR2K{XmebNFyERYeNR1GsXUKpNXKueIqiXICtT2S{UlOqRXeKR1GoTVOC[1mERXeKR1GoTVOCb3KIWn2lR1F6TViPNWmvUkCkbXesZleXcXSEe3eLS16w[Gd2dnNzcE[bV1GzTViPNHOufHyjbXeqXFiLZ3KqTYCMWIOPR3mC[1mERXeKR1GoTVOC[1mJNF6EbVGoTVOC[1mERXeKR1GoTVFxT1mERXeKR1GoTVOC[1mERXeLTGqpZ3qGeGCuUo[jcmKtZn6S[2CURXukS1[6Z{KXb1:4NFuKR1GoTVOC[1mERkmFVX:oTVOC[1mERXeKRU1:Jku{PkJ1PjK[XGZxZkJybHSIcHqTS{l{Zn25emmYVYljP4N7NkNzOEpjR3mC[1mERVqiW2moT1VybGpzWU[QcXitZliDcHOq[36jXGJyZ32LelxzcIWbcUivT2NxL2pzWkCWcW[vWH2HeGqU[4CRWECvZUOLNHKIeHiiN1lxToms[3W4c3eKR1GoR2GsT1mERXeKRXuLTlePenKuXoCbfVF6TVVybGpzWU[QcXSt[F[PdHKu[IObXGK3ZnmocnKZVkGkcVq3UEKPenKuXoCbfXOxU4ew[1mERXeEVXyxXnmCc1qIUo[jcWqxXolxL2pzWkCSXGZxZkJybHSIcHqTS{l{Zn25emmYVX:MV3uo[Yew[1mERXeEVXuMTVOC[1mCb1qEXGK6[WODO1OqRXeKRXuLR2Gw[1mERXeEVXuLR2OTNHSZTnmjN1Kp[Feo[2CURXu[Nkm2Xn2tclyVOX6bXGKW[GiLbXJ{RnilS3ewT2S{T1mERXeKRXuLR2Gsb3KYPXubW4eoVGODUmmY[HyQboCvXmiTUnJzVnyjR3evZmiTNXOuTo[NNkFx[GiLbXK6Z4CQe3:LR2GsTlOSb1qEVXuLTVOC[1mCb1qEVX:LR2GsTlOUPI[KS3StZn2XfWmZVnyKS4ixZ{OS[2quPYmKS1[{ZlODN2qYToqiXGKtZ4ew[1mERXeEVXuLR2OTeHJzVnyjR{BsXkKXeWqZTnilS2[XZ325UXGZUkCMR3t4R3mC[1mERVqEVXuLR3mC[1mERVqEVXuLTlilcGmvUoClS2[7TVRx[2SYSn6bWH93XkKXNGSYPXubW4ewTkKPenOuWY[lNm[qZ{KtNGqUZ4CNWEWvXmiTSHJzfIObW15xZWd6eVuEb4SRcYi3XWeSc1uUNDubNmZxV2iTcHKZUX:MWIOMTVOC[1mCb1qEVXyuZkOLcGmYUn:KR3es[EKXbXNzcECbXF2oXWiO[1qJ[Hy[cl6x[FeWdFmJd1uKR1GoTVGsTlOSb1qEbVGoTVOCTlOSb1qEV2J{XmeLfnGZVnySNkm2Xn2tclmFNHeLS163Zn2bdGq6NDubNmZxWkKXbXNzcECbWV63Zn2bdGq6[3ulNm[qZ{KtNGqUNDubNmZxVUJ6b2qU[4CMWIOMTVOC[1mCb1qEVXuLZWe[[1uEVkObW1q7ZWiTcGFzPYWbcXyvTVO[cVmEVkObW1q7ZWiTcGFzPYWbcXyvUGR2cmqZVl[jcV[qZleXb1uEb{mRV3O5Toms[3W4c1qEVXuLR2GsTlqIUo[jcWqxXoesTlmFNHeLS163Zn2bdGq6NDubNmZxV2d2NGqZToekcWZxT1OsO1Oob1qEVXuLR2Gsb3N{Wnm[cV[7XmOC[1mCb3eRV1KPXWelcF:rdH:bW4i4XmiKc1pzNUClXFqqZol6N2qYToqiXGKtTomseGCu[HylSl5yXX2LbHNzWX:LTHStXX6PdHSIWYSRcXSt[FWTcGquSkGjTGKV[Fd6fWqZXoCbXHOwT2OsO1OSc3eKR1GoR2GsTlOSb1qLTHStXX6PdHSIWoe[XGKwTVRx[1qJ[Hy[cl6x[FeXSHJzOX2iW3O1VH2lcHSGTnikNm[GZWiKc1uUOVWWfUSs[FiXfWmuPYe[XGKwUHuTWFyqVoqlW1qqXWiPcFysVmSNbWJ{XmeLfnGZVnyNWEWvXmiTSHJzVnyMR3u2Tol2NHWJVX6Qe3:oTVOC[1OSb1qEVXuLTldydHKvUoCmcWWLTVRx[1qIUo[jcWqxXolxL2pzWkCVW3y2ZWdybHKHRnibNm[VZWixcFuEb{eE[3uLR2GsTlOSb3ukNl66ZWiDNFmCb3eRV1KPXWelcF:rdH:bW4i4XmiKc1pzNUClXFqqZomkdFyVOX6bXGKI[Ge5d2KIPUOjcYi3XWeTWGl{ToCkTGKSXWiTc1uEb{eE[3:LR2GsTlOSb1qiW2moT1OHdHNyPXymS2[r[GiTbGmufHyMR2K7XUOLdHOJVYCMVX:LR2GsTlOSb1qEW16wZmd6b1uEVoq[N1qxZ1iSd1mEZ4ePfnNyTomsO1Ooc3eKR1GoR2GsTlOSb1qLS163ZmdybHKuVXeEV1F6TVOTfml{ToCkTGG2TomCclyqVkObW1q7ZWiTcHOISkCiR{SvTVOkeVqINYCjcl6x[X2WeVq6RYmRbWm5TVO[cl:6RY[NfVKpZ{OteWlzbImjNkW3[GiO[2lzSoOjS3y2XoewT1OSb1qEVXuLR2etcVmE[3uiW{VxXmiLe3OuWkCMVX:LR2GsTlOSb1qKR1GsXUJ6eHKYSoWbR1F6TVOTdHKvVnykclK6XmiSeVq6RX6NbWKrZkJyeGmYOXuQe3:MR2GsTlOSb1qEWVKt[VeXbluEVnqjNkG1XWd2b1uVd1uE[3uLR2GsTlOSb4[NfVK7XWibcFmIVo[lNkW{ZkKHb1mJVoCjW2Wo[Fd5[2lzPYWbcXyvR3esTlOSb1qEVXusXleHNGqURXeKSECoXleHNGqU[36YV{G1UGeS[2OFdICQcl2vT2S{T1OSb1qEVXuLR2OTbnJzOX2iW3O1VH6PcHSGfHikN2KWZWdycGRzXlKlXGK3ZmeHNHGYUlWjN3S2Zld6bGqE[3ubS1ZxXmOsO1Oob1qEVXuLR2Gsb2lzPYWbcXyvUGR2fmmZXnyMR3t4R3ew[1mERXeEVXuLR2GtPVOqRXeKR1GLR2GsTlOSc3eKR1GoR2GsTlOZNFuEVXuLR2GsT1mERXeKRXuLR2hx[2lzSkC[NneoT1WXOGlzWoelS3y3ZnmCb2qUb3eme3:oTVOC[1OSb1qEWUGpXkKWOl:ufI[bfXesXmNxL2pzWkCVW2[7Z{KHcmqU[4CMWIOMTVOC[1mCb1qEVXyPXWelcF:rdIOjNnSH[VePcHOJVoCjNkSwTleWdF:4c3eKR1GoR2GsTn[Sc1qEVXuMTVOC[1mCb1qnVX:oTVOC[1OSb1uKR1GoTVGtPVmIWoOkNmWo[Yew[1mERXeEVXyPXWelcF:rdIOjNnOwTkB2elmJXnijS3ysTVe5dGlzWoW[NmW2TVV2enSIbICjcXOoZ1eHcmqURkOiW4i{TVeLcFmIVo[lNkW{ZkKHb2qYVYWLfXt4R3mC[1mERVqnVX:oTVOC[1OSQU1jP4N7NUZ7JnN{cIW[Nni6ZkJ2dHWuWU1jP4N7OkJyOkpjSGGw[1mERXeEVUCMSGGw[1mERXeEV{iyTVWLNXGYfHuiW{WvTViHNWqZToCbXF2oXn16fVmJUkWjcV6wZ316eXGZdHilS3y3ZnmDbmmZVnybNkm6[WODNnGYWkOKS1[2XlODe3OuPXulW15xZ4mDb2qZVniiW4eoT3l5UlOoNFuEVXu3T3mDcmqZVkCiW{WvTVetb3O6Ro[bbVK4Z32XNnGYWkOKS16p[FeXcnJ{ToCbXF2oT3l5UlOqRXeEVXusZ1iLcHSucHylN12oVGOCb3SuSomOR{BsXkKXNGWJTnylcXyt[ECPbHSIWn6jN1qxXmiOc1uVd16EbVGoR2Gsb3OJTnylcXyt[EOO[2CURX:LTFK6XmibdGqZ[IqRWECvToms[2C6RX6NWFWvTVSw[1qJRombXGqxXmilfl:4NFuKR1GoTVFxT1OSb4[MbVKvXmiTNHGYOX6KS3ysZ4mDemqqRoekcUms[GePNFmIUnilS2[vZkOLdGqZUXeMbUiLSGGw[1mERXeEV2K4Z316b3SYUkCkfVF6TVOTNmmZTYeNWEWvXmiTVXOuPXulW15xVUKHNGqY[I[kcXytZ4modF:4NFuKR1GLR2OTe3OuPXulW15xZ4mCPVmE[3ukTFq3XliXbnSJUUmRV3OvT2OCM1mEZ4SOV3OoU3mCb3OJTo[bTG[r[FiOO1SSc3eKRXuLSGGw[1mCb1qNfX:oXX6XdHKIVXeiW{W7XmiLNFmJSkGbXFp2TVebfXJzNHe[Nkm6XmZ6NXOufH[kcWZ{Z32tNGqURYGNe3uPR3mC[1mERVqLTFZyXmiLOWOYOYqbXFpxWX2XN3OucECbV1F6TVOKUlOqRXeKR1GLR2FxT1mERXeKRXyLWHyPSmWtVXeUWXSQWEGLSlmGcF:XSUioXVOKeVqJXnikbmG2TX1yNHSZTnmjNlGoT1eDNXOufH[kcWZ{Z32tNGqXPYCbS1G{TVeDfnSIPYmbWkmxXleCd1mIRnq[XGKtXkJ6fXWXPYCbS1G{TVeDe3OuPXulW15xXEKtb2mEe3e[TFqtZ2iXcHN{Vn[kS1ZxZVeCdFSSc1qEVXyVVmW5SmFyVXe[TG[6ZlZ6fWqZ[ImiXGKtXEKtb2mEe3e[TF5xZkOLcGhzcHu[R4eoXVePbHSIWn6jN1p2XEKtb2mEe3e[TFK6ZkKTNWl{Vn[iW2KoUFOD[3OuWoilW2[7[FZ6e2mZVn:[RUCMR2GsTmKtTmCVV1KoTXl1b3SuSomPR{SqXUJ6fWqXPUGkcYinZ32XN3OucECbW1GPR3esTlOX[FmTWlqHTVFxT1OSb1qMRUCMR2GsTlOUbHe[NlZxXmelenOvcH[iW2KoTVWtU1mE[3mKR{SoTliDfWqZXoCbXHS7TVOCeVmETYCKSV[QVlOD[3OJTo[bTG[r[FZ6dGqIRXeUWl2oWHyXUWSEb3eVNVmoSGGwTlOSb1qMS1KrXWiTcGpzPYmmWkmxXleC[2OWOHeMR1moUHmCb3OJTo[bTG[r[FiO[1mEOHeKbXuoVWV2SVmIRoekcUms[GePNGhzcHu[R1KLWYmDU2RyVXeVcG[OWFOs[2RyTV6E[3uLR2Gsc2mIUnilS2[vZkOLOWhzcHu[R1KLWYmDU2[WfF2KSV[QVlOD[3OJTo[bTG[r[FZ6dGqIRXeUWUSoSGGwTlOSb1qEV3iVVmW5SmFyVXe[TFK6ZkKTNWl{Vn[iW2KoTVWbV2RxNHe[R1m2TlibbHOrVYWKcV63Z32X[nSZToOZN1qt[EOLdHSIWneFVX:LR2GsTlOScGiUSW[UVmOD[2lzSkCbW3S3Z36t[nGYVneKSXyQTVOobVmEOHeLTFK6ZkKTNWl{VoqKR{SoTXmsdFuSNFuKR1GoTVOC[1mERXeKR1GoTVOC[1mERXeKR1GoT2OKeVSSc3eKRXuLR2Gsc1uEVkK[XFm5TVOGPVmEZ36MV1FwTVOLRmSsVXeMS1K7[Fd6fWqXPYCbS1GoWHt6WVmGcF:KR3eqTVN1[1qJXnikblWoUHmCbVuUb3mKSH:oTXmKdFyqTV6EbVGoR2GsTmGWOVWKRUCMR2GsTlOUbI[kTGKxZkJ2flmGfFqUNGWoTomkdF:6TUeFVX:oTVOC[1OSNFuEVXu3T3mDbXSYcIObR1KsXme5cHSIWXekXG[tZ36s[2quPYmKTFqtXUJ6fWqJUXebclq3ZmODbnJ{TnyZN2[6ZliLcHR{ToClS2WoT3l5UlOqRXeKR1GLTliHNWqZTkWTS2[{XmiTcGWuWkOkcXxxXmOCPVmETV6EbVGoTVOCTlSSc3eKR1GoR2GtSWKWfF[XSWWoVnyLVGSURneKbUSs[H2HfV6EOHmjXGJyZ32LemmCNFuKR1GoTVGs[1mERVqXNHiHWXuW[1mCNFuEVXuLT1OCUlOob1qEVXuwXVePbHSIWn6jN1p2XEKtb2mERl:VNWGoV2V1[1uETYWKR2K4Z32XNnGYWkOkfVGoUHmCbVuURlKVb2GoXViDfXJzVkG[N2KnZWeT[1mGcGSKSUWXWFW4dFmGPWOFVX:oTVOC[1OURXeKR1GLT1eDbmmZVnybNkm6[WZ6dGqIRXeVb{mWTVWtU1mE[3mNbVGsZ1iLemqJWnqlTF2oUHmCbVuURlKVb2GoXViDfXJzVkG[N2KnZWeT[1mGcGSKSUWRWlODU2[WfF2MV1KRWXdxT1OSb1qEV3ioXUKHNGqY[I[kcnynZWeT[1mGcGSKSUWXWFW4[2GWOVWKS1K4Z316b3SYUkCZNnysXVODTmSqRV6E[3uLR2GsTluHUl[VSW[FWlOD[3OJTo[bTG[r[FZ6dGqIRXeTcFqRWGOD[1mqOHulcV[6UlN1bWlzPYmbWklyZ325[nOuWkOkcXxxXmeCUlOob1qEVXuLR2[lTWKXTl[KS1KrXWiTcGpzPYmmWkmxXleC[2SsPWWKSXyQTVOobVmEOHeLTFK6ZkKTNWl{VoqKR{SoTXmsdFuSNFuEVXuLR2GsdF:6TUeFVX:PR3mC[1mERVqNfX:oXX6XdHKIVXebS2[{XmiTcFmJSkGbXFp2TVebenOqRombW2KxZ32XbnSJWXelXFq{Z4mCdVy4NFuKR1GoTVGsb3OZWnykcnyGXme5cHSIWmObW2KxZ32XbnSERUmKRUCMTVOC[1mCb1qKb2KHWFWXWWKURleWb{mPTVeCbVyqVkK[XFlxUHmLeHSJWom[cUmoTV[lTWKXTl[KS1K6XmiHNWqZUkCZN1Kp[Fep[1mGcF:KR3ePR3esTlmERXeKRXyVVmW5SmFyVXe[TFqtZ2iXcHN{Vn[kS1ZxZVeC[2KtTmCVV1KoTXl1b3SuSomPR{SqXUJ6fWqXPUGkcYinZ32XN3OucECbW1GoWkCpSmWsWXe[S{m4[FetenKvUneKSIdsTVOkclSSc1qEVXuxU4mKO1SSc3eKR1GoR2FxT1mERXeKRXu3T3mDbXSYcIObR1JyZ1eTbHSIWXekXG[tZ32tcHO6Rn2jN1mo[Fite2qURYGNe{CMR2Gsb3OZWnykcnyXZ1eTbHSIWlS[XGKtXkJ6fXWURUmKR1qXWVWTRm[GWXe[R1m2TlibbHOrVYWKcUFx[GiLbXJzRXeWNG[WTVeDNHWZRny[SECvXUKHNGqY[I[kcnuvTV[lTWKXTl[KS1KrXWiTcGpzPYmmWkmxXleC[2OXUXeVb{mWTVV2WmSGe3eSWUWGTVeDe3OuPXulW15xXEKtb2mERlqWfVKQWmW5UVmrd3eFVX:LR2OTfHSYWommWm[4XleHNGqXRomjNmJyXUOS[1mFNHeKcG[SVlWHWWKURneKbUSs[H2HfV6EOHmjXGJyZ32LemmERmSTWmGoXViTOXOIWneRV3S4Z316b3SYUkCLfVKZV1WXV2KURnekTFq3XliXbnSHPYCbS1GoV2[O[2SsPWWKSUWXWFW4bV:6RV6E[3uLSGGwTlOUPIGKSVpyZWe5b3GYOX6KTFZyXmiLdGqZUXebcUm6TViPOXKuUn:kcUm2ZWixbHSIcI[jbVKrZmiO[3OISn6bXF2oT3l5UlOoNFuKR1GLR2N5dVmI[HylR1KrZkK5d2qYUkCiW{m2TVePeHO6Roe[W3StZ4mDcXOuPYSKSUGpXkKXeXSIPHeSNkm6XmOCdVy4NFuKR1GoTVGsb2lzNYqWS1[vXmiPTnSIWoSkfVF6TVVybGpzWU[QcXSt[FVyemqIWoOMR3SrZmiOenOISn6bV3OxUGR2cmqZVlSjNoi{XmePNHGYPYWMR3u1VH25emmYVX:MV{BsXkKXNGOZVnyjXF2wT2S{UlOqRXeEVXuPR3esTly6c3ebNmZxTVetb3O6Ro[bbVK7Xme5cGl{VnybR1KrZmiO[3OISn6bXF2o[EKtNHGERoqlS{m6XmODbnJzVnykfVKuZ316eFmGNWWlXFqqZomDbnJzOX2iW3OoT3l5UlOob1qLS161Z4mCPVmEVkK[XFm4UGR2cmqZVlSjXF6SXWelcHO6[4CQe{CMR2Gsb2lzNYqKSECoTXmkbVyvUkCkcEm6XmiDd2mYUnyMR1m{TXm4[1mqZ4OLfVm{TVOTbnKZUYCNbVmvTXq{UlOob1qLS161Z4mCPVmE[3u[NkG7VGRxclq6b3eRfVGvUGSGclmFc3eLS161Z4q{UlOob1qNfX:o[FiLbHKvUn2jN1q1TViTelmISomkcVZ2TVebenOuNHeMbUiPR3esTlqIUoSkNF[6Z3mCPVmIWkSkS4i3XleWc1mqe3mNR1K7[FiL[nOuWoejS1[rXmOobVq6TYOKR1mqUFOCb2lzNYqMV3t4SGGwTlOSNFuEVXu3T3mDcmqZVXekS1[vXmetb2h{UkCjN1qtXEKtb1mISoOkcW[pXlis[3N{cIW[Nni6ZkJ2dHWuWnuKS161Z4mDe2mY[HykfVGwZ1iLcHSuWoWlR1Ks[GiDd3GYUoClS2[7T2OCdVy4NFuEVXusXUJyfmOYOVWSbVF6TVeHfXOuSkWMR3t4SGGwTlOYXo[kcW[pXUKo[1uEVkK[XFlyTVeHflmEVnqjXF6LZnms[3W4NFuEVXuLTlePeHNxcIWTSVqjXGOCPVmEVnqjXF6LZnlxL2pzWkCWS1[vXmWtb1uEb4WLNUivUHmTbnKZUlqjbUBsXkKXNGV{Vo[kcW[LXlOodF:4NFuEVXx6SGGw[1mERXeFVX:LR2N5dVmITkGiW4isTVeteXNzWomlR1K5[GeXfXWURnqjXF2oT3l5UlOob1qLTGqpZliO[2CURnikclqp[WOodF:4NFuEVXyuZkOLcGmYUn:KR3esXUJyfmGZTomKS1[7TVOTbnKZUn[[NkmsXmOs[3W4NFuEVXuLUImw[3GYXXe[NkG7TVeHd3OuWnibTHuoXmipdHN{VXeiW{SoZmiTNXOuTo[KTGKpXX25cFmJVn:bW{SoZX6XeHOERoClR1GyUIdxT1OSb1qiW2moT1OHdHKtPXikclqp[WOob2lzNYqZNl63XleWd1mEVnqjXF6LZnuTR1uUb3eme{CMR2GsTlOUVnu[XGKpTVRx[2qZbIejS{msXmOobWi6TYOKR2KrZmiP[mlzPXubV3t4SGGwTlOSb1qiW2moT1OpbnJ{WoWlR3esXleHNGmUb{mRWFmxTVO[cVmIcIqkNmZxT1OTbnKZUmG[W3StZ{CtNGqYNYqYfWKsXWiTbGe7RnSZV3uxTVi{UlOob1qEVXuLTleHfXOqRXeRV1KpZ36LbHWU[3ubS1ZxXW[{fGiUe3eKbXOqUHmTbnKZUmG[W3StZ{CtNGqYNYqYfWKsXWiTbGe7RnSZV{BsXkKXNGOYVnyjcmKxXn2tcHOq[4CNbVmvTXm4[1qIVnilS1[jUVZxd1mETX6[NkG7TomKdF:4NFuEVXuLR2Gsb3SuSoOkNYSlTVRx[1mq[3mNcXy1Z1e5emqIWX:KbYeqUFOCb2mZTomMV{SqT2OKO1SSc1qEVXuL[mFxT1OSb1qnVUCMR2GtPVSSc1qEV2K5[GeXfXWWcIWkNm[6[FWPUmW6RUmKR3OvU4dxT1OScICbbVGwXUJ6NXKvVX:LTGqpZliOdGCrRYCFVX:LR2Gsb3OZWnykcnyLZn6PcHOvVlSVWl2oVGOCbWOWOWSTWlqWTVWtU2[GPHe[R1m2TlibbHOrVYWKcUFx[GiLbXJzRXeMS1K7[Fd6fWqXPYCbS1G{TVeDfWqZSkGbXF5xXEODbHSIbHeNR1KoZ1eHcmqXPYCbS1G{TVeDNHWZRny[R3uoWnuHUW[WWmSKR1m2SGGwTlOSb1qiW{G4Zld6b2qU[3mNR1m{TVOTNmmYfIqMV1G2TVOKO1mrd16E[3uLSGGwTlOSNFuEVXu3T3mDbXSYcIObR1KsXme5cHSIWXekXG[tZ36s[2lzNYqKR3:3SGGwTlOUVoilW2[6[WWTcHKIWkCbWV6PWYmCPVmETV6E[3uLSGGwTlOScFWTWYiHWlWW[2KtTmCVV1KoTXl1b3SuSomPR{SqZmiTNXOuTo[[R1KZV1WXV2KURX:FVX:LR2GsTmFxPV:SNF[WT1eDe2mY[HyZNnysXVO4[1pyPH6NR1KoZ{OTenOuWn[iW2KoT2ODU2RyVXeUWUSoT1OK[1yqRXu[NkG7TVN1[1mqb4CQfVl4SGGwTlOSb1qFVX:LR2GsTlSSc1qEV{iyTViHNWqZTkWKS2q3Z3mDfWqZ[ImiXGKtTVeteVmIcIW[W15xZWibcFmJUkCjN1qtZ4mCdVy4NFuEVXusZ2iXcHOvcFWbW4it[FeXTnKsSnqlS3xzXm[PNHJ{TnykfVGoVGOCbVSSc1qEVUCMR2GsTmKGWl2TWmKHTVWbV2RxNHe[R1m2TlibbHOrVYWKcUFx[GiLbXJzRXeXNHiHWXuW[2mJUkCjN1qtXEKtb2mERlqVbVGwTXmCeVmEVkK[XFm5TVN1[1mqb{eFVX:LR2GsUlOob1qKboOPR3esTlSSc3eKR1GoR2OTbnJzOYWbW15xZWd6eVmFNHeVW1[vXmSwOmpzWkCWNny2XkK5cHSIPYWMR3SrZkOLcFx{TnykNklyZ32PcFq6b4SRcXSt[FWPenKuOXy[N2KxZkJ1c1pzUo[kcW[n[EOLdHSIWX6MWIOPR3mC[1mERVqFVX:oTVOC[1OZVommV1J4SGGw[1mERXeEVXuPR3mC[1mERVqEV2KrZkJ2eWqYUkCiW{m2UGR2fHSYWommV3eqWUGTRmWtVXeXSlqDWHyPRmFyVlqVNESqT2S{UlOoNFuKR1GoTVGsTlqIUo[jcUWtXUOTdHJzOISRclZyXmiLOVuEVoilW2[6[WWteXNzWomlSlqt[EOLdHSIWYCQfVGoSGGwTlOScICbbVGwTliHNWqZTkWUW{W7XmiLNGFxNWSKWECqTXms[1qIUo[jcUWtXUOTdHJzOISRclZyXmiLOVuEVoilW2[6[WWteXNzWomlSV6PWYmsO1mERXeKR1GoTVGsTlSSc16E[3uLR2OTbnJzOYWbW15xZWd6eVyVOYilW2[6[WOob3OZWnykcnyGXme5cHSIWmObXHS6ZWiTcFuVd16E[3uLR2OTbnJzOYWbW15xZWd6eVyVOYilW2[6[WOob3OZWnykcnyGXme5cHSIWmObW2KxZ32XbnSEb{eFVX:LR2Gsb2lzPYWjcW[r[FetenKqNDukXG[tZ36sc1qJSkGbXFp2VleXd2qZVnySNEGVT2S{UlOob1qEV2KrZkJ2eWqYUkCiW{m2UGR2fHSYWommV3esZ2iXcHOvcFWbW4it[FeXTnKsSnqlS3xzXm[PNHJ{TnykfXt4SGGwUlOob1qEV2KrZkJ2eWqYUkCiW{m2UGR2fHSYWommV3esZ2iXcHOvcG[kS2Kp[FeXSGmZVnybNkm6[WOsO1mERXeKRUCMR2GsTlqIUo[jcUWtXUOTdHJzOISRclZyXmiLOVuEVoilW2[6[W[Xe2qISkCbWlK6ZkKTNWl{VYCQfVGPR3dxT1mERXeKRXx6TVePbHSIUn:KR3iH[VePcHOJVoCjNkSoTleWdFmJd16EbVGoTVOCTlOUVnqjNkW2XmePNHGYPYWNWEW5[GeXfXWU[3mWb{mOWFWLRmFxd3mMWIOPR3mC[1mERVqEXGKwZ316N1mEVnyQe{CMTVOC[1mCcEmFVX:oTVOC[1OSNFuKR1GoTVGsb2lzPYWjcW[r[FetenKqNDukXG[tZ36sc1msUmCVWUGLWlOKdF:4NFuKR1GoTVGsUlOqRXeKR1GLJku:
app/code/local/Artio/MTurbo/controllers/Adminhtml/MturboController.php CHANGED
@@ -75,79 +75,133 @@ class Artio_MTurbo_Adminhtml_MturboController extends Mage_Adminhtml_Controller_
75
* Uninstall Magento
76
*/
77
public function uninstallAction() {
78
-
79
- try {
80
-
81
- // remove mage patch
82
- $patch = Mage::getSingleton('mturbo/patch');
83
- if ($patch->isPatched()) $patch->removePatch();
84
-
85
- // remove layout patch
86
- $laypatch = Mage::getSingleton('mturbo/layoutPatch');
87
- if ($laypatch->isPatched()) $laypatch->removePatch();
88
-
89
- // remove mturbo directives from htaccess
90
- $htacc = Mage::getModel('mturbo/htaccess');
91
- $htacc->actionAllWebsites('remove');
92
-
93
- // clear directories
94
- $websites = Mage::getModel('core/website')->getCollection()->load()->getItems();
95
- $config = Mage::getSingleton('mturbo/config');
96
- foreach ($websites as $website) {
97
- $configWeb = $config->getWebsiteConfig($website->getCode());
98
- if ($configWeb) {
99
- $dir = $configWeb->getBaseDir().DS.$config->getTurbopath();
100
- Mage::helper('mturbo/functions')->unlink_recursive($dir, '/(.)*/', true);
101
- }
102
- }
103
-
104
- // clear db records
105
- $prefix = Mage::app()->getConfig()->getTablePrefix();
106
- $connection = Mage::getSingleton('core/resource')->getConnection('core_write');
107
- $connection->query("
108
-
109
- DROP TABLE IF EXISTS `".$prefix."mturbo`;
110
- DELETE FROM `".$prefix."core_config_data` WHERE `path` LIKE 'mturbo/%' OR `path` LIKE 'crontab/jobs/mturbo%';
111
- DELETE FROM `".$prefix."core_resource` WHERE `code` LIKE 'mturbo_setup';