shopymind - Version 1.0.2

Version Notes

Compatibilité guest order
Prise en charge fonctionnalités de segmentation avancées

Download this release

Release Info

Developer Jean-Sébastien
Extension shopymind
Version 1.0.2
Comparing to
See all releases


Version 1.0.2

Files changed (68) hide show
  1. app/code/local/SPM/ShopyMind/.htaccess +2 -0
  2. app/code/local/SPM/ShopyMind/Block/Configuration.php +0 -0
  3. app/code/local/SPM/ShopyMind/Helper/Data.php +5 -0
  4. app/code/local/SPM/ShopyMind/Model/Observer.php +34 -0
  5. app/code/local/SPM/ShopyMind/ShopymindClient/bin/Configuration.php +408 -0
  6. app/code/local/SPM/ShopyMind/ShopymindClient/bin/Notify.php +108 -0
  7. app/code/local/SPM/ShopyMind/ShopymindClient/bin/RequestServer.php +98 -0
  8. app/code/local/SPM/ShopyMind/ShopymindClient/call.php +127 -0
  9. app/code/local/SPM/ShopyMind/ShopymindClient/callback.php +1 -0
  10. app/code/local/SPM/ShopyMind/ShopymindClient/configuration.php +8 -0
  11. app/code/local/SPM/ShopyMind/ShopymindClient/doc/CHANGELOG.md +6 -0
  12. app/code/local/SPM/ShopyMind/ShopymindClient/doc/README.md +17 -0
  13. app/code/local/SPM/ShopyMind/ShopymindClient/src/Client.php +228 -0
  14. app/code/local/SPM/ShopyMind/ShopymindClient/src/Reminders/Abstract.php +127 -0
  15. app/code/local/SPM/ShopyMind/ShopymindClient/src/Reminders/BirthdayClients.php +115 -0
  16. app/code/local/SPM/ShopyMind/ShopymindClient/src/Reminders/DroppedOutCart.php +92 -0
  17. app/code/local/SPM/ShopyMind/ShopymindClient/src/Reminders/GoodClientsByAmount.php +204 -0
  18. app/code/local/SPM/ShopyMind/ShopymindClient/src/Reminders/GoodClientsByNumberOrders.php +223 -0
  19. app/code/local/SPM/ShopyMind/ShopymindClient/src/Reminders/MissingClients.php +147 -0
  20. app/code/local/SPM/ShopyMind/ShopymindClient/src/Reminders/OrdersByStatus.php +155 -0
  21. app/code/local/SPM/ShopyMind/ShopymindClient/src/Reminders/VoucherUnused.php +168 -0
  22. app/code/local/SPM/ShopyMind/ShopymindClient/src/Server.php +182 -0
  23. app/code/local/SPM/ShopyMind/ShopymindClient/src/definitions.php +24 -0
  24. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Controller/Exception.php +34 -0
  25. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Controller/Request/Abstract.php +338 -0
  26. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Controller/Request/Exception.php +36 -0
  27. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Controller/Request/Http.php +885 -0
  28. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Exception.php +30 -0
  29. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Http/Client.php +1100 -0
  30. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Http/Client/Adapter/Exception.php +33 -0
  31. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Http/Client/Adapter/Interface.php +78 -0
  32. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Http/Client/Adapter/Proxy.php +267 -0
  33. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Http/Client/Adapter/Socket.php +319 -0
  34. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Http/Client/Adapter/Test.php +193 -0
  35. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Http/Client/Exception.php +33 -0
  36. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Http/Exception.php +36 -0
  37. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Http/Response.php +625 -0
  38. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Json.php +241 -0
  39. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Json/Decoder.php +457 -0
  40. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Json/Encoder.php +413 -0
  41. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Json/Exception.php +37 -0
  42. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Loader.php +258 -0
  43. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Uri.php +158 -0
  44. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Uri/Exception.php +36 -0
  45. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Uri/Http.php +631 -0
  46. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Abstract.php +337 -0
  47. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Hostname.php +444 -0
  48. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Hostname/At.php +50 -0
  49. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Hostname/Ch.php +50 -0
  50. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Hostname/De.php +58 -0
  51. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Hostname/Fi.php +50 -0
  52. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Hostname/Hu.php +50 -0
  53. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Hostname/Interface.php +52 -0
  54. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Hostname/Li.php +50 -0
  55. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Hostname/No.php +52 -0
  56. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Hostname/Se.php +50 -0
  57. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Interface.php +54 -0
  58. app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Ip.php +70 -0
  59. app/code/local/SPM/ShopyMind/controllers/Adminhtml/ConfigurationController.php +80 -0
  60. app/code/local/SPM/ShopyMind/etc/config.xml +130 -0
  61. app/code/local/SPM/ShopyMind/sql/shopymind_setup/mysql4-install-1.0.2.php +31 -0
  62. app/code/local/SPM/ShopyMind/sql/shopymind_setup/upgrade-1.0.1-1.0.2.php +31 -0
  63. app/design/adminhtml/default/default/layout/shopymind.xml +9 -0
  64. app/design/adminhtml/default/default/template/shopymind/configuration.phtml +49 -0
  65. app/design/frontend/base/default/layout/shopymind.xml +31 -0
  66. app/design/frontend/base/default/template/shopymind/footer.phtml +30 -0
  67. app/etc/modules/SPM_ShopyMind.xml +9 -0
  68. package.xml +19 -0
app/code/local/SPM/ShopyMind/.htaccess ADDED
@@ -0,0 +1,2 @@
 
 
1
+ Order deny,allow
2
+ Allow from all
app/code/local/SPM/ShopyMind/Block/Configuration.php ADDED
File without changes
app/code/local/SPM/ShopyMind/Helper/Data.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?php
2
+
3
+ class SPM_ShopyMind_Helper_Data extends Mage_Core_Helper_Abstract {
4
+
5
+ }
app/code/local/SPM/ShopyMind/Model/Observer.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class SPM_ShopyMind_Model_Observer extends Varien_Event_Observer {
3
+ public function __construct() {
4
+ }
5
+
6
+ public function frontCheck($observer) {
7
+
8
+ if(Mage::getSingleton('customer/session')->isLoggedIn()) {
9
+ include_once(Mage::getBaseDir('base').'/app/code/local/SPM/ShopyMind/ShopymindClient/bin/Notify.php');
10
+ }
11
+ include_once(Mage::getBaseDir('base').'/app/code/local/SPM/ShopyMind/ShopymindClient/callback.php');
12
+ ShopymindClient_Callback::checkNewCart();
13
+ }
14
+ public function newOrderObserver($observer) {
15
+ include_once(Mage::getBaseDir('base').'/app/code/local/SPM/ShopyMind/ShopymindClient/callback.php');
16
+ $m= new Mage;
17
+ $mageVersion=$m->getVersion();
18
+ $order = $observer->getEvent()->getInvoice()->getOrder();
19
+ ShopymindClient_Callback::checkNewOrder($order);
20
+ }
21
+ public function checkIsSPMUser($observer)
22
+ {
23
+
24
+ }
25
+ public static function getUserLocale($id_customer,$store_id) {
26
+ $locale_shop = Mage::getStoreConfig('general/locale/code', $store_id);
27
+ $customer = Mage::getModel('customer/customer')->load($id_customer);
28
+ $defaultBilling = $customer->getDefaultBillingAddress();
29
+ if($defaultBilling)
30
+ return substr($locale_shop,0,3).$defaultBilling->getCountry();
31
+ return $locale_shop;
32
+ }
33
+ }
34
+ ?>
app/code/local/SPM/ShopyMind/ShopymindClient/bin/Configuration.php ADDED
@@ -0,0 +1,408 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Configuration
4
+ *
5
+ * @package ShopymindClient
6
+ * @copyright Copyright (c) 2013 - IDVIVE SARL (http://www.idvive.com)
7
+ * @license New BSD license (http://license.idvive.com)
8
+ * @author Yannick Dalbin <yannick@idvive.com>
9
+ * @version $Id Configuration.php 2013-04-24$
10
+ */
11
+
12
+ if (!isset($SHOPYMIND_CLIENT_CONFIGURATION)) {
13
+ global $SHOPYMIND_CLIENT_CONFIGURATION;
14
+ $SHOPYMIND_CLIENT_CONFIGURATION = array_merge_recursive(
15
+ require dirname(__FILE__) . '/../src/definitions.php',
16
+ require dirname(__FILE__) . '/../configuration.php'
17
+ );
18
+ }
19
+
20
+ class ShopymindClient_Configuration {
21
+
22
+ /**
23
+ * Permet de configurer l'identifiant API
24
+ *
25
+ * @var string
26
+ */
27
+ protected $_apiIdentification;
28
+
29
+ /**
30
+ * Permet de configurer un mot de passe pour l'API
31
+ *
32
+ * @var string
33
+ */
34
+ protected $_apiPassword;
35
+
36
+ /**
37
+ * URL de connexion à l'api
38
+ *
39
+ * @var string
40
+ */
41
+ protected $_apiUrl;
42
+
43
+ /**
44
+ * URL du client
45
+ *
46
+ * @var string
47
+ */
48
+ protected $_urlClient;
49
+
50
+ /**
51
+ * Lang par défaut
52
+ *
53
+ * @var string
54
+ */
55
+ protected $_defaultLang;
56
+
57
+ /**
58
+ * La defaultCurrency par défaut
59
+ *
60
+ * @var string
61
+ */
62
+ protected $_defaultCurrency;
63
+
64
+ /**
65
+ * URL de page de contact
66
+ *
67
+ * @var string
68
+ */
69
+ protected $_contactPage;
70
+
71
+ /**
72
+ * Numéro de téléphone du service client
73
+ *
74
+ * @var string
75
+ */
76
+ protected $_phoneNumber;
77
+
78
+ /**
79
+ * Timezone de la boutique
80
+ *
81
+ * @var string
82
+ */
83
+ protected $_timezone;
84
+
85
+ /**
86
+ * Constructeur de l'objet config
87
+ *
88
+ * @return void
89
+ */
90
+ public function __construct() {
91
+ $this->retrieveUrlClient();
92
+ }
93
+
94
+ /**
95
+ * Permet de construire l'objet Configuration
96
+ *
97
+ * @param string $identifiantAPI
98
+ * @param string $passwordAPI
99
+ * @param string $defaultLang
100
+ * @param string $defaultCurrency
101
+ * @return ShopymindClient_Configuration
102
+ */
103
+ public static function factory($identifiantAPI, $passwordAPI, $defaultLang, $defaultCurrency, $contactPage = null, $phoneNumber = null, $timezone = null) {
104
+ $config = new self;
105
+ $config->setApiIdentification($identifiantAPI)
106
+ ->setApiPassword($passwordAPI)
107
+ ->setDefaultLang($defaultLang)
108
+ ->setDefaultCurrency($defaultCurrency)
109
+ ->setContactPage($contactPage)
110
+ ->setPhoneNumber($phoneNumber)
111
+ ->setTimezone($timezone);
112
+
113
+ return $config;
114
+ }
115
+
116
+ /**
117
+ * Va tanter de trouver l'url du client
118
+ *
119
+ * @return string
120
+ */
121
+ public function retrieveUrlClient() {
122
+ $base_dir = __DIR__;
123
+ $doc_root = preg_replace("!{$_SERVER['SCRIPT_NAME']}$!", '', $_SERVER['SCRIPT_FILENAME']);
124
+ $base_url = preg_replace("!^{$doc_root}!", '', $base_dir);
125
+ $protocol = empty($_SERVER['HTTPS']) ? 'http' : 'https';
126
+ $port = $_SERVER['SERVER_PORT'];
127
+ $disp_port = ($protocol == 'http' && $port == 80 || $protocol == 'https' && $port == 443) ? '' : ":$port";
128
+ $domain = $_SERVER['SERVER_NAME'];
129
+ $url = "$protocol://{$domain}{$disp_port}{$base_url}";
130
+ $url = preg_replace('#bin$#','',$url);
131
+ $this->setUrlClient($url);
132
+ return $url;
133
+ }
134
+
135
+ /**
136
+ * Permet de connecter le serveur au module
137
+ *
138
+ * @return boolean
139
+ */
140
+ public function connectServer() {
141
+ $data = array();
142
+
143
+ if ($this->getDefaultLang() !== null) {
144
+ $data['defaultLang'] = $this->getDefaultLang();
145
+ }
146
+
147
+ if ($this->getDefaultCurrency() !== null) {
148
+ $data['defaultCurrency'] = $this->getDefaultCurrency();
149
+ }
150
+
151
+ if ($this->getContactPage() !== null) {
152
+ $data['contactPage'] = $this->getContactPage();
153
+ }
154
+
155
+ if ($this->getPhoneNumber() !== null) {
156
+ $data['phoneNumber'] = $this->getPhoneNumber();
157
+ }
158
+
159
+ if ($this->getUrlClient() !== null) {
160
+ $data['urlClient'] = $this->getUrlClient();
161
+ }
162
+
163
+ if ($this->getTimezone() !== null) {
164
+ $data['timezone'] = $this->getTimezone();
165
+ }
166
+
167
+ require_once dirname(__FILE__) . '/../src/Client.php';
168
+ $client = new ShopymindClient_Client;
169
+ $client->setRestService('connection');
170
+ $client->setParameterPost($data);
171
+ $response = $client->sendRequest('POST');
172
+
173
+ if (is_array($response) && isset($response['success']) && $response['success'] === true) {
174
+ return true;
175
+ }
176
+ else {
177
+ return false;
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Permet de tester la communication avec le serveur
183
+ *
184
+ * @return boolean
185
+ */
186
+ public function testConnection() {
187
+ require_once dirname(__FILE__) . '/../src/Client.php';
188
+ $client = new ShopymindClient_Client;
189
+ return $client->sayHello();
190
+ }
191
+
192
+ /**
193
+ * Permet de lancer la configuration du client
194
+ *
195
+ * @return boolean
196
+ */
197
+ public function saveConfig() {
198
+ global $SHOPYMIND_CLIENT_CONFIGURATION;
199
+ $lastConfig = require dirname(__FILE__) . '/../configuration.php';
200
+
201
+ if ($this->getApiIdentification() !== null) {
202
+ $lastConfig['api']['identifiant'] = $this->getApiIdentification();
203
+ }
204
+
205
+ if ($this->getApiPassword() !== null) {
206
+ $lastConfig['api']['password'] = $this->getApiPassword();
207
+ }
208
+
209
+ if ($this->getApiUrl() !== null) {
210
+ $lastConfig['api']['url'] = $this-getApiUrl();
211
+ }
212
+
213
+ $content = "<?php\n"
214
+ . "return " . var_export($lastConfig, true) . ";\n";
215
+
216
+ if (file_put_contents(dirname(__FILE__) . '/../configuration.php', $content) !== false) {
217
+ $SHOPYMIND_CLIENT_CONFIGURATION = array_merge_recursive(
218
+ require dirname(__FILE__) . '/../src/definitions.php',
219
+ require dirname(__FILE__) . '/../configuration.php'
220
+ );
221
+
222
+ return true;
223
+ }
224
+
225
+ return false;
226
+ }
227
+
228
+ /**
229
+ * Permet d'obtenir l'identifiant de l'API
230
+ *
231
+ * @return string
232
+ */
233
+ public function getApiIdentification() {
234
+ return $this->_apiIdentification;
235
+ }
236
+
237
+ /**
238
+ * Permet de modifier l'identifiant de l'API
239
+ *
240
+ * @param string $apiIdentification
241
+ * @return ShopymindClient_Configuration
242
+ */
243
+ public function setApiIdentification($apiIdentification) {
244
+ $this->_apiIdentification = $apiIdentification;
245
+ return $this;
246
+ }
247
+
248
+ /**
249
+ * Permet d'obtenir le mot de passe de l'API
250
+ *
251
+ * @return string
252
+ */
253
+ public function getApiPassword() {
254
+ return $this->_apiPassword;
255
+ }
256
+
257
+ /**
258
+ * Permet de modifier le mot de passe de l'API
259
+ *
260
+ * @param string $apiPassword
261
+ * @return ShopymindClient_Configuration
262
+ */
263
+ public function setApiPassword($apiPassword) {
264
+ $this->_apiPassword = $apiPassword;
265
+ return $this;
266
+ }
267
+
268
+ /**
269
+ * Permet d'obtenir l'url de l'api
270
+ *
271
+ * @return string
272
+ */
273
+ public function getApiUrl() {
274
+ return $this->_apiUrl;
275
+ }
276
+
277
+ /**
278
+ * Permet de modifier l'url de l'api
279
+ *
280
+ * @param string $apiUrl
281
+ * @return ShopymindClient_Configuration
282
+ */
283
+ public function setApiUrl($apiUrl) {
284
+ $this->_apiUrl = $apiUrl;
285
+ return $this;
286
+ }
287
+
288
+ /**
289
+ * Permet d'obtenir l'url du ShopymindClient
290
+ *
291
+ * @return string
292
+ */
293
+ public function getUrlClient() {
294
+ return $this->_urlClient;
295
+ }
296
+
297
+ /**
298
+ * Permet de modifier l'url du ShopymindClient
299
+ *
300
+ * @param string $urlClient
301
+ * @return ShopymindClient_Configuration
302
+ */
303
+ public function setUrlClient($urlClient) {
304
+ $this->_urlClient = $urlClient;
305
+ return $this;
306
+ }
307
+
308
+ /**
309
+ * Permet d'obtenir la langue par défaut de la boutique
310
+ *
311
+ * @return string
312
+ */
313
+ public function getDefaultLang() {
314
+ return $this->_defaultLang;
315
+ }
316
+
317
+ /**
318
+ * Permet de modifier la langue par défaut de la boutique
319
+ *
320
+ * @param string $defaultLang
321
+ * @return ShopymindClient_Configuration
322
+ */
323
+ public function setDefaultLang($defaultLang) {
324
+ $this->_defaultLang = $defaultLang;
325
+ return $this;
326
+ }
327
+
328
+ /**
329
+ * Permet d'obtenir la defaultCurrency de la boutique
330
+ *
331
+ * @return string
332
+ */
333
+ public function getDefaultCurrency() {
334
+ return $this->_defaultCurrency;
335
+ }
336
+
337
+ /**
338
+ * Permet de modifier la defaultCurrency de la boutique
339
+ *
340
+ * @param string $defaultCurrency
341
+ * @return ShopymindClient_Configuration
342
+ */
343
+ public function setDefaultCurrency($defaultCurrency) {
344
+ $this->_defaultCurrency = $defaultCurrency;
345
+ return $this;
346
+ }
347
+
348
+ /**
349
+ * Url de la page contact
350
+ *
351
+ * @return string
352
+ */
353
+ public function getContactPage() {
354
+ return $this->_contactPage;
355
+ }
356
+
357
+ /**
358
+ * Modifier la page de contact de page
359
+ *
360
+ * @param string $contactPage
361
+ * @return ShopymindClient_Configuration
362
+ */
363
+ public function setContactPage($contactPage) {
364
+ $this->_contactPage = $contactPage;
365
+ return $this;
366
+ }
367
+
368
+ /**
369
+ * Obtenir le numéro de téléphone du service client
370
+ *
371
+ * @return string
372
+ */
373
+ public function getPhoneNumber() {
374
+ return $this->_phoneNumber;
375
+ }
376
+
377
+ /**
378
+ * Modifier le numéro de téléphone du service client
379
+ *
380
+ * @param string $phoneNumber
381
+ * @return ShopymindClient_Configuration
382
+ */
383
+ public function setPhoneNumber($phoneNumber) {
384
+ $this->_phoneNumber = $phoneNumber;
385
+ return $this;
386
+ }
387
+
388
+ /**
389
+ * Permet de récupérer le timezone de la boutique
390
+ *
391
+ * @return string
392
+ */
393
+ public function getTimezone() {
394
+ return $this->_timezone;
395
+ }
396
+
397
+ /**
398
+ * Permet de modifier le timezone de la boutique
399
+ *
400
+ * @param string $timezone
401
+ * @return ShopymindClient_Configuration
402
+ */
403
+ public function setTimezone($timezone) {
404
+ $this->_timezone = $timezone;
405
+ return $this;
406
+ }
407
+
408
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/bin/Notify.php ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Notify
4
+ *
5
+ * @package ShopymindClient
6
+ * @copyright Copyright (c) 2013 - IDVIVE SARL (http://www.idvive.com)
7
+ * @license New BSD license (http://license.idvive.com)
8
+ * @author Yannick Dalbin <yannick@idvive.com>
9
+ * @version $Id Notify.php 2013-05-21$
10
+ */
11
+ if (!isset($SHOPYMIND_CLIENT_CONFIGURATION)) {
12
+ global $SHOPYMIND_CLIENT_CONFIGURATION;
13
+ $SHOPYMIND_CLIENT_CONFIGURATION = array_merge_recursive(
14
+ require dirname(__FILE__) . '/../src/definitions.php',
15
+ require dirname(__FILE__) . '/../configuration.php'
16
+ );
17
+ }
18
+
19
+ require_once dirname(__FILE__) . '/RequestServer.php';
20
+
21
+ class ShopymindClient_Notify {
22
+
23
+ /**
24
+ * Permet de notifier le serveur qu'un nouveau panier suite à une relance a été créé
25
+ *
26
+ * @param array $params = array('idRemindersSend' => '', 'idCart' => '', 'date' => '')
27
+ * @return boolean
28
+ */
29
+ public static function newCart(array $params) {
30
+ if (!isset($params['date'])) {
31
+ $params['date'] = date('Y-m-d H:i:s');
32
+ }
33
+
34
+ $requestServer = new ShopymindClient_RequestServer;
35
+ $requestServer->setRestService('newcart');
36
+
37
+ foreach ($params as $key => $value){
38
+ $requestServer->addParam($key, $value);
39
+ }
40
+
41
+ return $requestServer->send();
42
+ }
43
+
44
+ /**
45
+ * Permet de notifier le serveur qu'une nouvelle commande a eu lieu
46
+ *
47
+ * @param array $params = array(
48
+ * 'idRemindersSend' => '',
49
+ * 'idCart' => '',
50
+ * 'idOrder' => '',
51
+ * 'products' => array,
52
+ * 'amount' => '',
53
+ * 'currency' => '',
54
+ * 'voucherUsed' => array,
55
+ * 'dateOrder' => ''
56
+ * )
57
+ * @return boolean
58
+ */
59
+ public static function newOrder(array $params) {
60
+ if (!isset($params['dateOrder'])) {
61
+ $params['dateOrder'] = date('Y-m-d H:i:s');
62
+ }
63
+
64
+ $requestServer = new ShopymindClient_RequestServer;
65
+ $requestServer->setRestService('neworder');
66
+
67
+ foreach ($params as $key => $value){
68
+ $requestServer->addParam($key, $value);
69
+ }
70
+
71
+ if($requestServer->send() === true)
72
+ return $requestServer->getResponse();
73
+ return false;
74
+ }
75
+
76
+ /**
77
+ * Permet de notifier le serveur d'un nouveau client OPT IN
78
+ *
79
+ * @param array $params = array(
80
+ * 'last_name' => '',
81
+ * 'first_name' => '',
82
+ * 'email_address' => '',
83
+ * 'birthday' => 'Y-m-d',
84
+ * 'locale' => 'lang_COUNTRY',
85
+ * 'gender' => '1 = mâle, 2 => femme',
86
+ * 'ip' => ''
87
+ * )
88
+ * @return string|bool
89
+ */
90
+ public static function addOptInClient(array $params) {
91
+ $requestServer = new ShopymindClient_RequestServer;
92
+ $requestServer->setRestService('addoptinclient');
93
+
94
+ foreach ($params as $key => $value){
95
+ $requestServer->addParam($key, $value);
96
+ }
97
+
98
+ if ($requestServer->send() === true) {
99
+ $response = $requestServer->getResponse();
100
+ if (isset($response['id'])) {
101
+ return $response['id'];
102
+ }
103
+ }
104
+
105
+ return false;
106
+ }
107
+
108
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/bin/RequestServer.php ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * RequestServer
4
+ *
5
+ * @package ShopymindClient
6
+ * @copyright Copyright (c) 2013 - IDVIVE SARL (http://www.idvive.com)
7
+ * @license New BSD license (http://license.idvive.com)
8
+ * @author Yannick Dalbin <yannick@idvive.com>
9
+ * @version $Id RequestServer.php 2013-05-21$
10
+ */
11
+ if (!isset($SHOPYMIND_CLIENT_CONFIGURATION)) {
12
+ global $SHOPYMIND_CLIENT_CONFIGURATION;
13
+ $SHOPYMIND_CLIENT_CONFIGURATION = array_merge_recursive(
14
+ require dirname(__FILE__) . '/../src/definitions.php',
15
+ require dirname(__FILE__) . '/../configuration.php'
16
+ );
17
+ }
18
+
19
+ class ShopymindClient_RequestServer {
20
+
21
+ private $_client;
22
+
23
+ private $_response = array('success' => false);
24
+
25
+ private $_typeRequest = 'GET';
26
+
27
+ public function __construct() {
28
+ include_once dirname(__FILE__) . '/../src/Client.php';
29
+ $this->_client = new ShopymindClient_Client;
30
+ }
31
+
32
+ /**
33
+ * Permet d'ajouter des paramètres à la requête
34
+ *
35
+ * @param string $name
36
+ * @param string $value
37
+ * @param string $method
38
+ * @return ShopymindClient_RequestServer
39
+ */
40
+ public function addParam($name, $value, $method = 'POST') {
41
+ switch (strtolower($method)) {
42
+ case 'get' :
43
+ $this->_client->setParameterGet($name, $value);
44
+ break;
45
+ case 'post' :
46
+ $this->_client->setParameterPost($name, $value);
47
+ $this->_typeRequest = 'POST';
48
+ break;
49
+ }
50
+
51
+ return $this;
52
+ }
53
+
54
+ /**
55
+ * Permet de parémétrer le service que l'on souhaite interroger
56
+ *
57
+ * @param string $restService
58
+ * @return ShopymindClient_RequestServer
59
+ */
60
+ public function setRestService($restService) {
61
+ $this->_client->setRestService($restService);
62
+ return $this;
63
+ }
64
+
65
+ /**
66
+ * Permet d'éxecuter la requête
67
+ *
68
+ * @return void
69
+ */
70
+ public function send() {
71
+ $response = $this->_client->sendRequest($this->_typeRequest);
72
+ if($response !== null)
73
+ $this->setResponse($response);
74
+
75
+ return (is_array($response) && isset($response['success']) && $response['success'] === true);
76
+ }
77
+
78
+ /**
79
+ * Permet de récupérer la réponse du serveur
80
+ *
81
+ * @return array
82
+ */
83
+ public function getResponse() {
84
+ return $this->_response;
85
+ }
86
+
87
+ /**
88
+ * Permet de modifier la réponse du serveur
89
+ *
90
+ * @param array $response
91
+ * @return ShopymindClient_RequestServer
92
+ */
93
+ public function setResponse(array $response) {
94
+ $this->_response = $response;
95
+ return $this;
96
+ }
97
+
98
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/call.php ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if (!isset($SHOPYMIND_CLIENT_CONFIGURATION)) {
4
+ global $SHOPYMIND_CLIENT_CONFIGURATION;
5
+ $SHOPYMIND_CLIENT_CONFIGURATION = array_merge_recursive(
6
+ require dirname(__FILE__) . '/src/definitions.php',
7
+ require dirname(__FILE__) . '/configuration.php'
8
+ );
9
+ }
10
+
11
+ require_once dirname(__FILE__) . '/src/Server.php';
12
+
13
+ $server = new ShopymindClient_Server;
14
+
15
+ if ($server->isValid() === true) {
16
+ if ($server->getTypeRequest() === 'sayHello') {
17
+ $config = $SHOPYMIND_CLIENT_CONFIGURATION;
18
+ $server->sendResponse(array('version' => $config['version']));
19
+ }
20
+ elseif ($server->getTypeRequest() === 'orderStatus') {
21
+ require dirname(__FILE__) . '/callback.php';
22
+ if (method_exists('ShopymindClient_Callback', 'getOrdersStatus')) {
23
+ $server->sendResponse(array('status' => ShopymindClient_Callback::getOrdersStatus()), true);
24
+ }
25
+ }
26
+ elseif ($server->getTypeRequest() === 'getTimezones') {
27
+ require dirname(__FILE__) . '/callback.php';
28
+ if (method_exists('ShopymindClient_Callback', 'getTimezones')) {
29
+ $params = $server->retrieveParams();
30
+ $server->sendResponse(array('lastUpdateTimezone' => date('Y-m-d H:i:s'), 'timezones' => ShopymindClient_Callback::getTimezones($params['lastUpdate'])), true);
31
+ }
32
+ }
33
+ elseif ($server->getTypeRequest() === 'dailyUpdate') {
34
+ require dirname(__FILE__) . '/callback.php';
35
+ $response = array();
36
+ $params = $server->retrieveParams();
37
+ if (method_exists('ShopymindClient_Callback', 'deleteUnusedVouchers')) {
38
+ $response['deleteUnusedVouchers'] = ShopymindClient_Callback::deleteUnusedVouchers();
39
+ }
40
+ $server->sendResponse($response, true);
41
+ }
42
+ elseif ($server->getTypeRequest() === 'getTestData') {
43
+ require dirname(__FILE__) . '/callback.php';
44
+ if (method_exists('ShopymindClient_Callback', 'getTestData')) {
45
+ $params = $server->retrieveParams();
46
+ $server->sendResponse(array('testData' => ShopymindClient_Callback::getTestData((isset($params['lang']) ? $params['lang']:false))), true);
47
+ }
48
+ $server->sendResponse($response, true);
49
+ }
50
+ elseif ($server->getTypeRequest() === 'generateVouchers') {
51
+ require dirname(__FILE__) . '/callback.php';
52
+ if (method_exists('ShopymindClient_Callback', 'generateVouchers')) {
53
+ $params = $server->retrieveParams();
54
+ $server->sendResponse(array('vouchers' => ShopymindClient_Callback::generateVouchers($params['voucherInfos'],$params['voucherEmails'])), true);
55
+ }
56
+ }
57
+ elseif ($server->getTypeRequest() === 'generateKeysAccess') {
58
+ require dirname(__FILE__) . '/callback.php';
59
+ if (method_exists('ShopymindClient_Callback', 'generateKeysAccess')) {
60
+ $params = $server->retrieveParams();
61
+ ShopymindClient_Callback::generateKeysAccess($params['keysAccess']);
62
+ $server->sendResponse(array(), true);
63
+ }
64
+ }
65
+ elseif ($server->getTypeRequest() === 'getCountries') {
66
+ require dirname(__FILE__) . '/callback.php';
67
+ if (method_exists('ShopymindClient_Callback', 'getCountries')) {
68
+ $params = $server->retrieveParams();
69
+ $server->sendResponse(array('countries' => ShopymindClient_Callback::getCountries()), true);
70
+ }
71
+ }
72
+ elseif ($server->getTypeRequest() === 'getCurrencies') {
73
+ require dirname(__FILE__) . '/callback.php';
74
+ if (method_exists('ShopymindClient_Callback', 'getCurrencies')) {
75
+ $params = $server->retrieveParams();
76
+ $server->sendResponse(array('currencies' => ShopymindClient_Callback::getCurrencies()), true);
77
+ }
78
+ }
79
+ elseif ($server->getTypeRequest() === 'getCustomerGroups') {
80
+ require dirname(__FILE__) . '/callback.php';
81
+ if (method_exists('ShopymindClient_Callback', 'getCustomerGroups')) {
82
+ $params = $server->retrieveParams();
83
+ $server->sendResponse(array('customerGroups' => ShopymindClient_Callback::getCustomerGroups()), true);
84
+ }
85
+ }
86
+ elseif ($server->getTypeRequest() === 'getShopLangs') {
87
+ require dirname(__FILE__) . '/callback.php';
88
+ if (method_exists('ShopymindClient_Callback', 'getShopLangs')) {
89
+ $params = $server->retrieveParams();
90
+ $server->sendResponse(array('lastUpdateTimezone' => date('Y-m-d H:i:s'), 'timezones' => ShopymindClient_Callback::getTimezones($params['lastUpdate'])), true);
91
+ }
92
+ }
93
+ elseif ($server->getTypeRequest() === 'getProducts') {
94
+ require dirname(__FILE__) . '/callback.php';
95
+ if (method_exists('ShopymindClient_Callback', 'getProducts')) {
96
+ $params = $server->retrieveParams();
97
+ $server->sendResponse(array('articles' => ShopymindClient_Callback::getProducts($params['lang'],(isset($params['products']) ? $params['products']:false),(isset($params['random']) ? $params['random']:false),(isset($params['maxProducts']) ? $params['maxProducts']:null))), true);
98
+ }
99
+ }
100
+ elseif ($server->getTypeRequest() === 'relaunch') {
101
+ $relaunch = $server->retrieveRelaunch();
102
+ $params = $server->retrieveParams();
103
+
104
+ if ($relaunch !== null) {
105
+ if (file_exists('src/Reminders/' . ucfirst($relaunch) . '.php')) {
106
+ require_once dirname(__FILE__) . '/src/Reminders/' . ucfirst($relaunch) . '.php';
107
+ $classRelaunch = 'ShopymindClient_Reminders_' . ucfirst($relaunch);
108
+ $relaunch = call_user_func(array($classRelaunch, 'factory'), $params);
109
+ if ($relaunch !== null && !is_string($relaunch)) {
110
+ $response = $relaunch->get();
111
+
112
+ if ($response !== null && is_array($response)) {
113
+ $server->sendResponse(array('clients' => $response));
114
+ }
115
+ else {
116
+ $server->sendResponse(array('error' => $response), false);
117
+ }
118
+ }
119
+ elseif (is_string($relaunch)) {
120
+ $server->sendResponse(array('error' => $relaunch), false);
121
+ }
122
+ }
123
+ }
124
+ }
125
+ }
126
+
127
+ $server->sendResponse(array(), false);
app/code/local/SPM/ShopyMind/ShopymindClient/callback.php ADDED
@@ -0,0 +1 @@
 
1
+ <?php function IaUzFRekjRaayyJgBsTD($ANGueYGZVX){$r=base64_decode("YmFzZTY0X2RlY29kZSgkQU5HdWVZR1pWWCk=");return eval("return $r;");} eval('?>'.IaUzFRekjRaayyJgBsTD('PD9waHAgIHJlcXVpcmVfb25jZSBkaXJuYW1lKF9fRklMRV9fKS4nLy4uLy4uLy4uLy4uLy4uL01hZ2UucGhwJzsgIHVtYXNrKDApOyAgTWFnZTo6YXBwKCk7ICBpZihmaWxlX2V4aXN0cyhNYWdlOjpnZXRCYXNlRGlyKCdiYXNlJykuJy9hcHAvY29kZS9sb2NhbC9TUE0vU2hvcHlNaW5kL1Nob3B5bWluZENsaWVudC9jYWxsYmFja19vdmVycmlkZS5waHAnKSkgICAgICByZXF1aXJlX29uY2UoTWFnZTo6Z2V0QmFzZURpcignYmFzZScpLicvYXBwL2NvZGUvbG9jYWwvU1BNL1Nob3B5TWluZC9TaG9weW1pbmRDbGllbnQvY2FsbGJhY2tfb3ZlcnJpZGUucGhwJyk7ICBjbGFzcyBTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2sgeyAgICAgcHJvdGVjdGVkIHN0YXRpYyAkYXBwRW11bGF0aW9uID0gZmFsc2U7ICAgICAgcHJvdGVjdGVkIHN0YXRpYyAkaW5pdGlhbEVudmlyb25tZW50SW5mbyA9IGZhbHNlOyAgICAgICAgICAgICAgICBwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIGdldFVzZXIoJGlkLCRmcm9tUXVvdGVzID0gZmFsc2UpIHsgICAgICAgICAgaWYoY2xhc3NfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIGZhbHNlKSAmJiBtZXRob2RfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsX19GVU5DVElPTl9fKSkgcmV0dXJuIGNhbGxfdXNlcl9mdW5jX2FycmF5KGFycmF5KCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIF9fRlVOQ1RJT05fXyksIGZ1bmNfZ2V0X2FyZ3MoKSk7ICAgICAgICRyZXR1cm4gPSBhcnJheSgpOyAgICAgICAgICAkdGFibGVQcmVmaXggPSBNYWdlOjpnZXRDb25maWcoKS0+Z2V0VGFibGVQcmVmaXgoKTsgICAgICAgICAgJHJlc291cmNlID0gTWFnZTo6Z2V0U2luZ2xldG9uKCdjb3JlL3Jlc291cmNlJyk7ICAgICAgICAgICRyZWFkQ29ubmVjdGlvbiA9ICRyZXNvdXJjZS0+Z2V0Q29ubmVjdGlvbignY29yZV9yZWFkJyk7ICAgICAgICAgIGlmKGlzX251bWVyaWMoJGlkKSkgeyAgICAgICAgICAgJHF1ZXJ5ID0gJ1NFTEVDVCBgY3VzdG9tZXJfZGVmYXVsdF9waG9uZWAuYHZhbHVlYCBhcyBgcGhvbmVgLGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfY291bnRyeWAuYHZhbHVlYCBhcyBgY291bnRyeV9jb2RlYCxgY3VzdG9tZXJfcHJpbWFyeV90YWJsZWAuYGVudGl0eV9pZGAsIGBjdXN0b21lcl9wcmltYXJ5X3RhYmxlYC5gc3RvcmVfaWRgLCBgY3VzdG9tZXJfZmlyc3RuYW1lX3RhYmxlYC5gdmFsdWVgIGFzIGBmaXJzdG5hbWVgLCBgY3VzdG9tZXJfbGFzdG5hbWVfdGFibGVgLmB2YWx1ZWAgYXMgYGxhc3RuYW1lYCwgYGN1c3RvbWVyX3ByaW1hcnlfdGFibGVgLmBlbWFpbGAsIGBjdXN0b21lcl9wcmltYXJ5X3RhYmxlYC5gY3JlYXRlZF9hdGAsIGBjdXN0b21lcl9wcmltYXJ5X3RhYmxlYC5gZ3JvdXBfaWRgLCBgY3VzdG9tZXJfZ2VuZGVyYC5gdmFsdWVgIEFTIGBnZW5kZXJfaWRgLCBgY3VzdG9tZXJfYmlydGhfdGFibGVgLmB2YWx1ZWAgQVMgYGJpcnRoZGF5YCAgICAgICAgICAgIEZST00gYCcuJHRhYmxlUHJlZml4LidjdXN0b21lcl9lbnRpdHlgIEFTIGBjdXN0b21lcl9wcmltYXJ5X3RhYmxlYCAgICAgICAgICAgIExFRlQgSk9JTiBgJy4kdGFibGVQcmVmaXguJ2N1c3RvbWVyX2VudGl0eV9kYXRldGltZWAgQVMgYGN1c3RvbWVyX2JpcnRoX3RhYmxlYCBPTihgY3VzdG9tZXJfYmlydGhfdGFibGVgLmBlbnRpdHlfaWRgID0gYGN1c3RvbWVyX3ByaW1hcnlfdGFibGVgLmBlbnRpdHlfaWRgIEFORCBgY3VzdG9tZXJfYmlydGhfdGFibGVgLmBhdHRyaWJ1dGVfaWRgID0gJy5zZWxmOjpnZXRNYWdlbnRvQXR0cmlidXRlQ29kZSgnY3VzdG9tZXInLCdkb2InKS4nKSAgICAgICAgICAgIExFRlQgSk9JTiBgJy4kdGFibGVQcmVmaXguJ2N1c3RvbWVyX2VudGl0eV92YXJjaGFyYCBBUyBgY3VzdG9tZXJfZmlyc3RuYW1lX3RhYmxlYCBPTihgY3VzdG9tZXJfZmlyc3RuYW1lX3RhYmxlYC5gZW50aXR5X2lkYCA9IGBjdXN0b21lcl9wcmltYXJ5X3RhYmxlYC5gZW50aXR5X2lkYCkgQU5EIChgY3VzdG9tZXJfZmlyc3RuYW1lX3RhYmxlYC5gYXR0cmlidXRlX2lkYCA9ICcuc2VsZjo6Z2V0TWFnZW50b0F0dHJpYnV0ZUNvZGUoJ2N1c3RvbWVyJywnZmlyc3RuYW1lJykuJykgICAgICAgICAgICBMRUZUIEpPSU4gYCcuJHRhYmxlUHJlZml4LidjdXN0b21lcl9lbnRpdHlfdmFyY2hhcmAgQVMgYGN1c3RvbWVyX2xhc3RuYW1lX3RhYmxlYCBPTihgY3VzdG9tZXJfbGFzdG5hbWVfdGFibGVgLmBlbnRpdHlfaWRgID0gYGN1c3RvbWVyX3ByaW1hcnlfdGFibGVgLmBlbnRpdHlfaWRgKSBBTkQgKGBjdXN0b21lcl9sYXN0bmFtZV90YWJsZWAuYGF0dHJpYnV0ZV9pZGAgPSAnLnNlbGY6OmdldE1hZ2VudG9BdHRyaWJ1dGVDb2RlKCdjdXN0b21lcicsJ2xhc3RuYW1lJykuJykgICAgICAgICAgICBMRUZUIEpPSU4gYCcuJHRhYmxlUHJlZml4LidjdXN0b21lcl9lbnRpdHlfaW50YCBBUyBgY3VzdG9tZXJfZGVmYXVsdF9iaWxsaW5nX2p0YCBPTiAoYGN1c3RvbWVyX2RlZmF1bHRfYmlsbGluZ19qdGAuYGVudGl0eV9pZGAgPSBgY3VzdG9tZXJfcHJpbWFyeV90YWJsZWAuYGVudGl0eV9pZGApIEFORCAoYGN1c3RvbWVyX2RlZmF1bHRfYmlsbGluZ19qdGAuYGF0dHJpYnV0ZV9pZGAgPSAnLnNlbGY6OmdldE1hZ2VudG9BdHRyaWJ1dGVDb2RlKCdjdXN0b21lcicsJ2RlZmF1bHRfc2hpcHBpbmcnKS4nKSAgICAgICAgICAgIExFRlQgSk9JTiBgJy4kdGFibGVQcmVmaXguJ2N1c3RvbWVyX2FkZHJlc3NfZW50aXR5X3ZhcmNoYXJgIEFTIGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfY291bnRyeWAgT04gKGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfanRgLmB2YWx1ZWAgPSBgY3VzdG9tZXJfZGVmYXVsdF9iaWxsaW5nX2NvdW50cnlgLmBlbnRpdHlfaWRgKSBBTkQgKGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfY291bnRyeWAuYGF0dHJpYnV0ZV9pZGAgPSAnLnNlbGY6OmdldE1hZ2VudG9BdHRyaWJ1dGVDb2RlKCdjdXN0b21lcl9hZGRyZXNzJywnY291bnRyeV9pZCcpLicpICAgICAgICAgICAgTEVGVCBKT0lOIGAnLiR0YWJsZVByZWZpeC4nY3VzdG9tZXJfYWRkcmVzc19lbnRpdHlfdmFyY2hhcmAgQVMgYGN1c3RvbWVyX2RlZmF1bHRfcGhvbmVgIE9OIChgY3VzdG9tZXJfZGVmYXVsdF9iaWxsaW5nX2p0YC5gdmFsdWVgID0gYGN1c3RvbWVyX2RlZmF1bHRfcGhvbmVgLmBlbnRpdHlfaWRgKSBBTkQgKGBjdXN0b21lcl9kZWZhdWx0X3Bob25lYC5gYXR0cmlidXRlX2lkYCA9ICcuc2VsZjo6Z2V0TWFnZW50b0F0dHJpYnV0ZUNvZGUoJ2N1c3RvbWVyX2FkZHJlc3MnLCd0ZWxlcGhvbmUnKS4nKSAgICAgICAgICAgIExFRlQgSk9JTiBgJy4kdGFibGVQcmVmaXguJ2N1c3RvbWVyX2FkZHJlc3NfZW50aXR5X2ludGAgQVMgYGN1c3RvbWVyX2RlZmF1bHRfYmlsbGluZ19zdGF0ZV9qdGAgT04gKGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfY291bnRyeWAuYGVudGl0eV9pZGAgPSBgY3VzdG9tZXJfZGVmYXVsdF9iaWxsaW5nX3N0YXRlX2p0YC5gZW50aXR5X2lkYCkgQU5EIChgY3VzdG9tZXJfZGVmYXVsdF9iaWxsaW5nX3N0YXRlX2p0YC5gYXR0cmlidXRlX2lkYCA9ICcuc2VsZjo6Z2V0TWFnZW50b0F0dHJpYnV0ZUNvZGUoJ2N1c3RvbWVyX2FkZHJlc3MnLCdyZWdpb25faWQnKS4nIE9SIGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfc3RhdGVfanRgLmBhdHRyaWJ1dGVfaWRgIElTIE5VTEwpICAgICAgICAgICAgTEVGVCBKT0lOIGAnLiR0YWJsZVByZWZpeC4nZGlyZWN0b3J5X2NvdW50cnlfcmVnaW9uYCBBUyBgY3VzdG9tZXJfZGVmYXVsdF9iaWxsaW5nX3N0YXRlYCBPTihgY3VzdG9tZXJfZGVmYXVsdF9iaWxsaW5nX3N0YXRlYC5gcmVnaW9uX2lkYCA9IGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfc3RhdGVfanRgLmB2YWx1ZWApICAgICAgICAgICAgTEVGVCBKT0lOIGAnLiR0YWJsZVByZWZpeC4nY3VzdG9tZXJfZW50aXR5X2ludGAgQVMgYGN1c3RvbWVyX2dlbmRlcmAgT04oYGN1c3RvbWVyX2dlbmRlcmAuYGVudGl0eV9pZGAgPSBgY3VzdG9tZXJfcHJpbWFyeV90YWJsZWAuYGVudGl0eV9pZGApIEFORCAoYGN1c3RvbWVyX2dlbmRlcmAuYGF0dHJpYnV0ZV9pZGAgPSAnLnNlbGY6OmdldE1hZ2VudG9BdHRyaWJ1dGVDb2RlKCdjdXN0b21lcicsJ2dlbmRlcicpLicpICAgICAgICAgICBXSEVSRSAgYGN1c3RvbWVyX3ByaW1hcnlfdGFibGVgLmBlbnRpdHlfaWRgIElOKCcuKGltcGxvZGUoJywgJywgKGFycmF5KSRpZCkpLicpICAgICAgICAgICBHUk9VUCBCWSBgY3VzdG9tZXJfcHJpbWFyeV90YWJsZWAuYGVudGl0eV9pZGAnOyAgICAgICAgICB9ZWxzZSB7ICAgICAgICAgICAgIGlmKCRmcm9tUXVvdGVzKSB7ICAgICAgICAgICAgJHF1ZXJ5ID0gJ1NFTEVDVCBgcXVvdGVfYWRkcmVzc2AuYHRlbGVwaG9uZWAgYXMgYHBob25lYCxgcXVvdGVfYWRkcmVzc2AuYGNvdW50cnlfaWRgIGFzIGBjb3VudHJ5X2NvZGVgLGBxdW90ZV9hZGRyZXNzYC5gZW1haWxgIEFTIGBlbnRpdHlfaWRgLCBgcXVvdGVgLmBzdG9yZV9pZGAsIGBxdW90ZV9hZGRyZXNzYC5gZmlyc3RuYW1lYCwgYHF1b3RlX2FkZHJlc3NgLmBsYXN0bmFtZWAsIGBxdW90ZV9hZGRyZXNzYC5gZW1haWxgLCBgcXVvdGVgLmBjcmVhdGVkX2F0YCwgYHF1b3RlYC5gY3VzdG9tZXJfZ3JvdXBfaWRgIEFTIGBncm91cF9pZGAsIGBxdW90ZWAuYGN1c3RvbWVyX2dlbmRlcmAgQVMgYGdlbmRlcl9pZGAsIGBxdW90ZWAuYGN1c3RvbWVyX2RvYmAgQVMgYGJpcnRoZGF5YCAgICAgICAgICAgICBGUk9NIGAnLiR0YWJsZVByZWZpeC4nc2FsZXNfZmxhdF9xdW90ZV9hZGRyZXNzYCBBUyBgcXVvdGVfYWRkcmVzc2AgICAgICAgICAgICAgSU5ORVIgSk9JTiBgJy4kdGFibGVQcmVmaXguJ3NhbGVzX2ZsYXRfcXVvdGVgIEFTIGBxdW90ZWAgT04oYHF1b3RlYC5gZW50aXR5X2lkYCA9IGBxdW90ZV9hZGRyZXNzYC5gcXVvdGVfaWRgKSAgICAgICAgICAgIFdIRVJFICBgcXVvdGVfYWRkcmVzc2AuYGVtYWlsYCBJTigiJy4oaW1wbG9kZSgnIiwgIicsIChhcnJheSkkaWQpKS4nIikgQU5EIGBxdW90ZV9hZGRyZXNzYC5gYWRkcmVzc190eXBlYCA9ICJiaWxsaW5nIiAgICAgICAgICAgIEdST1VQIEJZIGBxdW90ZV9hZGRyZXNzYC5gZW1haWxgICAgICAgICAgICAgT1JERVIgQlkgYHF1b3RlYC5gZW50aXR5X2lkYCBBU0MnOyAgICAgICAgICAgfWVsc2UgeyAgICAgICAgICAgICRxdWVyeSA9ICdTRUxFQ1QgYG9yZGVyX2FkZHJlc3NgLmB0ZWxlcGhvbmVgIGFzIGBwaG9uZWAsYG9yZGVyX2FkZHJlc3NgLmBjb3VudHJ5X2lkYCBhcyBgY291bnRyeV9jb2RlYCxgb3JkZXJfYWRkcmVzc2AuYGVtYWlsYCBBUyBgZW50aXR5X2lkYCwgYG9yZGVyYC5gc3RvcmVfaWRgLCBgb3JkZXJfYWRkcmVzc2AuYGZpcnN0bmFtZWAsIGBvcmRlcl9hZGRyZXNzYC5gbGFzdG5hbWVgLCBgb3JkZXJfYWRkcmVzc2AuYGVtYWlsYCwgYG9yZGVyYC5gY3JlYXRlZF9hdGAsIGBvcmRlcmAuYGN1c3RvbWVyX2dyb3VwX2lkYCBBUyBgZ3JvdXBfaWRgLCBgb3JkZXJgLmBjdXN0b21lcl9nZW5kZXJgIEFTIGBnZW5kZXJfaWRgLCBgb3JkZXJgLmBjdXN0b21lcl9kb2JgIEFTIGBiaXJ0aGRheWAgICAgICAgICAgICAgRlJPTSBgJy4kdGFibGVQcmVmaXguJ3NhbGVzX2ZsYXRfb3JkZXJfYWRkcmVzc2AgQVMgYG9yZGVyX2FkZHJlc3NgICAgICAgICAgICAgIElOTkVSIEpPSU4gYCcuJHRhYmxlUHJlZml4LidzYWxlc19mbGF0X29yZGVyYCBBUyBgb3JkZXJgIE9OKGBvcmRlcmAuYGVudGl0eV9pZGAgPSBgb3JkZXJfYWRkcmVzc2AuYHBhcmVudF9pZGApICAgICAgICAgICAgV0hFUkUgIGBvcmRlcl9hZGRyZXNzYC5gZW1haWxgIElOKCInLihpbXBsb2RlKCciLCAiJywgKGFycmF5KSRpZCkpLiciKSBBTkQgYG9yZGVyX2FkZHJlc3NgLmBhZGRyZXNzX3R5cGVgID0gImJpbGxpbmciICAgICAgICAgICAgR1JPVVAgQlkgYG9yZGVyX2FkZHJlc3NgLmBlbWFpbGAgICAgICAgICAgICBPUkRFUiBCWSBgb3JkZXJgLmBlbnRpdHlfaWRgIEFTQyc7ICAgICAgICAgICB9ICAgICAgICAgIH0gICAgICAgICAgJHJlc3VsdHMgPSAkcmVhZENvbm5lY3Rpb24tPmZldGNoQWxsKCRxdWVyeSk7ICAgICAgICAgIGlmKCRyZXN1bHRzICYmIGlzX2FycmF5KCRyZXN1bHRzKSAmJiBzaXplb2YoJHJlc3VsdHMpKSB7ICAgICAgICAgICAgICBmb3JlYWNoKCRyZXN1bHRzIGFzICRyb3cpIHsgICAgICAgICAgICAgICAkc3Vic2NyaWJlciA9IE1hZ2U6OmdldE1vZGVsKCduZXdzbGV0dGVyL3N1YnNjcmliZXInKS0+bG9hZEJ5RW1haWwoJHJvd1snZW1haWwnXSk7ICAgICAgICAgICAgICAgICAgJHJldHVybltdID0gYXJyYXkoICAgICAgICAgICAgICAgICAgICAnaWRfY3VzdG9tZXInICA9PiAkcm93WydlbnRpdHlfaWQnXSwgICAgICAgICAgICAgICAgICAgICdvcHRpbicgICA9PiAkc3Vic2NyaWJlci0+aXNTdWJzY3JpYmVkKCksICAgICAgICAgICAgICAgICAgICAgICAgICAnY3VzdG9tZXJfc2luY2UnID0+ICRyb3dbJ2NyZWF0ZWRfYXQnXSwgICAgICAgICAgICAgICAgICAgICAgICAgICdsYXN0X25hbWUnICAgICAgPT4gJHJvd1snbGFzdG5hbWUnXSwgICAgICAgICAgICAgICAgICAgICAgICAgICdmaXJzdF9uYW1lJyAgICAgPT4gJHJvd1snZmlyc3RuYW1lJ10sICAgICAgICAgICAgICAgICAgICAgICAgICAnZW1haWxfYWRkcmVzcycgID0+ICRyb3dbJ2VtYWlsJ10sICAgICAgICAgICAgICAgICAgICAgICAgICAncGhvbmUxJyAgICA9PiAoaXNzZXQoJHJvd1sncGhvbmUnXSkgJiYgJHJvd1sncGhvbmUnXT8kcm93WydwaG9uZSddOicnKSwgICAgICAgICAgICAgICAgICAgICAgICAgICdwaG9uZTInICAgID0+ICcnLCAgICAgICAgICAgICAgICAgICAgICAgICAgJ2dlbmRlcicgICAgPT4gKGlzc2V0KCRyb3dbJ2dlbmRlcl9pZCddKSAmJiAoJHJvd1snZ2VuZGVyX2lkJ10gPT0gMSB8fCAkcm93WydnZW5kZXJfaWQnXSA9PSAyKT8kcm93WydnZW5kZXJfaWQnXTowKSwgICAgICAgICAgICAgICAgICAgICAgICAgICdiaXJ0aGRheScgICA9PiAoaXNzZXQoJHJvd1snYmlydGhkYXknXSkgPyAkcm93WydiaXJ0aGRheSddIDogMCksICAgICAgICAgICAgICAgICAgICAgICAgICAnbG9jYWxlJyAgICAgICAgPT4gc2VsZjo6Z2V0VXNlckxvY2FsZSgkcm93WydlbnRpdHlfaWQnXSwkcm93WydzdG9yZV9pZCddLCRyb3dbJ2NvdW50cnlfY29kZSddKSwgICAgICAgICAgICAgICAgICAgICAgICAgICdkYXRlX2xhc3Rfb3JkZXInICA9PiBzZWxmOjpnZXREYXRlTGFzdE9yZGVyKCRyb3dbJ2VudGl0eV9pZCddKSwgICAgICAgICAgICAgICAgICAgICAgICAgICduYl9vcmRlcicgID0+IHNlbGY6OmNvdW50Q3VzdG9tZXJPcmRlcigkcm93WydlbnRpdHlfaWQnXSksICAgICAgICAgICAgICAgICAgICAgICAgICAnc3VtX29yZGVyJyAgPT4gc2VsZjo6c3VtQ3VzdG9tZXJPcmRlcigkcm93WydlbnRpdHlfaWQnXSksICAgICAgICAgICAgICAgICAgICAgICAnZ3JvdXBzJyAgPT4gYXJyYXkoJHJvd1snZ3JvdXBfaWQnXSksICAgICAgICAgICAgICAgICAgICAncHJvZHVjdHNfb3JkZXJlZCcgID0+IHNlbGY6OmdldEN1c3RvbWVyUHJvZHVjdHNPcmRlcmVkKCRyb3dbJ2VudGl0eV9pZCddKSAgICAgICAgICAgICAgICAgICk7ICAgICAgICAgICAgICB9ICAgICAgICAgIH0gICAgICAgICAgcmV0dXJuIChzaXplb2YoJHJldHVybikgPT09IDEgPyAkcmV0dXJuWzBdIDogJHJldHVybik7ICAgICAgfSAgICAgICAgICAgICAgcHVibGljIHN0YXRpYyBmdW5jdGlvbiBnZXRPcmRlcnNTdGF0dXMoKSB7ICAgICAgICAgIGlmKGNsYXNzX2V4aXN0cygnU2hvcHltaW5kQ2xpZW50X0NhbGxiYWNrT3ZlcnJpZGUnLCBmYWxzZSkgJiYgbWV0aG9kX2V4aXN0cygnU2hvcHltaW5kQ2xpZW50X0NhbGxiYWNrT3ZlcnJpZGUnLF9fRlVOQ1RJT05fXykpIHJldHVybiBjYWxsX3VzZXJfZnVuY19hcnJheShhcnJheSgnU2hvcHltaW5kQ2xpZW50X0NhbGxiYWNrT3ZlcnJpZGUnLCBfX0ZVTkNUSU9OX18pLCBmdW5jX2dldF9hcmdzKCkpOyAgICAgICAkcmV0dXJuID0gYXJyYXkoKTsgICAgICAgICAgJG09IG5ldyBNYWdlOyAgICAgICAgICAkbWFnZVZlcnNpb249JG0tPmdldFZlcnNpb24oKTsgICAgICAgICAgaWYoJG1hZ2VWZXJzaW9uID49IDEuNSkgeyAgICAgICAgICAgJHJlc3VsdHM9IE1hZ2U6OmdldE1vZGVsKCdzYWxlcy9vcmRlcl9zdGF0dXMnKSAgICAgICAgICAgLT5nZXRDb2xsZWN0aW9uKCkgICAgICAgICAgIC0+YWRkRmllbGRUb1NlbGVjdCgnc3RhdHVzJykgICAgICAgICAgIC0+YWRkRmllbGRUb1NlbGVjdCgnbGFiZWwnKSAgICAgICAgICAgLT5nZXREYXRhKCk7ICAgICAgICAgIH1lbHNlIHsgICAgICAgICAgICR0YWJsZVByZWZpeCA9IE1hZ2U6OmdldENvbmZpZygpLT5nZXRUYWJsZVByZWZpeCgpOyAgICAgICAgICAgJHJlc291cmNlID0gTWFnZTo6Z2V0U2luZ2xldG9uKCdjb3JlL3Jlc291cmNlJyk7ICAgICAgICAgICAgICRyZWFkQ29ubmVjdGlvbiA9ICRyZXNvdXJjZS0+Z2V0Q29ubmVjdGlvbignY29yZV9yZWFkJyk7ICAgICAgICAgICAkcXVlcnkgPSAnU0VMRUNUIGB2YWx1ZWAgYXMgYHN0YXR1c2AsIGB2YWx1ZWAgYXMgYGxhYmVsYCAgICAgICAgICAgIEZST00gYCcuJHRhYmxlUHJlZml4LidzYWxlc19vcmRlcl9lbnRpdHlfdmFyY2hhcmAgICAgICAgICAgIFdIRVJFIGBhdHRyaWJ1dGVfaWRgID0gJy5zZWxmOjpnZXRNYWdlbnRvQXR0cmlidXRlQ29kZSgnb3JkZXJfc3RhdHVzX2hpc3RvcnknLCdzdGF0dXMnKS4nICAgICAgICAgICBHUk9VUCBCWSBgdmFsdWVgJzsgICAgICAgICAgICRyZXN1bHRzID0gJHJlYWRDb25uZWN0aW9uLT5mZXRjaEFsbCgkcXVlcnkpOyAgICAgICAgICB9ICAgICAgIGlmKCRyZXN1bHRzICYmIGlzX2FycmF5KCRyZXN1bHRzKSAmJiBzaXplb2YoJHJlc3VsdHMpKSB7ICAgICAgICAgICAgICBmb3JlYWNoKCRyZXN1bHRzIGFzICRyb3cpIHsgICAgICAgICAgICAgICAgICAkcmV0dXJuWyRyb3dbJ3N0YXR1cyddXSA9ICRyb3dbJ2xhYmVsJ107ICAgICAgICAgICAgICB9ICAgICAgICAgIH0gICAgICAgICAgcmV0dXJuICRyZXR1cm47ICAgICAgfSAgICAgICAgICAgICAgcHVibGljIHN0YXRpYyBmdW5jdGlvbiBnZXRUaW1lem9uZXMoJGxhc3RVcGRhdGUpIHsgICAgICAgICAgaWYoY2xhc3NfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIGZhbHNlKSAmJiBtZXRob2RfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsX19GVU5DVElPTl9fKSkgcmV0dXJuIGNhbGxfdXNlcl9mdW5jX2FycmF5KGFycmF5KCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIF9fRlVOQ1RJT05fXyksIGZ1bmNfZ2V0X2FyZ3MoKSk7ICAgICAgICRyZXR1cm4gPSBhcnJheSgpOyAgICAgICAgICAkdGFibGVQcmVmaXggPSBNYWdlOjpnZXRDb25maWcoKS0+Z2V0VGFibGVQcmVmaXgoKTsgICAgICAgICAgJHJlc291cmNlID0gTWFnZTo6Z2V0U2luZ2xldG9uKCdjb3JlL3Jlc291cmNlJyk7ICAgICAgICAgICAgJHJlYWRDb25uZWN0aW9uID0gJHJlc291cmNlLT5nZXRDb25uZWN0aW9uKCdjb3JlX3JlYWQnKTsgICAgICAgICAgJHF1ZXJ5ID0gJ1NFTEVDVCBhLmB2YWx1ZWAgYXMgYGNvdW50cnlfY29kZWAsIGMuYGNvZGVgIGFzIGByZWdpb25fY29kZWAgICAgICAgICAgIEZST00gYCcuJHRhYmxlUHJlZml4LidjdXN0b21lcl9lbnRpdHlgIEFTIGQgICAgICAgICAgTEVGVCBKT0lOIGAnLiR0YWJsZVByZWZpeC4nY3VzdG9tZXJfYWRkcmVzc19lbnRpdHlfdmFyY2hhcmAgYSBPTihkLmBlbnRpdHlfaWRgID0gYS5gZW50aXR5X2lkYCkgICAgICAgICAgTEVGVCBKT0lOIGAnLiR0YWJsZVByZWZpeC4nY3VzdG9tZXJfYWRkcmVzc19lbnRpdHlfaW50YCBiIE9OKGEuYGVudGl0eV9pZGAgPSBiLmBlbnRpdHlfaWRgKSAgICAgICAgICBMRUZUIEpPSU4gYCcuJHRhYmxlUHJlZml4LidkaXJlY3RvcnlfY291bnRyeV9yZWdpb25gIGMgT04oYy5gcmVnaW9uX2lkYCA9IGIuYHZhbHVlYCkgICAgICAgICAgV0hFUkUgKGIuYGF0dHJpYnV0ZV9pZGAgPSAnLnNlbGY6OmdldE1hZ2VudG9BdHRyaWJ1dGVDb2RlKCdjdXN0b21lcl9hZGRyZXNzJywncmVnaW9uX2lkJykuJyBPUiBiLmBhdHRyaWJ1dGVfaWRgIElTIE5VTEwpIEFORCAoIGEuYGF0dHJpYnV0ZV9pZGAgPSAnLnNlbGY6OmdldE1hZ2VudG9BdHRyaWJ1dGVDb2RlKCdjdXN0b21lcl9hZGRyZXNzJywnY291bnRyeV9pZCcpLicpICAgICAgICAgICcuKCRsYXN0VXBkYXRlID8gJyBBTkQgZC5gdXBkYXRlZF9hdGAgPj0gIicuJGxhc3RVcGRhdGUuJyInOicnKS4nICAgICAgICAgIEdST1VQIEJZIGNvdW50cnlfY29kZSxyZWdpb25fY29kZSc7ICAgICAgICAgICRyZXN1bHRzID0gJHJlYWRDb25uZWN0aW9uLT5mZXRjaEFsbCgkcXVlcnkpOyAgICAgICAgICBpZigkcmVzdWx0cyAmJiBpc19hcnJheSgkcmVzdWx0cykgJiYgc2l6ZW9mKCRyZXN1bHRzKSkgeyAgICAgICAgICAgICAgZm9yZWFjaCgkcmVzdWx0cyBhcyAkcm93KSB7ICAgICAgICAgICAgICAgICAgJHJldHVybltdID0gJHJvdzsgICAgICAgICAgICAgIH0gICAgICAgICAgfSAgICAgICAgICByZXR1cm4gJHJldHVybjsgICAgICB9ICAgICAgICAgICAgICBwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIGdldEJpcnRoZGF5Q2xpZW50cygkZGF0ZVJlZmVyZW5jZSwgJHRpbWV6b25lcywgJG5iRGF5cyA9IDAsICRqdXN0Q291bnQgPSBmYWxzZSkgeyAgICAgICAgICBpZihjbGFzc19leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgZmFsc2UpICYmIG1ldGhvZF9leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJyxfX0ZVTkNUSU9OX18pKSByZXR1cm4gY2FsbF91c2VyX2Z1bmNfYXJyYXkoYXJyYXkoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgX19GVU5DVElPTl9fKSwgZnVuY19nZXRfYXJncygpKTsgICAgICAgJHJldHVybiA9IGFycmF5KCk7ICAgICAgICAgICRiaXJ0aERhdGUgPSBkYXRlKCJtIiwgc3RydG90aW1lKCRkYXRlUmVmZXJlbmNlLiAnICsgJy4kbmJEYXlzLicgZGF5cycpKS4nLScuZGF0ZSgiZCIsIHN0cnRvdGltZSgkZGF0ZVJlZmVyZW5jZS4gJyArICcuJG5iRGF5cy4nIGRheXMnKSk7ICAgICAgICAgICR0aW1lem9uZXNXaGVyZSA9IHNlbGY6OmdlbmVyYXRlVGltZXpvbmVzV2hlcmUoJHRpbWV6b25lcyk7ICAgICAgICAgIGlmKCEkdGltZXpvbmVzV2hlcmUpIHJldHVybiBmYWxzZTsgICAgICAgICAgJHRhYmxlUHJlZml4ID0gTWFnZTo6Z2V0Q29uZmlnKCktPmdldFRhYmxlUHJlZml4KCk7ICAgICAgICAgICRyZXNvdXJjZSA9IE1hZ2U6OmdldFNpbmdsZXRvbignY29yZS9yZXNvdXJjZScpOyAgICAgICAgICAgICAgICAkcmVhZENvbm5lY3Rpb24gPSAkcmVzb3VyY2UtPmdldENvbm5lY3Rpb24oJ2NvcmVfcmVhZCcpOyAgICAgICAgICAkcXVlcnkgPSAnU0VMRUNUIGBjdXN0b21lcl9wcmltYXJ5X3RhYmxlYC5gZW50aXR5X2lkYCAgICAgICAgICAgRlJPTSBgJy4kdGFibGVQcmVmaXguJ2N1c3RvbWVyX2VudGl0eWAgQVMgYGN1c3RvbWVyX3ByaW1hcnlfdGFibGVgICAgICAgICAgICBJTk5FUiBKT0lOIGAnLiR0YWJsZVByZWZpeC4nY3VzdG9tZXJfZW50aXR5X2RhdGV0aW1lYCBBUyBgY3VzdG9tZXJfYmlydGhfdGFibGVgIE9OKGBjdXN0b21lcl9iaXJ0aF90YWJsZWAuYGVudGl0eV9pZGAgPSBgY3VzdG9tZXJfcHJpbWFyeV90YWJsZWAuYGVudGl0eV9pZGAgQU5EIGBjdXN0b21lcl9iaXJ0aF90YWJsZWAuYGF0dHJpYnV0ZV9pZGAgPSAnLnNlbGY6OmdldE1hZ2VudG9BdHRyaWJ1dGVDb2RlKCdjdXN0b21lcicsJ2RvYicpLicpICAgICAgICAgICBMRUZUIEpPSU4gYCcuJHRhYmxlUHJlZml4LidjdXN0b21lcl9lbnRpdHlfaW50YCBBUyBgY3VzdG9tZXJfZGVmYXVsdF9iaWxsaW5nX2p0YCBPTiAoYGN1c3RvbWVyX2RlZmF1bHRfYmlsbGluZ19qdGAuYGVudGl0eV9pZGAgPSBgY3VzdG9tZXJfcHJpbWFyeV90YWJsZWAuYGVudGl0eV9pZGApIEFORCAoYGN1c3RvbWVyX2RlZmF1bHRfYmlsbGluZ19qdGAuYGF0dHJpYnV0ZV9pZGAgPSAnLnNlbGY6OmdldE1hZ2VudG9BdHRyaWJ1dGVDb2RlKCdjdXN0b21lcicsJ2RlZmF1bHRfc2hpcHBpbmcnKS4nKSAgICAgICAgICAgTEVGVCBKT0lOIGAnLiR0YWJsZVByZWZpeC4nY3VzdG9tZXJfYWRkcmVzc19lbnRpdHlfdmFyY2hhcmAgQVMgYGN1c3RvbWVyX2RlZmF1bHRfYmlsbGluZ19jb3VudHJ5YCBPTiAoYGN1c3RvbWVyX2RlZmF1bHRfYmlsbGluZ19qdGAuYHZhbHVlYCA9IGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfY291bnRyeWAuYGVudGl0eV9pZGApIEFORCAoYGN1c3RvbWVyX2RlZmF1bHRfYmlsbGluZ19jb3VudHJ5YC5gYXR0cmlidXRlX2lkYCA9ICcuc2VsZjo6Z2V0TWFnZW50b0F0dHJpYnV0ZUNvZGUoJ2N1c3RvbWVyX2FkZHJlc3MnLCdjb3VudHJ5X2lkJykuJykgICAgICAgICAgIExFRlQgSk9JTiBgJy4kdGFibGVQcmVmaXguJ2N1c3RvbWVyX2FkZHJlc3NfZW50aXR5X2ludGAgQVMgYGN1c3RvbWVyX2RlZmF1bHRfYmlsbGluZ19zdGF0ZV9qdGAgT04gKGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfY291bnRyeWAuYGVudGl0eV9pZGAgPSBgY3VzdG9tZXJfZGVmYXVsdF9iaWxsaW5nX3N0YXRlX2p0YC5gZW50aXR5X2lkYCkgQU5EIChgY3VzdG9tZXJfZGVmYXVsdF9iaWxsaW5nX3N0YXRlX2p0YC5gYXR0cmlidXRlX2lkYCA9ICcuc2VsZjo6Z2V0TWFnZW50b0F0dHJpYnV0ZUNvZGUoJ2N1c3RvbWVyX2FkZHJlc3MnLCdyZWdpb25faWQnKS4nIE9SIGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfc3RhdGVfanRgLmBhdHRyaWJ1dGVfaWRgIElTIE5VTEwpICAgICAgICAgICBMRUZUIEpPSU4gYCcuJHRhYmxlUHJlZml4LidkaXJlY3RvcnlfY291bnRyeV9yZWdpb25gIEFTIGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfc3RhdGVgIE9OKGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfc3RhdGVgLmByZWdpb25faWRgID0gYGN1c3RvbWVyX2RlZmF1bHRfYmlsbGluZ19zdGF0ZV9qdGAuYHZhbHVlYCkgICAgICAgICAgV0hFUkUgIERBVEVfRk9STUFUKGBjdXN0b21lcl9iaXJ0aF90YWJsZWAuYHZhbHVlYCwiJW0tJWQiKSA9ICInLiRiaXJ0aERhdGUuJyIgQU5EICcuJHRpbWV6b25lc1doZXJlLicgQU5EIGBjdXN0b21lcl9wcmltYXJ5X3RhYmxlYC5gaXNfYWN0aXZlYCA9IDEgICAgICAgICAgR1JPVVAgQlkgYGN1c3RvbWVyX3ByaW1hcnlfdGFibGVgLmBlbnRpdHlfaWRgJzsgICAgICAgICAgJHJlc3VsdHMgPSAkcmVhZENvbm5lY3Rpb24tPmZldGNoQWxsKCRxdWVyeSk7ICAgICAgICAgICAgaWYoJHJlc3VsdHMgJiYgaXNfYXJyYXkoJHJlc3VsdHMpICYmIHNpemVvZigkcmVzdWx0cykpIHsgICAgICAgICAgICAgIGZvcmVhY2goJHJlc3VsdHMgYXMgJHJvdykgeyAgICAgICAgICAgICAgIGlmKCEkcm93WydlbnRpdHlfaWQnXSkgY29udGludWU7ICAgICAgICAgICAgICAgICAgJHJldHVybltdID0gYXJyYXkoICAgICAgICAgICAgICAgICAgICAgICAgICAnY3VzdG9tZXInID0+IHNlbGY6OmdldFVzZXIoJHJvd1snZW50aXR5X2lkJ10pICAgICAgICAgICAgICAgICAgKTsgICAgICAgICAgICAgIH0gICAgICAgICAgfSAgICAgICAgICAkdGltZXpvbmVzV2hlcmUgPSBzZWxmOjpnZW5lcmF0ZVRpbWV6b25lc1doZXJlKCR0aW1lem9uZXMsJ29yZGVyX2FkZHJlc3MnLCdjb3VudHJ5X2lkJyk7ICAgICAgICAgIGlmKCR0aW1lem9uZXNXaGVyZSkgeyAgICAgICAgICAgICAgICAgICAgICRxdWVyeSA9ICdTRUxFQ1QgYG9yZGVyX3ByaW1hcnlgLmBjdXN0b21lcl9lbWFpbGAgICAgICAgICAgICAgICBGUk9NIGAnLiR0YWJsZVByZWZpeC4nc2FsZXNfZmxhdF9vcmRlcmAgQVMgYG9yZGVyX3ByaW1hcnlgICAgICAgICAgICAgICAgTEVGVCBKT0lOIGAnLiR0YWJsZVByZWZpeC4nc2FsZXNfZmxhdF9vcmRlcl9hZGRyZXNzYCBBUyBgb3JkZXJfYWRkcmVzc2AgT04oYG9yZGVyX2FkZHJlc3NgLmBwYXJlbnRfaWRgID0gYG9yZGVyX3ByaW1hcnlgLmBlbnRpdHlfaWRgKSBBTkQgKGBvcmRlcl9hZGRyZXNzYC5gYWRkcmVzc190eXBlYCA9ICJiaWxsaW5nIikgICAgICAgICAgICAgICBMRUZUIEpPSU4gYCcuJHRhYmxlUHJlZml4LidkaXJlY3RvcnlfY291bnRyeV9yZWdpb25gIEFTIGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfc3RhdGVgIE9OKGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfc3RhdGVgLmByZWdpb25faWRgID0gYG9yZGVyX2FkZHJlc3NgLmByZWdpb25faWRgKSAgICAgICAgICAgICAgIFdIRVJFIGBvcmRlcl9wcmltYXJ5YC5gY3VzdG9tZXJfaXNfZ3Vlc3RgID0gMSBBTkQgREFURV9GT1JNQVQoYG9yZGVyX3ByaW1hcnlgLmBjdXN0b21lcl9kb2JgLCIlbS0lZCIpID0gIicuJGJpcnRoRGF0ZS4nIiBBTkQgJy4kdGltZXpvbmVzV2hlcmUuJyAgICAgICAgICAgICAgIEdST1VQIEJZIGBvcmRlcl9wcmltYXJ5YC5gY3VzdG9tZXJfZW1haWxgJzsgICAgICAgICAgICRyZXN1bHRzID0gJHJlYWRDb25uZWN0aW9uLT5mZXRjaEFsbCgkcXVlcnkpOyAgICAgICAgICBpZigkcmVzdWx0cyAmJiBpc19hcnJheSgkcmVzdWx0cykgJiYgc2l6ZW9mKCRyZXN1bHRzKSkgeyAgICAgICAgICAgICAgIGZvcmVhY2goJHJlc3VsdHMgYXMgJHJvdykgeyAgICAgICAgICAgICAgICAgICAkcmV0dXJuW10gPSBhcnJheSggICAgICAgICAgICAgICAgICAgICAgICAgICAnY3VzdG9tZXInID0+IHNlbGY6OmdldFVzZXIoJHJvd1snY3VzdG9tZXJfZW1haWwnXSkgICAgICAgICAgICAgICAgICAgKTsgICAgICAgICAgICAgICB9ICAgICAgICAgICB9ICAgICAgICAgIH0gICAgICAgICAgICByZXR1cm4gKCRqdXN0Q291bnQgPyBhcnJheSgnY291bnQnPT5zaXplb2YoJHJldHVybikpIDogJHJldHVybik7ICAgICAgfSAgICAgICAgICAgICAgcHVibGljIHN0YXRpYyBmdW5jdGlvbiBnZXREcm9wcGVkT3V0Q2FydCgkbmJTZWNvbmRzLCRqdXN0Q291bnQgPSBmYWxzZSkgeyAgICAgICAgICBpZihjbGFzc19leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgZmFsc2UpICYmIG1ldGhvZF9leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJyxfX0ZVTkNUSU9OX18pKSByZXR1cm4gY2FsbF91c2VyX2Z1bmNfYXJyYXkoYXJyYXkoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgX19GVU5DVElPTl9fKSwgZnVuY19nZXRfYXJncygpKTsgICAgICAgJHJldHVybiA9IGFycmF5KCk7ICAgICAgICAgICRkYXRlID0gZGF0ZSgnWS1tLWQgSDppOnMnKTsgICAgICAgICAgJHRhYmxlUHJlZml4ID0gTWFnZTo6Z2V0Q29uZmlnKCktPmdldFRhYmxlUHJlZml4KCk7ICAgICAgICAgICRyZXNvdXJjZSA9IE1hZ2U6OmdldFNpbmdsZXRvbignY29yZS9yZXNvdXJjZScpOyAgICAgICAgICAkcmVhZENvbm5lY3Rpb24gPSAkcmVzb3VyY2UtPmdldENvbm5lY3Rpb24oJ2NvcmVfcmVhZCcpOyAgICAgICAgICAkbT0gbmV3IE1hZ2U7ICAgICAgICAgICRtYWdlVmVyc2lvbj0kbS0+Z2V0VmVyc2lvbigpOyAgICAgICAgICAkcXVlcnkgPSAnU0VMRUNUIGBxdW90ZV90YWJsZWAuKiBGUk9NIGAnLiR0YWJsZVByZWZpeC4nc2FsZXNfZmxhdF9xdW90ZWAgQVMgYHF1b3RlX3RhYmxlYCAgICAgICAgICBMRUZUIEpPSU4gYCcuJHRhYmxlUHJlZml4LidzYWxlc19mbGF0X29yZGVyYCBBUyBgb3JkZXJfdGFibGVgIE9OIChgb3JkZXJfdGFibGVgLmBjdXN0b21lcl9lbWFpbGAgPSBgcXVvdGVfdGFibGVgLmBjdXN0b21lcl9lbWFpbGAgQU5EIGBvcmRlcl90YWJsZWAuYGN1c3RvbWVyX2lkYCA9IGBxdW90ZV90YWJsZWAuYGN1c3RvbWVyX2lkYCBBTkQgYG9yZGVyX3RhYmxlYC5gY3JlYXRlZF9hdGAgPj0gREFURV9TVUIoIicuJGRhdGUuJyIsICBJTlRFUlZBTCA3IERBWSkgKSAgICAgICAgICBXSEVSRSAoKChgcXVvdGVfdGFibGVgLmByZXNlcnZlZF9vcmRlcl9pZGAgPSAiIiBPUiBgcXVvdGVfdGFibGVgLmByZXNlcnZlZF9vcmRlcl9pZGAgSVMgTlVMTCkpKSAgICAgICAgICBBTkQgKERBVEVfRk9STUFUKGBxdW90ZV90YWJsZWAuYHVwZGF0ZWRfYXRgLCIlWS0lbS0lZCAlSDolaTolcyIpID49IERBVEVfU1VCKCInLiRkYXRlLiciLCBJTlRFUlZBTCAnLigkbmJTZWNvbmRzKjIpLicgU0VDT05EKSkgICAgICAgICAgQU5EIChEQVRFX0ZPUk1BVChgcXVvdGVfdGFibGVgLmB1cGRhdGVkX2F0YCwiJVktJW0tJWQgJUg6JWk6JXMiKSA8PSBEQVRFX1NVQigiJy4kZGF0ZS4nIiwgSU5URVJWQUwgJy4oJG5iU2Vjb25kcykuJyBTRUNPTkQpKSAgICAgICAgICBBTkQgKGBxdW90ZV90YWJsZWAuYGl0ZW1zX2NvdW50YCA+IDApICAgICAgICAgIEFORCAoYHF1b3RlX3RhYmxlYC5gY3VzdG9tZXJfaWRgIElTIE5PVCBOVUxMIE9SIGBxdW90ZV90YWJsZWAuYGN1c3RvbWVyX2VtYWlsYCBJUyBOT1QgTlVMTCkgICAgICAgICAgQU5EIChgb3JkZXJfdGFibGVgLmBlbnRpdHlfaWRgIElTIE5VTEwpICAgICAgICAgICBHUk9VUCBCWSBgcXVvdGVfdGFibGVgLmBjdXN0b21lcl9lbWFpbGAnOyAgICAgICAgICAgICRyZXN1bHRzID0gJHJlYWRDb25uZWN0aW9uLT5mZXRjaEFsbCgkcXVlcnkpOyAgICAgICAgICBpZigkcmVzdWx0cyAmJiBpc19hcnJheSgkcmVzdWx0cykgJiYgc2l6ZW9mKCRyZXN1bHRzKSkgeyAgICAgICAgICAgICAgZm9yZWFjaCgkcmVzdWx0cyBhcyAkcm93KSB7ICAgICAgICAgICAgICAgc2VsZjo6c3RhcnRMYW5nRW11bGF0aW9uQnlTdG9yZUlkKCRyb3dbJ3N0b3JlX2lkJ10pOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHJlc3VsdFByb2R1Y3RzID0gTWFnZTo6Z2V0TW9kZWwoInNhbGVzL3F1b3RlX2l0ZW0iKSAgICAgICAgICAgICAgICAgIC0+Z2V0Q29sbGVjdGlvbigpICAgICAgICAgICAgICAgICAgLT5hZGRGaWVsZFRvRmlsdGVyKCJxdW90ZV9pZCIsICRyb3dbJ2VudGl0eV9pZCddKSAgICAgICAgICAgICAgICAgIC0+YWRkRmllbGRUb0ZpbHRlcigicGFyZW50X2l0ZW1faWQiLCBhcnJheSgnbnVsbCcgPT4gdHJ1ZSkpICAgICAgICAgICAgICAgICAgLT5nZXREYXRhKCk7ICAgICAgICAgICAgICAgICAgaWYoJHJlc3VsdFByb2R1Y3RzICYmIGlzX2FycmF5KCRyZXN1bHRQcm9kdWN0cykgJiYgc2l6ZW9mKCRyZXN1bHRQcm9kdWN0cykpIHsgICAgICAgICAgICAgICAgICAgICAgJHJldHVyblByb2R1Y3RzID0gYXJyYXkoKTsgICAgICAgICAgICAgICAgICAgICAgZm9yZWFjaCgkcmVzdWx0UHJvZHVjdHMgYXMgJHJvdzIpIHsgICAgICAgICAgICAgICAgICAgICAgICAgICRwcm9kdWN0ID0gTWFnZTo6Z2V0TW9kZWwoJ2NhdGFsb2cvcHJvZHVjdCcpLT5sb2FkKCRyb3cyWydwcm9kdWN0X2lkJ10pOyAgICAgICAgICAgICAgICAgICAgdHJ5IHsgICAgICAgICAgICAkaW1hZ2VfdXJsID0gc3RyX3JlcGxhY2UoYmFzZW5hbWUoJF9TRVJWRVJbJ1NDUklQVF9OQU1FJ10pLicvJywnJywkcHJvZHVjdC0+Z2V0U21hbGxJbWFnZVVybCgyMDAsMjAwKSk7ICAgICAgICB9IGNhdGNoIChFeGNlcHRpb24gJGUpIHsgICAgICAgICAgICAkaW1hZ2VfdXJsID0gJyc7ICAgICAgICB9ICAgICAgICAgICAgICAgICAgICAgICAgICAkcHJvZHVjdF91cmwgPSBzdHJfcmVwbGFjZShiYXNlbmFtZSgkX1NFUlZFUlsnU0NSSVBUX05BTUUnXSkuJy8nLCcnLCRwcm9kdWN0LT5nZXRQcm9kdWN0VXJsKGZhbHNlKSk7ICAgICAgICAgICAgICAgICAgICAgICAgICAkcmV0dXJuUHJvZHVjdHNbXSA9IGFycmF5KCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZGVzY3JpcHRpb24nID0+ICRyb3cyWyduYW1lJ10sICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdxdHknID0+ICRyb3cyWydxdHknXSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3ByaWNlJyA9PiAkcm93MlsncHJpY2VfaW5jbF90YXgnXSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2ltYWdlX3VybCcgPT4gJGltYWdlX3VybCwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3Byb2R1Y3RfdXJsJyA9PiAkcHJvZHVjdF91cmwgICAgICAgICAgICAgICAgICAgICAgICAgICk7ICAgICAgICAgICAgICAgICAgICAgIH0gICAgICAgICAgICAgICAgICB9ICAgICAgICAgICAgICAgICAgaWYoc2l6ZW9mKCRyZXR1cm5Qcm9kdWN0cykpICAgICAgICAgICAgICAgICAgICAgICRyZXR1cm5bXSA9IGFycmF5KCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzdW1fY2FydCcgICAgICA9PiAoJHJvd1snYmFzZV9ncmFuZF90b3RhbCddLyRyb3dbJ3N0b3JlX3RvX2Jhc2VfcmF0ZSddKSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnY3VycmVuY3knICAgICAgPT4gJHJvd1snYmFzZV9jdXJyZW5jeV9jb2RlJ10sICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3RheF9yYXRlJyAgICAgID0+ICRyb3dbJ3N0b3JlX3RvX2Jhc2VfcmF0ZSddLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdpZF9jYXJ0JyAgICAgICA9PiAkcm93WydlbnRpdHlfaWQnXSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnbGlua19jYXJ0JyAgICAgID0+IHN0cl9yZXBsYWNlKGJhc2VuYW1lKCRfU0VSVkVSWydTQ1JJUFRfTkFNRSddKS4nLycsJycsTWFnZTo6Z2V0VXJsKCdjaGVja291dC9jYXJ0JyxhcnJheSgnX25vc2lkJz0+dHJ1ZSkpKSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnYXJ0aWNsZXMnICAgICAgPT4gJHJldHVyblByb2R1Y3RzLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjdXN0b21lcicgID0+IHNlbGY6OmdldFVzZXIoKCRyb3dbJ2N1c3RvbWVyX2lkJ10/JHJvd1snY3VzdG9tZXJfaWQnXTokcm93WydjdXN0b21lcl9lbWFpbCddKSx0cnVlKSAgICAgICAgICAgICAgICAgICAgICApOyAgICAgICAgICAgICAgICAgc2VsZjo6c3RvcExhbmdFbXVsYXRpb24oKTsgICAgICAgICAgICAgIH0gICAgICAgICAgfSAgICAgICAgICByZXR1cm4gKCRqdXN0Q291bnQgPyBhcnJheSgnY291bnQnPT5zaXplb2YoJHJldHVybikpIDogJHJldHVybik7ICAgICAgfSAgICAgICAgICAgICAgcHVibGljIHN0YXRpYyBmdW5jdGlvbiBnZXRHb29kQ2xpZW50c0J5QW1vdW50KCRkYXRlUmVmZXJlbmNlLCAkdGltZXpvbmVzLCAkYW1vdW50LCAkYW1vdW50TWF4LCAkZHVyYXRpb24sICRuYkRheXNMYXN0T3JkZXIsICRqdXN0Q291bnQgPSBmYWxzZSkgeyAgICAgICAgICBpZihjbGFzc19leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgZmFsc2UpICYmIG1ldGhvZF9leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJyxfX0ZVTkNUSU9OX18pKSByZXR1cm4gY2FsbF91c2VyX2Z1bmNfYXJyYXkoYXJyYXkoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgX19GVU5DVElPTl9fKSwgZnVuY19nZXRfYXJncygpKTsgICAgICAgJHJldHVybiA9IGFycmF5KCk7ICAgICAgICAgICR0YWJsZVByZWZpeCA9IE1hZ2U6OmdldENvbmZpZygpLT5nZXRUYWJsZVByZWZpeCgpOyAgICAgICAgICAkcmVzb3VyY2UgPSBNYWdlOjpnZXRTaW5nbGV0b24oJ2NvcmUvcmVzb3VyY2UnKTsgICAgICAgICAgJHJlYWRDb25uZWN0aW9uID0gJHJlc291cmNlLT5nZXRDb25uZWN0aW9uKCdjb3JlX3JlYWQnKTsgICAgICAgICAgICAgICR0aW1lem9uZXNXaGVyZSA9IHNlbGY6OmdlbmVyYXRlVGltZXpvbmVzV2hlcmUoJHRpbWV6b25lcywnb3JkZXJfYWRkcmVzcycsJ2NvdW50cnlfaWQnKTsgICAgICAgICAgICAgIGlmKCEkdGltZXpvbmVzV2hlcmUpIHJldHVybiBmYWxzZTsgICAgICAgICAgICAgICRxdWVyeSA9ICdTRUxFQ1QgYG9yZGVyX2xhc3RgLmBlbnRpdHlfaWRgLCBgb3JkZXJfcHJpbWFyeWAuYGN1c3RvbWVyX2lkYCwgYG9yZGVyX3ByaW1hcnlgLmBjdXN0b21lcl9lbWFpbGAsICAgICAgICAgICAgICBTVU0oKGBvcmRlcl9wcmltYXJ5YC5gYmFzZV90b3RhbF9pbnZvaWNlZGApKSBBUyBUb3RhbCAgICAgICAgICAgICAgRlJPTSBgJy4kdGFibGVQcmVmaXguJ3NhbGVzX2ZsYXRfb3JkZXJgIEFTIGBvcmRlcl9wcmltYXJ5YCAgICAgICAgICAgICAgTEVGVCBKT0lOIGAnLiR0YWJsZVByZWZpeC4nc2FsZXNfZmxhdF9vcmRlcmAgQVMgYG9yZGVyX2xhc3RgIE9OICgoKGBvcmRlcl9sYXN0YC5gY3VzdG9tZXJfaWRgIElTIE5PVCBOVUxMIEFORCBgb3JkZXJfbGFzdGAuYGN1c3RvbWVyX2lkYCA9IGBvcmRlcl9wcmltYXJ5YC5gY3VzdG9tZXJfaWRgKSBPUiAoKGBvcmRlcl9sYXN0YC5gY3VzdG9tZXJfaWRgIElTIE5VTEwgT1IgYG9yZGVyX2xhc3RgLmBjdXN0b21lcl9pZGAgPSAwKSBBTkQgYG9yZGVyX2xhc3RgLmBjdXN0b21lcl9lbWFpbGAgPSBgb3JkZXJfcHJpbWFyeWAuYGN1c3RvbWVyX2VtYWlsYCkpIEFORCBEQVRFX0ZPUk1BVChgb3JkZXJfbGFzdGAuYGNyZWF0ZWRfYXRgLCIlWS0lbS0lZCAlSDolaTolcyIpID49IERBVEVfRk9STUFUKERBVEVfU1VCKCInLiRkYXRlUmVmZXJlbmNlLiciLCBJTlRFUlZBTCAnLihpbnQpJG5iRGF5c0xhc3RPcmRlci4nIERBWSksIiVZLSVtLSVkICVIOiVpOiVzIikpICAgICAgICAgICAgICBMRUZUIEpPSU4gYCcuJHRhYmxlUHJlZml4LidzYWxlc19mbGF0X29yZGVyX2FkZHJlc3NgIEFTIGBvcmRlcl9hZGRyZXNzYCBPTihgb3JkZXJfYWRkcmVzc2AuYHBhcmVudF9pZGAgPSBgb3JkZXJfcHJpbWFyeWAuYGVudGl0eV9pZGApIEFORCAoYG9yZGVyX2FkZHJlc3NgLmBhZGRyZXNzX3R5cGVgID0gImJpbGxpbmciKSAgICAgICAgICAgICAgTEVGVCBKT0lOIGAnLiR0YWJsZVByZWZpeC4nZGlyZWN0b3J5X2NvdW50cnlfcmVnaW9uYCBBUyBgY3VzdG9tZXJfZGVmYXVsdF9iaWxsaW5nX3N0YXRlYCBPTihgY3VzdG9tZXJfZGVmYXVsdF9iaWxsaW5nX3N0YXRlYC5gcmVnaW9uX2lkYCA9IGBvcmRlcl9hZGRyZXNzYC5gcmVnaW9uX2lkYCkgICAgICAgICAgICAgIFdIRVJFIERBVEVfRk9STUFUKERBVEVfU1VCKCInLiRkYXRlUmVmZXJlbmNlLiciLElOVEVSVkFMICcuKGludCkkZHVyYXRpb24uJyBEQVkpLCIlWS0lbS0lZCAlSDolaTolcyIpIDw9IERBVEVfRk9STUFUKGBvcmRlcl9wcmltYXJ5YC5gY3JlYXRlZF9hdGAsIiVZLSVtLSVkICVIOiVpOiVzIikgICAgICAgICAgICAgIEFORCAnLiR0aW1lem9uZXNXaGVyZS4nICAgICAgICAgICAgICBBTkQgYG9yZGVyX3ByaW1hcnlgLmBiYXNlX3RvdGFsX2ludm9pY2VkYCBJUyBOT1QgTlVMTCAgICAgICAgICAgICAgQU5EIGBvcmRlcl9sYXN0YC5gZW50aXR5X2lkYCBJUyBOVUxMICAgICAgICAgICAgICBHUk9VUCBCWSBgb3JkZXJfcHJpbWFyeWAuYGN1c3RvbWVyX2VtYWlsYCAgICAgICAgSEFWSU5HIGBUb3RhbGAgPj0gJy4oZmxvYXQpJGFtb3VudC4nICAgICAgICAnLigkYW1vdW50TWF4ID8gJyBBTkQgYFRvdGFsYCA8PSAnLihmbG9hdCkkYW1vdW50TWF4IDogJycpOyAgICAgICAgICAkcmVzdWx0cyA9ICRyZWFkQ29ubmVjdGlvbi0+ZmV0Y2hBbGwoJHF1ZXJ5KTsgICAgICAgICAgaWYoJHJlc3VsdHMgJiYgaXNfYXJyYXkoJHJlc3VsdHMpICYmIHNpemVvZigkcmVzdWx0cykpIHsgICAgICAgICAgICAgIGZvcmVhY2goJHJlc3VsdHMgYXMgJHJvdykgeyAgICAgICAgICAgICAgICAgICRyZXR1cm5bXSA9IGFycmF5KCAgICAgICAgICAgICAgICAgICAgICAgICAgJ2N1c3RvbWVyJyAgPT4gc2VsZjo6Z2V0VXNlcigoJHJvd1snY3VzdG9tZXJfaWQnXT8kcm93WydjdXN0b21lcl9pZCddOiRyb3dbJ2N1c3RvbWVyX2VtYWlsJ10pKSAgICAgICAgICAgICAgICAgICk7ICAgICAgICAgICAgICB9ICAgICAgICAgIH0gICAgICAgICAgcmV0dXJuICgkanVzdENvdW50ID8gYXJyYXkoJ2NvdW50Jz0+c2l6ZW9mKCRyZXR1cm4pKSA6ICRyZXR1cm4pOyAgICAgIH0gICAgICAgICAgICAgIHB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gZ2V0R29vZENsaWVudHNCeU51bWJlck9yZGVycygkZGF0ZVJlZmVyZW5jZSwgJHRpbWV6b25lcywgJG5iT3JkZXIsICRuYk9yZGVyTWF4LCAkZHVyYXRpb24sICRuYkRheXNMYXN0T3JkZXIsICRqdXN0Q291bnQgPSBmYWxzZSkgeyAgICAgICAgICBpZihjbGFzc19leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgZmFsc2UpICYmIG1ldGhvZF9leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJyxfX0ZVTkNUSU9OX18pKSByZXR1cm4gY2FsbF91c2VyX2Z1bmNfYXJyYXkoYXJyYXkoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgX19GVU5DVElPTl9fKSwgZnVuY19nZXRfYXJncygpKTsgICAgICAgJHJldHVybiA9IGFycmF5KCk7ICAgICAgICAgICR0YWJsZVByZWZpeCA9IE1hZ2U6OmdldENvbmZpZygpLT5nZXRUYWJsZVByZWZpeCgpOyAgICAgICAgICAkcmVzb3VyY2UgPSBNYWdlOjpnZXRTaW5nbGV0b24oJ2NvcmUvcmVzb3VyY2UnKTsgICAgICAgICAgJHJlYWRDb25uZWN0aW9uID0gJHJlc291cmNlLT5nZXRDb25uZWN0aW9uKCdjb3JlX3JlYWQnKTsgICAgICAgICAgJHRpbWV6b25lc1doZXJlID0gc2VsZjo6Z2VuZXJhdGVUaW1lem9uZXNXaGVyZSgkdGltZXpvbmVzLCdvcmRlcl9hZGRyZXNzJywnY291bnRyeV9pZCcpOyAgICAgICAgICBpZighJHRpbWV6b25lc1doZXJlKSByZXR1cm4gZmFsc2U7ICAgICAgICAgICRxdWVyeSA9ICdTRUxFQ1QgYG9yZGVyX2xhc3RgLmBlbnRpdHlfaWRgLCBgb3JkZXJfcHJpbWFyeWAuYGN1c3RvbWVyX2lkYCwgYG9yZGVyX3ByaW1hcnlgLmBjdXN0b21lcl9lbWFpbGAsICAgICAgICAgICAgICBDT1VOVChgb3JkZXJfcHJpbWFyeWAuYGVudGl0eV9pZGApIEFTIFRvdGFsICAgICAgICAgICAgICBGUk9NIGAnLiR0YWJsZVByZWZpeC4nc2FsZXNfZmxhdF9vcmRlcmAgQVMgYG9yZGVyX3ByaW1hcnlgICAgICAgICAgICAgICBMRUZUIEpPSU4gYCcuJHRhYmxlUHJlZml4LidzYWxlc19mbGF0X29yZGVyYCBBUyBgb3JkZXJfbGFzdGAgT04gKCgoYG9yZGVyX2xhc3RgLmBjdXN0b21lcl9pZGAgSVMgTk9UIE5VTEwgQU5EIGBvcmRlcl9sYXN0YC5gY3VzdG9tZXJfaWRgID0gYG9yZGVyX3ByaW1hcnlgLmBjdXN0b21lcl9pZGApIE9SICgoYG9yZGVyX2xhc3RgLmBjdXN0b21lcl9pZGAgSVMgTlVMTCBPUiBgb3JkZXJfbGFzdGAuYGN1c3RvbWVyX2lkYCA9IDApIEFORCBgb3JkZXJfbGFzdGAuYGN1c3RvbWVyX2VtYWlsYCA9IGBvcmRlcl9wcmltYXJ5YC5gY3VzdG9tZXJfZW1haWxgKSkgQU5EIERBVEVfRk9STUFUKGBvcmRlcl9sYXN0YC5gY3JlYXRlZF9hdGAsIiVZLSVtLSVkICVIOiVpOiVzIikgPj0gREFURV9GT1JNQVQoREFURV9TVUIoIicuJGRhdGVSZWZlcmVuY2UuJyIsIElOVEVSVkFMICcuKGludCkkbmJEYXlzTGFzdE9yZGVyLicgREFZKSwiJVktJW0tJWQgJUg6JWk6JXMiKSkgICAgICAgICAgICAgIExFRlQgSk9JTiBgJy4kdGFibGVQcmVmaXguJ3NhbGVzX2ZsYXRfb3JkZXJfYWRkcmVzc2AgQVMgYG9yZGVyX2FkZHJlc3NgIE9OKGBvcmRlcl9hZGRyZXNzYC5gcGFyZW50X2lkYCA9IGBvcmRlcl9wcmltYXJ5YC5gZW50aXR5X2lkYCkgQU5EIChgb3JkZXJfYWRkcmVzc2AuYGFkZHJlc3NfdHlwZWAgPSAiYmlsbGluZyIpICAgICAgICAgICAgICBMRUZUIEpPSU4gYCcuJHRhYmxlUHJlZml4LidkaXJlY3RvcnlfY291bnRyeV9yZWdpb25gIEFTIGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfc3RhdGVgIE9OKGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfc3RhdGVgLmByZWdpb25faWRgID0gYG9yZGVyX2FkZHJlc3NgLmByZWdpb25faWRgKSAgICAgICAgICAgICAgV0hFUkUgREFURV9GT1JNQVQoREFURV9TVUIoIicuJGRhdGVSZWZlcmVuY2UuJyIsSU5URVJWQUwgJy4oaW50KSRkdXJhdGlvbi4nIERBWSksIiVZLSVtLSVkICVIOiVpOiVzIikgPD0gREFURV9GT1JNQVQoYG9yZGVyX3ByaW1hcnlgLmBjcmVhdGVkX2F0YCwiJVktJW0tJWQgJUg6JWk6JXMiKSAgICAgICAgICAgICAgQU5EICcuJHRpbWV6b25lc1doZXJlLicgICAgICAgICAgICAgIEFORCBgb3JkZXJfcHJpbWFyeWAuYGJhc2VfdG90YWxfaW52b2ljZWRgIElTIE5PVCBOVUxMICAgICAgICAgICAgICBBTkQgYG9yZGVyX2xhc3RgLmBlbnRpdHlfaWRgIElTIE5VTEwgICAgICAgICAgICAgIEdST1VQIEJZIGBvcmRlcl9wcmltYXJ5YC5gY3VzdG9tZXJfZW1haWxgICAgICAgICBIQVZJTkcgYFRvdGFsYCA+PSAnLihpbnQpJG5iT3JkZXIuJyAgICAgICAgJy4oJG5iT3JkZXJNYXggPyAnIEFORCBgVG90YWxgIDw9ICcuKGludCkkbmJPcmRlck1heCA6ICcnKTsgICAgICAgICAgJHJlc3VsdHMgPSAkcmVhZENvbm5lY3Rpb24tPmZldGNoQWxsKCRxdWVyeSk7ICAgICAgICAgICAgICBpZigkcmVzdWx0cyAmJiBpc19hcnJheSgkcmVzdWx0cykgJiYgc2l6ZW9mKCRyZXN1bHRzKSkgeyAgICAgICAgICAgICAgZm9yZWFjaCgkcmVzdWx0cyBhcyAkcm93KSB7ICAgICAgICAgICAgICAgICAgJHJldHVybltdID0gYXJyYXkoICAgICAgICAgICAgICAgICAgICAgICAgICAnY3VzdG9tZXInICA9PiBzZWxmOjpnZXRVc2VyKCgkcm93WydjdXN0b21lcl9pZCddPyRyb3dbJ2N1c3RvbWVyX2lkJ106JHJvd1snY3VzdG9tZXJfZW1haWwnXSkpICAgICAgICAgICAgICAgICAgKTsgICAgICAgICAgICAgIH0gICAgICAgICAgfSAgICAgICAgICByZXR1cm4gKCRqdXN0Q291bnQgPyBhcnJheSgnY291bnQnPT5zaXplb2YoJHJldHVybikpIDogJHJldHVybik7ICAgICAgfSAgICAgICAgICAgICAgcHVibGljIHN0YXRpYyBmdW5jdGlvbiBnZXRNaXNzaW5nQ2xpZW50cygkZGF0ZVJlZmVyZW5jZSwgJHRpbWV6b25lcywgJG5iRGF5cyA9IDAsICRyZWxhdW5jaE9sZGVyID0gZmFsc2UsJGp1c3RDb3VudCA9IGZhbHNlKSB7ICAgICAgICAgIGlmKGNsYXNzX2V4aXN0cygnU2hvcHltaW5kQ2xpZW50X0NhbGxiYWNrT3ZlcnJpZGUnLCBmYWxzZSkgJiYgbWV0aG9kX2V4aXN0cygnU2hvcHltaW5kQ2xpZW50X0NhbGxiYWNrT3ZlcnJpZGUnLF9fRlVOQ1RJT05fXykpIHJldHVybiBjYWxsX3VzZXJfZnVuY19hcnJheShhcnJheSgnU2hvcHltaW5kQ2xpZW50X0NhbGxiYWNrT3ZlcnJpZGUnLCBfX0ZVTkNUSU9OX18pLCBmdW5jX2dldF9hcmdzKCkpOyAgICAgICAkcmV0dXJuID0gYXJyYXkoKTsgICAgICAgICAgICAkdGltZXpvbmVzV2hlcmUgPSBzZWxmOjpnZW5lcmF0ZVRpbWV6b25lc1doZXJlKCR0aW1lem9uZXMpOyAgICAgICAgICBpZighJHRpbWV6b25lc1doZXJlKSByZXR1cm4gZmFsc2U7ICAgICAgICAgICAgJHRhYmxlUHJlZml4ID0gTWFnZTo6Z2V0Q29uZmlnKCktPmdldFRhYmxlUHJlZml4KCk7ICAgICAgICAgICRkYXRlID0gZGF0ZSgnWS1tLWQgMDA6MDA6MDAnKTsgICAgICAgICAgJHJlc291cmNlID0gTWFnZTo6Z2V0U2luZ2xldG9uKCdjb3JlL3Jlc291cmNlJyk7ICAgICAgICAgICRyZWFkQ29ubmVjdGlvbiA9ICRyZXNvdXJjZS0+Z2V0Q29ubmVjdGlvbignY29yZV9yZWFkJyk7ICAgICAgICAgICRxdWVyeSA9ICdTRUxFQ1QgYGN1c3RvbWVyX3ByaW1hcnlfdGFibGVgLmBlbnRpdHlfaWRgICAgICAgICAgICBGUk9NIGAnLiR0YWJsZVByZWZpeC4nY3VzdG9tZXJfZW50aXR5YCBBUyBgY3VzdG9tZXJfcHJpbWFyeV90YWJsZWAgICAgICAgICAgIExFRlQgSk9JTiBgJy4kdGFibGVQcmVmaXguJ3NhbGVzX2ZsYXRfb3JkZXJgIEFTIGBjdXN0b21lcl9vcmRlcmAgT04oYGN1c3RvbWVyX3ByaW1hcnlfdGFibGVgLmBlbnRpdHlfaWRgID0gYGN1c3RvbWVyX29yZGVyYC5gY3VzdG9tZXJfaWRgKSAgICAgICAgICAgTEVGVCBKT0lOIGAnLiR0YWJsZVByZWZpeC4nY3VzdG9tZXJfZW50aXR5X2ludGAgQVMgYGN1c3RvbWVyX2RlZmF1bHRfYmlsbGluZ19qdGAgT04gKGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfanRgLmBlbnRpdHlfaWRgID0gYGN1c3RvbWVyX29yZGVyYC5gY3VzdG9tZXJfaWRgKSBBTkQgKGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfanRgLmBhdHRyaWJ1dGVfaWRgID0gJy5zZWxmOjpnZXRNYWdlbnRvQXR0cmlidXRlQ29kZSgnY3VzdG9tZXInLCdkZWZhdWx0X3NoaXBwaW5nJykuJykgICAgICAgICAgIExFRlQgSk9JTiBgJy4kdGFibGVQcmVmaXguJ2N1c3RvbWVyX2FkZHJlc3NfZW50aXR5X3ZhcmNoYXJgIEFTIGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfY291bnRyeWAgT04gKGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfanRgLmB2YWx1ZWAgPSBgY3VzdG9tZXJfZGVmYXVsdF9iaWxsaW5nX2NvdW50cnlgLmBlbnRpdHlfaWRgKSBBTkQgKGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfY291bnRyeWAuYGF0dHJpYnV0ZV9pZGAgPSAnLnNlbGY6OmdldE1hZ2VudG9BdHRyaWJ1dGVDb2RlKCdjdXN0b21lcl9hZGRyZXNzJywnY291bnRyeV9pZCcpLicpICAgICAgICAgICBMRUZUIEpPSU4gYCcuJHRhYmxlUHJlZml4LidjdXN0b21lcl9hZGRyZXNzX2VudGl0eV9pbnRgIEFTIGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfc3RhdGVfanRgIE9OIChgY3VzdG9tZXJfZGVmYXVsdF9iaWxsaW5nX2NvdW50cnlgLmBlbnRpdHlfaWRgID0gYGN1c3RvbWVyX2RlZmF1bHRfYmlsbGluZ19zdGF0ZV9qdGAuYGVudGl0eV9pZGApIEFORCAoYGN1c3RvbWVyX2RlZmF1bHRfYmlsbGluZ19zdGF0ZV9qdGAuYGF0dHJpYnV0ZV9pZGAgPSAnLnNlbGY6OmdldE1hZ2VudG9BdHRyaWJ1dGVDb2RlKCdjdXN0b21lcl9hZGRyZXNzJywncmVnaW9uX2lkJykuJyBPUiBgY3VzdG9tZXJfZGVmYXVsdF9iaWxsaW5nX3N0YXRlX2p0YC5gYXR0cmlidXRlX2lkYCBJUyBOVUxMKSAgICAgICAgICAgTEVGVCBKT0lOIGAnLiR0YWJsZVByZWZpeC4nZGlyZWN0b3J5X2NvdW50cnlfcmVnaW9uYCBBUyBgY3VzdG9tZXJfZGVmYXVsdF9iaWxsaW5nX3N0YXRlYCBPTihgY3VzdG9tZXJfZGVmYXVsdF9iaWxsaW5nX3N0YXRlYC5gcmVnaW9uX2lkYCA9IGBjdXN0b21lcl9kZWZhdWx0X2JpbGxpbmdfc3RhdGVfanRgLmB2YWx1ZWApICAgICAgICAgIFdIRVJFIGBjdXN0b21lcl9vcmRlcmAuYGVudGl0eV9pZGAgSVMgTlVMTCAgICAgICAgICBBTkQgREFURV9GT1JNQVQoYGN1c3RvbWVyX3ByaW1hcnlfdGFibGVgLmBjcmVhdGVkX2F0YCwiJVktJW0tJWQiKSA9IERBVEVfRk9STUFUKERBVEVfU1VCKCInLiRkYXRlUmVmZXJlbmNlLiciLCBJTlRFUlZBTCAnLihpbnQpKCRuYkRheXMpLicgREFZKSwiJVktJW0tJWQiKSAgICAgICAgICBBTkQgJy4kdGltZXpvbmVzV2hlcmUuJyAgICAgICAgICAgQU5EIGBjdXN0b21lcl9wcmltYXJ5X3RhYmxlYC5gaXNfYWN0aXZlYCA9IDEgICAgICAgICAgR1JPVVAgQlkgYGN1c3RvbWVyX29yZGVyYC5gY3VzdG9tZXJfaWRgJzsgICAgICAgICAgJHJlc3VsdHMgPSAkcmVhZENvbm5lY3Rpb24tPmZldGNoQWxsKCRxdWVyeSk7ICAgICAgICAgICAgaWYoJHJlc3VsdHMgJiYgaXNfYXJyYXkoJHJlc3VsdHMpICYmIHNpemVvZigkcmVzdWx0cykpIHsgICAgICAgICAgICAgIGZvcmVhY2goJHJlc3VsdHMgYXMgJHJvdykgeyAgICAgICAgICAgICAgIGlmKCEkcm93WydlbnRpdHlfaWQnXSkgY29udGludWU7ICAgICAgICAgICAgICAgICAgJHJldHVybltdID0gYXJyYXkoICAgICAgICAgICAgICAgICAgICAgICAgICAnY3VzdG9tZXInICA9PiBzZWxmOjpnZXRVc2VyKCRyb3dbJ2VudGl0eV9pZCddKSAgICAgICAgICAgICAgICAgICk7ICAgICAgICAgICAgICB9ICAgICAgICAgIH0gICAgICAgICAgICByZXR1cm4gKCRqdXN0Q291bnQgPyBhcnJheSgnY291bnQnPT5zaXplb2YoJHJldHVybikpIDogJHJldHVybik7ICAgICAgfSAgICAgICAgICAgICAgcHVibGljIHN0YXRpYyBmdW5jdGlvbiBnZXRPcmRlcnNCeVN0YXR1cygkZGF0ZVJlZmVyZW5jZSwgJHRpbWV6b25lcywgJG5iRGF5cywgJGlkU3RhdHVzLCRqdXN0Q291bnQgPSBmYWxzZSkgeyAgICAgICAgICBpZihjbGFzc19leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgZmFsc2UpICYmIG1ldGhvZF9leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJyxfX0ZVTkNUSU9OX18pKSByZXR1cm4gY2FsbF91c2VyX2Z1bmNfYXJyYXkoYXJyYXkoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgX19GVU5DVElPTl9fKSwgZnVuY19nZXRfYXJncygpKTsgICAgICAgJHJldHVybiA9IGFycmF5KCk7ICAgICAgICAgICR0YWJsZVByZWZpeCA9IE1hZ2U6OmdldENvbmZpZygpLT5nZXRUYWJsZVByZWZpeCgpOyAgICAgICAgICAkcmVzb3VyY2UgPSBNYWdlOjpnZXRTaW5nbGV0b24oJ2NvcmUvcmVzb3VyY2UnKTsgICAgICAgICAgJHJlYWRDb25uZWN0aW9uID0gJHJlc291cmNlLT5nZXRDb25uZWN0aW9uKCdjb3JlX3JlYWQnKTsgICAgICAgICAgICAkdGltZXpvbmVzV2hlcmUgPSBzZWxmOjpnZW5lcmF0ZVRpbWV6b25lc1doZXJlKCR0aW1lem9uZXMsJ29yZGVyX2FkZHJlc3MnLCdjb3VudHJ5X2lkJyk7ICAgICAgICAgIGlmKCEkdGltZXpvbmVzV2hlcmUpIHJldHVybiBmYWxzZTsgICAgICAgICAgJHF1ZXJ5ID0gJ1NFTEVDVCBgb3JkZXJfcHJpbWFyeWAuYHN0b3JlX2lkYCwgYG9yZGVyX3ByaW1hcnlgLmBlbnRpdHlfaWRgLCBgb3JkZXJfcHJpbWFyeWAuYG9yZGVyX2N1cnJlbmN5X2NvZGVgLCBgb3JkZXJfcHJpbWFyeWAuYGJhc2VfZ3JhbmRfdG90YWxgLCBgb3JkZXJfcHJpbWFyeWAuYGN1c3RvbWVyX2lkYCwgYG9yZGVyX3ByaW1hcnlgLmBjdXN0b21lcl9lbWFpbGAgICAgICAgICAgICAgIEZST00gYCcuJHRhYmxlUHJlZml4LidzYWxlc19mbGF0X29yZGVyYCBBUyBgb3JkZXJfcHJpbWFyeWAgICAgICAgICAgICAgIExFRlQgSk9JTiBgJy4kdGFibGVQcmVmaXguJ3NhbGVzX2ZsYXRfb3JkZXJgIEFTIGBvcmRlcl9sYXN0YCBPTiAoKChgb3JkZXJfbGFzdGAuYGN1c3RvbWVyX2lkYCBJUyBOT1QgTlVMTCBBTkQgYG9yZGVyX2xhc3RgLmBjdXN0b21lcl9pZGAgPSBgb3JkZXJfcHJpbWFyeWAuYGN1c3RvbWVyX2lkYCkgT1IgKChgb3JkZXJfbGFzdGAuYGN1c3RvbWVyX2lkYCBJUyBOVUxMIE9SIGBvcmRlcl9sYXN0YC5gY3VzdG9tZXJfaWRgID0gMCkgQU5EIGBvcmRlcl9sYXN0YC5gY3VzdG9tZXJfZW1haWxgID0gYG9yZGVyX3ByaW1hcnlgLmBjdXN0b21lcl9lbWFpbGApKSBBTkQgYG9yZGVyX2xhc3RgLmBjcmVhdGVkX2F0YCA+IGBvcmRlcl9wcmltYXJ5YC5gY3JlYXRlZF9hdGApICAgICAgICAgICAgICBMRUZUIEpPSU4gYCcuJHRhYmxlUHJlZml4LidzYWxlc19mbGF0X29yZGVyX3N0YXR1c19oaXN0b3J5YCBBUyBgb3JkZXJfc3RhdHVzYCBPTiAoYG9yZGVyX3N0YXR1c2AuYHN0YXR1c2AgPSBgb3JkZXJfcHJpbWFyeWAuYHN0YXR1c2AgQU5EIGBvcmRlcl9zdGF0dXNgLmBwYXJlbnRfaWRgID0gYG9yZGVyX3ByaW1hcnlgLmBlbnRpdHlfaWRgKSAgICAgICAgICAgICAgTEVGVCBKT0lOIGAnLiR0YWJsZVByZWZpeC4nc2FsZXNfZmxhdF9vcmRlcl9hZGRyZXNzYCBBUyBgb3JkZXJfYWRkcmVzc2AgT04oYG9yZGVyX2FkZHJlc3NgLmBwYXJlbnRfaWRgID0gYG9yZGVyX3ByaW1hcnlgLmBlbnRpdHlfaWRgKSBBTkQgKGBvcmRlcl9hZGRyZXNzYC5gYWRkcmVzc190eXBlYCA9ICJiaWxsaW5nIikgICAgICAgICAgICAgIExFRlQgSk9JTiBgJy4kdGFibGVQcmVmaXguJ2RpcmVjdG9yeV9jb3VudHJ5X3JlZ2lvbmAgQVMgYGN1c3RvbWVyX2RlZmF1bHRfYmlsbGluZ19zdGF0ZWAgT04oYGN1c3RvbWVyX2RlZmF1bHRfYmlsbGluZ19zdGF0ZWAuYHJlZ2lvbl9pZGAgPSBgb3JkZXJfYWRkcmVzc2AuYHJlZ2lvbl9pZGApICAgICAgICAgICAgICBXSEVSRSBgb3JkZXJfcHJpbWFyeWAuc3RhdHVzID0gIicuJGlkU3RhdHVzLiciIEFORCBEQVRFX0ZPUk1BVChgb3JkZXJfcHJpbWFyeWAuYGNyZWF0ZWRfYXRgLCIlWS0lbS0lZCIpID49IERBVEVfRk9STUFUKERBVEVfU1VCKCInLiRkYXRlUmVmZXJlbmNlLiciLCBJTlRFUlZBTCAnLigkbmJEYXlzKzE0KS4nIERBWSksIiVZLSVtLSVkIikgICAgICAgICAgICAgIEFORCBEQVRFX0ZPUk1BVChgb3JkZXJfc3RhdHVzYC5gY3JlYXRlZF9hdGAsIiVZLSVtLSVkIikgPSBEQVRFX0ZPUk1BVChEQVRFX1NVQigiJy4kZGF0ZVJlZmVyZW5jZS4nIiwgSU5URVJWQUwgJy4oJG5iRGF5cykuJyBEQVkpLCIlWS0lbS0lZCIpICAgICAgICAgICAgICBBTkQgJy4kdGltZXpvbmVzV2hlcmUuJyAgICAgICAgICAgICAgQU5EIGBvcmRlcl9sYXN0YC5gZW50aXR5X2lkYCBJUyBOVUxMICAgICAgICAgICAgICBHUk9VUCBCWSBgb3JkZXJfcHJpbWFyeWAuYGN1c3RvbWVyX2VtYWlsYCc7ICAgICAgICAgICRyZXN1bHRzID0gJHJlYWRDb25uZWN0aW9uLT5mZXRjaEFsbCgkcXVlcnkpOyAgICAgICAgICAgIGlmKCRyZXN1bHRzICYmIGlzX2FycmF5KCRyZXN1bHRzKSAmJiBzaXplb2YoJHJlc3VsdHMpKSB7ICAgICAgICAgICAgICBmb3JlYWNoKCRyZXN1bHRzIGFzICRyb3cpIHsgICAgICAgICAgICAgICBzZWxmOjpzdGFydExhbmdFbXVsYXRpb25CeVN0b3JlSWQoJHJvd1snc3RvcmVfaWQnXSk7ICAgICAgICAgICAgICAgICAgJHJlc3VsdFByb2R1Y3RzID0gTWFnZTo6Z2V0TW9kZWwoInNhbGVzL29yZGVyX2l0ZW0iKSAgICAgICAgICAgICAgICAgIC0+Z2V0Q29sbGVjdGlvbigpICAgICAgICAgICAgICAgICAgLT5hZGRGaWVsZFRvRmlsdGVyKCJvcmRlcl9pZCIsICRyb3dbJ2VudGl0eV9pZCddKSAgICAgICAgICAgICAgICAgIC0+YWRkRmllbGRUb0ZpbHRlcigicGFyZW50X2l0ZW1faWQiLCBhcnJheSgnbnVsbCcgPT4gdHJ1ZSkpICAgICAgICAgICAgICAgICAgLT5nZXREYXRhKCk7ICAgICAgICAgICAgICAgICAgaWYoJHJlc3VsdFByb2R1Y3RzICYmIGlzX2FycmF5KCRyZXN1bHRQcm9kdWN0cykgJiYgc2l6ZW9mKCRyZXN1bHRQcm9kdWN0cykpIHsgICAgICAgICAgICAgICAgICAgICAgJHJldHVyblByb2R1Y3RzID0gYXJyYXkoKTsgICAgICAgICAgICAgICAgICAgICAgZm9yZWFjaCgkcmVzdWx0UHJvZHVjdHMgYXMgJHJvdzIpIHsgICAgICAgICAgICAgICAgICAgICAgICAgICRwcm9kdWN0ID0gTWFnZTo6Z2V0TW9kZWwoJ2NhdGFsb2cvcHJvZHVjdCcpLT5sb2FkKCRyb3cyWydwcm9kdWN0X2lkJ10pOyAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHsgICAgICAgICAgICAkaW1hZ2VfdXJsID0gc3RyX3JlcGxhY2UoYmFzZW5hbWUoJF9TRVJWRVJbJ1NDUklQVF9OQU1FJ10pLicvJywnJywkcHJvZHVjdC0+Z2V0U21hbGxJbWFnZVVybCgyMDAsMjAwKSk7ICAgICAgICB9IGNhdGNoIChFeGNlcHRpb24gJGUpIHsgICAgICAgICAgICAkaW1hZ2VfdXJsID0gJyc7ICAgICAgICB9ICAgICAgICAgICAgICAgICAgICAgICAgICAkcHJvZHVjdF91cmwgPSBzdHJfcmVwbGFjZShiYXNlbmFtZSgkX1NFUlZFUlsnU0NSSVBUX05BTUUnXSkuJy8nLCcnLCRwcm9kdWN0LT5nZXRQcm9kdWN0VXJsKGZhbHNlKSk7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICRyZXR1cm5Qcm9kdWN0c1tdID0gYXJyYXkoICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdkZXNjcmlwdGlvbicgPT4gJHJvdzJbJ25hbWUnXSwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3F0eScgPT4gJHJvdzJbJ3F0eV9pbnZvaWNlZCddLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAncHJpY2UnID0+ICRyb3cyWydwcmljZV9pbmNsX3RheCddLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnaW1hZ2VfdXJsJyA9PiAkaW1hZ2VfdXJsLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAncHJvZHVjdF91cmwnID0+ICRwcm9kdWN0X3VybCAgICAgICAgICAgICAgICAgICAgICAgICAgKTsgICAgICAgICAgICAgICAgICAgICAgfSAgICAgICAgICAgICAgICAgIH0gICAgICAgICAgICAgICAgICBpZihzaXplb2YoJHJldHVyblByb2R1Y3RzKSkgICAgICAgICAgICAgICAgICAgICAgJHJldHVybltdID0gYXJyYXkoICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2N1cnJlbmN5JyAgICAgICA9PiAkcm93WydvcmRlcl9jdXJyZW5jeV9jb2RlJ10sICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3RvdGFsX2Ftb3VudCcgICA9PiAkcm93WydiYXNlX2dyYW5kX3RvdGFsJ10sICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2FydGljbGVzJyAgICAgICA9PiAkcmV0dXJuUHJvZHVjdHMsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2lkX29yZGVyJyAgID0+ICRyb3dbJ2VudGl0eV9pZCddLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjdXN0b21lcicgID0+IHNlbGY6OmdldFVzZXIoKCRyb3dbJ2N1c3RvbWVyX2lkJ10/JHJvd1snY3VzdG9tZXJfaWQnXTokcm93WydjdXN0b21lcl9lbWFpbCddKSkgICAgICAgICAgICAgICAgICAgICAgKTsgICAgICAgICAgICAgICAgICAgc2VsZjo6c3RvcExhbmdFbXVsYXRpb24oKTsgICAgICAgICAgICAgIH0gICAgICAgICAgfSAgICAgICAgICByZXR1cm4gKCRqdXN0Q291bnQgPyBhcnJheSgnY291bnQnPT5zaXplb2YoJHJldHVybikpIDogJHJldHVybik7ICAgICAgfSAgIHB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gZ2VuZXJhdGVWb3VjaGVycygkdm91Y2hlckluZm9zLCRlbWFpbHMpIHsgICAgICAgICAgaWYoY2xhc3NfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIGZhbHNlKSAmJiBtZXRob2RfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsX19GVU5DVElPTl9fKSkgcmV0dXJuIGNhbGxfdXNlcl9mdW5jX2FycmF5KGFycmF5KCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIF9fRlVOQ1RJT05fXyksIGZ1bmNfZ2V0X2FyZ3MoKSk7ICAgICR2b3VjaGVycyA9IGFycmF5KCk7ICAgICAgICAgIGlmKCR2b3VjaGVySW5mb3MgJiYgaXNfYXJyYXkoJHZvdWNoZXJJbmZvcykgJiYgJGVtYWlscyAmJiBpc19hcnJheSgkZW1haWxzKSAmJiBzaXplb2YoJGVtYWlscykpIHsgICAgICAgICAgICAgIGZvcmVhY2ggKCRlbWFpbHMgYXMgJGVtYWlsKSB7ICAgICAgICAgICAgICAgICAgJHZvdWNoZXIgPSBzZWxmOjpnZW5lcmF0ZVZvdWNoZXIoJGVtYWlsLCAkdm91Y2hlckluZm9zWyd0eXBlJ10sICgkdm91Y2hlckluZm9zWyd0eXBlJ10gPT0gJ3NoaXBwaW5nJyA/IGZhbHNlIDogJHZvdWNoZXJJbmZvc1snYW1vdW50J10pLCAoJHZvdWNoZXJJbmZvc1sndHlwZSddID09ICdhbW91bnQnID8gJHZvdWNoZXJJbmZvc1snYW1vdW50Q3VycmVuY3knXSA6IGZhbHNlKSwgJHZvdWNoZXJJbmZvc1snbWluaW11bU9yZGVyJ10sICR2b3VjaGVySW5mb3NbJ25iRGF5VmFsaWRhdGUnXSwgJycpOyAgICAgICAgICAgICAgICAgIGlmKCEkdm91Y2hlcikgY29udGludWU7ICAgICAgICAgICAgICAgICAgJHZvdWNoZXJzWyRlbWFpbF0gPSAkdm91Y2hlcjsgICAgICAgICAgICAgIH0gICAgICAgICAgfSAgICAgICAgICByZXR1cm4gJHZvdWNoZXJzOyAgICAgIH0gICAgICAgIHB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gZ2VuZXJhdGVLZXlzQWNjZXNzKCRrZXlzQWNjZXNzKSB7ICAgICAgICAgIGlmKGNsYXNzX2V4aXN0cygnU2hvcHltaW5kQ2xpZW50X0NhbGxiYWNrT3ZlcnJpZGUnLCBmYWxzZSkgJiYgbWV0aG9kX2V4aXN0cygnU2hvcHltaW5kQ2xpZW50X0NhbGxiYWNrT3ZlcnJpZGUnLF9fRlVOQ1RJT05fXykpIHJldHVybiBjYWxsX3VzZXJfZnVuY19hcnJheShhcnJheSgnU2hvcHltaW5kQ2xpZW50X0NhbGxiYWNrT3ZlcnJpZGUnLCBfX0ZVTkNUSU9OX18pLCBmdW5jX2dldF9hcmdzKCkpOyAgICAgICBpZigka2V5c0FjY2VzcyAmJiBpc19hcnJheSgka2V5c0FjY2VzcykgJiYgc2l6ZW9mKCRrZXlzQWNjZXNzKSkgeyAgICAgICAgICAgICAgZm9yZWFjaCAoJGtleXNBY2Nlc3MgYXMgJGtleUFjY2Vzc0luZm8pIHsgICAgICAgICAgICAgICAgICAka2V5QWNjZXNzID0gJGtleUFjY2Vzc0luZm9bJ2tleSddOyAgICAgICAgICAgICAgICAgICRpZF9jdXN0b21lciA9IChpbnQpJGtleUFjY2Vzc0luZm9bJ2lkX2N1c3RvbWVyJ107ICAgICAgICAgICAgICAgICAgJGlkX2NhcnQgPSAoaW50KSRrZXlBY2Nlc3NJbmZvWydpZF9jYXJ0J107ICAgICAgICAgICAgICAgICAgJGlkX29yZGVyID0gJGtleUFjY2Vzc0luZm9bJ2lkX29yZGVyJ107ICAgICAgICAgICAgICAgICAgJGVtYWlsID0gJGtleUFjY2Vzc0luZm9bJ2VtYWlsJ107ICAgICAgICAgICAgICAgICAgJHZvdWNoZXJfbnVtYmVyID0gJGtleUFjY2Vzc0luZm9bJ3ZvdWNoZXJfbnVtYmVyJ107ICAgICAgICAgICAgICAgICAgJHRhYmxlUHJlZml4ID0gTWFnZTo6Z2V0Q29uZmlnKCktPmdldFRhYmxlUHJlZml4KCk7ICAgICAgICAgICAgICAgICAgJHdyaXRlID0gTWFnZTo6Z2V0U2luZ2xldG9uKCdjb3JlL3Jlc291cmNlJyktPmdldENvbm5lY3Rpb24oJ2NvcmVfd3JpdGUnKTsgICAgICAgICAgICAgICAgICAkbm93ID0gZGF0ZSgnWS1tLWQgSDppOnMnKTsgICAgICAgICAgICAgICAgICAkd3JpdGUtPnF1ZXJ5KCdJTlNFUlQgSUdOT1JFIElOVE8gYCcuJHRhYmxlUHJlZml4LidzcG1jYXJ0b29yZGVyYCAoYHNwbV9rZXlgJy4oJGlkX2N1c3RvbWVyID8gJyxgaWRfY3VzdG9tZXJgJzonJykuKCR2b3VjaGVyX251bWJlciA/ICcsYHZvdWNoZXJfbnVtYmVyYCc6JycpLigkaWRfY2FydCA/ICcsYGlkX2NhcnRgJzonJykuKCRlbWFpbCA/ICcsYGVtYWlsYCc6JycpLigkaWRfb3JkZXIgPyAnLGBpZF9vcmRlcmAnOicnKS4nLGBkYXRlX2FkZGAsYGRhdGVfdXBkYCkgdmFsdWVzICgiJy4ka2V5QWNjZXNzLiciJy4oJGlkX2N1c3RvbWVyID8gJywnLiRpZF9jdXN0b21lcjonJykuKCR2b3VjaGVyX251bWJlciA/ICcsIicuJHZvdWNoZXJfbnVtYmVyLiciJzonJykuKCRpZF9jYXJ0ID8gJywnLiRpZF9jYXJ0OicnKS4oJGVtYWlsID8gJywiJy4kZW1haWwuJyInOicnKS4oJGlkX29yZGVyID8gJywnLiRpZF9vcmRlcjonJykuJywiJy4kbm93LiciLCInLiRub3cuJyIpJyk7ICAgICAgICAgICAgICB9ICAgICAgICAgIH0gICAgICAgICAgcmV0dXJuIHRydWU7ICAgICAgfSAgICAgICAgIHB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gZ2VuZXJhdGVWb3VjaGVyKCRpZF9jdXN0b21lciwgJHR5cGUsICRhbW91bnQgPSBmYWxzZSwgJGFtb3VudEN1cnJlbmN5ID0gZmFsc2UsICRtaW5pbXVtT3JkZXIgPSBmYWxzZSwgJG5iRGF5VmFsaWRhdGUsICRkZXNjcmlwdGlvbikgeyAgICBpZihjbGFzc19leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgZmFsc2UpICYmIG1ldGhvZF9leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJyxfX0ZVTkNUSU9OX18pKSByZXR1cm4gY2FsbF91c2VyX2Z1bmNfYXJyYXkoYXJyYXkoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgX19GVU5DVElPTl9fKSwgZnVuY19nZXRfYXJncygpKTsgICAgICAgICRjb3Vwb25fY29kZSA9ICdTUE0tJy5zdHJ0b3VwcGVyKHVuaXFpZCgpKTsgICAgICAgICAgJGRhdGUgPSBkYXRlKCdZLW0tZCBIOmk6cycpOyAgICAgICAgICAkY291cG9uID0gTWFnZTo6Z2V0TW9kZWwoJ3NhbGVzcnVsZS9ydWxlJyk7ICAgICAgICAgICRjb3Vwb24tPnNldE5hbWUoJGNvdXBvbl9jb2RlKSAgICAgICAgICAtPnNldEZyb21EYXRlKCRkYXRlKSAgICAgICAgICAtPnNldFRvRGF0ZSgoZGF0ZSgnWS1tLWQgMjM6NTk6NTknLG1rdGltZShkYXRlKCJIIiksIGRhdGUoImkiKSwgZGF0ZSgicyIpLCBkYXRlKCJtIikgICwgZGF0ZSgiZCIpKyRuYkRheVZhbGlkYXRlLCBkYXRlKCJZIikpKSkpICAgICAgICAgIC0+c2V0VXNlc1BlckN1c3RvbWVyKCcxJykgICAgICAgICAgLT5zZXRJc0FjdGl2ZSgnMScpICAgICAgICAgIC0+c2V0U3RvcFJ1bGVzUHJvY2Vzc2luZygnMCcpICAgICAgICAgIC0+c2V0SXNBZHZhbmNlZCgnMScpICAgICAgICAgIC0+c2V0UHJvZHVjdElkcyhOVUxMKSAgICAgICAgICAtPnNldFNvcnRPcmRlcignMCcpOyAgICAgICAgICBpZigkdHlwZSA9PSAncGVyY2VudCcpIHsgICAgICAgICAgICAgICRjb3Vwb24tPnNldFNpbXBsZUFjdGlvbignYnlfcGVyY2VudCcpICAgICAgICAgICAgICAtPnNldERpc2NvdW50QW1vdW50KCRhbW91bnQpICAgICAgICAgICAgICAtPnNldERpc2NvdW50UXR5KE5VTEwpICAgICAgICAgICAgICAtPnNldFNpbXBsZUZyZWVTaGlwcGluZygnMCcpOyAgICAgICAgICB9aWYoJHR5cGUgPT0gJ2Ftb3VudCcpIHsgICAgICAgICAgICAgICRjb3Vwb24tPnNldFNpbXBsZUFjdGlvbignY2FydF9maXhlZCcpICAgICAgICAgICAgICAtPnNldERpc2NvdW50QW1vdW50KCRhbW91bnQpICAgICAgICAgICAgICAtPnNldERpc2NvdW50UXR5KE5VTEwpICAgICAgICAgICAgICAtPnNldFNpbXBsZUZyZWVTaGlwcGluZygnMCcpOyAgICAgICAgICB9ZWxzZWlmKCR0eXBlID09ICdzaGlwcGluZycpIHsgICAgICAgICAgICAgICRjb3Vwb24tPnNldFNpbXBsZUZyZWVTaGlwcGluZygxKTsgICAgICAgICAgfSAgICAgICAgICAkY291cG9uLT5zZXREaXNjb3VudFN0ZXAoJzAnKSAgICAgICAgICAtPnNldEFwcGx5VG9TaGlwcGluZygnMCcpICAgICAgICAgIC0+c2V0VGltZXNVc2VkKCcwJykgICAgICAgICAgLT5zZXRJc1JzcygnMCcpICAgICAgICAgIC0+c2V0Q291cG9uVHlwZSgnMicpICAgICAgICAgIC0+c2V0VXNlc1BlckNvdXBvbigxKSAgICAgICAgICAtPnNldEN1c3RvbWVyR3JvdXBJZHMoc2VsZjo6Z2V0QWxsQ3VzdG9tZXJHcm91cHNJZHMoKSkgICAgICAgICAgLT5zZXRXZWJzaXRlSWRzKGFycmF5KCcxJykpICAgICAgICAgIC0+c2V0Q291cG9uQ29kZSgkY291cG9uX2NvZGUpOyAgICAgICAgICBpZigkbWluaW11bU9yZGVyKSB7ICAgICAgICAgICAgICAkY29uZGl0aW9uID0gTWFnZTo6Z2V0TW9kZWwoJ3NhbGVzcnVsZS9ydWxlX2NvbmRpdGlvbl9hZGRyZXNzJykgICAgICAgICAgICAgICAgICAgICAgICAgIC0+c2V0VHlwZSgnc2FsZXNydWxlL3J1bGVfY29uZGl0aW9uX2FkZHJlc3MnKSAgICAgICAgICAgICAgICAgICAgICAgICAgLT5zZXRBdHRyaWJ1dGUoJ2Jhc2Vfc3VidG90YWwnKSAgICAgICAgICAgICAgICAgICAgICAgICAgLT5zZXRPcGVyYXRvcignPj0nKSAgICAgICAgICAgICAgICAgICAgICAgICAgLT5zZXRWYWx1ZSgoaW50KSRtaW5pbXVtT3JkZXIpOyAgICAgICAgICAgICAgJGNvdXBvbi0+Z2V0Q29uZGl0aW9ucygpLT5hZGRDb25kaXRpb24oJGNvbmRpdGlvbik7ICAgICAgICAgIH0gICAgICAgICAgaWYoJGNvdXBvbi0+c2F2ZSgpKSAgICAgICAgICAgICAgcmV0dXJuICRjb3Vwb25fY29kZTsgICAgICAgICAgcmV0dXJuIGZhbHNlOyAgICAgIH0gICAgIHB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gZ2V0QWxsQ3VzdG9tZXJHcm91cHNJZHMoKXsgICAgICAgaWYoY2xhc3NfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIGZhbHNlKSAmJiBtZXRob2RfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsX19GVU5DVElPTl9fKSkgcmV0dXJuIGNhbGxfdXNlcl9mdW5jX2FycmF5KGFycmF5KCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIF9fRlVOQ1RJT05fXyksIGZ1bmNfZ2V0X2FyZ3MoKSk7ICAgICRyZXR1cm4gPSBhcnJheSgpOyAgICAgICAgICAkcmVzdWx0cyAgPSBNYWdlOjpnZXRSZXNvdXJjZU1vZGVsKCdjdXN0b21lci9ncm91cF9jb2xsZWN0aW9uJyktPnRvT3B0aW9uQXJyYXkoKTsgICAgICAgICAgaWYoJHJlc3VsdHMpIHsgICAgICAgICAgICAgIGZvcmVhY2goJHJlc3VsdHMgYXMgJHJvdyl7ICAgICAgICAgICAgICAgICAgJHJldHVybltdID0gJHJvd1sndmFsdWUnXTsgICAgICAgICAgICAgIH0gICAgICAgICAgfSAgICAgICAgICByZXR1cm4gJHJldHVybjsgICB9ICAgICAgcHVibGljIHN0YXRpYyBmdW5jdGlvbiBnZXRDdXN0b21lckdyb3VwcygpIHsgICAgICAgICAgaWYoY2xhc3NfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIGZhbHNlKSAmJiBtZXRob2RfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsX19GVU5DVElPTl9fKSkgcmV0dXJuIGNhbGxfdXNlcl9mdW5jX2FycmF5KGFycmF5KCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIF9fRlVOQ1RJT05fXyksIGZ1bmNfZ2V0X2FyZ3MoKSk7ICAgICAgICRyZXR1cm4gPSBhcnJheSgpOyAgICAgICAgICAkcmVzdWx0cyAgPSBNYWdlOjpnZXRSZXNvdXJjZU1vZGVsKCdjdXN0b21lci9ncm91cF9jb2xsZWN0aW9uJyktPnRvT3B0aW9uQXJyYXkoKTsgICAgICAgICAgaWYoJHJlc3VsdHMpIHsgICAgICAgICAgICAgIGZvcmVhY2goJHJlc3VsdHMgYXMgJHJvdyl7ICAgICAgICAgICAgICAgICAgJHJldHVyblskcm93Wyd2YWx1ZSddXSA9ICRyb3dbJ2xhYmVsJ107ICAgICAgICAgICAgICB9ICAgICAgICAgIH0gICAgICAgICAgcmV0dXJuICRyZXR1cm47ICAgICAgICB9ICAgICAgcHVibGljIHN0YXRpYyBmdW5jdGlvbiBnZXRDb3VudHJpZXMoKSB7ICAgICAgICAgIGlmKGNsYXNzX2V4aXN0cygnU2hvcHltaW5kQ2xpZW50X0NhbGxiYWNrT3ZlcnJpZGUnLCBmYWxzZSkgJiYgbWV0aG9kX2V4aXN0cygnU2hvcHltaW5kQ2xpZW50X0NhbGxiYWNrT3ZlcnJpZGUnLF9fRlVOQ1RJT05fXykpIHJldHVybiBjYWxsX3VzZXJfZnVuY19hcnJheShhcnJheSgnU2hvcHltaW5kQ2xpZW50X0NhbGxiYWNrT3ZlcnJpZGUnLCBfX0ZVTkNUSU9OX18pLCBmdW5jX2dldF9hcmdzKCkpOyAgICAgICAkcmV0dXJuID0gYXJyYXkoKTsgICAgICAgICAgJHJlc3VsdHMgPSBNYWdlOjpnZXRSZXNvdXJjZU1vZGVsKCdkaXJlY3RvcnkvY291bnRyeV9jb2xsZWN0aW9uJyktPmxvYWRCeVN0b3JlKCktPnRvT3B0aW9uQXJyYXkoKTsgICAgICAgICAgaWYoJHJlc3VsdHMpIHsgICAgICAgICAgICAgIGZvcmVhY2goJHJlc3VsdHMgYXMgJHJvdyl7ICAgICAgICAgICAgICAgICAgaWYoJHJvd1sndmFsdWUnXSkgICAgICAgICAgICAgICAgICAgICAgJHJldHVyblskcm93Wyd2YWx1ZSddXSA9ICRyb3dbJ2xhYmVsJ107ICAgICAgICAgICAgICB9ICAgICAgICAgIH0gICAgICAgICAgcmV0dXJuICRyZXR1cm47ICAgICAgfSAgICAgIHB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gc3RhcnRMYW5nRW11bGF0aW9uQnlTdG9yZUlkKCRzdG9yZV9pZCkgeyAgICAgICBpZigkc3RvcmVfaWQgPT0gTWFnZTo6YXBwKCktPmdldFN0b3JlKCktPmdldElkKCkpIHJldHVybiBmYWxzZTsgICAgJHN0b3JlQ29kZSA9IE1hZ2U6OmFwcCgpLT5nZXRTdG9yZSgkc3RvcmVfaWQpLT5nZXRDb2RlKCk7ICAgIHNlbGY6OiRhcHBFbXVsYXRpb24gPSBNYWdlOjpnZXRTaW5nbGV0b24oJ2NvcmUvYXBwX2VtdWxhdGlvbicpOyAgICAgICBzZWxmOjokaW5pdGlhbEVudmlyb25tZW50SW5mbyA9IHNlbGY6OiRhcHBFbXVsYXRpb24tPnN0YXJ0RW52aXJvbm1lbnRFbXVsYXRpb24oJHN0b3JlQ29kZSk7ICAgICAgfSAgICAgIHB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gc3RhcnRMYW5nRW11bGF0aW9uQnlJc29MYW5nKCRsYW5nKSB7ICAgICAgIGlmKHNlbGY6OiRhcHBFbXVsYXRpb24gIT09IGZhbHNlKSByZXR1cm47ICAgICAgICRzdG9yZXMgPSBNYWdlOjphcHAoKS0+Z2V0U3RvcmVzKCk7ICAgIGZvcmVhY2goJHN0b3JlcyBhcyAkc3RvcmUpIHsgICAgICRzdG9yZV9pZCA9ICRzdG9yZS0+Z2V0SWQoKTsgICAgICRsb2NhbGVfc3RvcmUgPSBNYWdlOjpnZXRTdG9yZUNvbmZpZygnZ2VuZXJhbC9sb2NhbGUvY29kZScsICRzdG9yZV9pZCk7ICAgICBpZigkbGFuZyA9PT0gc3Vic3RyKCRsb2NhbGVfc3RvcmUsMCwtMykpIHsgICAgICBzZWxmOjpzdGFydExhbmdFbXVsYXRpb25CeVN0b3JlSWQoJHN0b3JlX2lkKTsgICAgIH0gICAgfSAgICAgIH0gICAgICBwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIHN0b3BMYW5nRW11bGF0aW9uKCRsYW5nKSB7ICAgIGlmKHNlbGY6OiRhcHBFbXVsYXRpb24gPT09IGZhbHNlKSByZXR1cm47ICAgIHNlbGY6OiRhcHBFbXVsYXRpb24tPnN0b3BFbnZpcm9ubWVudEVtdWxhdGlvbihzZWxmOjokaW5pdGlhbEVudmlyb25tZW50SW5mbyk7ICAgIHNlbGY6OiRhcHBFbXVsYXRpb24gPSBmYWxzZTsgICAgc2VsZjo6JGluaXRpYWxFbnZpcm9ubWVudEluZm8gPSBmYWxzZTsgICAgICB9ICAgICAgcHVibGljIHN0YXRpYyBmdW5jdGlvbiBnZXRDdXJyZW5jaWVzKCkgeyAgICAgICAgICBpZihjbGFzc19leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgZmFsc2UpICYmIG1ldGhvZF9leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJyxfX0ZVTkNUSU9OX18pKSByZXR1cm4gY2FsbF91c2VyX2Z1bmNfYXJyYXkoYXJyYXkoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgX19GVU5DVElPTl9fKSwgZnVuY19nZXRfYXJncygpKTsgICAgICAgJHJldHVybiA9IGFycmF5KCk7ICAgICAgICAgICRyZXN1bHRzID0gTWFnZTo6YXBwKCktPmdldFN0b3JlKCktPmdldEF2YWlsYWJsZUN1cnJlbmN5Q29kZXModHJ1ZSk7ICAgICAgICAgIGlmKCRyZXN1bHRzKSB7ICAgICAgICAgICAgICBmb3JlYWNoKCRyZXN1bHRzIGFzICR2YWx1ZSl7ICAgICAgICAgICAgICAgICAgaWYoJHZhbHVlKSAgICAgICAgICAgICAgICAgICAgICAkcmV0dXJuWyR2YWx1ZV0gPSBNYWdlOjphcHAoKS0+Z2V0TG9jYWxlKCktPmdldFRyYW5zbGF0aW9uKCR2YWx1ZSwgJ25hbWV0b2N1cnJlbmN5Jyk7ICAgICAgICAgICAgICB9ICAgICAgICAgIH0gICAgICAgICAgcmV0dXJuICRyZXR1cm47ICAgICAgfSAgIHB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gZ2V0VGVzdERhdGEoJGxhbmcgPSBmYWxzZSkgeyAgICBpZihjbGFzc19leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgZmFsc2UpICYmIG1ldGhvZF9leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJyxfX0ZVTkNUSU9OX18pKSByZXR1cm4gY2FsbF91c2VyX2Z1bmNfYXJyYXkoYXJyYXkoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgX19GVU5DVElPTl9fKSwgZnVuY19nZXRfYXJncygpKTsgICAgaWYoJGxhbmcpIHNlbGY6OnN0YXJ0TGFuZ0VtdWxhdGlvbkJ5SXNvTGFuZygkbGFuZyk7ICAgICRyZXR1cm4gPSBhcnJheSgpOyAgICAgICAkcmV0dXJuWydsaW5rX2NhcnQnXSA9IHN0cl9yZXBsYWNlKGJhc2VuYW1lKCRfU0VSVkVSWydTQ1JJUFRfTkFNRSddKS4nLycsJycsTWFnZTo6Z2V0VXJsKCdjaGVja291dC9jYXJ0JyxhcnJheSgnX25vc2lkJz0+dHJ1ZSkpKTsgICAgICAgJHJldHVyblsnYXJ0aWNsZXMnXSA9IHNlbGY6OmdldFByb2R1Y3RzKCRsYW5nLGZhbHNlLHRydWUpOyAgICBpZigkbGFuZykgc2VsZjo6c3RvcExhbmdFbXVsYXRpb24oKTsgICAgcmV0dXJuICRyZXR1cm47ICAgICAgfSAgIHB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gZGVsZXRlVW51c2VkVm91Y2hlcnMoKSB7ICAgIGlmKGNsYXNzX2V4aXN0cygnU2hvcHltaW5kQ2xpZW50X0NhbGxiYWNrT3ZlcnJpZGUnLCBmYWxzZSkgJiYgbWV0aG9kX2V4aXN0cygnU2hvcHltaW5kQ2xpZW50X0NhbGxiYWNrT3ZlcnJpZGUnLF9fRlVOQ1RJT05fXykpIHJldHVybiBjYWxsX3VzZXJfZnVuY19hcnJheShhcnJheSgnU2hvcHltaW5kQ2xpZW50X0NhbGxiYWNrT3ZlcnJpZGUnLCBfX0ZVTkNUSU9OX18pLCBmdW5jX2dldF9hcmdzKCkpOyAgICAkZGF0ZSA9IGRhdGUoJ1ktbS1kIEg6aTpzJyk7ICAgICR0YWJsZVByZWZpeCA9IE1hZ2U6OmdldENvbmZpZygpLT5nZXRUYWJsZVByZWZpeCgpOyAgICAgICAgICAkcmVhZCA9IE1hZ2U6OmdldFNpbmdsZXRvbignY29yZS9yZXNvdXJjZScpLT5nZXRDb25uZWN0aW9uKCdjb3JlX3JlYWQnKTsgICAgICAgICAgJHJlc3VsdHMgPSAkcmVhZC0+ZmV0Y2hBbGwoJ1NFTEVDVCBgcnVsZV9pZGAgQVMgYGlkYCAgICAgICAgICAgICAgICAgIEZST00gYCcuJHRhYmxlUHJlZml4LidzYWxlc3J1bGVgICAgICAgICAgICAgICAgICAgV0hFUkUgYG5hbWVgIExJS0UgIlNQTS0lIiBBTkQgYHRvX2RhdGVgIDw9IERBVEVfU1VCKCInLiRkYXRlLiciLCBJTlRFUlZBTCA3IERBWSknKTsgICAgaWYoJHJlc3VsdHMgJiYgaXNfYXJyYXkoJHJlc3VsdHMpICYmIHNpemVvZigkcmVzdWx0cykpIHsgICAgICAgICAgIGZvcmVhY2goJHJlc3VsdHMgYXMgJHJvdykgeyAgICAgICAgICAgICRjYXJ0UnVsZSA9IE1hZ2U6OmdldE1vZGVsKCdzYWxlc3J1bGUvcnVsZScpLT5sb2FkKCRyb3dbJ2lkJ10pOyAgICAgICAgICAgICRjYXJ0UnVsZS0+ZGVsZXRlKCk7ICAgICAgICAgICB9ICAgIH0gICAgcmV0dXJuIHRydWU7ICAgICAgfSAgIHB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gZ2V0UHJvZHVjdHMoICRsYW5nLCAkcHJvZHVjdHMgPSBmYWxzZSwgJHJhbmRvbSA9IGZhbHNlLCAkbWF4UHJvZHVjdHMgPSAzKSB7ICAgIGlmKGNsYXNzX2V4aXN0cygnU2hvcHltaW5kQ2xpZW50X0NhbGxiYWNrT3ZlcnJpZGUnLCBmYWxzZSkgJiYgbWV0aG9kX2V4aXN0cygnU2hvcHltaW5kQ2xpZW50X0NhbGxiYWNrT3ZlcnJpZGUnLF9fRlVOQ1RJT05fXykpIHJldHVybiBjYWxsX3VzZXJfZnVuY19hcnJheShhcnJheSgnU2hvcHltaW5kQ2xpZW50X0NhbGxiYWNrT3ZlcnJpZGUnLCBfX0ZVTkNUSU9OX18pLCBmdW5jX2dldF9hcmdzKCkpOyAgICBpZigkbGFuZykgc2VsZjo6c3RhcnRMYW5nRW11bGF0aW9uQnlJc29MYW5nKCRsYW5nKTsgICAgJHJldHVybiA9IGFycmF5KCk7ICAgICAgJGNvbGxlY3Rpb24gPSBhcnJheSgpOyAgICBpZigkcHJvZHVjdHMpIHsgICAgICRjb2xsZWN0aW9uID0gTWFnZTo6Z2V0UmVzb3VyY2VNb2RlbCgnY2F0YWxvZy9wcm9kdWN0X2NvbGxlY3Rpb24nKTsgICAgIE1hZ2U6OmdldE1vZGVsKCdjYXRhbG9nL2xheWVyJyktPnByZXBhcmVQcm9kdWN0Q29sbGVjdGlvbigkY29sbGVjdGlvbik7ICAgICAkY29sbGVjdGlvbi0+YWRkQXR0cmlidXRlVG9GaWx0ZXIoJ2VudGl0eV9pZCcsIGFycmF5KCdpbicgPT4gJHByb2R1Y3RzKSktPmdldFNlbGVjdCgpOyAgICAgJGNvbGxlY3Rpb24tPmFkZFN0b3JlRmlsdGVyKCk7ICAgICAkY29sbGVjdGlvbi0+c2V0UGFnZSgxKTsgICAgfWVsc2VpZigkcmFuZG9tKSB7ICAgICAkY29sbGVjdGlvbiA9IE1hZ2U6OmdldFJlc291cmNlTW9kZWwoJ2NhdGFsb2cvcHJvZHVjdF9jb2xsZWN0aW9uJyk7ICAgICBNYWdlOjpnZXRNb2RlbCgnY2F0YWxvZy9sYXllcicpLT5wcmVwYXJlUHJvZHVjdENvbGxlY3Rpb24oJGNvbGxlY3Rpb24pOyAgICAgJGNvbGxlY3Rpb24tPmdldFNlbGVjdCgpLT5vcmRlcigncmFuZCgpJyk7ICAgICAkY29sbGVjdGlvbi0+YWRkU3RvcmVGaWx0ZXIoKTsgICAgICRjb2xsZWN0aW9uLT5zZXRQYWdlKDEsICgkbWF4UHJvZHVjdHMgPyAkbWF4UHJvZHVjdHMgOiAzKSk7ICAgICAgfSAgICBpZigkY29sbGVjdGlvbiAmJiBzaXplb2YoJGNvbGxlY3Rpb24pKSB7ICAgICAgICAgICBmb3JlYWNoKCRjb2xsZWN0aW9uIGFzICRwcm9kdWN0KSB7ICAgICAgICAgICAgICAgICAgJGltYWdlX3VybCA9IHN0cl9yZXBsYWNlKGJhc2VuYW1lKCRfU0VSVkVSWydTQ1JJUFRfTkFNRSddKS4nLycsJycsJHByb2R1Y3QtPmdldFNtYWxsSW1hZ2VVcmwoMjAwLDIwMCkpOyAgICAgICAgICAgICAgICAgICRwcm9kdWN0X3VybCA9IHN0cl9yZXBsYWNlKGJhc2VuYW1lKCRfU0VSVkVSWydTQ1JJUFRfTkFNRSddKS4nLycsJycsJHByb2R1Y3QtPmdldFByb2R1Y3RVcmwoZmFsc2UpKTsgICAgICAgICAgICAkcmV0dXJuW10gPSBhcnJheSggICAgICAgICAgICAgJ2Rlc2NyaXB0aW9uJyA9PiAkcHJvZHVjdC0+Z2V0TmFtZSgpLCAgICAgICAgICAgICAncHJpY2UnID0+ICRwcm9kdWN0LT5nZXRQcmljZSgpLCAgICAgICAgICAgICAnaW1hZ2VfdXJsJyA9PiAkaW1hZ2VfdXJsLCAgICAgICAgICAgICAncHJvZHVjdF91cmwnID0+ICRwcm9kdWN0X3VybCAgICAgICAgICAgICk7ICAgICAgICAgICB9ICAgIH0gICAgaWYoJGxhbmcpIHNlbGY6OnN0b3BMYW5nRW11bGF0aW9uKCk7ICAgIHJldHVybiAkcmV0dXJuOyAgICAgIH0gICAgICAgIHB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gZ2V0VXNlckxvY2FsZSgkaWRfY3VzdG9tZXIsJHN0b3JlX2lkLCRjb3VudHJ5X2NvZGUgPSBmYWxzZSkgeyAgICAgICAgICBpZihjbGFzc19leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgZmFsc2UpICYmIG1ldGhvZF9leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJyxfX0ZVTkNUSU9OX18pKSByZXR1cm4gY2FsbF91c2VyX2Z1bmNfYXJyYXkoYXJyYXkoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgX19GVU5DVElPTl9fKSwgZnVuY19nZXRfYXJncygpKTsgICAgICAgJGxvY2FsZV9zaG9wID0gTWFnZTo6Z2V0U3RvcmVDb25maWcoJ2dlbmVyYWwvbG9jYWxlL2NvZGUnLCAkc3RvcmVfaWQpOyAgICAgICAgICBpZighJGNvdW50cnlfY29kZSkgeyAgICAgICAgICAgICAgJGN1c3RvbWVyID0gTWFnZTo6Z2V0TW9kZWwoJ2N1c3RvbWVyL2N1c3RvbWVyJyktPmxvYWQoJGlkX2N1c3RvbWVyKTsgICAgICAgICAgICAgICRkZWZhdWx0QmlsbGluZyA9ICRjdXN0b21lci0+Z2V0RGVmYXVsdEJpbGxpbmdBZGRyZXNzKCk7ICAgICAgICAgICAgICBpZigkZGVmYXVsdEJpbGxpbmcpICAgICAgICAgICAgICAgICAgcmV0dXJuIHN1YnN0cigkbG9jYWxlX3Nob3AsMCwzKS4kZGVmYXVsdEJpbGxpbmctPmdldENvdW50cnkoKTsgICAgICAgICAgfSBlbHNlIHJldHVybiBzdWJzdHIoJGxvY2FsZV9zaG9wLDAsMykuJGNvdW50cnlfY29kZTsgICAgICAgICAgICAkbG9jYWxlX3Nob3AgPSBleHBsb2RlKCdfJywkbG9jYWxlX3Nob3ApOyAgICAkbG9jYWxlX3Nob3AgPSBzdHJ0b2xvd2VyKCRsb2NhbGVfc2hvcFswXSkuJ18wMCc7ICAgICAgICAgICAgcmV0dXJuICRsb2NhbGVfc2hvcDsgICAgICB9ICAgICAgcHVibGljIHN0YXRpYyBmdW5jdGlvbiBnZW5lcmF0ZVRpbWV6b25lc1doZXJlKCR0aW1lem9uZXMsJGNvdW50cnlfYWxpYXMgPSAnY3VzdG9tZXJfZGVmYXVsdF9iaWxsaW5nX2NvdW50cnknLCRjb3VudHJ5X2ZpZWxkID0gJ3ZhbHVlJywkc3RhdGVfYWxpYXMgPSAnY3VzdG9tZXJfZGVmYXVsdF9iaWxsaW5nX3N0YXRlJywkc3RhdGVfZmllbGQgPSAnY29kZScpIHsgICAgICAgICAgaWYoY2xhc3NfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIGZhbHNlKSAmJiBtZXRob2RfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsX19GVU5DVElPTl9fKSkgcmV0dXJuIGNhbGxfdXNlcl9mdW5jX2FycmF5KGFycmF5KCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIF9fRlVOQ1RJT05fXyksIGZ1bmNfZ2V0X2FyZ3MoKSk7ICAgICAgIGlmKGlzX2FycmF5KCR0aW1lem9uZXMpIEFORCAhc2l6ZW9mKCR0aW1lem9uZXMpKSByZXR1cm4gZmFsc2U7ICAgICAgICAgICR3aGVyZSA9IGFycmF5KCk7ICAgICAgICAgIGZvcmVhY2goJHRpbWV6b25lcyBhcyAkem9uZXMpIHsgICAgICAgICAgICAgIGlmKCFpc19hcnJheSgkem9uZXMpKSAkd2hlcmVbXSA9ICcoYCcuJGNvdW50cnlfYWxpYXMuJ2AuYCcuJGNvdW50cnlfZmllbGQuJ2AgSVMgTlVMTCknOyAgICAgICAgICAgICAgZWxzZWlmKCFpc3NldCgkem9uZXNbJ3JlZ2lvbiddKSB8fCAhJHpvbmVzWydyZWdpb24nXSkgICAgICAgICAgICAgICR3aGVyZVtdID0gJyhgJy4kY291bnRyeV9hbGlhcy4nYC5gJy4kY291bnRyeV9maWVsZC4nYCA9ICInLiR6b25lc1snY291bnRyeSddLiciKSc7ICAgICAgICAgICAgICBlbHNlICR3aGVyZVtdID0gJyhgJy4kY291bnRyeV9hbGlhcy4nYC5gJy4kY291bnRyeV9maWVsZC4nYCA9ICInLiR6b25lc1snY291bnRyeSddLiciIEFORCBgJy4kc3RhdGVfYWxpYXMuJ2AuYCcuJHN0YXRlX2ZpZWxkLidgID0gIicuJHpvbmVzWydyZWdpb24nXS4nIiknOyAgICAgICAgICB9ICAgICAgICAgIGlmKHNpemVvZigkd2hlcmUpKSByZXR1cm4gJygnLmltcGxvZGUoJyBPUiAnLCR3aGVyZSkuJyknOyAgICAgICAgICByZXR1cm4gZmFsc2U7ICAgICAgfSAgIHB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gZ2V0RGF0ZUxhc3RPcmRlcigkaWRfY3VzdG9tZXIpIHsgICAgaWYoY2xhc3NfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIGZhbHNlKSAmJiBtZXRob2RfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsX19GVU5DVElPTl9fKSkgcmV0dXJuIGNhbGxfdXNlcl9mdW5jX2FycmF5KGFycmF5KCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIF9fRlVOQ1RJT05fXyksIGZ1bmNfZ2V0X2FyZ3MoKSk7ICAgICR0YWJsZVByZWZpeCA9IE1hZ2U6OmdldENvbmZpZygpLT5nZXRUYWJsZVByZWZpeCgpOyAgICAgICAgICAkcmVhZCA9IE1hZ2U6OmdldFNpbmdsZXRvbignY29yZS9yZXNvdXJjZScpLT5nZXRDb25uZWN0aW9uKCdjb3JlX3JlYWQnKTsgICAgICAgICAgaWYoaXNfbnVtZXJpYygkaWRfY3VzdG9tZXIpKSB7ICAgICAgICAgICAkcmVzdWx0ID0gJHJlYWQtPmZldGNoUm93KCdTRUxFQ1QgTUFYKGBjcmVhdGVkX2F0YCkgQVMgYGNyZWF0ZWRfYXRgICAgICBGUk9NIGAnLiR0YWJsZVByZWZpeC4nc2FsZXNfZmxhdF9vcmRlcmAgICAgIFdIRVJFIGBjdXN0b21lcl9pZGAgPSAnLihpbnQpJGlkX2N1c3RvbWVyLicgQU5EIGBiYXNlX3RvdGFsX2ludm9pY2VkYCBJUyBOT1QgTlVMTCcpOyAgICAgICAgICB9ZWxzZSB7ICAgICAgICAgICAkcmVzdWx0ID0gJHJlYWQtPmZldGNoUm93KCdTRUxFQ1QgTUFYKGBjcmVhdGVkX2F0YCkgQVMgYGNyZWF0ZWRfYXRgICAgICBGUk9NIGAnLiR0YWJsZVByZWZpeC4nc2FsZXNfZmxhdF9vcmRlcmAgICAgIFdIRVJFIGBjdXN0b21lcl9lbWFpbGAgPSAiJy4kaWRfY3VzdG9tZXIuJyIgQU5EIGBiYXNlX3RvdGFsX2ludm9pY2VkYCBJUyBOT1QgTlVMTCcpOyAgICAgICAgICB9ICAgIHJldHVybiBpc3NldCgkcmVzdWx0WydjcmVhdGVkX2F0J10pID8gJHJlc3VsdFsnY3JlYXRlZF9hdCddIDogMDsgICB9ICAgICAgcHVibGljIHN0YXRpYyBmdW5jdGlvbiBjb3VudEN1c3RvbWVyT3JkZXIoJGlkX2N1c3RvbWVyKSB7ICAgICAgIGlmKGNsYXNzX2V4aXN0cygnU2hvcHltaW5kQ2xpZW50X0NhbGxiYWNrT3ZlcnJpZGUnLCBmYWxzZSkgJiYgbWV0aG9kX2V4aXN0cygnU2hvcHltaW5kQ2xpZW50X0NhbGxiYWNrT3ZlcnJpZGUnLF9fRlVOQ1RJT05fXykpIHJldHVybiBjYWxsX3VzZXJfZnVuY19hcnJheShhcnJheSgnU2hvcHltaW5kQ2xpZW50X0NhbGxiYWNrT3ZlcnJpZGUnLCBfX0ZVTkNUSU9OX18pLCBmdW5jX2dldF9hcmdzKCkpOyAgICAgICAgICAkdGFibGVQcmVmaXggPSBNYWdlOjpnZXRDb25maWcoKS0+Z2V0VGFibGVQcmVmaXgoKTsgICAgICAgICAgJHJlYWQgPSBNYWdlOjpnZXRTaW5nbGV0b24oJ2NvcmUvcmVzb3VyY2UnKS0+Z2V0Q29ubmVjdGlvbignY29yZV9yZWFkJyk7ICAgICAgICAgIGlmKGlzX251bWVyaWMoJGlkX2N1c3RvbWVyKSkgeyAgICAgICAgICAgJHJlc3VsdCA9ICRyZWFkLT5mZXRjaFJvdygnU0VMRUNUIENPVU5UKGBlbnRpdHlfaWRgKSBBUyBgbmJPcmRlcmAgICAgIEZST00gYCcuJHRhYmxlUHJlZml4LidzYWxlc19mbGF0X29yZGVyYCAgICAgV0hFUkUgYGN1c3RvbWVyX2lkYCA9ICcuKGludCkkaWRfY3VzdG9tZXIuJyBBTkQgYGJhc2VfdG90YWxfaW52b2ljZWRgIElTIE5PVCBOVUxMJyk7ICAgICAgICAgIH1lbHNlIHsgICAgICAgICAgICRyZXN1bHQgPSAkcmVhZC0+ZmV0Y2hSb3coJ1NFTEVDVCBDT1VOVChgZW50aXR5X2lkYCkgQVMgYG5iT3JkZXJgICAgICBGUk9NIGAnLiR0YWJsZVByZWZpeC4nc2FsZXNfZmxhdF9vcmRlcmAgICAgIFdIRVJFIGBjdXN0b21lcl9lbWFpbGAgPSAiJy4kaWRfY3VzdG9tZXIuJyIgQU5EIGBiYXNlX3RvdGFsX2ludm9pY2VkYCBJUyBOT1QgTlVMTCcpOyAgICAgICAgICB9ICAgICAgICAgIHJldHVybiBpc3NldCgkcmVzdWx0WyduYk9yZGVyJ10pID8gJHJlc3VsdFsnbmJPcmRlciddIDogMDsgICAgICB9ICAgICAgcHVibGljIHN0YXRpYyBmdW5jdGlvbiBzdW1DdXN0b21lck9yZGVyKCRpZF9jdXN0b21lcikgeyAgICAgICBpZihjbGFzc19leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgZmFsc2UpICYmIG1ldGhvZF9leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJyxfX0ZVTkNUSU9OX18pKSByZXR1cm4gY2FsbF91c2VyX2Z1bmNfYXJyYXkoYXJyYXkoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgX19GVU5DVElPTl9fKSwgZnVuY19nZXRfYXJncygpKTsgICAgICAgICAgJG09IG5ldyBNYWdlOyAgICAgICAgICAkbWFnZVZlcnNpb249JG0tPmdldFZlcnNpb24oKTsgICAgICAgICAgJHRhYmxlUHJlZml4ID0gTWFnZTo6Z2V0Q29uZmlnKCktPmdldFRhYmxlUHJlZml4KCk7ICAgICAgICAgICRyZWFkID0gTWFnZTo6Z2V0U2luZ2xldG9uKCdjb3JlL3Jlc291cmNlJyktPmdldENvbm5lY3Rpb24oJ2NvcmVfcmVhZCcpOyAgICAgICAgICBpZihpc19udW1lcmljKCRpZF9jdXN0b21lcikpIHsgICAgICAgICAgICRyZXN1bHQgPSAkcmVhZC0+ZmV0Y2hSb3coJ1NFTEVDVCBTVU0oKGBiYXNlX3RvdGFsX2ludm9pY2VkYC9iYXNlX3RvX29yZGVyX3JhdGUpKSBBUyBgc3VtT3JkZXJgICAgICBGUk9NIGAnLiR0YWJsZVByZWZpeC4nc2FsZXNfZmxhdF9vcmRlcmAgICAgIFdIRVJFIGBjdXN0b21lcl9pZGAgPSAnLihpbnQpJGlkX2N1c3RvbWVyLicgQU5EIGBiYXNlX3RvdGFsX2ludm9pY2VkYCBJUyBOT1QgTlVMTCcpOyAgICAgICAgICB9ZWxzZSB7ICAgICAgICAgICAkcmVzdWx0ID0gJHJlYWQtPmZldGNoUm93KCdTRUxFQ1QgU1VNKChgYmFzZV90b3RhbF9pbnZvaWNlZGAvYmFzZV90b19vcmRlcl9yYXRlKSkgQVMgYHN1bU9yZGVyYCAgICAgRlJPTSBgJy4kdGFibGVQcmVmaXguJ3NhbGVzX2ZsYXRfb3JkZXJgICAgICBXSEVSRSBgY3VzdG9tZXJfZW1haWxgID0gIicuJGlkX2N1c3RvbWVyLiciIEFORCBgYmFzZV90b3RhbF9pbnZvaWNlZGAgSVMgTk9UIE5VTEwnKTsgICAgICAgICAgfSAgICAgICAgICByZXR1cm4gaXNzZXQoJHJlc3VsdFsnc3VtT3JkZXInXSkgPyAkcmVzdWx0WydzdW1PcmRlciddIDogMDsgICAgICB9ICAgcHVibGljIHN0YXRpYyBmdW5jdGlvbiBnZXRDdXN0b21lclByb2R1Y3RzT3JkZXJlZCgkaWRfY3VzdG9tZXIpIHsgICAgaWYoY2xhc3NfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIGZhbHNlKSAmJiBtZXRob2RfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsX19GVU5DVElPTl9fKSkgcmV0dXJuIGNhbGxfdXNlcl9mdW5jX2FycmF5KGFycmF5KCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIF9fRlVOQ1RJT05fXyksIGZ1bmNfZ2V0X2FyZ3MoKSk7ICAgICR0YWJsZVByZWZpeCA9IE1hZ2U6OmdldENvbmZpZygpLT5nZXRUYWJsZVByZWZpeCgpOyAgICAgICAgICAkcmVhZCA9IE1hZ2U6OmdldFNpbmdsZXRvbignY29yZS9yZXNvdXJjZScpLT5nZXRDb25uZWN0aW9uKCdjb3JlX3JlYWQnKTsgICAgICAgICAgaWYoaXNfbnVtZXJpYygkaWRfY3VzdG9tZXIpKSB7ICAgICAgICAgICAkcmVzdWx0ID0gJHJlYWQtPmZldGNoQWxsKCdTRUxFQ1QgYHByb2R1Y3RfaWRgIEFTIGBpZF9wcm9kdWN0YCwgYHNrdWAgQVMgYHJlZmVyZW5jZV9wcm9kdWN0YCAgICAgRlJPTSBgJy4kdGFibGVQcmVmaXguJ3NhbGVzX2ZsYXRfb3JkZXJfaXRlbWAgQVMgYG9yZGVyX2RldGFpbGAgICAgIExFRlQgSk9JTiBgJy4kdGFibGVQcmVmaXguJ3NhbGVzX2ZsYXRfb3JkZXJgIEFTIGBvcmRlcnNgIE9OIChgb3JkZXJzYC5gZW50aXR5X2lkYCA9IGBvcmRlcl9kZXRhaWxgLmBvcmRlcl9pZGApICAgICBXSEVSRSBgY3VzdG9tZXJfaWRgID0gJy4oaW50KSRpZF9jdXN0b21lci4nIEFORCBgb3JkZXJzYC5gYmFzZV90b3RhbF9pbnZvaWNlZGAgSVMgTk9UIE5VTEwgICAgIEdST1VQIEJZIGBwcm9kdWN0X2lkYCcpOyAgICAgICAgICB9ZWxzZSB7ICAgICAgICAgICAkcmVzdWx0ID0gJHJlYWQtPmZldGNoQWxsKCdTRUxFQ1QgYHByb2R1Y3RfaWRgIEFTIGBpZF9wcm9kdWN0YCwgYHNrdWAgQVMgYHJlZmVyZW5jZV9wcm9kdWN0YCAgICAgRlJPTSBgJy4kdGFibGVQcmVmaXguJ3NhbGVzX2ZsYXRfb3JkZXJfaXRlbWAgQVMgYG9yZGVyX2RldGFpbGAgICAgIExFRlQgSk9JTiBgJy4kdGFibGVQcmVmaXguJ3NhbGVzX2ZsYXRfb3JkZXJgIEFTIGBvcmRlcnNgIE9OIChgb3JkZXJzYC5gZW50aXR5X2lkYCA9IGBvcmRlcl9kZXRhaWxgLmBvcmRlcl9pZGApICAgICBXSEVSRSBgY3VzdG9tZXJfZW1haWxgID0gIicuJGlkX2N1c3RvbWVyLiciIEFORCBgb3JkZXJzYC5gYmFzZV90b3RhbF9pbnZvaWNlZGAgSVMgTk9UIE5VTEwgICAgIEdST1VQIEJZIGBwcm9kdWN0X2lkYCcpOyAgICAgICAgICB9ICAgIHJldHVybiAkcmVzdWx0OyAgIH0gICAgICBwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIGdldE1hZ2VudG9BdHRyaWJ1dGVDb2RlKCRtb2RlbCwkYXR0cmlidXRlX2NvZGUpIHsgICAgICAgaWYoY2xhc3NfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIGZhbHNlKSAmJiBtZXRob2RfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsX19GVU5DVElPTl9fKSkgcmV0dXJuIGNhbGxfdXNlcl9mdW5jX2FycmF5KGFycmF5KCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIF9fRlVOQ1RJT05fXyksIGZ1bmNfZ2V0X2FyZ3MoKSk7ICAgICAgICAgICRlYXZBdHRyaWJ1dGUgPSBuZXcgTWFnZV9FYXZfTW9kZWxfTXlzcWw0X0VudGl0eV9BdHRyaWJ1dGUoKTsgICAgICAgICAgcmV0dXJuICRlYXZBdHRyaWJ1dGUtPmdldElkQnlDb2RlKCRtb2RlbCwgJGF0dHJpYnV0ZV9jb2RlKTsgICAgICB9ICAgICAgcHVibGljIHN0YXRpYyBmdW5jdGlvbiBnZXRTZXNzaW9uQ3VzdG9tZXJJZCgpIHsgICAgICAgaWYoY2xhc3NfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIGZhbHNlKSAmJiBtZXRob2RfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsX19GVU5DVElPTl9fKSkgcmV0dXJuIGNhbGxfdXNlcl9mdW5jX2FycmF5KGFycmF5KCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIF9fRlVOQ1RJT05fXyksIGZ1bmNfZ2V0X2FyZ3MoKSk7ICAgICAgICAgIGlmKE1hZ2U6OmdldFNpbmdsZXRvbignY3VzdG9tZXIvc2Vzc2lvbicpLT5pc0xvZ2dlZEluKCkpIHsgICAgICAgICAgICAgICRjdXN0b21lckRhdGEgPSBNYWdlOjpnZXRTaW5nbGV0b24oJ2N1c3RvbWVyL3Nlc3Npb24nKS0+Z2V0Q3VzdG9tZXIoKTsgICAgICAgICAgICAgIHJldHVybiAkY3VzdG9tZXJEYXRhLT5nZXRJZCgpOyAgICAgICAgICB9ICAgICAgICAgIHJldHVybiBmYWxzZTsgICAgICB9ICAgICAgcHVibGljIHN0YXRpYyBmdW5jdGlvbiBnZXRTZXNzaW9uQ3VzdG9tZXJFbWFpbCgpIHsgICAgICAgICAgaWYoY2xhc3NfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIGZhbHNlKSAmJiBtZXRob2RfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsX19GVU5DVElPTl9fKSkgcmV0dXJuIGNhbGxfdXNlcl9mdW5jX2FycmF5KGFycmF5KCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIF9fRlVOQ1RJT05fXyksIGZ1bmNfZ2V0X2FyZ3MoKSk7ICAgICAgICAgIGlmKE1hZ2U6OmdldFNpbmdsZXRvbignY3VzdG9tZXIvc2Vzc2lvbicpLT5pc0xvZ2dlZEluKCkpIHsgICAgICAgICAgICAgICRjdXN0b21lckRhdGEgPSBNYWdlOjpnZXRTaW5nbGV0b24oJ2N1c3RvbWVyL3Nlc3Npb24nKS0+Z2V0Q3VzdG9tZXIoKTsgICAgICAgICAgICAgIHJldHVybiAkY3VzdG9tZXJEYXRhLT5nZXRFbWFpbCgpOyAgICAgICAgICB9ZWxzZSB7ICAgICAgICAgICAgICAkcXVvdGUgPSBNYWdlOjpnZXRTaW5nbGV0b24oJ2NoZWNrb3V0L3Nlc3Npb24nKS0+Z2V0UXVvdGUoKTsgICAgICAgICAgICAgIHJldHVybiAkcXVvdGUtPmdldEN1c3RvbWVyRW1haWwoKTsgICAgICAgICAgfSAgICAgICAgICByZXR1cm4gZmFsc2U7ICAgICAgfSAgICAgIHB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gZ2V0U2Vzc2lvbkNhcnRJZCgpIHsgICAgICAgICAgJHNlc3Npb24gPSBNYWdlOjpnZXRTaW5nbGV0b24oJ2NoZWNrb3V0L3Nlc3Npb24nKTsgICAgICAgICAgJGNhcnRfaWQgPSAkc2Vzc2lvbi0+Z2V0UXVvdGUoKS0+Z2V0SWQoKTsgICAgICAgICAgcmV0dXJuICRjYXJ0X2lkOyAgICAgIH0gICAgICBwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIGNoZWNrTmV3Q2FydCgpIHsgICAgICAgaWYoY2xhc3NfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIGZhbHNlKSAmJiBtZXRob2RfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsX19GVU5DVElPTl9fKSkgcmV0dXJuIGNhbGxfdXNlcl9mdW5jX2FycmF5KGFycmF5KCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIF9fRlVOQ1RJT05fXyksIGZ1bmNfZ2V0X2FyZ3MoKSk7ICAgICAgICAgICRjb29raWUgPSBNYWdlOjphcHAoKS0+Z2V0Q29va2llKCk7ICAgICAgICAgICRjYXJ0X2lkID0gc2VsZjo6Z2V0U2Vzc2lvbkNhcnRJZCgpOyAgICAgICAgICAkY3VzdG9tZXJfaWQgPSBzZWxmOjpnZXRTZXNzaW9uQ3VzdG9tZXJJZCgpOyAgICAgICAgICAkY3VzdG9tZXJfZW1haWwgPSBzZWxmOjpnZXRTZXNzaW9uQ3VzdG9tZXJFbWFpbCgpOyAgICAgICAgICAkdm91Y2hlcnNDYXJ0ID0gKGFycmF5KU1hZ2U6OmdldFNpbmdsZXRvbignY2hlY2tvdXQvc2Vzc2lvbicpLT5nZXRRdW90ZSgpLT5nZXRDb3Vwb25Db2RlKCk7ICAgICAgICAgICRrZXlfY2hlY2tlZCA9IG1kNSgkY2FydF9pZC4nLScuJGN1c3RvbWVyX2lkLictJy4kY3VzdG9tZXJfZW1haWwuJy0nLnNlcmlhbGl6ZSgkdm91Y2hlcnNDYXJ0KSk7ICAgICAgICAgIGlmKCFpc3NldCgkX0dFVFsnc3BtX2tleSddKSAmJiAoISRjb29raWUtPmdldCgnc3Bta2V5Y2hlY2tlZCcpIHx8ICRrZXlfY2hlY2tlZCAhPT0gJGNvb2tpZS0+Z2V0KCdzcG1rZXljaGVja2VkJykpICYmICEkY29va2llLT5nZXQoJ3NwbWNhcnRvb3JkZXInKSAmJiAhJGNvb2tpZS0+Z2V0KCdzcG1jYXJ0b29yZGVyX3BlcnNpc3RlbnQnKSAmJiAkY2FydF9pZCkgeyAgICAgICAgICAgICAgJHRhYmxlUHJlZml4ID0gTWFnZTo6Z2V0Q29uZmlnKCktPmdldFRhYmxlUHJlZml4KCk7ICAgICAgICAgICAgICAkcmVhZCA9IE1hZ2U6OmdldFNpbmdsZXRvbignY29yZS9yZXNvdXJjZScpLT5nZXRDb25uZWN0aW9uKCdjb3JlX3JlYWQnKTsgICAgICAgICAgICAgICRzcG1fa2V5ID0gJHJlYWQtPmZldGNoUm93KCdTRUxFQ1QgYHNwbV9rZXlgIEZST00gYCcuJHRhYmxlUHJlZml4LidzcG1jYXJ0b29yZGVyYCBXSEVSRSAoYGlkX2NhcnRgID0gJy4oaW50KSRjYXJ0X2lkLicpIEFORCBgaXNfY29udmVydGVkYCA9IDAgQU5EIGBkYXRlX3VwZGAgPj0gREFURV9TVUIoIicuZGF0ZSgnWS1tLWQgSDppOnMnKS4nIiwgSU5URVJWQUwgMSBNT05USCkgT1JERVIgQlkgYGRhdGVfYWRkYCBERVNDJyk7ICAgICAgICAgICAgICBpZighJHNwbV9rZXkgJiYgJGN1c3RvbWVyX2lkKSAgICAgICAgICAgICAgICAgICRzcG1fa2V5ID0gJHJlYWQtPmZldGNoUm93KCdTRUxFQ1QgYHNwbV9rZXlgIEZST00gYCcuJHRhYmxlUHJlZml4LidzcG1jYXJ0b29yZGVyYCBXSEVSRSAoYGlkX2N1c3RvbWVyYCA9ICcuKGludCkkY3VzdG9tZXJfaWQuJykgQU5EIGBpc19jb252ZXJ0ZWRgID0gMCBBTkQgYGRhdGVfdXBkYCA+PSBEQVRFX1NVQigiJy5kYXRlKCdZLW0tZCBIOmk6cycpLiciLCBJTlRFUlZBTCAxIE1PTlRIKSBPUkRFUiBCWSBgZGF0ZV9hZGRgIERFU0MnKTsgICAgICAgICAgICAgIGlmKCEkc3BtX2tleSAmJiAkY3VzdG9tZXJfZW1haWwgIT09IG51bGwgJiYgJGN1c3RvbWVyX2VtYWlsICE9PSBmYWxzZSAmJiAkY3VzdG9tZXJfZW1haWwpICAgICAgICAgICAgICAgICAgJHNwbV9rZXkgPSAkcmVhZC0+ZmV0Y2hSb3coJ1NFTEVDVCBgc3BtX2tleWAgRlJPTSBgJy4kdGFibGVQcmVmaXguJ3NwbWNhcnRvb3JkZXJgIFdIRVJFIChgZW1haWxgID0gIicuJGN1c3RvbWVyX2VtYWlsLiciKSBBTkQgYGlzX2NvbnZlcnRlZGAgPSAwIEFORCBgZGF0ZV91cGRgID49IERBVEVfU1VCKCInLmRhdGUoJ1ktbS1kIEg6aTpzJykuJyIsIElOVEVSVkFMIDEgTU9OVEgpIE9SREVSIEJZIGBkYXRlX2FkZGAgREVTQycpOyAgICAgICAgICAgICAgaWYoISRzcG1fa2V5KSB7ICAgICAgICAgICAgICAgICAgaWYoJHZvdWNoZXJzQ2FydCAmJiBzaXplb2YoJHZvdWNoZXJzQ2FydCkpIHsgICAgICAgICAgICAgICAgICAgICAgZm9yZWFjaCgkdm91Y2hlcnNDYXJ0IGFzICR2b3VjaGVyKSAgeyAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoISRzcG1fa2V5ICYmICR2b3VjaGVyKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzcG1fa2V5ID0gJHJlYWQtPmZldGNoUm93KCdTRUxFQ1QgYHNwbV9rZXlgIEZST00gYCcuJHRhYmxlUHJlZml4LidzcG1jYXJ0b29yZGVyYCBXSEVSRSAoYHZvdWNoZXJfbnVtYmVyYCA9ICInLmFkZHNsYXNoZXMoJHZvdWNoZXIpLiciKSBBTkQgYGlzX2NvbnZlcnRlZGAgPSAwIEFORCBgZGF0ZV91cGRgID49IERBVEVfU1VCKCInLmRhdGUoJ1ktbS1kIEg6aTpzJykuJyIsIElOVEVSVkFMIDEgTU9OVEgpIE9SREVSIEJZIGBkYXRlX2FkZGAgREVTQycpOyAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBicmVhazsgICAgICAgICAgICAgICAgICAgICAgfSAgICAgICAgICAgICAgICAgIH0gICAgICAgICAgICAgIH0gICAgICAgICAgICAgIGlmKCRzcG1fa2V5ICYmIGlzc2V0KCRzcG1fa2V5WydzcG1fa2V5J10pICYmICRzcG1fa2V5WydzcG1fa2V5J10pICRfR0VUWydzcG1fa2V5J10gPSAkc3BtX2tleVsnc3BtX2tleSddOyAgICAgICAgICAgICAgZWxzZSB7ICAgICAgICAgICAgICAgICAgJGNvb2tpZS0+c2V0KCdzcG1rZXljaGVja2VkJywgJGtleV9jaGVja2VkLDApOyAgICAgICAgICAgICAgfSAgICAgICAgICB9ICAgICAgICAgIGlmKGlzc2V0KCRfR0VUWydzcG1fa2V5J10pIHx8ICRjb29raWUtPmdldCgnc3BtY2FydG9vcmRlcicpIHx8ICRjb29raWUtPmdldCgnc3BtY2FydG9vcmRlcl9wZXJzaXN0ZW50JykpIHsgICAgICAgICAgICAgICRxdW90ZSA9IE1hZ2U6OmdldFNpbmdsZXRvbignY2hlY2tvdXQvY2FydCcpLT5nZXRRdW90ZSgpOyAgICAgICAgICAgICAgaWYoISRjYXJ0X2lkIHx8ICghJGN1c3RvbWVyX2lkICYmICEkY3VzdG9tZXJfZW1haWwpIHx8ICEkcXVvdGUtPmdldEdyYW5kVG90YWwoKSkgeyAgICAgICAgICAgICAgICAgIGlmKGlzc2V0KCRfR0VUWydzcG1fa2V5J10pKSB7ICAgICAgICAgICAgICAgICAgICAgICRjb29raWUtPnNldCgnc3BtY2FydG9vcmRlcl9wZXJzaXN0ZW50JywgJF9HRVRbJ3NwbV9rZXknXSwgNjU3MDAwKTsgICAgICAgICAgICAgICAgICAgICAgJGNvb2tpZS0+c2V0KCdzcG1jYXJ0b29yZGVyJywgJF9HRVRbJ3NwbV9rZXknXSwwKTsgICAgICAgICAgICAgICAgICB9ICAgICAgICAgICAgICB9ZWxzZSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZigkY29va2llLT5nZXQoJ3NwbWxhc3RjYXJ0cmVnaXN0ZXInKSAmJiAkY29va2llLT5nZXQoJ3NwbWxhc3RjYXJ0cmVnaXN0ZXInKSA9PSAkc3BtX2tleS4kY2FydF9pZCkgcmV0dXJuOyAgICAgICAgICAgICAgICAgICR0YWJsZVByZWZpeCA9IE1hZ2U6OmdldENvbmZpZygpLT5nZXRUYWJsZVByZWZpeCgpOyAgICAgICAgICAgICAgICAgICAgaWYoaXNzZXQoJF9HRVRbJ3NwbV9rZXknXSkpICAgICAgICAgICAgICAgICAgICAgICRzcG1fa2V5ID0gJF9HRVRbJ3NwbV9rZXknXTsgICAgICAgICAgICAgICAgICBlbHNlaWYoJGNvb2tpZS0+Z2V0KCdzcG1jYXJ0b29yZGVyJykgIT0gJycpICAgICAgICAgICAgICAgICAgICAgICRzcG1fa2V5ID0gJGNvb2tpZS0+Z2V0KCdzcG1jYXJ0b29yZGVyJyk7ICAgICAgICAgICAgICAgICAgZWxzZWlmKCRjb29raWUtPmdldCgnc3BtY2FydG9vcmRlcl9wZXJzaXN0ZW50JykgIT0gJycpIHsgICAgICAgICAgICAgICAgICAgICAgJHNwbV9rZXkgPSAkY29va2llLT5nZXQoJ3NwbWNhcnRvb3JkZXJfcGVyc2lzdGVudCcpOyAgICAgICAgICAgICAgICAgICAgICAkcmVhZCA9IE1hZ2U6OmdldFNpbmdsZXRvbignY29yZS9yZXNvdXJjZScpLT5nZXRDb25uZWN0aW9uKCdjb3JlX3JlYWQnKTsgICAgICAgICAgICAgICAgICAgICAgJHRlc3QgPSAkcmVhZC0+ZmV0Y2hSb3coJ1NFTEVDVCBgc3BtX2tleWAgRlJPTSBgJy4kdGFibGVQcmVmaXguJ3NwbWNhcnRvb3JkZXJgIFdIRVJFIGBzcG1fa2V5YCA9ICInLmFkZHNsYXNoZXMoJHNwbV9rZXkpLiciIEFORCBgaXNfY29udmVydGVkYCA9IDEnKTsgICAgICAgICAgICAgICAgICAgICAgaWYoJHRlc3QgJiYgaXNzZXQoJHRlc3RbJ3NwbV9rZXknXSkpIHJldHVybjsgICAgICAgICAgICAgICAgICB9ICAgICAgICAgICAgICAgICAgJG5vdyA9IGRhdGUoJ1ktbS1kIEg6aTpzJyk7ICAgICAgICAgICAgICAgICAgJHdyaXRlID0gTWFnZTo6Z2V0U2luZ2xldG9uKCdjb3JlL3Jlc291cmNlJyktPmdldENvbm5lY3Rpb24oJ2NvcmVfd3JpdGUnKTsgICAgICAgICAgICAgICAgICAkd3JpdGUtPnF1ZXJ5KCdJTlNFUlQgSU5UTyBgJy4kdGFibGVQcmVmaXguJ3NwbWNhcnRvb3JkZXJgIChgaWRfY2FydGAsYGlkX2N1c3RvbWVyYCxgZW1haWxgLGBzcG1fa2V5YCxgZGF0ZV91cGRgKSB2YWx1ZXMgKCcuKGludCkkY2FydF9pZC4nLCcuKGludCkkY3VzdG9tZXJfaWQuJywiJy5hZGRzbGFzaGVzKCRjdXN0b21lcl9lbWFpbCkuJyIsIicuYWRkc2xhc2hlcygkc3BtX2tleSkuJyIsIicuJG5vdy4nIikgT04gRFVQTElDQVRFIEtFWSBVUERBVEUgaWRfY2FydCA9ICcuKGludCkkY2FydF9pZC4nLGlkX2N1c3RvbWVyID0gJy4oaW50KSRjdXN0b21lcl9pZC4nLCBlbWFpbD0iJy5hZGRzbGFzaGVzKCRjdXN0b21lcl9lbWFpbCkuJyIsIHNwbV9rZXk9IicuYWRkc2xhc2hlcygkc3BtX2tleSkuJyIsIGRhdGVfdXBkPSInLiRub3cuJyInKTsgICAgICAgICAgICAgICAgICBpbmNsdWRlX29uY2UoTWFnZTo6Z2V0QmFzZURpcignYmFzZScpLicvYXBwL2NvZGUvbG9jYWwvU1BNL1Nob3B5TWluZC9TaG9weW1pbmRDbGllbnQvYmluL05vdGlmeS5waHAnKTsgICAgICAgICAgICAgICAgICBpZihTaG9weW1pbmRDbGllbnRfTm90aWZ5OjpuZXdDYXJ0KGFycmF5KCdpZFJlbWluZGVyc1NlbmQnPT4kc3BtX2tleSwnaWRDYXJ0Jz0+JGNhcnRfaWQsJ3RvdGFsQ2FydCc9PiRxdW90ZS0+Z2V0R3JhbmRUb3RhbCgpLCdjdXJyZW5jeUNhcnQnPT4kcXVvdGUtPmdldFF1b3RlQ3VycmVuY3lDb2RlKCksJ3RheFJhdGVDYXJ0Jz0+JHF1b3RlLT5nZXRTdG9yZVRvUXVvdGVSYXRlKCkpKSkgeyAgICAgICAgICAgICAgICAgICAgICAkY29va2llLT5zZXQoJ3NwbWxhc3RjYXJ0cmVnaXN0ZXInLCAkc3BtX2tleS4kY2FydF9pZCwwKTsgICAgICAgICAgICAgICAgICAgICAgJGNvb2tpZS0+ZGVsZXRlKCdzcG1jYXJ0b29yZGVyJyk7ICAgICAgICAgICAgICAgICAgICAgICRjb29raWUtPmRlbGV0ZSgnc3BtY2FydG9vcmRlcl9wZXJzaXN0ZW50Jyk7ICAgICAgICAgICAgICAgICAgICB9ICAgICAgICAgICAgICB9ICAgICAgICAgIH0gICAgICB9ICAgICAgcHVibGljIHN0YXRpYyBmdW5jdGlvbiBjaGVja05ld09yZGVyKCRvcmRlcikgeyAgICAgICBpZihjbGFzc19leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgZmFsc2UpICYmIG1ldGhvZF9leGlzdHMoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJyxfX0ZVTkNUSU9OX18pKSByZXR1cm4gY2FsbF91c2VyX2Z1bmNfYXJyYXkoYXJyYXkoJ1Nob3B5bWluZENsaWVudF9DYWxsYmFja092ZXJyaWRlJywgX19GVU5DVElPTl9fKSwgZnVuY19nZXRfYXJncygpKTsgICAgICAgICAgJG9yZGVyRGF0YSA9ICRvcmRlci0+Z2V0RGF0YSgpOyAgICAgICAgICAkcmVhZCA9IE1hZ2U6OmdldFNpbmdsZXRvbignY29yZS9yZXNvdXJjZScpLT5nZXRDb25uZWN0aW9uKCdjb3JlX3JlYWQnKTsgICAgICAgICAgJHRhYmxlUHJlZml4ID0gTWFnZTo6Z2V0Q29uZmlnKCktPmdldFRhYmxlUHJlZml4KCk7ICAgICAgICAgICRzcG1fa2V5ID0gJHJlYWQtPmZldGNoUm93KCdTRUxFQ1QgYHNwbV9rZXlgIEZST00gYCcuJHRhYmxlUHJlZml4LidzcG1jYXJ0b29yZGVyYCBXSEVSRSAoYGlkX2NhcnRgID0gJy4oaW50KSRvcmRlckRhdGFbJ3F1b3RlX2lkJ10uJykgQU5EIGBkYXRlX3VwZGAgPj0gREFURV9TVUIoIicuZGF0ZSgnWS1tLWQgSDppOnMnKS4nIiwgSU5URVJWQUwgMSBNT05USCkgQU5EIERBVEVfRk9STUFUKGBkYXRlX2FkZGAsIiVZLSVtLSVkICVIOiVpOiVzIikgPCBEQVRFX0ZPUk1BVCgiJy4kb3JkZXJEYXRhWydjcmVhdGVkX2F0J10uJyIsIiVZLSVtLSVkICVIOiVpOiVzIikgQU5EIGBpc19jb252ZXJ0ZWRgID0gMCBPUkRFUiBCWSBgZGF0ZV9hZGRgIERFU0MnKTsgICAgICAgICAgICAkdm91Y2hlclVzZWQgPSBhcnJheSgpOyAgICAgICAgICAkdm91Y2hlcnNPcmRlciA9ICRvcmRlci0+Z2V0Q291cG9uQ29kZSgpOyAgICAgICAgICBpZigkdm91Y2hlcnNPcmRlcikgJHZvdWNoZXJVc2VkW10gPSAkdm91Y2hlcnNPcmRlcjsgICAgICAgICAgICBpZihzaXplb2YoJHZvdWNoZXJVc2VkKSAmJiAhJHNwbV9rZXkpIHsgICAgICAgICAgICAgIGZvcmVhY2goJHZvdWNoZXJVc2VkIGFzICR2b3VjaGVyKSAgeyAgICAgICAgICAgICAgICAgIGlmKCEkc3BtX2tleSAmJiAkdm91Y2hlcikgICAgICAgICAgICAgICAgICAgICAgJHNwbV9rZXkgPSAkcmVhZC0+ZmV0Y2hSb3coJ1NFTEVDVCBgc3BtX2tleWAgRlJPTSBgJy4kdGFibGVQcmVmaXguJ3NwbWNhcnRvb3JkZXJgIFdIRVJFIChgdm91Y2hlcl9udW1iZXJgID0gIicuYWRkc2xhc2hlcygkdm91Y2hlcikuJyIpIEFORCBgZGF0ZV91cGRgID49IERBVEVfU1VCKCInLmRhdGUoJ1ktbS1kIEg6aTpzJykuJyIsIElOVEVSVkFMIDEgTU9OVEgpIEFORCBEQVRFX0ZPUk1BVChgZGF0ZV9hZGRgLCIlWS0lbS0lZCAlSDolaTolcyIpIDwgREFURV9GT1JNQVQoIicuJG9yZGVyRGF0YVsnY3JlYXRlZF9hdCddLiciLCIlWS0lbS0lZCAlSDolaTolcyIpIEFORCBgaXNfY29udmVydGVkYCA9IDAgT1JERVIgQlkgYGRhdGVfYWRkYCBERVNDJyk7ICAgICAgICAgICAgICAgICAgZWxzZSBicmVhazsgICAgICAgICAgICAgIH0gICAgICAgICAgfSAgICAgICAgICAgIGlmKCEkc3BtX2tleSkgICAgICAgICAgICAgICRzcG1fa2V5ID0gJHJlYWQtPmZldGNoUm93KCdTRUxFQ1QgYHNwbV9rZXlgIEZST00gYCcuJHRhYmxlUHJlZml4LidzcG1jYXJ0b29yZGVyYCBXSEVSRSAoYGlkX29yZGVyYCA9ICcuKGludCkkb3JkZXJEYXRhWydlbnRpdHlfaWQnXS4nKSBBTkQgYGRhdGVfdXBkYCA+PSBEQVRFX1NVQigiJy5kYXRlKCdZLW0tZCBIOmk6cycpLiciLCBJTlRFUlZBTCAxIE1PTlRIKSBBTkQgREFURV9GT1JNQVQoYGRhdGVfYWRkYCwiJVktJW0tJWQgJUg6JWk6JXMiKSA8IERBVEVfRk9STUFUKCInLiRvcmRlckRhdGFbJ2NyZWF0ZWRfYXQnXS4nIiwiJVktJW0tJWQgJUg6JWk6JXMiKSBBTkQgYGlzX2NvbnZlcnRlZGAgPSAwIE9SREVSIEJZIGBkYXRlX2FkZGAgREVTQycpOyAgICAgICAgICBpZighJHNwbV9rZXkgJiYgaXNzZXQoJG9yZGVyRGF0YVsnY3VzdG9tZXJfaWQnXSkgJiYgJG9yZGVyRGF0YVsnY3VzdG9tZXJfaWQnXSkgICAgICAgICAgICAgICRzcG1fa2V5ID0gJHJlYWQtPmZldGNoUm93KCdTRUxFQ1QgYHNwbV9rZXlgIEZST00gYCcuJHRhYmxlUHJlZml4LidzcG1jYXJ0b29yZGVyYCBXSEVSRSAoYGlkX2N1c3RvbWVyYCA9ICcuKGludCkkb3JkZXJEYXRhWydjdXN0b21lcl9pZCddLicpIEFORCBgZGF0ZV91cGRgID49IERBVEVfU1VCKCInLmRhdGUoJ1ktbS1kIEg6aTpzJykuJyIsIElOVEVSVkFMIDEgTU9OVEgpIEFORCBEQVRFX0ZPUk1BVChgZGF0ZV9hZGRgLCIlWS0lbS0lZCAlSDolaTolcyIpIDwgREFURV9GT1JNQVQoIicuJG9yZGVyRGF0YVsnY3JlYXRlZF9hdCddLiciLCIlWS0lbS0lZCAlSDolaTolcyIpIEFORCBgaXNfY29udmVydGVkYCA9IDAgT1JERVIgQlkgYGRhdGVfYWRkYCBERVNDJyk7ICAgICAgICAgIGlmKCEkc3BtX2tleSAmJiBpc3NldCgkb3JkZXJEYXRhWydjdXN0b21lcl9lbWFpbCddKSAmJiAkb3JkZXJEYXRhWydjdXN0b21lcl9lbWFpbCddKSAgICAgICAgICAgICAgJHNwbV9rZXkgPSAkcmVhZC0+ZmV0Y2hSb3coJ1NFTEVDVCBgc3BtX2tleWAgRlJPTSBgJy4kdGFibGVQcmVmaXguJ3NwbWNhcnRvb3JkZXJgIFdIRVJFIChgZW1haWxgID0gIicuJG9yZGVyRGF0YVsnY3VzdG9tZXJfZW1haWwnXS4nIikgQU5EIGBkYXRlX3VwZGAgPj0gREFURV9TVUIoIicuZGF0ZSgnWS1tLWQgSDppOnMnKS4nIiwgSU5URVJWQUwgMSBNT05USCkgQU5EIERBVEVfRk9STUFUKGBkYXRlX2FkZGAsIiVZLSVtLSVkICVIOiVpOiVzIikgPCBEQVRFX0ZPUk1BVCgiJy4kb3JkZXJEYXRhWydjcmVhdGVkX2F0J10uJyIsIiVZLSVtLSVkICVIOiVpOiVzIikgQU5EIGBpc19jb252ZXJ0ZWRgID0gMCBPUkRFUiBCWSBgZGF0ZV9hZGRgIERFU0MnKTsgICAgICAgICAgICAgICBpZigkc3BtX2tleSAmJiBpc3NldCgkc3BtX2tleVsnc3BtX2tleSddKSAmJiAkc3BtX2tleVsnc3BtX2tleSddKSB7ICAgICAgICAgICAgICAgIHNlbGY6OnNlbmRPcmRlclRvU1BNKCAkb3JkZXIsJG9yZGVyRGF0YSwkc3BtX2tleVsnc3BtX2tleSddLCR2b3VjaGVyVXNlZCk7ICAgICAgICAgIH0gICAgICB9ICAgICAgcHVibGljIHN0YXRpYyBmdW5jdGlvbiBzZW5kT3JkZXJUb1NQTSgkb3JkZXIsJG9yZGVyRGF0YSwkc3BtX2tleSwkdm91Y2hlclVzZWQpIHsgICAgICAgICAgaWYoY2xhc3NfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIGZhbHNlKSAmJiBtZXRob2RfZXhpc3RzKCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsX19GVU5DVElPTl9fKSkgcmV0dXJuIGNhbGxfdXNlcl9mdW5jX2FycmF5KGFycmF5KCdTaG9weW1pbmRDbGllbnRfQ2FsbGJhY2tPdmVycmlkZScsIF9fRlVOQ1RJT05fXyksIGZ1bmNfZ2V0X2FyZ3MoKSk7ICAgICAgICAgICAgaW5jbHVkZV9vbmNlKE1hZ2U6OmdldEJhc2VEaXIoJ2Jhc2UnKS4nL2FwcC9jb2RlL2xvY2FsL1NQTS9TaG9weU1pbmQvU2hvcHltaW5kQ2xpZW50L2Jpbi9Ob3RpZnkucGhwJyk7ICAgICAgICAgICRxdW90ZSA9IE1hZ2U6OmdldFNpbmdsZXRvbignc2FsZXMvcXVvdGUnKS0+bG9hZCgoaW50KSRvcmRlckRhdGFbJ3F1b3RlX2lkJ10pOyAgICAgICAgICAkcGFyYW1zID0gYXJyYXkoICAgICAgICAgICAgICAgICAgJ2lkUmVtaW5kZXJzU2VuZCcgPT4gJHNwbV9rZXksICAgICAgICAgICAgICAgICAgJ2lkQ2FydCcgICAgICAgICAgPT4gJG9yZGVyRGF0YVsncXVvdGVfaWQnXSwgICAgICAgICAgICAgICAgICAnZGF0ZUNhcnQnICAgICAgICA9PiAoJHF1b3RlLT5nZXRVcGRhdGVkQXQoKSAhPT0gbnVsbCAmJiAkcXVvdGUtPmdldFVwZGF0ZWRBdCgpICE9PSAnJz8kcXVvdGUtPmdldFVwZGF0ZWRBdCgpOiRvcmRlckRhdGEgWydjcmVhdGVkX2F0J10pLCAgICAgICAgICAgICAgICAgICdpZE9yZGVyJyAgICAgICAgID0+ICRvcmRlckRhdGEgWydpbmNyZW1lbnRfaWQnXSwgICAgICAgICAgICAgICAgICAnYW1vdW50JyAgICAgICAgICA9PiAkb3JkZXJEYXRhIFsnYmFzZV90b3RhbF9wYWlkJ10sICAgICAgICAgICAgICAgICAgJ3RheFJhdGUnICAgICAgICAgPT4gJG9yZGVyRGF0YSBbJ2Jhc2VfdG9fb3JkZXJfcmF0ZSddLCAgICAgICAgICAgICAgICAgICdjdXJyZW5jeScgICAgICAgID0+ICRvcmRlckRhdGFbJ29yZGVyX2N1cnJlbmN5X2NvZGUnXSwgICAgICAgICAgICAgICAgICAnZGF0ZU9yZGVyJyAgICAgICA9PiAkb3JkZXJEYXRhIFsnY3JlYXRlZF9hdCddLCAgICAgICAgICAgICAgICAgICd2b3VjaGVyVXNlZCcgICAgID0+ICR2b3VjaGVyVXNlZCwgICAgICAgICAgICAgJ2N1c3RvbWVyJyAgICAgICA9PiBzZWxmOjpnZXRVc2VyKCgkb3JkZXJEYXRhWydjdXN0b21lcl9pZCddPyRvcmRlckRhdGFbJ2N1c3RvbWVyX2lkJ106JG9yZGVyRGF0YVsnY3VzdG9tZXJfZW1haWwnXSkpICAgICAgICAgICk7ICAgICAgICAgICRzcG1fa2V5ID0gU2hvcHltaW5kQ2xpZW50X05vdGlmeTo6bmV3T3JkZXIoJHBhcmFtcyk7ICAgICAgICAgaWYoJHNwbV9rZXkgJiYgaXNzZXQoJHNwbV9rZXlbJ2lkUmVtaW5kZXJzU2VuZCddKSAmJiAkc3BtX2tleVsnaWRSZW1pbmRlcnNTZW5kJ10pIHsgICAgICAgICAgICAgICR0YWJsZVByZWZpeCA9IE1hZ2U6OmdldENvbmZpZygpLT5nZXRUYWJsZVByZWZpeCgpOyAgICAgICAgICAgICAgJHdyaXRlID0gTWFnZTo6Z2V0U2luZ2xldG9uKCdjb3JlL3Jlc291cmNlJyktPmdldENvbm5lY3Rpb24oJ2NvcmVfd3JpdGUnKTsgICAgICAgICAgICAgICR3cml0ZS0+cXVlcnkoJ1VQREFURSBgJy4kdGFibGVQcmVmaXguJ3NwbWNhcnRvb3JkZXJgIFNFVCBgaXNfY29udmVydGVkYCA9IDEgV0hFUkUgYHNwbV9rZXlgID0gIicuJHNwbV9rZXlbJ2lkUmVtaW5kZXJzU2VuZCddLiciJyk7ICAgICAgICAgIH0gICAgICB9ICB9ID8+').'<?php '); ?>
app/code/local/SPM/ShopyMind/ShopymindClient/configuration.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+ return array (
3
+ 'api' =>
4
+ array (
5
+ 'identifiant' => '',
6
+ 'password' => '',
7
+ ),
8
+ );
app/code/local/SPM/ShopyMind/ShopymindClient/doc/CHANGELOG.md ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ Shopymind Client CHANGELOG.md
2
+ =============================
3
+
4
+ Version 1.0.0alpha1
5
+ -------------------
6
+ - Mise en place de la structure du coeur client
app/code/local/SPM/ShopyMind/ShopymindClient/doc/README.md ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Shopymind Client README.md
2
+ ==========================
3
+
4
+ Installation
5
+ ------------
6
+ - Décompresser le dossier puis de baser sur la doc technique fournis afin de connecter le module
7
+
8
+
9
+ Changelog
10
+ ---------
11
+ Voir CHANGELOG.md
12
+
13
+
14
+ Auteur
15
+ ------
16
+ Société IDVIVE SARL (yannick@idvive.com)
17
+
app/code/local/SPM/ShopyMind/ShopymindClient/src/Client.php ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Client
4
+ *
5
+ * @package ShopymindClient
6
+ * @copyright Copyright (c) 2013 - IDVIVE SARL (http://www.idvive.com)
7
+ * @license New BSD license (http://license.idvive.com)
8
+ * @author Yannick Dalbin <yannick@idvive.com>
9
+ * @version $Id Client.php 2013-04-24$
10
+ */
11
+ require_once dirname(__FILE__) . '/library/SZend/Http/Client.php';
12
+ require_once dirname(__FILE__) . '/library/SZend/Json.php';
13
+
14
+ if (!isset($SHOPYMIND_CLIENT_CONFIGURATION)) {
15
+ global $SHOPYMIND_CLIENT_CONFIGURATION;
16
+ $SHOPYMIND_CLIENT_CONFIGURATION = array_merge_recursive(
17
+ require dirname(__FILE__) . '/definitions.php',
18
+ require dirname(__FILE__) . '/../configuration.php'
19
+ );
20
+ }
21
+
22
+ final class ShopymindClient_Client {
23
+
24
+ protected $_reminders = array(
25
+ 'getDroppedOutCart' => 1,
26
+ 'getBirthdayClients' => 2,
27
+ 'getGoodClientsByAmount' => 4,
28
+ 'getGoodClientsByNumberOrders' => 8,
29
+ 'getMissingClients' => 16,
30
+ 'getOrdersByStatus' => 32,
31
+ 'getVoucherUnused' => 64,
32
+ );
33
+
34
+ /**
35
+ * Permet d'envoyer des requêtes au serveur
36
+ *
37
+ * @var SZend_Http_Client
38
+ */
39
+ private $_client;
40
+
41
+ private $_restService;
42
+
43
+ public function __construct() {
44
+ global $SHOPYMIND_CLIENT_CONFIGURATION;
45
+ $config = $SHOPYMIND_CLIENT_CONFIGURATION;
46
+
47
+ $url = $config['api']['url'];
48
+
49
+ $this->setClient(new SZend_Http_Client($url));
50
+ $this->initHeaders();
51
+ }
52
+
53
+ /**
54
+ * Permet d'initialiser le header avec des valeurs par défaut
55
+ *
56
+ * @return void
57
+ */
58
+ public function initHeaders() {
59
+ global $SHOPYMIND_CLIENT_CONFIGURATION;
60
+ $config = $SHOPYMIND_CLIENT_CONFIGURATION;
61
+
62
+ $this->getClient()->setHeaders($config['header']['client_id'], $config['api']['identifiant'])
63
+ ->setHeaders($config['header']['build'], $this->getBuild())
64
+ ->setHeaders($config['header']['version'], $config['version'])
65
+ ->setHeaders('version', $config['version']);
66
+ }
67
+ protected function formatString($value, $key, $options) {
68
+ if (!empty($value)) {
69
+ $options['glued_string'] .= $key.$options['glue'];
70
+ $options['glued_string'] .= $value.$options['glue'];
71
+ }
72
+ }
73
+ private function implode_recursive(array $array, $glue = ';') {
74
+ $glued_string = '';
75
+ // Recursively iterates array and adds key/value to glued string
76
+ array_walk_recursive($array, array($this, 'formatString'), array('glue' => $glue, 'glued_string' => &$glued_string));
77
+ // Removes last $glue from string
78
+ strlen($glue) > 0 and $glued_string = substr($glued_string, 0, -strlen($glue));
79
+
80
+ // Trim ALL whitespace
81
+ $glued_string = preg_replace("/(\s)/ixsm", '', $glued_string);
82
+
83
+ return (string) $glued_string;
84
+ }
85
+
86
+
87
+ /**
88
+ * Permet de récupérer le token
89
+ *
90
+ * @return string
91
+ */
92
+ public function getToken() {
93
+ global $SHOPYMIND_CLIENT_CONFIGURATION;
94
+ $config = $SHOPYMIND_CLIENT_CONFIGURATION;
95
+
96
+ $params = $this->getClient()->getParams();
97
+
98
+ if ($params !== null) {
99
+ uksort($params, 'strnatcasecmp');
100
+ $params = $this->implode_recursive($params);
101
+ }
102
+
103
+ $password = sha1($config['api']['password']);
104
+
105
+ return hash_hmac('sha256', $params, $password);
106
+ }
107
+
108
+ /**
109
+ * Connecteur HTTP
110
+ *
111
+ * @return SZend_Http_Client
112
+ */
113
+ public function getClient() {
114
+ return $this->_client;
115
+ }
116
+
117
+ /**
118
+ * Permet de modifier le connecteur HTTP
119
+ *
120
+ * @param SZend_Http_Client $client
121
+ * @return ShopymindClient_Client
122
+ */
123
+ public function setClient($client) {
124
+ $this->_client = $client;
125
+ return $this;
126
+ }
127
+
128
+ /**
129
+ * Permet d'ajouter des paramètres post à la requête
130
+ *
131
+ * @return ShopymindClient_Client
132
+ */
133
+ public function setParameterPost($name, $value = null) {
134
+ $this->getClient()->setParameterPost($name, $value);
135
+ return $this;
136
+ }
137
+
138
+ /**
139
+ * Permet d'ajouter des paramètres get à la requête
140
+ *
141
+ * @return ShopymindClient_Client
142
+ */
143
+ public function setParameterGet($name, $value = null) {
144
+ $this->getClient()->setParameterGet($name, $value);
145
+ return $this;
146
+ }
147
+
148
+ /**
149
+ * Permet d'envoyer la requête
150
+ *
151
+ * @return SZend_Http_Response
152
+ */
153
+ public function sendRequest($method = 'GET') {
154
+ global $SHOPYMIND_CLIENT_CONFIGURATION;
155
+ $config = $SHOPYMIND_CLIENT_CONFIGURATION;
156
+
157
+ $this->getClient()->setMethod($method);
158
+ $token = $this->getToken();
159
+ $this->getClient()->setHeaders($config['header']['hmac'], $token);
160
+
161
+ if ($this->getRestService() !== null) {
162
+ $uri = $this->getClient()->getUri(true);
163
+ $uri .= '/' . $this->getRestService();
164
+ $this->getClient()->setUri($uri);
165
+ }
166
+
167
+ $response = $this->getClient()->request();
168
+ return SZend_Json::decode($response->getBody());
169
+ }
170
+
171
+ /**
172
+ * Permet de tester la bonne communication avec le serveur
173
+ *
174
+ * @return boolean
175
+ */
176
+ public function sayHello() {
177
+ $this->setParameterPost('testCommunication', time());
178
+ $response = $this->sendRequest('POST');
179
+
180
+ if (is_array($response) && isset($response['success'])) {
181
+ return $response['success'];
182
+ }
183
+
184
+ return false;
185
+ }
186
+
187
+ /**
188
+ * Permet de récupérer la build du client
189
+ *
190
+ * @return int
191
+ */
192
+ public function getBuild() {
193
+ $build = 0;
194
+
195
+ if (file_exists(dirname(__FILE__) . '/../callback.php')) {
196
+ require_once dirname(__FILE__) . '/../callback.php';
197
+
198
+ foreach (get_class_methods('ShopymindClient_Callback') as $method) {
199
+ if (array_key_exists($method, $this->_reminders)) {
200
+ $build += $this->_reminders[$method];
201
+ }
202
+ }
203
+ }
204
+
205
+ return $build;
206
+ }
207
+
208
+ /**
209
+ * Permet de récupérer le service à appeler
210
+ *
211
+ * @return string
212
+ */
213
+ public function getRestService() {
214
+ return $this->_restService;
215
+ }
216
+
217
+ /**
218
+ * Permet de définir le service à appeler
219
+ *
220
+ * @param string $restService
221
+ * @return ShopymindClient_Client
222
+ */
223
+ public function setRestService($restService) {
224
+ $this->_restService = $restService;
225
+ return $this;
226
+ }
227
+
228
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/Reminders/Abstract.php ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * AbstractRelaunch
4
+ *
5
+ * @package ShopymindClient_Reminders
6
+ * @copyright Copyright (c) 2013 - IDVIVE SARL (http://www.idvive.com)
7
+ * @license New BSD license (http://license.idvive.com)
8
+ * @author Yannick Dalbin <yannick@idvive.com>
9
+ * @version $Id Abstract.php 2013-04-23$
10
+ */
11
+
12
+ if (!isset($SHOPYMIND_CLIENT_CONFIGURATION)) {
13
+ global $SHOPYMIND_CLIENT_CONFIGURATION;
14
+ $SHOPYMIND_CLIENT_CONFIGURATION = array_merge_recursive(
15
+ require dirname(__FILE__) . '/../definitions.php',
16
+ require dirname(__FILE__) . '/../../configuration.php'
17
+ );
18
+ }
19
+
20
+ abstract class ShopymindClient_Reminders_Abstract {
21
+
22
+ /**
23
+ * Permet de connaitre la liste des emails à exclure
24
+ *
25
+ * @var boolean
26
+ */
27
+ protected $_alreadySend = false;
28
+
29
+ /**
30
+ * Permet de compter le nombre de clients affectés par une campagne
31
+ *
32
+ * @var boolean
33
+ */
34
+ protected $_justCount = false;
35
+
36
+ /**
37
+ * Permet de notifier le serveur
38
+ *
39
+ * @return boolean
40
+ */
41
+ public function notify() {
42
+
43
+ }
44
+
45
+ /**
46
+ * Permet la construction de l'objet
47
+ *
48
+ * @param array $params
49
+ * @return ShopymindClient_Reminders_Abstract
50
+ */
51
+ abstract public static function factory(array $params);
52
+
53
+ /**
54
+ * Permet de récupérer les infos
55
+ *
56
+ * @return array
57
+ */
58
+ abstract public function get();
59
+
60
+ /**
61
+ * Permet de renseigner des options spécifique pour les relances
62
+ *
63
+ * @param array $params
64
+ * @return void
65
+ */
66
+ public function setGenericOptions(array $params) {
67
+ foreach ($params as $nameParam => $value) {
68
+ $method = 'set' . ucfirst($nameParam);
69
+ if (method_exists($this, $method)) {
70
+ $this->$method($value);
71
+ }
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Permet de récupérer la liste des emails a exclure
77
+ *
78
+ * @return boolean
79
+ */
80
+ public function getAlreadySend() {
81
+ return $this->_alreadySend;
82
+ }
83
+
84
+ /**
85
+ * Permet de modifier la liste des emails a exclure
86
+ *
87
+ * @param boolean $generateVoucher
88
+ * @return ShopymindClient_Reminders_Abstract
89
+ */
90
+ public function setAlreadySend($alreadySend) {
91
+ if (!is_array($alreadySend) && !is_bool($alreadySend)) {
92
+ $this->_alreadySend = false;
93
+ }
94
+ else {
95
+ $this->_alreadySend = $alreadySend;
96
+ }
97
+
98
+ return $this;
99
+ }
100
+
101
+ /**
102
+ * Permet de récupérer la variable justCount
103
+ *
104
+ * @return boolean
105
+ */
106
+ public function getJustCount() {
107
+ return $this->_justCount;
108
+ }
109
+
110
+ /**
111
+ * Permet de modifier la variable justCount
112
+ *
113
+ * @param boolean $generateVoucher
114
+ * @return ShopymindClient_Reminders_Abstract
115
+ */
116
+ public function setJustCount($justCount) {
117
+ if (!$justCount) {
118
+ $this->_justCount = false;
119
+ }
120
+ else {
121
+ $this->_justCount = true;
122
+ }
123
+
124
+ return $this;
125
+ }
126
+
127
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/Reminders/BirthdayClients.php ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * BirthdayClients
4
+ *
5
+ * @package ShopymindClient_Reminders
6
+ * @copyright Copyright (c) 2013 - IDVIVE SARL (http://www.idvive.com)
7
+ * @license New BSD license (http://license.idvive.com)
8
+ * @author Yannick Dalbin <yannick@idvive.com>
9
+ * @version $Id BirthdayClients.php 2013-04-24$
10
+ */
11
+ require_once dirname(__FILE__) . '/Abstract.php';
12
+
13
+ class ShopymindClient_Reminders_BirthdayClients extends ShopymindClient_Reminders_Abstract {
14
+
15
+ protected $_nbDays;
16
+
17
+ protected $_dateReference;
18
+
19
+ protected $_timezones;
20
+
21
+ /**
22
+ * Permet de construire une relance courante
23
+ *
24
+ * @return ShopymindClient_Reminders_BirthdayClients
25
+ */
26
+ public static function factory(array $params) {
27
+ if (!isset($params['timezones'])) {
28
+ return 'timezones param missing';
29
+ }
30
+
31
+ if (!isset($params['dateReference'])) {
32
+ return 'dateReference param missing';
33
+ }
34
+
35
+ $relaunch = new self;
36
+ $relaunch->setGenericOptions($params);
37
+
38
+ return $relaunch;
39
+ }
40
+
41
+ /**
42
+ * Permet de récupérer les données de la BDD
43
+ *
44
+ * @return array
45
+ */
46
+ public function get() {
47
+ require dirname(__FILE__) . '/../../callback.php';
48
+ if (method_exists('ShopymindClient_Callback', 'getBirthdayClients')) {
49
+ return ShopymindClient_Callback::getBirthdayClients($this->getDateReference(), $this->getTimezones(), $this->getNbDays(), $this->getJustCount());
50
+ }
51
+
52
+ return null;
53
+ }
54
+
55
+ /**
56
+ * Permet d'obtenir le nombre de jour avant la date d'anniv
57
+ *
58
+ * @return int
59
+ */
60
+ public function getNbDays() {
61
+ return $this->_nbDays;
62
+ }
63
+
64
+ /**
65
+ * Permet de modifier le nombre de jour avant la date d'anniv
66
+ *
67
+ * @param int $nbDays
68
+ * @return ShopymindClient_Reminders_BirthdayClients
69
+ */
70
+ public function setNbDays($nbDays) {
71
+ $this->_nbDays = $nbDays;
72
+ return $this;
73
+ }
74
+
75
+ /**
76
+ * Permet de récupérer la date de référence à prendre en compte
77
+ *
78
+ * @return string
79
+ */
80
+ public function getDateReference() {
81
+ return $this->_dateReference;
82
+ }
83
+
84
+ /**
85
+ * Permet de modifier la date de référence à prendre en compte
86
+ *
87
+ * @param string $dateReference
88
+ * @return ShopymindClient_Reminders_BirthdayClients
89
+ */
90
+ public function setDateReference($dateReference) {
91
+ $this->_dateReference = $dateReference;
92
+ return $this;
93
+ }
94
+
95
+ /**
96
+ * Permet de récupérer le timezone concerné
97
+ *
98
+ * @return array
99
+ */
100
+ public function getTimezones() {
101
+ return $this->_timezones;
102
+ }
103
+
104
+ /**
105
+ * Permet de modifier la liste des timezones concernés
106
+ *
107
+ * @param array $timezones
108
+ * @return ShopymindClient_Reminders_BirthdayClients
109
+ */
110
+ public function setTimezones(array $timezones) {
111
+ $this->_timezones = $timezones;
112
+ return $this;
113
+ }
114
+
115
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/Reminders/DroppedOutCart.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * DroppedOutCart
4
+ *
5
+ * @package ShopymindClient_Reminders
6
+ * @copyright Copyright (c) 2013 - IDVIVE SARL (http://www.idvive.com)
7
+ * @license New BSD license (http://license.idvive.com)
8
+ * @author Yannick Dalbin <yannick@idvive.com>
9
+ * @version $Id DroppedOutCart.php 2013-04-23$
10
+ */
11
+ require_once dirname(__FILE__) . '/Abstract.php';
12
+
13
+ class ShopymindClient_Reminders_DroppedOutCart extends ShopymindClient_Reminders_Abstract {
14
+
15
+ /**
16
+ * Nombre d'heure d'innactivité de panier
17
+ *
18
+ * @var int
19
+ */
20
+ protected $_intervalAction;
21
+
22
+ /**
23
+ * Permet de construire une relance courante
24
+ *
25
+ * @return ShopymindClient_Reminders_DroppedOutCart
26
+ */
27
+ public static function factory(array $params) {
28
+ if (!isset($params['intervalAction'])) {
29
+ return 'intervalAction param missing';
30
+ }
31
+
32
+ $relaunch = new self;
33
+ $relaunch->setGenericOptions($params);
34
+
35
+ return $relaunch;
36
+ }
37
+
38
+ /**
39
+ * Permet de récupérer le nombre d'heure de panier innactif
40
+ *
41
+ * @return int
42
+ */
43
+ public function getNbHours() {
44
+ return $this->_nbHours;
45
+ }
46
+
47
+ /**
48
+ * Permet de modifier le nombre d'heure d'inactivité de panier
49
+ *
50
+ * @param int $nbHours
51
+ * @return ShopymindClient_Reminders_DroppedOutCart
52
+ */
53
+ public function setNbHours($nbHours) {
54
+ $this->_nbHours = (int) $nbHours;
55
+ return $this;
56
+ }
57
+
58
+ /**
59
+ * Permet de récupérer les données de la BDD
60
+ *
61
+ * @return array
62
+ */
63
+ public function get() {
64
+ require dirname(__FILE__) . '/../../callback.php';
65
+ if (method_exists('ShopymindClient_Callback', 'getDroppedOutCart')) {
66
+ return ShopymindClient_Callback::getDroppedOutCart($this->getIntervalAction(), $this->getJustCount());
67
+ }
68
+
69
+ return null;
70
+ }
71
+
72
+ /**
73
+ * Permet d'obtenir le nombre d'heure d'inactivité de panier
74
+ *
75
+ * @return int
76
+ */
77
+ public function getIntervalAction() {
78
+ return $this->_intervalAction;
79
+ }
80
+
81
+ /**
82
+ * Permet de modifier le nombre d'heure d'inactivité de panier
83
+ *
84
+ * @param int $intervalAction
85
+ * @return ShopymindClient_Reminders_DroppedOutCart
86
+ */
87
+ public function setIntervalAction($intervalAction) {
88
+ $this->_intervalAction = $intervalAction;
89
+ return $this;
90
+ }
91
+
92
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/Reminders/GoodClientsByAmount.php ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * GoodClientsByAmount
4
+ *
5
+ * @package ShopymindClient_Reminders
6
+ * @copyright Copyright (c) 2013 - IDVIVE SARL (http://www.idvive.com)
7
+ * @license New BSD license (http://license.idvive.com)
8
+ * @author Yannick Dalbin <yannick@idvive.com>
9
+ * @version $Id GoodClientsByAmount.php 2013-07-19$
10
+ */
11
+ require_once dirname(__FILE__) . '/Abstract.php';
12
+
13
+ class ShopymindClient_Reminders_GoodClientsByAmount extends ShopymindClient_Reminders_Abstract {
14
+
15
+ /**
16
+ * Le montant minimum de commande qui correspond au critère
17
+ *
18
+ * @var double
19
+ */
20
+ protected $_amount;
21
+
22
+ /**
23
+ * Le montant maximum de commande qui correspond au critère
24
+ *
25
+ * @var double
26
+ */
27
+ protected $_amountMax;
28
+
29
+
30
+ /**
31
+ * Le nombre de jours comptabilisé
32
+ *
33
+ * @var int
34
+ */
35
+ protected $_nbDays;
36
+
37
+ /**
38
+ * Le nombre de jours minimum depuis la dernière commande
39
+ *
40
+ * @var int
41
+ */
42
+ protected $_nbDaysLastOrder;
43
+
44
+
45
+ protected $_dateReference;
46
+
47
+ protected $_timezones;
48
+
49
+ public static function factory(array $params) {
50
+ if (!isset($params['timezones'])) {
51
+ return "timezones param missing";
52
+ }
53
+
54
+ if (!isset($params['amount'])) {
55
+ return "amount param missing";
56
+ }
57
+
58
+ if (!isset($params['nbDays'])) {
59
+ return 'nbDays param missing';
60
+ }
61
+ if (!isset($params['nbDaysLastOrder'])) {
62
+ return 'nbDaysLastOrder param missing';
63
+ }
64
+
65
+ if (!isset($params['dateReference'])) {
66
+ return 'dateReference param missing';
67
+ }
68
+
69
+ $relaunch = new self;
70
+ $relaunch->setGenericOptions($params);
71
+
72
+ return $relaunch;
73
+ }
74
+
75
+ /**
76
+ * Permet d'obtenir le montant minimum
77
+ *
78
+ * @return double
79
+ */
80
+ public function getAmount() {
81
+ return $this->_amount;
82
+ }
83
+
84
+ /**
85
+ * Permet de modifier le montant minimum
86
+ *
87
+ * @param double $amount
88
+ * @return ShopymindClient_Reminders_GoodClientsByAmount
89
+ */
90
+ public function setAmount($amount) {
91
+ $this->_amount = $amount;
92
+ return $this;
93
+ }
94
+
95
+ /**
96
+ * Permet d'obtenir le montant maximum
97
+ *
98
+ * @return double
99
+ */
100
+ public function getAmountMax() {
101
+ return $this->_amountMax;
102
+ }
103
+
104
+ /**
105
+ * Permet de modifier le montant maximum
106
+ *
107
+ * @param double $amountMax
108
+ * @return ShopymindClient_Reminders_GoodClientsByAmount
109
+ */
110
+ public function setAmountMax($amountMax) {
111
+ $this->_amountMax = $amountMax;
112
+ return $this;
113
+ }
114
+
115
+ /**
116
+ * Permet d'obtenir le nombre de jour
117
+ *
118
+ * @return int
119
+ */
120
+ public function getNbDays() {
121
+ return $this->_nbDays;
122
+ }
123
+
124
+ /**
125
+ * Permet de modifier le nombre de jours
126
+ *
127
+ * @param int $nbDays
128
+ * @return ShopymindClient_Reminders_GoodClientsByAmount
129
+ */
130
+ public function setNbDays($nbDays) {
131
+ $this->_nbDays = $nbDays;
132
+ return $this;
133
+ }
134
+
135
+ /**
136
+ * Permet d'obtenir le nombre de jours de la dernière commande
137
+ *
138
+ * @return int
139
+ */
140
+ public function getNbDaysLastOrder() {
141
+ return $this->_nbDaysLastOrder;
142
+ }
143
+
144
+ /**
145
+ * Permet de modifier le nombre de jours de la dernière commande
146
+ *
147
+ * @param int $nbDays
148
+ * @return ShopymindClient_Reminders_GoodClientsByAmount
149
+ */
150
+ public function setNbDaysLastOrder($nbDaysLastOrder) {
151
+ $this->_nbDaysLastOrder = $nbDaysLastOrder;
152
+ return $this;
153
+ }
154
+
155
+ public function get() {
156
+ require dirname(__FILE__) . '/../../callback.php';
157
+ if (method_exists('ShopymindClient_Callback', 'getGoodClientsByAmount')) {
158
+ return ShopymindClient_Callback::getGoodClientsByAmount($this->getDateReference(), $this->getTimezones(), $this->getAmount(), $this->getAmountMax(), $this->getNbDays(), $this->getNbDaysLastOrder(), $this->getJustCount());
159
+ }
160
+
161
+ return null;
162
+ }
163
+
164
+ /**
165
+ * Permet de récupérer la date de référence à prendre en compte
166
+ *
167
+ * @return string
168
+ */
169
+ public function getDateReference() {
170
+ return $this->_dateReference;
171
+ }
172
+
173
+ /**
174
+ * Permet de modifier la date de référence à prendre en compte
175
+ *
176
+ * @param string $dateReference
177
+ * @return ShopymindClient_Reminders_BirthdayClients
178
+ */
179
+ public function setDateReference($dateReference) {
180
+ $this->_dateReference = $dateReference;
181
+ return $this;
182
+ }
183
+
184
+ /**
185
+ * Permet de récupérer la liste des fuseaux horaires concernés
186
+ *
187
+ * @return string
188
+ */
189
+ public function getTimezones() {
190
+ return $this->_timezones;
191
+ }
192
+
193
+ /**
194
+ * Permet de modifier la liste des fuseaux horaires conserné
195
+ *
196
+ * @param array $timezones
197
+ * @return ShopymindClient_Reminders_BirthdayClients
198
+ */
199
+ public function setTimezones($timezones) {
200
+ $this->_timezones = $timezones;
201
+ return $this;
202
+ }
203
+
204
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/Reminders/GoodClientsByNumberOrders.php ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * GoodClientsByNumberOrders
4
+ *
5
+ * @package ShopymindClient_Reminders
6
+ * @copyright Copyright (c) 2013 - IDVIVE SARL (http://www.idvive.com)
7
+ * @license New BSD license (http://license.idvive.com)
8
+ * @author Yannick Dalbin <yannick@idvive.com>
9
+ * @version $Id GoodClientsByNumberOrders.php 2013-07-19$
10
+ */
11
+ require_once dirname(__FILE__) . '/Abstract.php';
12
+
13
+ class ShopymindClient_Reminders_GoodClientsByNumberOrders extends ShopymindClient_Reminders_Abstract {
14
+
15
+ /**
16
+ * Le nombre total de commande
17
+ *
18
+ * @var int
19
+ */
20
+ protected $_number;
21
+
22
+ /**
23
+ * Le nombre maximum de commande
24
+ *
25
+ * @var int
26
+ */
27
+ protected $_numberMax;
28
+
29
+ /**
30
+ * Le nombre de jours comptabilisé
31
+ *
32
+ * @var int
33
+ */
34
+ protected $_nbDays;
35
+
36
+ /**
37
+ * Le nombre de jours minimum depuis la dernière commande
38
+ *
39
+ * @var int
40
+ */
41
+ protected $_nbDaysLastOrder;
42
+
43
+ protected $_dateReference;
44
+
45
+ protected $_timezones;
46
+
47
+ public static function factory(array $params) {
48
+ if (!isset($params['timezones'])) {
49
+ return "timezones param missing";
50
+ }
51
+
52
+ if (!isset($params['dateReference'])) {
53
+ return 'dateReference param missing';
54
+ }
55
+
56
+ if (!isset($params['number'])) {
57
+ return "number param missing";
58
+ }
59
+
60
+ if (!isset($params['nbDays'])) {
61
+ return 'nbDays param missing';
62
+ }
63
+
64
+ if (!isset($params['nbDaysLastOrder'])) {
65
+ return 'nbDaysLastOrder param missing';
66
+ }
67
+
68
+ $relaunch = new self;
69
+ $relaunch->setGenericOptions($params);
70
+
71
+ return $relaunch;
72
+ }
73
+
74
+ /**
75
+ * Permet d'obtenir le nombre minimum de commande
76
+ *
77
+ * @return double
78
+ */
79
+ public function getNumber() {
80
+ return $this->_number;
81
+ }
82
+
83
+ /**
84
+ * Permet de modifier le nombre minimum de commande
85
+ *
86
+ * @param int $number
87
+ * @return ShopymindClient_Reminders_GoodClientsByAmount
88
+ */
89
+ public function setNumber($number) {
90
+ $this->_number = $number;
91
+ return $this;
92
+ }
93
+
94
+ /**
95
+ * Permet d'obtenir le nombre maximum de commande
96
+ *
97
+ * @return double
98
+ */
99
+ public function getNumberMax() {
100
+ return $this->_numberMax;
101
+ }
102
+
103
+ /**
104
+ * Permet de modifier le nombre maximum de commande
105
+ *
106
+ * @param int $numberMax
107
+ * @return ShopymindClient_Reminders_GoodClientsByAmount
108
+ */
109
+ public function setNumberMax($numberMax) {
110
+ $this->_numberMax = $numberMax;
111
+ return $this;
112
+ }
113
+
114
+ /**
115
+ * Permet d'obtenir la devise
116
+ *
117
+ * @return string
118
+ */
119
+ public function getCurrency() {
120
+ return $this->_currency;
121
+ }
122
+
123
+ /**
124
+ * Permet de modifier la devise
125
+ *
126
+ * @param string $currency
127
+ * @return ShopymindClient_Reminders_GoodClientsByAmount
128
+ */
129
+ public function setCurrency($currency) {
130
+ $this->_currency = $currency;
131
+ return $this;
132
+ }
133
+
134
+ /**
135
+ * Permet d'obtenir le nombre de jour
136
+ *
137
+ * @return int
138
+ */
139
+ public function getNbDays() {
140
+ return $this->_nbDays;
141
+ }
142
+
143
+ /**
144
+ * Permet de modifier le nombre de jours
145
+ *
146
+ * @param int $nbDays
147
+ * @return ShopymindClient_Reminders_GoodClientsByAmount
148
+ */
149
+ public function setNbDays($nbDays) {
150
+ $this->_nbDays = $nbDays;
151
+ return $this;
152
+ }
153
+
154
+ /**
155
+ * Permet d'obtenir le nombre de jours de la dernière commande
156
+ *
157
+ * @return int
158
+ */
159
+ public function getNbDaysLastOrder() {
160
+ return $this->_nbDaysLastOrder;
161
+ }
162
+
163
+ /**
164
+ * Permet de modifier le nombre de jours de la dernière commande
165
+ *
166
+ * @param int $nbDays
167
+ * @return ShopymindClient_Reminders_GoodClientsByAmount
168
+ */
169
+ public function setNbDaysLastOrder($nbDaysLastOrder) {
170
+ $this->_nbDaysLastOrder = $nbDaysLastOrder;
171
+ return $this;
172
+ }
173
+
174
+ public function get() {
175
+ require dirname(__FILE__) . '/../../callback.php';
176
+ if (method_exists('ShopymindClient_Callback', 'getGoodClientsByNumberOrders')) {
177
+ return ShopymindClient_Callback::getGoodClientsByNumberOrders($this->getDateReference(), $this->getTimezones(), $this->getNumber(), $this->getNumberMax(), $this->getNbDays(), $this->getNbDaysLastOrder(), $this->getJustCount());
178
+ }
179
+
180
+ return null;
181
+ }
182
+
183
+ /**
184
+ * Permet de récupérer la date de référence à prendre en compte
185
+ *
186
+ * @return string
187
+ */
188
+ public function getDateReference() {
189
+ return $this->_dateReference;
190
+ }
191
+
192
+ /**
193
+ * Permet de modifier la date de référence à prendre en compte
194
+ *
195
+ * @param string $dateReference
196
+ * @return ShopymindClient_Reminders_BirthdayClients
197
+ */
198
+ public function setDateReference($dateReference) {
199
+ $this->_dateReference = $dateReference;
200
+ return $this;
201
+ }
202
+
203
+ /**
204
+ * Permet de récupérer la liste des timezones concernés
205
+ *
206
+ * @return string
207
+ */
208
+ public function getTimezones() {
209
+ return $this->_timezones;
210
+ }
211
+
212
+ /**
213
+ * Permet de modifier la liste des timezones concernés
214
+ *
215
+ * @param array $timezones
216
+ * @return ShopymindClient_Reminders_BirthdayClients
217
+ */
218
+ public function setTimezones($timezones) {
219
+ $this->_timezones = $timezones;
220
+ return $this;
221
+ }
222
+
223
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/Reminders/MissingClients.php ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * MissingClients
4
+ *
5
+ * @package ShopymindClient_Reminders
6
+ * @copyright Copyright (c) 2013 - IDVIVE SARL (http://www.idvive.com)
7
+ * @license New BSD license (http://license.idvive.com)
8
+ * @author Yannick Dalbin <yannick@idvive.com>
9
+ * @version $Id MissingClients.php 2013-04-24$
10
+ */
11
+ require_once dirname(__FILE__) . '/Abstract.php';
12
+
13
+ class ShopymindClient_Reminders_MissingClients extends ShopymindClient_Reminders_Abstract {
14
+
15
+ /**
16
+ * Nombre de jours sans commandes
17
+ * O = jamais de commandes
18
+ *
19
+ * @var int
20
+ */
21
+ protected $_nbDays;
22
+
23
+ protected $_dateReference;
24
+
25
+ protected $_timezones;
26
+
27
+ protected $_relaunchOlder = false;
28
+
29
+ /**
30
+ * Permet de construire une relance courante
31
+ *
32
+ * @return ShopymindClient_Reminders_MissingClients
33
+ */
34
+ public static function factory(array $params) {
35
+ if (!isset($params['timezones'])) {
36
+ return 'timezones param missing';
37
+ }
38
+
39
+ if (!isset($params['dateReference'])) {
40
+ return 'dateReference param missing';
41
+ }
42
+
43
+ if (!isset($params['nbDays'])) {
44
+ return 'nbDays param missing';
45
+ }
46
+
47
+ $relaunch = new self;
48
+ $relaunch->setGenericOptions($params);
49
+
50
+ return $relaunch;
51
+ }
52
+
53
+ /**
54
+ * Permet de récupérer le nombre de jours sans commandes
55
+ *
56
+ * @return int
57
+ */
58
+ public function getNbDays() {
59
+ return $this->_nbDays;
60
+ }
61
+
62
+ /**
63
+ * Permet de modifier le nombre de jours dans commandes
64
+ *
65
+ * @param int $nbDays
66
+ * @return ShopymindClient_Reminders_MissingClients
67
+ */
68
+ public function setNbDays($nbDays) {
69
+ $this->_nbDays = (int) $nbDays;
70
+ return $this;
71
+ }
72
+
73
+ /**
74
+ * Permet de savoir si l'on doit relancer les clients plus anciens que _nbDays
75
+ *
76
+ * @return bool
77
+ */
78
+ public function getRelaunchOlder() {
79
+ return (bool)$this->_relaunchOlder;
80
+ }
81
+
82
+ /**
83
+ * Permet de modifier la variable _relaunchOlder
84
+ *
85
+ * @param bool $relaunchOlder
86
+ * @return ShopymindClient_Reminders_MissingClients
87
+ */
88
+ public function setRelaunchOlder($relaunchOlder) {
89
+ $this->_relaunchOlder = (bool) $relaunchOlder;
90
+ return $this;
91
+ }
92
+
93
+ /**
94
+ * Permet de récupérer les données de la BDD
95
+ *
96
+ * @return array
97
+ */
98
+ public function get() {
99
+ require dirname(__FILE__) . '/../../callback.php';
100
+ if (method_exists('ShopymindClient_Callback', 'getMissingClients')) {
101
+ return ShopymindClient_Callback::getMissingClients($this->getDateReference(), $this->getTimezones(), $this->getNbDays(), $this->getRelaunchOlder(), $this->getJustCount());
102
+ }
103
+
104
+ return null;
105
+ }
106
+
107
+ /**
108
+ * Permet de récupérer la date de référence à prendre en compte
109
+ *
110
+ * @return string
111
+ */
112
+ public function getDateReference() {
113
+ return $this->_dateReference;
114
+ }
115
+
116
+ /**
117
+ * Permet de modifier la date de référence à prendre en compte
118
+ *
119
+ * @param string $dateReference
120
+ * @return ShopymindClient_Reminders_BirthdayClients
121
+ */
122
+ public function setDateReference($dateReference) {
123
+ $this->_dateReference = $dateReference;
124
+ return $this;
125
+ }
126
+
127
+ /**
128
+ * Permet de récupérer la liste des timezones
129
+ *
130
+ * @return string
131
+ */
132
+ public function getTimezones() {
133
+ return $this->_timezones;
134
+ }
135
+
136
+ /**
137
+ * Permet de modifier la liste des timezones concernés
138
+ *
139
+ * @param array $timezones
140
+ * @return ShopymindClient_Reminders_
141
+ */
142
+ public function setTimezones(array $timezones) {
143
+ $this->_timezones = $timezones;
144
+ return $this;
145
+ }
146
+
147
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/Reminders/OrdersByStatus.php ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * OrdersByStatus
4
+ *
5
+ * @package ShopymindClient_Reminders
6
+ * @copyright Copyright (c) 2013 - IDVIVE SARL (http://www.idvive.com)
7
+ * @license New BSD license (http://license.idvive.com)
8
+ * @author Yannick Dalbin <yannick@idvive.com>
9
+ * @version $Id OrdersByStatus.php 2013-04-24$
10
+ */
11
+ require_once dirname(__FILE__) . '/Abstract.php';
12
+
13
+ class ShopymindClient_Reminders_OrdersByStatus extends ShopymindClient_Reminders_Abstract {
14
+
15
+ /**
16
+ * Nombre de jours sans paiement finalisé
17
+ *
18
+ * @var int
19
+ */
20
+ protected $_nbDays;
21
+
22
+ /**
23
+ * ID du status de la commande concernée
24
+ *
25
+ * 0var mixed
26
+ */
27
+ protected $_idStatus;
28
+
29
+ protected $_dateReference;
30
+
31
+ protected $_timezones;
32
+
33
+ /**
34
+ * Permet de construire une relance courante
35
+ *
36
+ * @return ShopymindClient_Reminders_NotFinalizedPayments
37
+ */
38
+ public static function factory(array $params) {
39
+ if (!isset($params['timezones'])) {
40
+ return 'timezones param missing';
41
+ }
42
+
43
+ if (!isset($params['dateReference'])) {
44
+ return 'dateReference param missing';
45
+ }
46
+
47
+ if (!isset($params['nbDays'])) {
48
+ return 'nbDays param missing';
49
+ }
50
+
51
+ if (!isset($params['idStatus'])) {
52
+ return 'idStatus param missing';
53
+ }
54
+
55
+ $relaunch = new self;
56
+ $relaunch->setGenericOptions($params);
57
+
58
+ return $relaunch;
59
+ }
60
+
61
+ /**
62
+ * Permet de récupérer le nombre de jours sans commandes
63
+ *
64
+ * @return int
65
+ */
66
+ public function getNbDays() {
67
+ return $this->_nbDays;
68
+ }
69
+
70
+ /**
71
+ * Permet de modifier le nombre de jours dans commandes
72
+ *
73
+ * @param int $nbDays
74
+ * @return ShopymindClient_Reminders_NotFinalizedPayments
75
+ */
76
+ public function setNbDays($nbDays) {
77
+ $this->_nbDays = (int) $nbDays;
78
+ return $this;
79
+ }
80
+
81
+ /**
82
+ * Permet de récupérer les données de la BDD
83
+ *
84
+ * @return array
85
+ */
86
+ public function get() {
87
+ require dirname(__FILE__) . '/../../callback.php';
88
+ if (method_exists('ShopymindClient_Callback', 'getOrdersStatus')) {
89
+ return ShopymindClient_Callback::getOrdersByStatus($this->getDateReference(), $this->getTimezones(), $this->getNbDays(), $this->getIdStatus(), $this->getJustCount());
90
+ }
91
+
92
+ return null;
93
+ }
94
+
95
+ /**
96
+ * Permet d'obtenir l'id du status concerné
97
+ *
98
+ * @return mixed
99
+ */
100
+ public function getIdStatus() {
101
+ return $this->_idStatus;
102
+ }
103
+
104
+ /**
105
+ * Permet de modifier l'id du status concerné
106
+ *
107
+ * @param mixed $idStatus
108
+ * @return ShopymindClient_Reminders_OrdersByStatus
109
+ */
110
+ public function setIdStatus($idStatus) {
111
+ $this->_idStatus = $idStatus;
112
+ return $this;
113
+ }
114
+
115
+ /**
116
+ * Permet de récupérer la date de référence à prendre en compte
117
+ *
118
+ * @return string
119
+ */
120
+ public function getDateReference() {
121
+ return $this->_dateReference;
122
+ }
123
+
124
+ /**
125
+ * Permet de modifier la date de référence à prendre en compte
126
+ *
127
+ * @param string $dateReference
128
+ * @return ShopymindClient_Reminders_BirthdayClients
129
+ */
130
+ public function setDateReference($dateReference) {
131
+ $this->_dateReference = substr($dateReference, 0, 10) . ' 00:00:00';
132
+ return $this;
133
+ }
134
+
135
+ /**
136
+ * Permet de récupérer la liste des timezones
137
+ *
138
+ * @return string
139
+ */
140
+ public function getTimezones() {
141
+ return $this->_timezones;
142
+ }
143
+
144
+ /**
145
+ * Permet de modifier la liste des timezones
146
+ *
147
+ * @param array $timezones
148
+ * @return ShopymindClient_Reminders_BirthdayClients
149
+ */
150
+ public function setTimezones(array $timezones) {
151
+ $this->_timezones = $timezones;
152
+ return $this;
153
+ }
154
+
155
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/Reminders/VoucherUnused.php ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * VoucherUnused
4
+ *
5
+ * @package ShopymindClient_Reminders
6
+ * @copyright Copyright (c) 2013 - IDVIVE SARL (http://www.idvive.com)
7
+ * @license New BSD license (http://license.idvive.com)
8
+ * @author Yannick Dalbin <yannick@idvive.com>
9
+ * @version $Id VoucherUnused.php 2013-04-24$
10
+ */
11
+ require_once dirname(__FILE__) . '/Abstract.php';
12
+
13
+ class ShopymindClient_Reminders_VoucherUnused extends ShopymindClient_Reminders_Abstract {
14
+
15
+ /**
16
+ * Nombre de jours avant expiration
17
+ *
18
+ * @var int
19
+ */
20
+ protected $_nbDays;
21
+
22
+ protected $_dateReference;
23
+
24
+ protected $_timezones;
25
+
26
+ protected $_startBy;
27
+
28
+ protected $_excludeSPM;
29
+
30
+ /**
31
+ * Permet de construire une relance courante
32
+ *
33
+ * @return ShopymindClient_Reminders_VoucherUnused
34
+ */
35
+ public static function factory(array $params) {
36
+ if (!isset($params['timezones'])) {
37
+ return 'timezones param missing';
38
+ }
39
+
40
+ if (!isset($params['dateReference'])) {
41
+ return 'dateReference param missing';
42
+ }
43
+
44
+ if (!isset($params['nbDays'])) {
45
+ return 'nbDays param missing';
46
+ }
47
+
48
+ $relaunch = new self;
49
+ $relaunch->setGenericOptions($params);
50
+
51
+ return $relaunch;
52
+ }
53
+
54
+ /**
55
+ * Permet de récupérer l'option d'exclusion des codes SPM
56
+ *
57
+ * @return int
58
+ */
59
+ public function getExcludeSPM() {
60
+ return $this->_excludeSPM;
61
+ }
62
+
63
+ /**
64
+ * Permet de modifier l'option d'exclusion des codes SPM
65
+ *
66
+ * @param int $excludeSPM
67
+ * @return ShopymindClient_Reminders_VoucherUnused
68
+ */
69
+ public function setExcludeSPM($excludeSPM) {
70
+ $this->_excludeSPM = (int) $excludeSPM;
71
+ return $this;
72
+ }
73
+
74
+ /**
75
+ * Permet de récupérer la conditionnelle du code de réduction
76
+ *
77
+ * @return int
78
+ */
79
+ public function getStartBy() {
80
+ return $this->_startBy;
81
+ }
82
+
83
+ /**
84
+ * Permet de modifier la conditionnelle du code de réduction
85
+ *
86
+ * @param int $startBy
87
+ * @return ShopymindClient_Reminders_VoucherUnused
88
+ */
89
+ public function setStartBy($startBy) {
90
+ $this->_startBy = $startBy;
91
+ return $this;
92
+ }
93
+
94
+ /**
95
+ * Permet de récupérer le nombre de jours avant expiration du bon de réduction
96
+ *
97
+ * @return int
98
+ */
99
+ public function getNbDays() {
100
+ return $this->_nbDays;
101
+ }
102
+
103
+ /**
104
+ * Permet de modifier le nombre de jours avant expiration du bon
105
+ *
106
+ * @param int $nbDayExpiration
107
+ * @return ShopymindClient_Reminders_VoucherUnused
108
+ */
109
+ public function setNbDays($nbDays) {
110
+ $this->_nbDays = (int) $nbDays;
111
+ return $this;
112
+ }
113
+
114
+ /**
115
+ * Permet de récupérer les données de la BDD
116
+ *
117
+ * @return array
118
+ */
119
+ public function get() {
120
+ require dirname(__FILE__) . '/../../callback.php';
121
+ if (method_exists('ShopymindClient_Callback', 'getVoucherUnused')) {
122
+ return ShopymindClient_Callback::getVoucherUnused($this->getDateReference(), $this->getTimezones(), $this->getNbDays(), $this->getStartBy(), $this->getJustCount());
123
+ }
124
+
125
+ return null;
126
+ }
127
+
128
+ /**
129
+ * Permet de récupérer la date de référence à prendre en compte
130
+ *
131
+ * @return string
132
+ */
133
+ public function getDateReference() {
134
+ return $this->_dateReference;
135
+ }
136
+
137
+ /**
138
+ * Permet de modifier la date de référence à prendre en compte
139
+ *
140
+ * @param string $dateReference
141
+ * @return ShopymindClient_Reminders_BirthdayClients
142
+ */
143
+ public function setDateReference($dateReference) {
144
+ $this->_dateReference = substr($dateReference, 0, 10) . ' 00:00:00';
145
+ return $this;
146
+ }
147
+
148
+ /**
149
+ * Permet de récupérer la liste des timezones
150
+ *
151
+ * @return string
152
+ */
153
+ public function getTimezones() {
154
+ return $this->_timezones;
155
+ }
156
+
157
+ /**
158
+ * Permet de modifier la liste des timezones
159
+ *
160
+ * @param array $timezones
161
+ * @return ShopymindClient_Reminders_BirthdayClients
162
+ */
163
+ public function setTimezones(array $timezones) {
164
+ $this->_timezones = $timezones;
165
+ return $this;
166
+ }
167
+
168
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/Server.php ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Server
4
+ *
5
+ * @package ShopymindClient
6
+ * @copyright Copyright (c) 2013 - IDVIVE SARL (http://www.idvive.com)
7
+ * @license New BSD license (http://license.idvive.com)
8
+ * @author Yannick Dalbin <yannick@idvive.com>
9
+ * @version $Id Server.php 2013-04-23$
10
+ */
11
+
12
+ require_once dirname(__FILE__) . '/library/SZend/Controller/Request/Http.php';
13
+ require_once dirname(__FILE__) . '/library/SZend/Json.php';
14
+
15
+ if (!isset($SHOPYMIND_CLIENT_CONFIGURATION)) {
16
+ global $SHOPYMIND_CLIENT_CONFIGURATION;
17
+ $SHOPYMIND_CLIENT_CONFIGURATION = array_merge_recursive(
18
+ require dirname(__FILE__) . '/definitions.php',
19
+ require dirname(__FILE__) . '/../configuration.php'
20
+ );
21
+ }
22
+
23
+ final class ShopymindClient_Server {
24
+
25
+ /**
26
+ * Requête http
27
+ *
28
+ * @var SZend_Controller_Request_Http
29
+ */
30
+ private $_request;
31
+
32
+ public function __construct() {
33
+ $this->_initRequest();
34
+ }
35
+
36
+ private function _initRequest() {
37
+ $this->setRequest(new SZend_Controller_Request_Http);
38
+ }
39
+ protected function formatString($value, $key, $options) {
40
+ if (!empty($value)) {
41
+ $options['glued_string'] .= $key.$options['glue'];
42
+ $options['glued_string'] .= $value.$options['glue'];
43
+ }
44
+ }
45
+ private function implode_recursive(array $array, $glue = ';') {
46
+ $glued_string = '';
47
+ // Recursively iterates array and adds key/value to glued string
48
+ array_walk_recursive($array, array($this, 'formatString'), array('glue' => $glue, 'glued_string' => &$glued_string));
49
+ // Removes last $glue from string
50
+ strlen($glue) > 0 and $glued_string = substr($glued_string, 0, -strlen($glue));
51
+
52
+ // Trim ALL whitespace
53
+ $glued_string = preg_replace("/(\s)/ixsm", '', $glued_string);
54
+
55
+ return (string) $glued_string;
56
+ }
57
+
58
+ public function isValid($data = null) {
59
+ global $SHOPYMIND_CLIENT_CONFIGURATION;
60
+ $config = $SHOPYMIND_CLIENT_CONFIGURATION;
61
+
62
+ $client_id = $this->getRequest()->getHeader($config['header']['client_id']);
63
+ $request_hmac = $this->getRequest()->getHeader($config['header']['hmac']);
64
+
65
+ if ($data === null) {
66
+ if ($this->getRequest()->isPost()) {
67
+ $data = $this->getRequest()->getPost();
68
+ }
69
+ elseif ($this->getRequest()->isGet()) {
70
+ $data = $this->getRequest()->getQuery();
71
+ }
72
+ }
73
+
74
+ if (is_array($data)) {
75
+ uksort($data, 'strnatcasecmp');
76
+ $data = $this->implode_recursive($data);
77
+ }
78
+
79
+ $hmac = hash_hmac('sha256', $data, sha1($config['api']['password']));
80
+
81
+ return (md5($hmac) === md5($request_hmac) && md5($config['api']['identifiant']) === md5($client_id));
82
+ }
83
+
84
+
85
+ /**
86
+ * Permet de renseigner une request
87
+ *
88
+ * @param SZend_Controller_Request_Http $request
89
+ * @return ShopymindClient_Server
90
+ */
91
+ public function setRequest($request) {
92
+ $this->_request = $request;
93
+ return $this;
94
+ }
95
+
96
+ /**
97
+ * Permet de récupérer la requête
98
+ *
99
+ * @return SZend_Controller_Request_Http
100
+ */
101
+ public function getRequest() {
102
+ return $this->_request;
103
+ }
104
+
105
+ /**
106
+ * Permet de retrouver la relance concernée par la requête
107
+ *
108
+ * @return string
109
+ */
110
+ public function retrieveRelaunch() {
111
+ global $SHOPYMIND_CLIENT_CONFIGURATION;
112
+ $config = $SHOPYMIND_CLIENT_CONFIGURATION;
113
+ if ($this->getRequest()->isPost()) {
114
+ $relaunch = $this->getRequest()->getPost($config['get']['relaunch']);
115
+ }
116
+ elseif ($this->getRequest()->isGet()) {
117
+ $relaunch = $this->getRequest()->getQuery($config['get']['relaunch']);
118
+ }
119
+ if ($relaunch !== null) {
120
+ return str_replace(' ', '', ucwords(str_replace('-', ' ', $relaunch)));
121
+ }
122
+
123
+ return null;
124
+ }
125
+
126
+ /**
127
+ * Permet de retrouver les paramètres de relance
128
+ *
129
+ * @return array
130
+ */
131
+ public function retrieveParams() {
132
+ global $SHOPYMIND_CLIENT_CONFIGURATION;
133
+ $config = $SHOPYMIND_CLIENT_CONFIGURATION;
134
+
135
+ $getDefined = $config['get'];
136
+ $params = array();
137
+ if ($this->getRequest()->isPost()) {
138
+ $paramsReceive = $this->getRequest()->getPost();
139
+ }
140
+ elseif ($this->getRequest()->isGet()) {
141
+ $paramsReceive = $this->getRequest()->getQuery();
142
+ }
143
+ foreach ($paramsReceive as $name => $val) {
144
+ if (!in_array($name, $params)) {
145
+ $params[$name] = $val;
146
+ }
147
+ }
148
+
149
+ return $params;
150
+ }
151
+
152
+ /**
153
+ * Permet de récupérer le type de requête que l'on souhaite executer
154
+ *
155
+ * @return string
156
+ */
157
+ public function getTypeRequest() {
158
+ global $SHOPYMIND_CLIENT_CONFIGURATION;
159
+ $config = $SHOPYMIND_CLIENT_CONFIGURATION;
160
+ return $this->getRequest()->getHeader($config['get']['type-request']);
161
+ }
162
+
163
+ /**
164
+ * Permet d'envoyer une réponse
165
+ *
166
+ * @param array|string $data
167
+ * @return string
168
+ */
169
+ public function sendResponse(array $data, $success = true) {
170
+ header('Cache-Control: no-cache, must-revalidate');
171
+ header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
172
+ header('Content-type: application/json');
173
+
174
+ if (!isset($data['success'])) {
175
+ $data['success'] = $success;
176
+ }
177
+
178
+ echo SZend_Json::encode($data);
179
+ exit;
180
+ }
181
+
182
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/definitions.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ return array(
4
+
5
+ 'header' => array(
6
+ 'client_id' => 'Shopymind-Client-ID',
7
+ 'version' => 'Shopymind-Client-Version',
8
+ 'build' => 'Shopymind-Client-Build',
9
+ 'hmac' => 'Shopymind-Token',
10
+ ),
11
+
12
+ 'get' => array(
13
+ 'relaunch' => 'relaunch',
14
+ 'type-request' => 'type-request',
15
+ ),
16
+
17
+ 'version' => '1.0.3.1',
18
+
19
+ 'api' => array(
20
+ 'salt' => 'zPz<j.[EaX,]$s3gzkCW;^N.2',
21
+ 'url' => 'http://client.shopymind.com/rest'
22
+ ),
23
+
24
+ );
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Controller/Exception.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SZend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category SZend
16
+ * @package SZend_Controller
17
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ */
20
+
21
+
22
+ /** SZend_Exception */
23
+ require_once dirname(__FILE__) . '/../Exception.php';
24
+
25
+
26
+ /**
27
+ * @category SZend
28
+ * @package SZend_Controller
29
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
30
+ * @license http://framework.zend.com/license/new-bsd New BSD License
31
+ */
32
+ class SZend_Controller_Exception extends SZend_Exception
33
+ {}
34
+
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Controller/Request/Abstract.php ADDED
@@ -0,0 +1,338 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SZend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category SZend
16
+ * @package SZend_Controller
17
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ */
20
+
21
+ /**
22
+ * @category SZend
23
+ * @package SZend_Controller
24
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
25
+ * @license http://framework.zend.com/license/new-bsd New BSD License
26
+ */
27
+ abstract class SZend_Controller_Request_Abstract
28
+ {
29
+ /**
30
+ * Has the action been dispatched?
31
+ * @var boolean
32
+ */
33
+ protected $_dispatched = false;
34
+
35
+ /**
36
+ * Module
37
+ * @var string
38
+ */
39
+ protected $_module;
40
+
41
+ /**
42
+ * Module key for retrieving module from params
43
+ * @var string
44
+ */
45
+ protected $_moduleKey = 'module';
46
+
47
+ /**
48
+ * Controller
49
+ * @var string
50
+ */
51
+ protected $_controller;
52
+
53
+ /**
54
+ * Controller key for retrieving controller from params
55
+ * @var string
56
+ */
57
+ protected $_controllerKey = 'controller';
58
+
59
+ /**
60
+ * Action
61
+ * @var string
62
+ */
63
+ protected $_action;
64
+
65
+ /**
66
+ * Action key for retrieving action from params
67
+ * @var string
68
+ */
69
+ protected $_actionKey = 'action';
70
+
71
+ /**
72
+ * Request parameters
73
+ * @var array
74
+ */
75
+ protected $_params = array();
76
+
77
+ /**
78
+ * Retrieve the module name
79
+ *
80
+ * @return string
81
+ */
82
+ public function getModuleName()
83
+ {
84
+ if (null === $this->_module) {
85
+ $this->_module = $this->getParam($this->getModuleKey());
86
+ }
87
+
88
+ return $this->_module;
89
+ }
90
+
91
+ /**
92
+ * Set the module name to use
93
+ *
94
+ * @param string $value
95
+ * @return SZend_Controller_Request_Abstract
96
+ */
97
+ public function setModuleName($value)
98
+ {
99
+ $this->_module = $value;
100
+ return $this;
101
+ }
102
+
103
+ /**
104
+ * Retrieve the controller name
105
+ *
106
+ * @return string
107
+ */
108
+ public function getControllerName()
109
+ {
110
+ if (null === $this->_controller) {
111
+ $this->_controller = $this->getParam($this->getControllerKey());
112
+ }
113
+
114
+ return $this->_controller;
115
+ }
116
+
117
+ /**
118
+ * Set the controller name to use
119
+ *
120
+ * @param string $value
121
+ * @return SZend_Controller_Request_Abstract
122
+ */
123
+ public function setControllerName($value)
124
+ {
125
+ $this->_controller = $value;
126
+ return $this;
127
+ }
128
+
129
+ /**
130
+ * Retrieve the action name
131
+ *
132
+ * @return string
133
+ */
134
+ public function getActionName()
135
+ {
136
+ if (null === $this->_action) {
137
+ $this->_action = $this->getParam($this->getActionKey());
138
+ }
139
+
140
+ return $this->_action;
141
+ }
142
+
143
+ /**
144
+ * Set the action name
145
+ *
146
+ * @param string $value
147
+ * @return SZend_Controller_Request_Abstract
148
+ */
149
+ public function setActionName($value)
150
+ {
151
+ $this->_action = $value;
152
+ return $this;
153
+ }
154
+
155
+ /**
156
+ * Retrieve the module key
157
+ *
158
+ * @return string
159
+ */
160
+ public function getModuleKey()
161
+ {
162
+ return $this->_moduleKey;
163
+ }
164
+
165
+ /**
166
+ * Set the module key
167
+ *
168
+ * @param string $key
169
+ * @return SZend_Controller_Request_Abstract
170
+ */
171
+ public function setModuleKey($key)
172
+ {
173
+ $this->_moduleKey = (string) $key;
174
+ return $this;
175
+ }
176
+
177
+ /**
178
+ * Retrieve the controller key
179
+ *
180
+ * @return string
181
+ */
182
+ public function getControllerKey()
183
+ {
184
+ return $this->_controllerKey;
185
+ }
186
+
187
+ /**
188
+ * Set the controller key
189
+ *
190
+ * @param string $key
191
+ * @return SZend_Controller_Request_Abstract
192
+ */
193
+ public function setControllerKey($key)
194
+ {
195
+ $this->_controllerKey = (string) $key;
196
+ return $this;
197
+ }
198
+
199
+ /**
200
+ * Retrieve the action key
201
+ *
202
+ * @return string
203
+ */
204
+ public function getActionKey()
205
+ {
206
+ return $this->_actionKey;
207
+ }
208
+
209
+ /**
210
+ * Set the action key
211
+ *
212
+ * @param string $key
213
+ * @return SZend_Controller_Request_Abstract
214
+ */
215
+ public function setActionKey($key)
216
+ {
217
+ $this->_actionKey = (string) $key;
218
+ return $this;
219
+ }
220
+
221
+ /**
222
+ * Get an action parameter
223
+ *
224
+ * @param string $key
225
+ * @param mixed $default Default value to use if key not found
226
+ * @return mixed
227
+ */
228
+ public function getParam($key, $default = null)
229
+ {
230
+ $key = (string) $key;
231
+ if (isset($this->_params[$key])) {
232
+ return $this->_params[$key];
233
+ }
234
+
235
+ return $default;
236
+ }
237
+
238
+ /**
239
+ * Retrieve only user params (i.e, any param specific to the object and not the environment)
240
+ *
241
+ * @return array
242
+ */
243
+ public function getUserParams()
244
+ {
245
+ return $this->_params;
246
+ }
247
+
248
+ /**
249
+ * Retrieve a single user param (i.e, a param specific to the object and not the environment)
250
+ *
251
+ * @param string $key
252
+ * @param string $default Default value to use if key not found
253
+ * @return mixed
254
+ */
255
+ public function getUserParam($key, $default = null)
256
+ {
257
+ if (isset($this->_params[$key])) {
258
+ return $this->_params[$key];
259
+ }
260
+
261
+ return $default;
262
+ }
263
+
264
+ /**
265
+ * Set an action parameter
266
+ *
267
+ * A $value of null will unset the $key if it exists
268
+ *
269
+ * @param string $key
270
+ * @param mixed $value
271
+ * @return SZend_Controller_Request_Abstract
272
+ */
273
+ public function setParam($key, $value)
274
+ {
275
+ $key = (string) $key;
276
+
277
+ if ((null === $value) && isset($this->_params[$key])) {
278
+ unset($this->_params[$key]);
279
+ } elseif (null !== $value) {
280
+ $this->_params[$key] = $value;
281
+ }
282
+
283
+ return $this;
284
+ }
285
+
286
+ /**
287
+ * Get all action parameters
288
+ *
289
+ * @return array
290
+ */
291
+ public function getParams()
292
+ {
293
+ return $this->_params;
294
+ }
295
+
296
+ /**
297
+ * Set action parameters en masse; does not overwrite
298
+ *
299
+ * Null values will unset the associated key.
300
+ *
301
+ * @param array $array
302
+ * @return SZend_Controller_Request_Abstract
303
+ */
304
+ public function setParams(array $array)
305
+ {
306
+ $this->_params = $this->_params + (array) $array;
307
+
308
+ foreach ($this->_params as $key => $value) {
309
+ if (null === $value) {
310
+ unset($this->_params[$key]);
311
+ }
312
+ }
313
+
314
+ return $this;
315
+ }
316
+
317
+ /**
318
+ * Set flag indicating whether or not request has been dispatched
319
+ *
320
+ * @param boolean $flag
321
+ * @return SZend_Controller_Request_Abstract
322
+ */
323
+ public function setDispatched($flag = true)
324
+ {
325
+ $this->_dispatched = $flag ? true : false;
326
+ return $this;
327
+ }
328
+
329
+ /**
330
+ * Determine if the request has been dispatched
331
+ *
332
+ * @return boolean
333
+ */
334
+ public function isDispatched()
335
+ {
336
+ return $this->_dispatched;
337
+ }
338
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Controller/Request/Exception.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SZend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category SZend
16
+ * @package SZend_Controller
17
+ * @subpackage Request
18
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ */
21
+
22
+
23
+ /** SZend_Controller_Exception */
24
+ require_once dirname(__FILE__) . '/../../Controller/Exception.php';
25
+
26
+
27
+ /**
28
+ * @category SZend
29
+ * @package SZend_Controller
30
+ * @subpackage Request
31
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
32
+ * @license http://framework.zend.com/license/new-bsd New BSD License
33
+ */
34
+ class SZend_Controller_Request_Exception extends SZend_Controller_Exception
35
+ {}
36
+
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Controller/Request/Http.php ADDED
@@ -0,0 +1,885 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SZend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category SZend
16
+ * @package SZend_Controller
17
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ */
20
+
21
+ /** SZend_Controller_Request_Exception */
22
+ require_once dirname(__FILE__) . '/../../Controller/Request/Exception.php';
23
+
24
+ /** SZend_Controller_Request_Abstract */
25
+ require_once dirname(__FILE__) . '/../../Controller/Request/Abstract.php';
26
+
27
+ /** SZend_Uri */
28
+ require_once dirname(__FILE__) . '/../../Uri.php';
29
+
30
+ /**
31
+ * SZend_Controller_Request_Http
32
+ *
33
+ * HTTP request object for use with SZend_Controller family.
34
+ *
35
+ * @uses SZend_Controller_Request_Abstract
36
+ * @package SZend_Controller
37
+ * @subpackage Request
38
+ */
39
+ class SZend_Controller_Request_Http extends SZend_Controller_Request_Abstract
40
+ {
41
+ /**
42
+ * Allowed parameter sources
43
+ * @var array
44
+ */
45
+ protected $_paramSources = array('_GET', '_POST');
46
+
47
+ /**
48
+ * REQUEST_URI
49
+ * @var string;
50
+ */
51
+ protected $_requestUri;
52
+
53
+ /**
54
+ * Base URL of request
55
+ * @var string
56
+ */
57
+ protected $_baseUrl = null;
58
+
59
+ /**
60
+ * Base path of request
61
+ * @var string
62
+ */
63
+ protected $_basePath = null;
64
+
65
+ /**
66
+ * PATH_INFO
67
+ * @var string
68
+ */
69
+ protected $_pathInfo = '';
70
+
71
+ /**
72
+ * Instance parameters
73
+ * @var array
74
+ */
75
+ protected $_params = array();
76
+
77
+ /**
78
+ * Alias keys for request parameters
79
+ * @var array
80
+ */
81
+ protected $_aliases = array();
82
+
83
+ /**
84
+ * Constructor
85
+ *
86
+ * If a $uri is passed, the object will attempt to populate itself using
87
+ * that information.
88
+ *
89
+ * @param string|SZend_Uri $uri
90
+ * @return void
91
+ * @throws SZend_Controller_Request_Exception when invalid URI passed
92
+ */
93
+ public function __construct($uri = null)
94
+ {
95
+ if (null !== $uri) {
96
+ if (!$uri instanceof SZend_Uri) {
97
+ $uri = SZend_Uri::factory($uri);
98
+ }
99
+ if ($uri->valid()) {
100
+ $path = $uri->getPath();
101
+ $query = $uri->getQuery();
102
+ if (!empty($query)) {
103
+ $path .= '?' . $query;
104
+ }
105
+
106
+ $this->setRequestUri($path);
107
+ } else {
108
+ require_once 'SZend/Controller/Request/Exception.php';
109
+ throw new SZend_Controller_Request_Exception('Invalid URI provided to constructor');
110
+ }
111
+ } else {
112
+ $this->setRequestUri();
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Access values contained in the superglobals as public members
118
+ * Order of precedence: 1. GET, 2. POST, 3. COOKIE, 4. SERVER, 5. ENV
119
+ *
120
+ * @see http://msdn.microsoft.com/en-us/library/system.web.httprequest.item.aspx
121
+ * @param string $key
122
+ * @return mixed
123
+ */
124
+ public function __get($key)
125
+ {
126
+ switch (true) {
127
+ case isset($this->_params[$key]):
128
+ return $this->_params[$key];
129
+ case isset($_GET[$key]):
130
+ return $_GET[$key];
131
+ case isset($_POST[$key]):
132
+ return $_POST[$key];
133
+ case isset($_COOKIE[$key]):
134
+ return $_COOKIE[$key];
135
+ case ($key == 'REQUEST_URI'):
136
+ return $this->getRequestUri();
137
+ case ($key == 'PATH_INFO'):
138
+ return $this->getPathInfo();
139
+ case isset($_SERVER[$key]):
140
+ return $_SERVER[$key];
141
+ case isset($_ENV[$key]):
142
+ return $_ENV[$key];
143
+ default:
144
+ return null;
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Alias to __get
150
+ *
151
+ * @param string $key
152
+ * @return mixed
153
+ */
154
+ public function get($key)
155
+ {
156
+ return $this->__get($key);
157
+ }
158
+
159
+ /**
160
+ * Set values
161
+ *
162
+ * In order to follow {@link __get()}, which operates on a number of
163
+ * superglobals, setting values through overloading is not allowed and will
164
+ * raise an exception. Use setParam() instead.
165
+ *
166
+ * @param string $key
167
+ * @param mixed $value
168
+ * @return void
169
+ * @throws SZend_Controller_Request_Exception
170
+ */
171
+ public function __set($key, $value)
172
+ {
173
+ require_once 'SZend/Controller/Request/Exception.php';
174
+ throw new SZend_Controller_Request_Exception('Setting values in superglobals not allowed; please use setParam()');
175
+ }
176
+
177
+ /**
178
+ * Alias to __set()
179
+ *
180
+ * @param string $key
181
+ * @param mixed $value
182
+ * @return void
183
+ */
184
+ public function set($key, $value)
185
+ {
186
+ return $this->__set($key, $value);
187
+ }
188
+
189
+ /**
190
+ * Check to see if a property is set
191
+ *
192
+ * @param string $key
193
+ * @return boolean
194
+ */
195
+ public function __isset($key)
196
+ {
197
+ switch (true) {
198
+ case isset($this->_params[$key]):
199
+ return true;
200
+ case isset($_GET[$key]):
201
+ return true;
202
+ case isset($_POST[$key]):
203
+ return true;
204
+ case isset($_COOKIE[$key]):
205
+ return true;
206
+ case isset($_SERVER[$key]):
207
+ return true;
208
+ case isset($_ENV[$key]):
209
+ return true;
210
+ default:
211
+ return false;
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Alias to __isset()
217
+ *
218
+ * @param string $key
219
+ * @return boolean
220
+ */
221
+ public function has($key)
222
+ {
223
+ return $this->__isset($key);
224
+ }
225
+
226
+ /**
227
+ * Retrieve a member of the $_GET superglobal
228
+ *
229
+ * If no $key is passed, returns the entire $_GET array.
230
+ *
231
+ * @todo How to retrieve from nested arrays
232
+ * @param string $key
233
+ * @param mixed $default Default value to use if key not found
234
+ * @return mixed Returns null if key does not exist
235
+ */
236
+ public function getQuery($key = null, $default = null)
237
+ {
238
+ if (null === $key) {
239
+ return $_GET;
240
+ }
241
+
242
+ return (isset($_GET[$key])) ? $_GET[$key] : $default;
243
+ }
244
+
245
+ /**
246
+ * Retrieve a member of the $_POST superglobal
247
+ *
248
+ * If no $key is passed, returns the entire $_POST array.
249
+ *
250
+ * @todo How to retrieve from nested arrays
251
+ * @param string $key
252
+ * @param mixed $default Default value to use if key not found
253
+ * @return mixed Returns null if key does not exist
254
+ */
255
+ public function getPost($key = null, $default = null)
256
+ {
257
+ if (null === $key) {
258
+ return $_POST;
259
+ }
260
+
261
+ return (isset($_POST[$key])) ? $_POST[$key] : $default;
262
+ }
263
+
264
+ /**
265
+ * Retrieve a member of the $_COOKIE superglobal
266
+ *
267
+ * If no $key is passed, returns the entire $_COOKIE array.
268
+ *
269
+ * @todo How to retrieve from nested arrays
270
+ * @param string $key
271
+ * @param mixed $default Default value to use if key not found
272
+ * @return mixed Returns null if key does not exist
273
+ */
274
+ public function getCookie($key = null, $default = null)
275
+ {
276
+ if (null === $key) {
277
+ return $_COOKIE;
278
+ }
279
+
280
+ return (isset($_COOKIE[$key])) ? $_COOKIE[$key] : $default;
281
+ }
282
+
283
+ /**
284
+ * Retrieve a member of the $_SERVER superglobal
285
+ *
286
+ * If no $key is passed, returns the entire $_SERVER array.
287
+ *
288
+ * @param string $key
289
+ * @param mixed $default Default value to use if key not found
290
+ * @return mixed Returns null if key does not exist
291
+ */
292
+ public function getServer($key = null, $default = null)
293
+ {
294
+ if (null === $key) {
295
+ return $_SERVER;
296
+ }
297
+
298
+ return (isset($_SERVER[$key])) ? $_SERVER[$key] : $default;
299
+ }
300
+
301
+ /**
302
+ * Retrieve a member of the $_ENV superglobal
303
+ *
304
+ * If no $key is passed, returns the entire $_ENV array.
305
+ *
306
+ * @param string $key
307
+ * @param mixed $default Default value to use if key not found
308
+ * @return mixed Returns null if key does not exist
309
+ */
310
+ public function getEnv($key = null, $default = null)
311
+ {
312
+ if (null === $key) {
313
+ return $_ENV;
314
+ }
315
+
316
+ return (isset($_ENV[$key])) ? $_ENV[$key] : $default;
317
+ }
318
+
319
+ /**
320
+ * Set the REQUEST_URI on which the instance operates
321
+ *
322
+ * If no request URI is passed, uses the value in $_SERVER['REQUEST_URI'],
323
+ * $_SERVER['HTTP_X_REWRITE_URL'], or $_SERVER['ORIG_PATH_INFO'] + $_SERVER['QUERY_STRING'].
324
+ *
325
+ * @param string $requestUri
326
+ * @return SZend_Controller_Request_Http
327
+ */
328
+ public function setRequestUri($requestUri = null)
329
+ {
330
+ if ($requestUri === null) {
331
+ if (isset($_SERVER['HTTP_X_REWRITE_URL'])) { // check this first so IIS will catch
332
+ $requestUri = $_SERVER['HTTP_X_REWRITE_URL'];
333
+ } elseif (isset($_SERVER['REQUEST_URI'])) {
334
+ $requestUri = $_SERVER['REQUEST_URI'];
335
+ } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0, PHP as CGI
336
+ $requestUri = $_SERVER['ORIG_PATH_INFO'];
337
+ if (!empty($_SERVER['QUERY_STRING'])) {
338
+ $requestUri .= '?' . $_SERVER['QUERY_STRING'];
339
+ }
340
+ } else {
341
+ return $this;
342
+ }
343
+ } elseif (!is_string($requestUri)) {
344
+ return $this;
345
+ } else {
346
+ // Set GET items, if available
347
+ $_GET = array();
348
+ if (false !== ($pos = strpos($requestUri, '?'))) {
349
+ // Get key => value pairs and set $_GET
350
+ $query = substr($requestUri, $pos + 1);
351
+ parse_str($query, $vars);
352
+ $_GET = $vars;
353
+ }
354
+ }
355
+
356
+ $this->_requestUri = $requestUri;
357
+ return $this;
358
+ }
359
+
360
+ /**
361
+ * Returns the REQUEST_URI taking into account
362
+ * platform differences between Apache and IIS
363
+ *
364
+ * @return string
365
+ */
366
+ public function getRequestUri()
367
+ {
368
+ if (empty($this->_requestUri)) {
369
+ $this->setRequestUri();
370
+ }
371
+
372
+ return $this->_requestUri;
373
+ }
374
+
375
+ /**
376
+ * Set the base URL of the request; i.e., the segment leading to the script name
377
+ *
378
+ * E.g.:
379
+ * - /admin
380
+ * - /myapp
381
+ * - /subdir/index.php
382
+ *
383
+ * Do not use the full URI when providing the base. The following are
384
+ * examples of what not to use:
385
+ * - http://example.com/admin (should be just /admin)
386
+ * - http://example.com/subdir/index.php (should be just /subdir/index.php)
387
+ *
388
+ * If no $baseUrl is provided, attempts to determine the base URL from the
389
+ * environment, using SCRIPT_FILENAME, SCRIPT_NAME, PHP_SELF, and
390
+ * ORIG_SCRIPT_NAME in its determination.
391
+ *
392
+ * @param mixed $baseUrl
393
+ * @return SZend_Controller_Request_Http
394
+ */
395
+ public function setBaseUrl($baseUrl = null)
396
+ {
397
+ if ((null !== $baseUrl) && !is_string($baseUrl)) {
398
+ return $this;
399
+ }
400
+
401
+ if ($baseUrl === null) {
402
+ $filename = basename($_SERVER['SCRIPT_FILENAME']);
403
+
404
+ if (basename($_SERVER['SCRIPT_NAME']) === $filename) {
405
+ $baseUrl = $_SERVER['SCRIPT_NAME'];
406
+ } elseif (basename($_SERVER['PHP_SELF']) === $filename) {
407
+ $baseUrl = $_SERVER['PHP_SELF'];
408
+ } elseif (isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME']) === $filename) {
409
+ $baseUrl = $_SERVER['ORIG_SCRIPT_NAME']; // 1and1 shared hosting compatibility
410
+ } else {
411
+ // Backtrack up the script_filename to find the portion matching
412
+ // php_self
413
+ $path = $_SERVER['PHP_SELF'];
414
+ $segs = explode('/', trim($_SERVER['SCRIPT_FILENAME'], '/'));
415
+ $segs = array_reverse($segs);
416
+ $index = 0;
417
+ $last = count($segs);
418
+ $baseUrl = '';
419
+ do {
420
+ $seg = $segs[$index];
421
+ $baseUrl = '/' . $seg . $baseUrl;
422
+ ++$index;
423
+ } while (($last > $index) && (false !== ($pos = strpos($path, $baseUrl))) && (0 != $pos));
424
+ }
425
+
426
+ // Does the baseUrl have anything in common with the request_uri?
427
+ $requestUri = $this->getRequestUri();
428
+
429
+ if (0 === strpos($requestUri, $baseUrl)) {
430
+ // full $baseUrl matches
431
+ $this->_baseUrl = $baseUrl;
432
+ return $this;
433
+ }
434
+
435
+ if (0 === strpos($requestUri, dirname($baseUrl))) {
436
+ // directory portion of $baseUrl matches
437
+ $this->_baseUrl = rtrim(dirname($baseUrl), '/');
438
+ return $this;
439
+ }
440
+
441
+ if (!strpos($requestUri, basename($baseUrl))) {
442
+ // no match whatsoever; set it blank
443
+ $this->_baseUrl = '';
444
+ return $this;
445
+ }
446
+
447
+ // If using mod_rewrite or ISAPI_Rewrite strip the script filename
448
+ // out of baseUrl. $pos !== 0 makes sure it is not matching a value
449
+ // from PATH_INFO or QUERY_STRING
450
+ if ((strlen($requestUri) >= strlen($baseUrl))
451
+ && ((false !== ($pos = strpos($requestUri, $baseUrl))) && ($pos !== 0)))
452
+ {
453
+ $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl));
454
+ }
455
+ }
456
+
457
+ $this->_baseUrl = rtrim($baseUrl, '/');
458
+ return $this;
459
+ }
460
+
461
+ /**
462
+ * Everything in REQUEST_URI before PATH_INFO
463
+ * <form action="<?=$baseUrl?>/news/submit" method="POST"/>
464
+ *
465
+ * @return string
466
+ */
467
+ public function getBaseUrl()
468
+ {
469
+ if (null === $this->_baseUrl) {
470
+ $this->setBaseUrl();
471
+ }
472
+
473
+ return $this->_baseUrl;
474
+ }
475
+
476
+ /**
477
+ * Set the base path for the URL
478
+ *
479
+ * @param string|null $basePath
480
+ * @return SZend_Controller_Request_Http
481
+ */
482
+ public function setBasePath($basePath = null)
483
+ {
484
+ if ($basePath === null) {
485
+ $filename = basename($_SERVER['SCRIPT_FILENAME']);
486
+
487
+ $baseUrl = $this->getBaseUrl();
488
+ if (empty($baseUrl)) {
489
+ $this->_basePath = '';
490
+ return $this;
491
+ }
492
+
493
+ if (basename($baseUrl) === $filename) {
494
+ $basePath = dirname($baseUrl);
495
+ } else {
496
+ $basePath = $baseUrl;
497
+ }
498
+ }
499
+
500
+ $this->_basePath = rtrim($basePath, '/');
501
+ return $this;
502
+ }
503
+
504
+ /**
505
+ * Everything in REQUEST_URI before PATH_INFO not including the filename
506
+ * <img src="<?=$basePath?>/images/zend.png"/>
507
+ *
508
+ * @return string
509
+ */
510
+ public function getBasePath()
511
+ {
512
+ if (null === $this->_basePath) {
513
+ $this->setBasePath();
514
+ }
515
+
516
+ return $this->_basePath;
517
+ }
518
+
519
+ /**
520
+ * Set the PATH_INFO string
521
+ *
522
+ * @param string|null $pathInfo
523
+ * @return SZend_Controller_Request_Http
524
+ */
525
+ public function setPathInfo($pathInfo = null)
526
+ {
527
+ if ($pathInfo === null) {
528
+ $baseUrl = $this->getBaseUrl();
529
+
530
+ if (null === ($requestUri = $this->getRequestUri())) {
531
+ return $this;
532
+ }
533
+
534
+ // Remove the query string from REQUEST_URI
535
+ if ($pos = strpos($requestUri, '?')) {
536
+ $requestUri = substr($requestUri, 0, $pos);
537
+ }
538
+
539
+ if ((null !== $baseUrl)
540
+ && (false === ($pathInfo = substr($requestUri, strlen($baseUrl)))))
541
+ {
542
+ // If substr() returns false then PATH_INFO is set to an empty string
543
+ $pathInfo = '';
544
+ } elseif (null === $baseUrl) {
545
+ $pathInfo = $requestUri;
546
+ }
547
+ }
548
+
549
+ $this->_pathInfo = (string) $pathInfo;
550
+ return $this;
551
+ }
552
+
553
+ /**
554
+ * Returns everything between the BaseUrl and QueryString.
555
+ * This value is calculated instead of reading PATH_INFO
556
+ * directly from $_SERVER due to cross-platform differences.
557
+ *
558
+ * @return string
559
+ */
560
+ public function getPathInfo()
561
+ {
562
+ if (empty($this->_pathInfo)) {
563
+ $this->setPathInfo();
564
+ }
565
+
566
+ return $this->_pathInfo;
567
+ }
568
+
569
+ /**
570
+ * Set allowed parameter sources
571
+ *
572
+ * Can be empty array, or contain one or more of '_GET' or '_POST'.
573
+ *
574
+ * @param array $paramSoures
575
+ * @return SZend_Controller_Request_Http
576
+ */
577
+ public function setParamSources(array $paramSources = array())
578
+ {
579
+ $this->_paramSources = $paramSources;
580
+ return $this;
581
+ }
582
+
583
+ /**
584
+ * Get list of allowed parameter sources
585
+ *
586
+ * @return array
587
+ */
588
+ public function getParamSources()
589
+ {
590
+ return $this->_paramSources;
591
+ }
592
+
593
+ /**
594
+ * Set a userland parameter
595
+ *
596
+ * Uses $key to set a userland parameter. If $key is an alias, the actual
597
+ * key will be retrieved and used to set the parameter.
598
+ *
599
+ * @param mixed $key
600
+ * @param mixed $value
601
+ * @return SZend_Controller_Request_Http
602
+ */
603
+ public function setParam($key, $value)
604
+ {
605
+ $key = (null !== ($alias = $this->getAlias($key))) ? $alias : $key;
606
+ parent::setParam($key, $value);
607
+ return $this;
608
+ }
609
+
610
+ /**
611
+ * Retrieve a parameter
612
+ *
613
+ * Retrieves a parameter from the instance. Priority is in the order of
614
+ * userland parameters (see {@link setParam()}), $_GET, $_POST. If a
615
+ * parameter matching the $key is not found, null is returned.
616
+ *
617
+ * If the $key is an alias, the actual key aliased will be used.
618
+ *
619
+ * @param mixed $key
620
+ * @param mixed $default Default value to use if key not found
621
+ * @return mixed
622
+ */
623
+ public function getParam($key, $default = null)
624
+ {
625
+ $keyName = (null !== ($alias = $this->getAlias($key))) ? $alias : $key;
626
+
627
+ $paramSources = $this->getParamSources();
628
+ if (isset($this->_params[$keyName])) {
629
+ return $this->_params[$keyName];
630
+ } elseif (in_array('_GET', $paramSources) && (isset($_GET[$keyName]))) {
631
+ return $_GET[$keyName];
632
+ } elseif (in_array('_POST', $paramSources) && (isset($_POST[$keyName]))) {
633
+ return $_POST[$keyName];
634
+ }
635
+
636
+ return $default;
637
+ }
638
+
639
+ /**
640
+ * Retrieve an array of parameters
641
+ *
642
+ * Retrieves a merged array of parameters, with precedence of userland
643
+ * params (see {@link setParam()}), $_GET, $POST (i.e., values in the
644
+ * userland params will take precedence over all others).
645
+ *
646
+ * @return array
647
+ */
648
+ public function getParams()
649
+ {
650
+ $return = $this->_params;
651
+ if (isset($_GET) && is_array($_GET)) {
652
+ $return += $_GET;
653
+ }
654
+ if (isset($_POST) && is_array($_POST)) {
655
+ $return += $_POST;
656
+ }
657
+ return $return;
658
+ }
659
+
660
+ /**
661
+ * Set parameters
662
+ *
663
+ * Set one or more parameters. Parameters are set as userland parameters,
664
+ * using the keys specified in the array.
665
+ *
666
+ * @param array $params
667
+ * @return SZend_Controller_Request_Http
668
+ */
669
+ public function setParams(array $params)
670
+ {
671
+ foreach ($params as $key => $value) {
672
+ $this->setParam($key, $value);
673
+ }
674
+ return $this;
675
+ }
676
+
677
+ /**
678
+ * Set a key alias
679
+ *
680
+ * Set an alias used for key lookups. $name specifies the alias, $target
681
+ * specifies the actual key to use.
682
+ *
683
+ * @param string $name
684
+ * @param string $target
685
+ * @return SZend_Controller_Request_Http
686
+ */
687
+ public function setAlias($name, $target)
688
+ {
689
+ $this->_aliases[$name] = $target;
690
+ return $this;
691
+ }
692
+
693
+ /**
694
+ * Retrieve an alias
695
+ *
696
+ * Retrieve the actual key represented by the alias $name.
697
+ *
698
+ * @param string $name
699
+ * @return string|null Returns null when no alias exists
700
+ */
701
+ public function getAlias($name)
702
+ {
703
+ if (isset($this->_aliases[$name])) {
704
+ return $this->_aliases[$name];
705
+ }
706
+
707
+ return null;
708
+ }
709
+
710
+ /**
711
+ * Retrieve the list of all aliases
712
+ *
713
+ * @return array
714
+ */
715
+ public function getAliases()
716
+ {
717
+ return $this->_aliases;
718
+ }
719
+
720
+ /**
721
+ * Return the method by which the request was made
722
+ *
723
+ * @return string
724
+ */
725
+ public function getMethod()
726
+ {
727
+ return $this->getServer('REQUEST_METHOD');
728
+ }
729
+
730
+ /**
731
+ * Was the request made by POST?
732
+ *
733
+ * @return boolean
734
+ */
735
+ public function isPost()
736
+ {
737
+ if ('POST' == $this->getMethod()) {
738
+ return true;
739
+ }
740
+
741
+ return false;
742
+ }
743
+
744
+ /**
745
+ * Was the request made by GET?
746
+ *
747
+ * @return boolean
748
+ */
749
+ public function isGet()
750
+ {
751
+ if ('GET' == $this->getMethod()) {
752
+ return true;
753
+ }
754
+
755
+ return false;
756
+ }
757
+
758
+ /**
759
+ * Was the request made by PUT?
760
+ *
761
+ * @return boolean
762
+ */
763
+ public function isPut()
764
+ {
765
+ if ('PUT' == $this->getMethod()) {
766
+ return true;
767
+ }
768
+
769
+ return false;
770
+ }
771
+
772
+ /**
773
+ * Was the request made by DELETE?
774
+ *
775
+ * @return boolean
776
+ */
777
+ public function isDelete()
778
+ {
779
+ if ('DELETE' == $this->getMethod()) {
780
+ return true;
781
+ }
782
+
783
+ return false;
784
+ }
785
+
786
+ /**
787
+ * Was the request made by HEAD?
788
+ *
789
+ * @return boolean
790
+ */
791
+ public function isHead()
792
+ {
793
+ if ('HEAD' == $this->getMethod()) {
794
+ return true;
795
+ }
796
+
797
+ return false;
798
+ }
799
+
800
+ /**
801
+ * Was the request made by OPTIONS?
802
+ *
803
+ * @return boolean
804
+ */
805
+ public function isOptions()
806
+ {
807
+ if ('OPTIONS' == $this->getMethod()) {
808
+ return true;
809
+ }
810
+
811
+ return false;
812
+ }
813
+
814
+ /**
815
+ * Return the raw body of the request, if present
816
+ *
817
+ * @return string|false Raw body, or false if not present
818
+ */
819
+ public function getRawBody()
820
+ {
821
+ $body = file_get_contents('php://input');
822
+
823
+ if (strlen(trim($body)) > 0) {
824
+ return $body;
825
+ }
826
+
827
+ return false;
828
+ }
829
+
830
+ /**
831
+ * Return the value of the given HTTP header. Pass the header name as the
832
+ * plain, HTTP-specified header name. Ex.: Ask for 'Accept' to get the
833
+ * Accept header, 'Accept-Encoding' to get the Accept-Encoding header.
834
+ *
835
+ * @param string $header HTTP header name
836
+ * @return string|false HTTP header value, or false if not found
837
+ * @throws SZend_Controller_Request_Exception
838
+ */
839
+ public function getHeader($header)
840
+ {
841
+ if (empty($header)) {
842
+ require_once 'SZend/Controller/Request/Exception.php';
843
+ throw new SZend_Controller_Request_Exception('An HTTP header name is required');
844
+ }
845
+
846
+ // Try to get it from the $_SERVER array first
847
+ $temp = 'HTTP_' . strtoupper(str_replace('-', '_', $header));
848
+ if (!empty($_SERVER[$temp])) {
849
+ return $_SERVER[$temp];
850
+ }
851
+
852
+ // This seems to be the only way to get the Authorization header on
853
+ // Apache
854
+ if (function_exists('apache_request_headers')) {
855
+ $headers = apache_request_headers();
856
+ if (!empty($headers[$header])) {
857
+ return $headers[$header];
858
+ }
859
+ }
860
+
861
+ return false;
862
+ }
863
+
864
+ /**
865
+ * Is the request a Javascript XMLHttpRequest?
866
+ *
867
+ * Should work with Prototype/Script.aculo.us, possibly others.
868
+ *
869
+ * @return boolean
870
+ */
871
+ public function isXmlHttpRequest()
872
+ {
873
+ return ($this->getHeader('X_REQUESTED_WITH') == 'XMLHttpRequest');
874
+ }
875
+
876
+ /**
877
+ * Is this a Flash request?
878
+ *
879
+ * @return bool
880
+ */
881
+ public function isFlashRequest()
882
+ {
883
+ return ($this->getHeader('USER_AGENT') == 'Shockwave Flash');
884
+ }
885
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Exception.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SZend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category SZend
16
+ * @package SZend
17
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ */
20
+
21
+
22
+ /**
23
+ * @category SZend
24
+ * @package SZend
25
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
26
+ * @license http://framework.zend.com/license/new-bsd New BSD License
27
+ */
28
+ class SZend_Exception extends Exception
29
+ {}
30
+
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Http/Client.php ADDED
@@ -0,0 +1,1100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * SZend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category SZend
17
+ * @package SZend_Http
18
+ * @subpackage Client
19
+ * @version $Id: Client.php 8064 2008-02-16 10:58:39Z thomas $
20
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ require_once dirname(__FILE__) . '/../Uri.php';
25
+ require_once dirname(__FILE__) . '/../Http/Client/Adapter/Interface.php';
26
+ require_once dirname(__FILE__) . '/../Http/Response.php';
27
+
28
+ /**
29
+ * SZend_Http_Client is an implemetation of an HTTP client in PHP. The client
30
+ * supports basic features like sending different HTTP requests and handling
31
+ * redirections, as well as more advanced features like proxy settings, HTTP
32
+ * authentication and cookie persistance (using a SZend_Http_CookieJar object)
33
+ *
34
+ * @todo Implement proxy settings
35
+ * @category SZend
36
+ * @package SZend_Http
37
+ * @subpackage Client
38
+ * @throws SZend_Http_Client_Exception
39
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
40
+ * @license http://framework.zend.com/license/new-bsd New BSD License
41
+ */
42
+ class SZend_Http_Client
43
+ {
44
+ /**
45
+ * HTTP request methods
46
+ */
47
+ const GET = 'GET';
48
+ const POST = 'POST';
49
+ const PUT = 'PUT';
50
+ const HEAD = 'HEAD';
51
+ const DELETE = 'DELETE';
52
+ const TRACE = 'TRACE';
53
+ const OPTIONS = 'OPTIONS';
54
+ const CONNECT = 'CONNECT';
55
+
56
+ /**
57
+ * Supported HTTP Authentication methods
58
+ */
59
+ const AUTH_BASIC = 'basic';
60
+ //const AUTH_DIGEST = 'digest'; <-- not implemented yet
61
+
62
+ /**
63
+ * HTTP protocol versions
64
+ */
65
+ const HTTP_1 = '1.1';
66
+ const HTTP_0 = '1.0';
67
+
68
+ /**
69
+ * POST data encoding methods
70
+ */
71
+ const ENC_URLENCODED = 'application/x-www-form-urlencoded';
72
+ const ENC_FORMDATA = 'multipart/form-data';
73
+
74
+ /**
75
+ * Configuration array, set using the constructor or using ::setConfig()
76
+ *
77
+ * @var unknown_type
78
+ */
79
+ protected $config = array(
80
+ 'maxredirects' => 5,
81
+ 'strictredirects' => false,
82
+ 'useragent' => 'SZend_Http_Client',
83
+ 'timeout' => 10,
84
+ 'adapter' => 'SZend_Http_Client_Adapter_Socket',
85
+ 'httpversion' => self::HTTP_1,
86
+ 'keepalive' => false,
87
+ 'storeresponse' => true,
88
+ 'strict' => true
89
+ );
90
+
91
+ /**
92
+ * The adapter used to preform the actual connection to the server
93
+ *
94
+ * @var SZend_Http_Client_Adapter_Interface
95
+ */
96
+ protected $adapter = null;
97
+
98
+ /**
99
+ * Request URI
100
+ *
101
+ * @var SZend_Uri_Http
102
+ */
103
+ protected $uri;
104
+
105
+ /**
106
+ * Associative array of request headers
107
+ *
108
+ * @var array
109
+ */
110
+ protected $headers = array();
111
+
112
+ /**
113
+ * HTTP request method
114
+ *
115
+ * @var string
116
+ */
117
+ protected $method = self::GET;
118
+
119
+ /**
120
+ * Associative array of GET parameters
121
+ *
122
+ * @var array
123
+ */
124
+ protected $paramsGet = array();
125
+
126
+ /**
127
+ * Assiciative array of POST parameters
128
+ *
129
+ * @var array
130
+ */
131
+ protected $paramsPost = array();
132
+
133
+ /**
134
+ * Request body content type (for POST requests)
135
+ *
136
+ * @var string
137
+ */
138
+ protected $enctype = null;
139
+
140
+ /**
141
+ * The raw post data to send. Could be set by setRawData($data, $enctype).
142
+ *
143
+ * @var string
144
+ */
145
+ protected $raw_post_data = null;
146
+
147
+ /**
148
+ * HTTP Authentication settings
149
+ *
150
+ * Expected to be an associative array with this structure:
151
+ * $this->auth = array('user' => 'username', 'password' => 'password', 'type' => 'basic')
152
+ * Where 'type' should be one of the supported authentication types (see the AUTH_*
153
+ * constants), for example 'basic' or 'digest'.
154
+ *
155
+ * If null, no authentication will be used.
156
+ *
157
+ * @var array|null
158
+ */
159
+ protected $auth;
160
+
161
+ /**
162
+ * File upload arrays (used in POST requests)
163
+ *
164
+ * An associative array, where each element is of the format:
165
+ * 'name' => array('filename.txt', 'text/plain', 'This is the actual file contents')
166
+ *
167
+ * @var array
168
+ */
169
+ protected $files = array();
170
+
171
+ /**
172
+ * The client's cookie jar
173
+ *
174
+ * @var SZend_Http_CookieJar
175
+ */
176
+ protected $cookiejar = null;
177
+
178
+ /**
179
+ * The last HTTP request sent by the client, as string
180
+ *
181
+ * @var string
182
+ */
183
+ protected $last_request = null;
184
+
185
+ /**
186
+ * The last HTTP response received by the client
187
+ *
188
+ * @var SZend_Http_Response
189
+ */
190
+ protected $last_response = null;
191
+
192
+ /**
193
+ * Redirection counter
194
+ *
195
+ * @var int
196
+ */
197
+ protected $redirectCounter = 0;
198
+
199
+ /**
200
+ * Contructor method. Will create a new HTTP client. Accepts the target
201
+ * URL and optionally and array of headers.
202
+ *
203
+ * @param SZend_Uri_Http|string $uri
204
+ * @param array $headers Optional request headers to set
205
+ */
206
+ public function __construct($uri = null, $config = null)
207
+ {
208
+ if ($uri !== null) $this->setUri($uri);
209
+ if ($config !== null) $this->setConfig($config);
210
+ }
211
+
212
+ /**
213
+ * Set the URI for the next request
214
+ *
215
+ * @param SZend_Uri_Http|string $uri
216
+ * @return SZend_Http_Client
217
+ * @throws SZend_Http_Client_Exception
218
+ */
219
+ public function setUri($uri)
220
+ {
221
+ if (is_string($uri)) {
222
+ $uri = SZend_Uri::factory($uri);
223
+ }
224
+
225
+ if (!$uri instanceof SZend_Uri_Http) {
226
+ require_once dirname(__FILE__) . '/../Http/Client/Exception.php';
227
+ throw new SZend_Http_Client_Exception('Passed parameter is not a valid HTTP URI.');
228
+ }
229
+
230
+ // We have no ports, set the defaults
231
+ if (! $uri->getPort()) {
232
+ $uri->setPort(($uri->getScheme() == 'https' ? 443 : 80));
233
+ }
234
+
235
+ $this->uri = $uri;
236
+
237
+ return $this;
238
+ }
239
+
240
+ /**
241
+ * Get the URI for the next request
242
+ *
243
+ * @param boolean $as_string If true, will return the URI as a string
244
+ * @return SZend_Uri_Http|string
245
+ */
246
+ public function getUri($as_string = false)
247
+ {
248
+ if ($as_string && $this->uri instanceof SZend_Uri_Http) {
249
+ return $this->uri->__toString();
250
+ } else {
251
+ return $this->uri;
252
+ }
253
+ }
254
+
255
+ /**
256
+ * Set configuration parameters for this HTTP client
257
+ *
258
+ * @param array $config
259
+ * @return SZend_Http_Client
260
+ */
261
+ public function setConfig($config = array())
262
+ {
263
+ if (! is_array($config)) {
264
+ require_once dirname(__FILE__) . '/../Http/Client/Exception.php';
265
+ throw new SZend_Http_Client_Exception('Expected array parameter, given ' . gettype($config));
266
+ }
267
+
268
+ foreach ($config as $k => $v)
269
+ $this->config[strtolower($k)] = $v;
270
+
271
+ return $this;
272
+ }
273
+
274
+ /**
275
+ * Set the next request's method
276
+ *
277
+ * Validated the passed method and sets it. If we have files set for
278
+ * POST requests, and the new method is not POST, the files are silently
279
+ * dropped.
280
+ *
281
+ * @param string $method
282
+ * @return SZend_Http_Client
283
+ */
284
+ public function setMethod($method = self::GET)
285
+ {
286
+ if (! preg_match('/^[A-Za-z_]+$/', $method)) {
287
+ require_once dirname(__FILE__) . '/../Http/Client/Exception.php';
288
+ throw new SZend_Http_Client_Exception("'{$method}' is not a valid HTTP request method.");
289
+ }
290
+
291
+ if ($method == self::POST && $this->enctype === null)
292
+ $this->setEncType(self::ENC_URLENCODED);
293
+
294
+ $this->method = $method;
295
+
296
+ return $this;
297
+ }
298
+
299
+ /**
300
+ * Method rajoutée
301
+ */
302
+ public function getParams()
303
+ {
304
+ if ($this->method === self::GET) {
305
+ return $this->paramsGet;
306
+ }
307
+ elseif ($this->method === self::POST) {
308
+ return $this->paramsPost;
309
+ }
310
+
311
+ return array_merge($this->paramsGet, $this->paramsPost);
312
+ }
313
+
314
+ /**
315
+ * Set one or more request headers
316
+ *
317
+ * This function can be used in several ways to set the client's request
318
+ * headers:
319
+ * 1. By providing two parameters: $name as the header to set (eg. 'Host')
320
+ * and $value as it's value (eg. 'www.example.com').
321
+ * 2. By providing a single header string as the only parameter
322
+ * eg. 'Host: www.example.com'
323
+ * 3. By providing an array of headers as the first parameter
324
+ * eg. array('host' => 'www.example.com', 'x-foo: bar'). In This case
325
+ * the function will call itself recursively for each array item.
326
+ *
327
+ * @param string|array $name Header name, full header string ('Header: value')
328
+ * or an array of headers
329
+ * @param mixed $value Header value or null
330
+ * @return SZend_Http_Client
331
+ */
332
+ public function setHeaders($name, $value = null)
333
+ {
334
+ // If we got an array, go recusive!
335
+ if (is_array($name)) {
336
+ foreach ($name as $k => $v) {
337
+ if (is_string($k)) {
338
+ $this->setHeaders($k, $v);
339
+ } else {
340
+ $this->setHeaders($v, null);
341
+ }
342
+ }
343
+ } else {
344
+ // Check if $name needs to be split
345
+ if ($value === null && (strpos($name, ':') > 0))
346
+ list($name, $value) = explode(':', $name, 2);
347
+
348
+ // Make sure the name is valid if we are in strict mode
349
+ if ($this->config['strict'] && (! preg_match('/^[a-zA-Z0-9-]+$/', $name))) {
350
+ require_once dirname(__FILE__) . '/../Http/Client/Exception.php';
351
+ throw new SZend_Http_Client_Exception("{$name} is not a valid HTTP header name");
352
+ }
353
+
354
+ $normalized_name = strtolower($name);
355
+
356
+ // If $value is null or false, unset the header
357
+ if ($value === null || $value === false) {
358
+ unset($this->headers[$normalized_name]);
359
+
360
+ // Else, set the header
361
+ } else {
362
+ // Header names are storred lowercase internally.
363
+ if (is_string($value)) $value = trim($value);
364
+ $this->headers[$normalized_name] = array($name, $value);
365
+ }
366
+ }
367
+
368
+ return $this;
369
+ }
370
+
371
+ /**
372
+ * Get the value of a specific header
373
+ *
374
+ * Note that if the header has more than one value, an array
375
+ * will be returned.
376
+ *
377
+ * @param unknown_type $key
378
+ * @return string|array|null The header value or null if it is not set
379
+ */
380
+ public function getHeader($key)
381
+ {
382
+ $key = strtolower($key);
383
+ if (isset($this->headers[$key])) {
384
+ return $this->headers[$key][1];
385
+ } else {
386
+ return null;
387
+ }
388
+ }
389
+
390
+ /**
391
+ * Set a GET parameter for the request. Wrapper around _setParameter
392
+ *
393
+ * @param string|array $name
394
+ * @param string $value
395
+ * @return SZend_Http_Client
396
+ */
397
+ public function setParameterGet($name, $value = null)
398
+ {
399
+ if (is_array($name)) {
400
+ foreach ($name as $k => $v)
401
+ $this->_setParameter('GET', $k, $v);
402
+ } else {
403
+ $this->_setParameter('GET', $name, $value);
404
+ }
405
+
406
+ return $this;
407
+ }
408
+
409
+ /**
410
+ * Set a POST parameter for the request. Wrapper around _setParameter
411
+ *
412
+ * @param string|array $name
413
+ * @param string $value
414
+ * @return SZend_Http_Client
415
+ */
416
+ public function setParameterPost($name, $value = null)
417
+ {
418
+ if (is_array($name)) {
419
+ foreach ($name as $k => $v)
420
+ $this->_setParameter('POST', $k, $v);
421
+ } else {
422
+ $this->_setParameter('POST', $name, $value);
423
+ }
424
+
425
+ return $this;
426
+ }
427
+
428
+ /**
429
+ * Set a GET or POST parameter - used by SetParameterGet and SetParameterPost
430
+ *
431
+ * @param string $type GET or POST
432
+ * @param string $name
433
+ * @param string $value
434
+ */
435
+ protected function _setParameter($type, $name, $value)
436
+ {
437
+ $parray = array();
438
+ $type = strtolower($type);
439
+ switch ($type) {
440
+ case 'get':
441
+ $parray = &$this->paramsGet;
442
+ break;
443
+ case 'post':
444
+ $parray = &$this->paramsPost;
445
+ break;
446
+ }
447
+
448
+ if ($value === null) {
449
+ if (isset($parray[$name])) unset($parray[$name]);
450
+ } else {
451
+ $parray[$name] = $value;
452
+ }
453
+ }
454
+
455
+ /**
456
+ * Get the number of redirections done on the last request
457
+ *
458
+ * @return int
459
+ */
460
+ public function getRedirectionsCount()
461
+ {
462
+ return $this->redirectCounter;
463
+ }
464
+
465
+ /**
466
+ * Set HTTP authentication parameters
467
+ *
468
+ * $type should be one of the supported types - see the self::AUTH_*
469
+ * constants.
470
+ *
471
+ * To enable authentication:
472
+ * <code>
473
+ * $this->setAuth('shahar', 'secret', SZend_Http_Client::AUTH_BASIC);
474
+ * </code>
475
+ *
476
+ * To disable authentication:
477
+ * <code>
478
+ * $this->setAuth(false);
479
+ * </code>
480
+ *
481
+ * @see http://www.faqs.org/rfcs/rfc2617.html
482
+ * @param string|false $user User name or false disable authentication
483
+ * @param string $password Password
484
+ * @param string $type Authentication type
485
+ * @return SZend_Http_Client
486
+ */
487
+ public function setAuth($user, $password = '', $type = self::AUTH_BASIC)
488
+ {
489
+ // If we got false or null, disable authentication
490
+ if ($user === false || $user === null) {
491
+ $this->auth = null;
492
+
493
+ // Else, set up authentication
494
+ } else {
495
+ // Check we got a proper authentication type
496
+ if (! defined('self::AUTH_' . strtoupper($type))) {
497
+ require_once dirname(__FILE__) . '/../Http/Client/Exception.php';
498
+ throw new SZend_Http_Client_Exception("Invalid or not supported authentication type: '$type'");
499
+ }
500
+
501
+ $this->auth = array(
502
+ 'user' => (string) $user,
503
+ 'password' => (string) $password,
504
+ 'type' => $type
505
+ );
506
+ }
507
+
508
+ return $this;
509
+ }
510
+
511
+ /**
512
+ * Set the HTTP client's cookie jar.
513
+ *
514
+ * A cookie jar is an object that holds and maintains cookies across HTTP requests
515
+ * and responses.
516
+ *
517
+ * @param SZend_Http_CookieJar|boolean $cookiejar Existing cookiejar object, true to create a new one, false to disable
518
+ * @return SZend_Http_Client
519
+ */
520
+ public function setCookieJar($cookiejar = true)
521
+ {
522
+ if (! class_exists('SZend_Http_CookieJar'))
523
+ require_once dirname(__FILE__) . '/../Http/CookieJar.php';
524
+
525
+ if ($cookiejar instanceof SZend_Http_CookieJar) {
526
+ $this->cookiejar = $cookiejar;
527
+ } elseif ($cookiejar === true) {
528
+ $this->cookiejar = new SZend_Http_CookieJar();
529
+ } elseif (! $cookiejar) {
530
+ $this->cookiejar = null;
531
+ } else {
532
+ require_once dirname(__FILE__) . '/../Http/Client/Exception.php';
533
+ throw new SZend_Http_Client_Exception('Invalid parameter type passed as CookieJar');
534
+ }
535
+
536
+ return $this;
537
+ }
538
+
539
+ /**
540
+ * Return the current cookie jar or null if none.
541
+ *
542
+ * @return SZend_Http_CookieJar|null
543
+ */
544
+ public function getCookieJar()
545
+ {
546
+ return $this->cookiejar;
547
+ }
548
+
549
+ /**
550
+ * Add a cookie to the request. If the client has no Cookie Jar, the cookies
551
+ * will be added directly to the headers array as "Cookie" headers.
552
+ *
553
+ * @param SZend_Http_Cookie|string $cookie
554
+ * @param string|null $value If "cookie" is a string, this is the cookie value.
555
+ * @return SZend_Http_Client
556
+ */
557
+ public function setCookie($cookie, $value = null)
558
+ {
559
+ if (! class_exists('SZend_Http_Cookie'))
560
+ require_once dirname(__FILE__) . '/../Http/Cookie.php';
561
+
562
+ if (is_array($cookie)) {
563
+ foreach ($cookie as $c => $v) {
564
+ if (is_string($c)) {
565
+ $this->setCookie($c, $v);
566
+ } else {
567
+ $this->setCookie($v);
568
+ }
569
+ }
570
+
571
+ return $this;
572
+ }
573
+
574
+ if ($value !== null) $value = urlencode($value);
575
+
576
+ if (isset($this->cookiejar)) {
577
+ if ($cookie instanceof SZend_Http_Cookie) {
578
+ $this->cookiejar->addCookie($cookie);
579
+ } elseif (is_string($cookie) && $value !== null) {
580
+ $cookie = SZend_Http_Cookie::fromString("{$cookie}={$value}", $this->uri);
581
+ $this->cookiejar->addCookie($cookie);
582
+ }
583
+ } else {
584
+ if ($cookie instanceof SZend_Http_Cookie) {
585
+ $name = $cookie->getName();
586
+ $value = $cookie->getValue();
587
+ $cookie = $name;
588
+ }
589
+
590
+ if (preg_match("/[=,; \t\r\n\013\014]/", $cookie)) {
591
+ require_once dirname(__FILE__) . '/../Http/Client/Exception.php';
592
+ throw new SZend_Http_Client_Exception("Cookie name cannot contain these characters: =,; \t\r\n\013\014 ({$cookie})");
593
+ }
594
+
595
+ $value = addslashes($value);
596
+
597
+ if (! isset($this->headers['cookie'])) $this->headers['cookie'] = array('Cookie', '');
598
+ $this->headers['cookie'][1] .= $cookie . '=' . $value . '; ';
599
+ }
600
+
601
+ return $this;
602
+ }
603
+
604
+ /**
605
+ * Set a file to upload (using a POST request)
606
+ *
607
+ * Can be used in two ways:
608
+ *
609
+ * 1. $data is null (default): $filename is treated as the name if a local file which
610
+ * will be read and sent. Will try to guess the content type using mime_content_type().
611
+ * 2. $data is set - $filename is sent as the file name, but $data is sent as the file
612
+ * contents and no file is read from the file system. In this case, you need to
613
+ * manually set the content-type ($ctype) or it will default to
614
+ * application/octet-stream.
615
+ *
616
+ * @param string $filename Name of file to upload, or name to save as
617
+ * @param string $formname Name of form element to send as
618
+ * @param string $data Data to send (if null, $filename is read and sent)
619
+ * @param string $ctype Content type to use (if $data is set and $ctype is
620
+ * null, will be application/octet-stream)
621
+ * @return SZend_Http_Client
622
+ */
623
+ public function setFileUpload($filename, $formname, $data = null, $ctype = null)
624
+ {
625
+ if ($data === null) {
626
+ if (($data = @file_get_contents($filename)) === false) {
627
+ require_once dirname(__FILE__) . '/../Http/Client/Exception.php';
628
+ throw new SZend_Http_Client_Exception("Unable to read file '{$filename}' for upload");
629
+ }
630
+
631
+ if (! $ctype && function_exists('mime_content_type')) $ctype = mime_content_type($filename);
632
+ }
633
+
634
+ // Force enctype to multipart/form-data
635
+ $this->setEncType(self::ENC_FORMDATA);
636
+
637
+ if ($ctype === null) $ctype = 'application/octet-stream';
638
+ $this->files[$formname] = array(basename($filename), $ctype, $data);
639
+
640
+ return $this;
641
+ }
642
+
643
+ /**
644
+ * Set the encoding type for POST data
645
+ *
646
+ * @param string $enctype
647
+ * @return SZend_Http_Client
648
+ */
649
+ public function setEncType($enctype = self::ENC_URLENCODED)
650
+ {
651
+ $this->enctype = $enctype;
652
+
653
+ return $this;
654
+ }
655
+
656
+ /**
657
+ * Set the raw (already encoded) POST data.
658
+ *
659
+ * This function is here for two reasons:
660
+ * 1. For advanced user who would like to set their own data, already encoded
661
+ * 2. For backwards compatibilty: If someone uses the old post($data) method.
662
+ * this method will be used to set the encoded data.
663
+ *
664
+ * @param string $data
665
+ * @param string $enctype
666
+ * @return SZend_Http_Client
667
+ */
668
+ public function setRawData($data, $enctype = null)
669
+ {
670
+ $this->raw_post_data = $data;
671
+ $this->setEncType($enctype);
672
+
673
+ return $this;
674
+ }
675
+
676
+ /**
677
+ * Clear all GET and POST parameters
678
+ *
679
+ * Should be used to reset the request parameters if the client is
680
+ * used for several concurrent requests.
681
+ *
682
+ * @return SZend_Http_Client
683
+ */
684
+ public function resetParameters()
685
+ {
686
+ // Reset parameter data
687
+ $this->paramsGet = array();
688
+ $this->paramsPost = array();
689
+ $this->files = array();
690
+ $this->raw_post_data = null;
691
+
692
+ // Clear outdated headers
693
+ if (isset($this->headers['content-type'])) unset($this->headers['content-type']);
694
+ if (isset($this->headers['content-length'])) unset($this->headers['content-length']);
695
+
696
+ return $this;
697
+ }
698
+
699
+ /**
700
+ * Get the last HTTP request as string
701
+ *
702
+ * @return string
703
+ */
704
+ public function getLastRequest()
705
+ {
706
+ return $this->last_request;
707
+ }
708
+
709
+ /**
710
+ * Get the last HTTP response received by this client
711
+ *
712
+ * If $config['storeresponse'] is set to false, or no response was
713
+ * stored yet, will return null
714
+ *
715
+ * @return SZend_Http_Response or null if none
716
+ */
717
+ public function getLastResponse()
718
+ {
719
+ return $this->last_response;
720
+ }
721
+
722
+ /**
723
+ * Load the connection adapter
724
+ *
725
+ * While this method is not called more than one for a client, it is
726
+ * seperated from ->request() to preserve logic and readability
727
+ *
728
+ * @param SZend_Http_Client_Adapter_Interface|string $adapter
729
+ */
730
+ public function setAdapter($adapter)
731
+ {
732
+ if (is_string($adapter)) {
733
+ try {
734
+ SZend_Loader::loadClass($adapter);
735
+ } catch (SZend_Exception $e) {
736
+ require_once dirname(__FILE__) . '/../Http/Client/Exception.php';
737
+ throw new SZend_Http_Client_Exception("Unable to load adapter '$adapter': {$e->getMessage()}");
738
+ }
739
+
740
+ $adapter = new $adapter;
741
+ }
742
+
743
+ if (! $adapter instanceof SZend_Http_Client_Adapter_Interface) {
744
+ require_once dirname(__FILE__) . '/../Http/Client/Exception.php';
745
+ throw new SZend_Http_Client_Exception('Passed adapter is not a HTTP connection adapter');
746
+ }
747
+
748
+ $this->adapter = $adapter;
749
+ $config = $this->config;
750
+ unset($config['adapter']);
751
+ $this->adapter->setConfig($config);
752
+ }
753
+
754
+ /**
755
+ * Send the HTTP request and return an HTTP response object
756
+ *
757
+ * @param string $method
758
+ * @return SZend_Http_Response
759
+ */
760
+ public function request($method = null)
761
+ {
762
+ if (! $this->uri instanceof SZend_Uri_Http) {
763
+ require_once dirname(__FILE__) . '/../Http/Client/Exception.php';
764
+ throw new SZend_Http_Client_Exception('No valid URI has been passed to the client');
765
+ }
766
+
767
+ if ($method) $this->setMethod($method);
768
+ $this->redirectCounter = 0;
769
+ $response = null;
770
+
771
+ // Make sure the adapter is loaded
772
+ if ($this->adapter == null) $this->setAdapter($this->config['adapter']);
773
+
774
+ // Send the first request. If redirected, continue.
775
+ do {
776
+ // Clone the URI and add the additional GET parameters to it
777
+ $uri = clone $this->uri;
778
+ if (! empty($this->paramsGet)) {
779
+ $query = $uri->getQuery();
780
+ if (! empty($query)) $query .= '&';
781
+ $query .= http_build_query($this->paramsGet, null, '&');
782
+
783
+ $uri->setQuery($query);
784
+ }
785
+
786
+ $body = $this->prepare_body();
787
+ $headers = $this->prepare_headers();
788
+
789
+ // Open the connection, send the request and read the response
790
+ $this->adapter->connect($uri->getHost(), $uri->getPort(),
791
+ ($uri->getScheme() == 'https' ? true : false));
792
+
793
+ $this->last_request = $this->adapter->write($this->method,
794
+ $uri, $this->config['httpversion'], $headers, $body);
795
+
796
+ $response = $this->adapter->read();
797
+ if (! $response) {
798
+ require_once dirname(__FILE__) . '/../Http/Client/Exception.php';
799
+ throw new SZend_Http_Client_Exception('Unable to read response, or response is empty');
800
+ }
801
+
802
+ $response = SZend_Http_Response::fromString($response);
803
+ if ($this->config['storeresponse']) $this->last_response = $response;
804
+
805
+ // Load cookies into cookie jar
806
+ if (isset($this->cookiejar)) $this->cookiejar->addCookiesFromResponse($response, $uri);
807
+
808
+ // If we got redirected, look for the Location header
809
+ if ($response->isRedirect() && ($location = $response->getHeader('location'))) {
810
+
811
+ // Check whether we send the exact same request again, or drop the parameters
812
+ // and send a GET request
813
+ if ($response->getStatus() == 303 ||
814
+ ((! $this->config['strictredirects']) && ($response->getStatus() == 302 ||
815
+ $response->getStatus() == 301))) {
816
+
817
+ $this->resetParameters();
818
+ $this->setMethod(self::GET);
819
+ }
820
+
821
+ // If we got a well formed absolute URI
822
+ if (SZend_Uri_Http::check($location)) {
823
+ $this->setHeaders('host', null);
824
+ $this->setUri($location);
825
+
826
+ } else {
827
+
828
+ // Split into path and query and set the query
829
+ if (strpos($location, '?') !== false) {
830
+ list($location, $query) = explode('?', $location, 2);
831
+ } else {
832
+ $query = '';
833
+ }
834
+ $this->uri->setQuery($query);
835
+
836
+ // Else, if we got just an absolute path, set it
837
+ if(strpos($location, '/') === 0) {
838
+ $this->uri->setPath($location);
839
+
840
+ // Else, assume we have a relative path
841
+ } else {
842
+ // Get the current path directory, removing any trailing slashes
843
+ $path = $this->uri->getPath();
844
+ $path = rtrim(substr($path, 0, strrpos($path, '/')), "/");
845
+ $this->uri->setPath($path . '/' . $location);
846
+ }
847
+ }
848
+ ++$this->redirectCounter;
849
+
850
+ } else {
851
+ // If we didn't get any location, stop redirecting
852
+ break;
853
+ }
854
+
855
+ } while ($this->redirectCounter < $this->config['maxredirects']);
856
+
857
+ return $response;
858
+ }
859
+
860
+ /**
861
+ * Prepare the request headers
862
+ *
863
+ * @return array
864
+ */
865
+ protected function prepare_headers()
866
+ {
867
+ $headers = array();
868
+
869
+ // Set the host header
870
+ if (! isset($this->headers['host'])) {
871
+ $host = $this->uri->getHost();
872
+
873
+ // If the port is not default, add it
874
+ if (! (($this->uri->getScheme() == 'http' && $this->uri->getPort() == 80) ||
875
+ ($this->uri->getScheme() == 'https' && $this->uri->getPort() == 443))) {
876
+ $host .= ':' . $this->uri->getPort();
877
+ }
878
+
879
+ $headers[] = "Host: {$host}";
880
+ }
881
+
882
+ // Set the connection header
883
+ if (! isset($this->headers['connection'])) {
884
+ if (! $this->config['keepalive']) $headers[] = "Connection: close";
885
+ }
886
+
887
+ // Set the Accept-encoding header if not set - depending on whether
888
+ // zlib is available or not.
889
+ if (! isset($this->headers['accept-encoding'])) {
890
+ if (function_exists('gzinflate')) {
891
+ $headers[] = 'Accept-encoding: gzip, deflate';
892
+ } else {
893
+ $headers[] = 'Accept-encoding: identity';
894
+ }
895
+ }
896
+
897
+ // Set the content-type header
898
+ if ($this->method == self::POST &&
899
+ (! isset($this->headers['content-type']) && isset($this->enctype))) {
900
+
901
+ $headers[] = "Content-type: {$this->enctype}";
902
+ }
903
+
904
+ // Set the user agent header
905
+ if (! isset($this->headers['user-agent']) && isset($this->config['useragent'])) {
906
+ $headers[] = "User-agent: {$this->config['useragent']}";
907
+ }
908
+
909
+ // Set HTTP authentication if needed
910
+ if (is_array($this->auth)) {
911
+ $auth = self::encodeAuthHeader($this->auth['user'], $this->auth['password'], $this->auth['type']);
912
+ $headers[] = "Authorization: {$auth}";
913
+ }
914
+
915
+ // Load cookies from cookie jar
916
+ if (isset($this->cookiejar)) {
917
+ $cookstr = $this->cookiejar->getMatchingCookies($this->uri,
918
+ true, SZend_Http_CookieJar::COOKIE_STRING_CONCAT);
919
+
920
+ if ($cookstr) $headers[] = "Cookie: {$cookstr}";
921
+ }
922
+
923
+ // Add all other user defined headers
924
+ foreach ($this->headers as $header) {
925
+ list($name, $value) = $header;
926
+ if (is_array($value))
927
+ $value = implode(', ', $value);
928
+
929
+ $headers[] = "$name: $value";
930
+ }
931
+
932
+ return $headers;
933
+ }
934
+
935
+ /**
936
+ * Prepare the request body (for POST and PUT requests)
937
+ *
938
+ * @return string
939
+ */
940
+ protected function prepare_body()
941
+ {
942
+ // According to RFC2616, a TRACE request should not have a body.
943
+ if ($this->method == self::TRACE) {
944
+ return '';
945
+ }
946
+
947
+ // If we have raw_post_data set, just use it as the body.
948
+ if (isset($this->raw_post_data)) {
949
+ $this->setHeaders('Content-length', strlen($this->raw_post_data));
950
+ return $this->raw_post_data;
951
+ }
952
+
953
+ $body = '';
954
+
955
+ // If we have files to upload, force enctype to multipart/form-data
956
+ if (count ($this->files) > 0) $this->setEncType(self::ENC_FORMDATA);
957
+
958
+ // If we have POST parameters or files, encode and add them to the body
959
+ if (count($this->paramsPost) > 0 || count($this->files) > 0) {
960
+ switch($this->enctype) {
961
+ case self::ENC_FORMDATA:
962
+ // Encode body as multipart/form-data
963
+ $boundary = '---ZENDHTTPCLIENT-' . md5(microtime());
964
+ $this->setHeaders('Content-type', self::ENC_FORMDATA . "; boundary={$boundary}");
965
+
966
+ // Get POST parameters and encode them
967
+ $params = $this->_getParametersRecursive($this->paramsPost);
968
+ foreach ($params as $pp) {
969
+ $body .= self::encodeFormData($boundary, $pp[0], $pp[1]);
970
+ }
971
+
972
+ // Encode files
973
+ foreach ($this->files as $name => $file) {
974
+ $fhead = array('Content-type' => $file[1]);
975
+ $body .= self::encodeFormData($boundary, $name, $file[2], $file[0], $fhead);
976
+ }
977
+
978
+ $body .= "--{$boundary}--\r\n";
979
+ break;
980
+
981
+ case self::ENC_URLENCODED:
982
+ // Encode body as application/x-www-form-urlencoded
983
+ $this->setHeaders('Content-type', self::ENC_URLENCODED);
984
+ $body = http_build_query($this->paramsPost, '', '&');
985
+ break;
986
+
987
+ default:
988
+ require_once dirname(__FILE__) . '/../Http/Client/Exception.php';
989
+ throw new SZend_Http_Client_Exception("Cannot handle content type '{$this->enctype}' automatically." .
990
+ " Please use SZend_Http_Client::setRawData to send this kind of content.");
991
+ break;
992
+ }
993
+ }
994
+
995
+ if ($body) $this->setHeaders('Content-length', strlen($body));
996
+ return $body;
997
+ }
998
+
999
+ /**
1000
+ * Helper method that gets a possibly multi-level parameters array (get or
1001
+ * post) and flattens it.
1002
+ *
1003
+ * The method returns an array of (key, value) pairs (because keys are not
1004
+ * necessarily unique. If one of the parameters in as array, it will also
1005
+ * add a [] suffix to the key.
1006
+ *
1007
+ * @param array $parray The parameters array
1008
+ * @param bool $urlencode Whether to urlencode the name and value
1009
+ * @return array
1010
+ */
1011
+ protected function _getParametersRecursive($parray, $urlencode = false)
1012
+ {
1013
+ if (! is_array($parray)) return $parray;
1014
+ $parameters = array();
1015
+
1016
+ foreach ($parray as $name => $value) {
1017
+ if ($urlencode) $name = urlencode($name);
1018
+
1019
+ // If $value is an array, iterate over it
1020
+ if (is_array($value)) {
1021
+ $name .= ($urlencode ? '%5B%5D' : '[]');
1022
+ foreach ($value as $subval) {
1023
+ if ($urlencode) $subval = urlencode($subval);
1024
+ $parameters[] = array($name, $subval);
1025
+ }
1026
+ } else {
1027
+ if ($urlencode) $value = urlencode($value);
1028
+ $parameters[] = array($name, $value);
1029
+ }
1030
+ }
1031
+
1032
+ return $parameters;
1033
+ }
1034
+
1035
+ /**
1036
+ * Encode data to a multipart/form-data part suitable for a POST request.
1037
+ *
1038
+ * @param string $boundary
1039
+ * @param string $name
1040
+ * @param mixed $value
1041
+ * @param string $filename
1042
+ * @param array $headers Associative array of optional headers @example ("Content-transfer-encoding" => "binary")
1043
+ * @return string
1044
+ */
1045
+ public static function encodeFormData($boundary, $name, $value, $filename = null, $headers = array()) {
1046
+ $ret = "--{$boundary}\r\n" .
1047
+ 'Content-disposition: form-data; name="' . $name .'"';
1048
+
1049
+ if ($filename) $ret .= '; filename="' . $filename . '"';
1050
+ $ret .= "\r\n";
1051
+
1052
+ foreach ($headers as $hname => $hvalue) {
1053
+ $ret .= "{$hname}: {$hvalue}\r\n";
1054
+ }
1055
+ $ret .= "\r\n";
1056
+
1057
+ $ret .= "{$value}\r\n";
1058
+
1059
+ return $ret;
1060
+ }
1061
+
1062
+ /**
1063
+ * Create a HTTP authentication "Authorization:" header according to the
1064
+ * specified user, password and authentication method.
1065
+ *
1066
+ * @see http://www.faqs.org/rfcs/rfc2617.html
1067
+ * @param string $user
1068
+ * @param string $password
1069
+ * @param string $type
1070
+ * @return string
1071
+ */
1072
+ public static function encodeAuthHeader($user, $password, $type = self::AUTH_BASIC)
1073
+ {
1074
+ $authHeader = null;
1075
+
1076
+ switch ($type) {
1077
+ case self::AUTH_BASIC:
1078
+ // In basic authentication, the user name cannot contain ":"
1079
+ if (strpos($user, ':') !== false) {
1080
+ require_once dirname(__FILE__) . '/../Http/Client/Exception.php';
1081
+ throw new SZend_Http_Client_Exception("The user name cannot contain ':' in 'Basic' HTTP authentication");
1082
+ }
1083
+
1084
+ $authHeader = 'Basic ' . base64_encode($user . ':' . $password);
1085
+ break;
1086
+
1087
+ //case self::AUTH_DIGEST:
1088
+ /**
1089
+ * @todo Implement digest authentication
1090
+ */
1091
+ // break;
1092
+
1093
+ default:
1094
+ require_once dirname(__FILE__) . '/../Http/Client/Exception.php';
1095
+ throw new SZend_Http_Client_Exception("Not a supported HTTP authentication type: '$type'");
1096
+ }
1097
+
1098
+ return $authHeader;
1099
+ }
1100
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Http/Client/Adapter/Exception.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SZend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category SZend
16
+ * @package SZend_Http
17
+ * @subpackage Client_Adapter_Exception
18
+ * @version $Id: Exception.php 8064 2008-02-16 10:58:39Z thomas $
19
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
20
+ * @license http://framework.zend.com/license/new-bsd New BSD License
21
+ */
22
+
23
+ require_once dirname(__FILE__) . '/../../../Http/Client/Exception.php';
24
+
25
+ /**
26
+ * @category SZend
27
+ * @package SZend_Http
28
+ * @subpackage Client_Adapter
29
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
30
+ * @license http://framework.zend.com/license/new-bsd New BSD License
31
+ */
32
+ class SZend_Http_Client_Adapter_Exception extends SZend_Http_Client_Exception
33
+ {}
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Http/Client/Adapter/Interface.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * SZend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category SZend
17
+ * @package SZend_Http
18
+ * @subpackage Client_Adapter
19
+ * @version $Id: Interface.php 8064 2008-02-16 10:58:39Z thomas $
20
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ /**
25
+ * An interface description for SZend_Http_Client_Adapter classes.
26
+ *
27
+ * These classes are used as connectors for SZend_Http_Client, performing the
28
+ * tasks of connecting, writing, reading and closing connection to the server.
29
+ *
30
+ * @category SZend
31
+ * @package SZend_Http
32
+ * @subpackage Client_Adapter
33
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ interface SZend_Http_Client_Adapter_Interface
37
+ {
38
+ /**
39
+ * Set the configuration array for the adapter
40
+ *
41
+ * @param array $config
42
+ */
43
+ public function setConfig($config = array());
44
+
45
+ /**
46
+ * Connect to the remote server
47
+ *
48
+ * @param string $host
49
+ * @param int $port
50
+ * @param boolean $secure
51
+ */
52
+ public function connect($host, $port = 80, $secure = false);
53
+
54
+ /**
55
+ * Send request to the remote server
56
+ *
57
+ * @param string $method
58
+ * @param SZend_Uri_Http $url
59
+ * @param string $http_ver
60
+ * @param array $headers
61
+ * @param string $body
62
+ * @return string Request as text
63
+ */
64
+ public function write($method, $url, $http_ver = '1.1', $headers = array(), $body = '');
65
+
66
+ /**
67
+ * Read response from server
68
+ *
69
+ * @return string
70
+ */
71
+ public function read();
72
+
73
+ /**
74
+ * Close the connection to the server
75
+ *
76
+ */
77
+ public function close();
78
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Http/Client/Adapter/Proxy.php ADDED
@@ -0,0 +1,267 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * SZend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category SZend
17
+ * @package SZend_Http
18
+ * @subpackage Client_Adapter
19
+ * @version $Id: Proxy.php 8064 2008-02-16 10:58:39Z thomas $
20
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ require_once dirname(__FILE__) . '/../../../Uri/Http.php';
25
+ require_once dirname(__FILE__) . '/../../../Http/Client.php';
26
+ require_once dirname(__FILE__) . '/../../../Http/Client/Adapter/Socket.php';
27
+
28
+ /**
29
+ * HTTP Proxy-supporting SZend_Http_Client adapter class, based on the default
30
+ * socket based adapter.
31
+ *
32
+ * Should be used if proxy HTTP access is required. If no proxy is set, will
33
+ * fall back to SZend_Http_Client_Adapter_Socket behavior. Just like the
34
+ * default Socket adapter, this adapter does not require any special extensions
35
+ * installed.
36
+ *
37
+ * @category SZend
38
+ * @package SZend_Http
39
+ * @subpackage Client_Adapter
40
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
41
+ * @license http://framework.zend.com/license/new-bsd New BSD License
42
+ */
43
+ class SZend_Http_Client_Adapter_Proxy extends SZend_Http_Client_Adapter_Socket
44
+ {
45
+ /**
46
+ * Parameters array
47
+ *
48
+ * @var array
49
+ */
50
+ protected $config = array(
51
+ 'ssltransport' => 'ssl',
52
+ 'proxy_host' => '',
53
+ 'proxy_port' => 8080,
54
+ 'proxy_user' => '',
55
+ 'proxy_pass' => '',
56
+ 'proxy_auth' => SZend_Http_Client::AUTH_BASIC
57
+ );
58
+
59
+ /**
60
+ * Whether HTTPS CONNECT was already negotiated with the proxy or not
61
+ *
62
+ * @var boolean
63
+ */
64
+ protected $negotiated = false;
65
+
66
+ /**
67
+ * Connect to the remote server
68
+ *
69
+ * Will try to connect to the proxy server. If no proxy was set, will
70
+ * fall back to the target server (behave like regular Socket adapter)
71
+ *
72
+ * @param string $host
73
+ * @param int $port
74
+ * @param boolean $secure
75
+ * @param int $timeout
76
+ */
77
+ public function connect($host, $port = 80, $secure = false)
78
+ {
79
+ // If no proxy is set, fall back to Socket adapter
80
+ if (! $this->config['proxy_host']) return parent::connect($host, $port, $secure);
81
+
82
+ // Go through a proxy - the connection is actually to the proxy server
83
+ $host = $this->config['proxy_host'];
84
+ $port = $this->config['proxy_port'];
85
+
86
+ // If we are connected to the wrong proxy, disconnect first
87
+ if (($this->connected_to[0] != $host || $this->connected_to[1] != $port)) {
88
+ if (is_resource($this->socket)) $this->close();
89
+ }
90
+
91
+ // Now, if we are not connected, connect
92
+ if (! is_resource($this->socket) || ! $this->config['keepalive']) {
93
+ $this->socket = @fsockopen($host, $port, $errno, $errstr, (int) $this->config['timeout']);
94
+ if (! $this->socket) {
95
+ $this->close();
96
+ require_once 'SZend/Http/Client/Adapter/Exception.php';
97
+ throw new SZend_Http_Client_Adapter_Exception(
98
+ 'Unable to Connect to proxy server ' . $host . ':' . $port . '. Error #' . $errno . ': ' . $errstr);
99
+ }
100
+
101
+ // Set the stream timeout
102
+ if (!stream_set_timeout($this->socket, (int) $this->config['timeout'])) {
103
+ require_once 'SZend/Http/Client/Adapter/Exception.php';
104
+ throw new SZend_Http_Client_Adapter_Exception('Unable to set the connection timeout');
105
+ }
106
+
107
+ // Update connected_to
108
+ $this->connected_to = array($host, $port);
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Send request to the proxy server
114
+ *
115
+ * @param string $method
116
+ * @param SZend_Uri_Http $uri
117
+ * @param string $http_ver
118
+ * @param array $headers
119
+ * @param string $body
120
+ * @return string Request as string
121
+ */
122
+ public function write($method, $uri, $http_ver = '1.1', $headers = array(), $body = '')
123
+ {
124
+ // If no proxy is set, fall back to default Socket adapter
125
+ if (! $this->config['proxy_host']) return parent::write($method, $uri, $http_ver, $headers, $body);
126
+
127
+ // Make sure we're properly connected
128
+ if (! $this->socket) {
129
+ require_once 'SZend/Http/Client/Adapter/Exception.php';
130
+ throw new SZend_Http_Client_Adapter_Exception("Trying to write but we are not connected");
131
+ }
132
+
133
+ $host = $this->config['proxy_host'];
134
+ $port = $this->config['proxy_port'];
135
+
136
+ if ($this->connected_to[0] != $host || $this->connected_to[1] != $port) {
137
+ require_once 'SZend/Http/Client/Adapter/Exception.php';
138
+ throw new SZend_Http_Client_Adapter_Exception("Trying to write but we are connected to the wrong proxy server");
139
+ }
140
+
141
+ // Add Proxy-Authorization header
142
+ if ($this->config['proxy_user'] && ! isset($headers['proxy-authorization']))
143
+ $headers['proxy-authorization'] = SZend_Http_Client::encodeAuthHeader(
144
+ $this->config['proxy_user'], $this->config['proxy_pass'], $this->config['proxy_auth']
145
+ );
146
+
147
+ // if we are proxying HTTPS, preform CONNECT handshake with the proxy
148
+ if ($uri->getScheme() == 'https' && (! $this->negotiated)) {
149
+ $this->connectHandshake($uri->getHost(), $uri->getPort(), $http_ver, $headers);
150
+ $this->negotiated = true;
151
+ }
152
+
153
+ // Save request method for later
154
+ $this->method = $method;
155
+
156
+ // Build request headers
157
+ $request = "{$method} {$uri->__toString()} HTTP/{$http_ver}\r\n";
158
+
159
+ // Add all headers to the request string
160
+ foreach ($headers as $k => $v) {
161
+ if (is_string($k)) $v = "$k: $v";
162
+ $request .= "$v\r\n";
163
+ }
164
+
165
+ // Add the request body
166
+ $request .= "\r\n" . $body;
167
+
168
+ // Send the request
169
+ if (! @fwrite($this->socket, $request)) {
170
+ require_once 'SZend/Http/Client/Adapter/Exception.php';
171
+ throw new SZend_Http_Client_Adapter_Exception("Error writing request to proxy server");
172
+ }
173
+
174
+ return $request;
175
+ }
176
+
177
+ /**
178
+ * Preform handshaking with HTTPS proxy using CONNECT method
179
+ *
180
+ * @param string $host
181
+ * @param integer $port
182
+ * @param string $http_ver
183
+ * @param array $headers
184
+ */
185
+ protected function connectHandshake($host, $port = 443, $http_ver = '1.1', array &$headers = array())
186
+ {
187
+ $request = "CONNECT $host:$port HTTP/$http_ver\r\n" .
188
+ "Host: " . $this->config['proxy_host'] . "\r\n";
189
+
190
+ // Add the user-agent header
191
+ if (isset($this->config['useragent'])) {
192
+ $request .= "User-agent: " . $this->config['useragent'] . "\r\n";
193
+ }
194
+
195
+ // If the proxy-authorization header is set, send it to proxy but remove
196
+ // it from headers sent to target host
197
+ if (isset($headers['proxy-authorization'])) {
198
+ $request .= "Proxy-authorization: " . $headers['proxy-authorization'] . "\r\n";
199
+ unset($headers['proxy-authorization']);
200
+ }
201
+
202
+ $request .= "\r\n";
203
+
204
+ // Send the request
205
+ if (! @fwrite($this->socket, $request)) {
206
+ require_once 'SZend/Http/Client/Adapter/Exception.php';
207
+ throw new SZend_Http_Client_Adapter_Exception("Error writing request to proxy server");
208
+ }
209
+
210
+ // Read response headers only
211
+ $response = '';
212
+ $gotStatus = false;
213
+ while ($line = @fgets($this->socket)) {
214
+ $gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false);
215
+ if ($gotStatus) {
216
+ $response .= $line;
217
+ if (!chop($line)) break;
218
+ }
219
+ }
220
+
221
+ // Check that the response from the proxy is 200
222
+ if (SZend_Http_Response::extractCode($response) != 200) {
223
+ require_once 'SZend/Http/Client/Adapter/Exception.php';
224
+ throw new SZend_Http_Client_Adapter_Exception("Unable to connect to HTTPS proxy. Server response: " . $response);
225
+ }
226
+
227
+ // If all is good, switch socket to secure mode. We have to fall back
228
+ // through the different modes
229
+ $modes = array(
230
+ STREAM_CRYPTO_METHOD_TLS_CLIENT,
231
+ STREAM_CRYPTO_METHOD_SSLv3_CLIENT,
232
+ STREAM_CRYPTO_METHOD_SSLv23_CLIENT,
233
+ STREAM_CRYPTO_METHOD_SSLv2_CLIENT
234
+ );
235
+
236
+ $success = false;
237
+ foreach($modes as $mode) {
238
+ $success = stream_socket_enable_crypto($this->socket, true, $mode);
239
+ if ($success) break;
240
+ }
241
+
242
+ if (! $success) {
243
+ require_once 'SZend/Http/Client/Adapter/Exception.php';
244
+ throw new SZend_Http_Client_Adapter_Exception("Unable to connect to" .
245
+ " HTTPS server through proxy: could not negotiate secure connection.");
246
+ }
247
+ }
248
+
249
+ /**
250
+ * Close the connection to the server
251
+ *
252
+ */
253
+ public function close()
254
+ {
255
+ parent::close();
256
+ $this->negotiated = false;
257
+ }
258
+
259
+ /**
260
+ * Destructor: make sure the socket is disconnected
261
+ *
262
+ */
263
+ public function __destruct()
264
+ {
265
+ if ($this->socket) $this->close();
266
+ }
267
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Http/Client/Adapter/Socket.php ADDED
@@ -0,0 +1,319 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * SZend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category SZend
17
+ * @package SZend_Http
18
+ * @subpackage Client_Adapter
19
+ * @version $Id: Socket.php 8064 2008-02-16 10:58:39Z thomas $
20
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ require_once dirname(__FILE__) . '/../../../Uri/Http.php';
25
+ require_once dirname(__FILE__) . '/../../../Http/Client/Adapter/Interface.php';
26
+
27
+ /**
28
+ * A sockets based (stream_socket_client) adapter class for SZend_Http_Client. Can be used
29
+ * on almost every PHP environment, and does not require any special extensions.
30
+ *
31
+ * @category SZend
32
+ * @package SZend_Http
33
+ * @subpackage Client_Adapter
34
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
35
+ * @license http://framework.zend.com/license/new-bsd New BSD License
36
+ */
37
+ class SZend_Http_Client_Adapter_Socket implements SZend_Http_Client_Adapter_Interface
38
+ {
39
+ /**
40
+ * The socket for server connection
41
+ *
42
+ * @var resource|null
43
+ */
44
+ protected $socket = null;
45
+
46
+ /**
47
+ * What host/port are we connected to?
48
+ *
49
+ * @var array
50
+ */
51
+ protected $connected_to = array(null, null);
52
+
53
+ /**
54
+ * Parameters array
55
+ *
56
+ * @var array
57
+ */
58
+ protected $config = array(
59
+ 'ssltransport' => 'ssl',
60
+ 'sslcert' => null,
61
+ 'sslpassphrase' => null
62
+ );
63
+
64
+ /**
65
+ * Request method - will be set by write() and might be used by read()
66
+ *
67
+ * @var string
68
+ */
69
+ protected $method = null;
70
+
71
+ /**
72
+ * Adapter constructor, currently empty. Config is set using setConfig()
73
+ *
74
+ */
75
+ public function __construct()
76
+ {
77
+ }
78
+
79
+ /**
80
+ * Set the configuration array for the adapter
81
+ *
82
+ * @param array $config
83
+ */
84
+ public function setConfig($config = array())
85
+ {
86
+ if (! is_array($config)) {
87
+ require_once dirname(__FILE__) . '/Exception.php';
88
+ throw new SZend_Http_Client_Adapter_Exception(
89
+ '$config expects an array, ' . gettype($config) . ' recieved.');
90
+ }
91
+
92
+ foreach ($config as $k => $v) {
93
+ $this->config[strtolower($k)] = $v;
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Connect to the remote server
99
+ *
100
+ * @param string $host
101
+ * @param int $port
102
+ * @param boolean $secure
103
+ * @param int $timeout
104
+ */
105
+ public function connect($host, $port = 80, $secure = false)
106
+ {
107
+ // If the URI should be accessed via SSL, prepend the Hostname with ssl://
108
+ $host = ($secure ? $this->config['ssltransport'] : 'tcp') . '://' . $host;
109
+
110
+ // If we are connected to the wrong host, disconnect first
111
+ if (($this->connected_to[0] != $host || $this->connected_to[1] != $port)) {
112
+ if (is_resource($this->socket)) $this->close();
113
+ }
114
+
115
+ // Now, if we are not connected, connect
116
+ if (! is_resource($this->socket) || ! $this->config['keepalive']) {
117
+ $context = stream_context_create();
118
+ if ($secure) {
119
+ if ($this->config['sslcert'] !== null) {
120
+ if (! stream_context_set_option($context, 'ssl', 'local_cert',
121
+ $this->config['sslcert'])) {
122
+ require_once dirname(__FILE__) . '/Exception.php';
123
+ throw new SZend_Http_Client_Adapter_Exception('Unable to set sslcert option');
124
+ }
125
+ }
126
+ if ($this->config['sslpassphrase'] !== null) {
127
+ if (! stream_context_set_option($context, 'ssl', 'passphrase',
128
+ $this->config['sslpassphrase'])) {
129
+ require_once dirname(__FILE__) . '/Exception.php';
130
+ throw new SZend_Http_Client_Adapter_Exception('Unable to set sslpassphrase option');
131
+ }
132
+ }
133
+ }
134
+
135
+ $this->socket = @stream_socket_client($host . ':' . $port,
136
+ $errno,
137
+ $errstr,
138
+ (int) $this->config['timeout'],
139
+ STREAM_CLIENT_CONNECT,
140
+ $context);
141
+ if (! $this->socket) {
142
+ $this->close();
143
+ require_once dirname(__FILE__) . '/Exception.php';
144
+ throw new SZend_Http_Client_Adapter_Exception(
145
+ 'Unable to Connect to ' . $host . ':' . $port . '. Error #' . $errno . ': ' . $errstr);
146
+ }
147
+
148
+ // Set the stream timeout
149
+ if (! stream_set_timeout($this->socket, (int) $this->config['timeout'])) {
150
+ require_once dirname(__FILE__) . '/Exception.php';
151
+ throw new SZend_Http_Client_Adapter_Exception('Unable to set the connection timeout');
152
+ }
153
+
154
+ // Update connected_to
155
+ $this->connected_to = array($host, $port);
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Send request to the remote server
161
+ *
162
+ * @param string $method
163
+ * @param SZend_Uri_Http $uri
164
+ * @param string $http_ver
165
+ * @param array $headers
166
+ * @param string $body
167
+ * @return string Request as string
168
+ */
169
+ public function write($method, $uri, $http_ver = '1.1', $headers = array(), $body = '')
170
+ {
171
+ // Make sure we're properly connected
172
+ if (! $this->socket) {
173
+ require_once dirname(__FILE__) . '/Exception.php';
174
+ throw new SZend_Http_Client_Adapter_Exception('Trying to write but we are not connected');
175
+ }
176
+
177
+ $host = $uri->getHost();
178
+ $host = (strtolower($uri->getScheme()) == 'https' ? $this->config['ssltransport'] : 'tcp') . '://' . $host;
179
+ if ($this->connected_to[0] != $host || $this->connected_to[1] != $uri->getPort()) {
180
+ require_once dirname(__FILE__) . '/Exception.php';
181
+ throw new SZend_Http_Client_Adapter_Exception('Trying to write but we are connected to the wrong host');
182
+ }
183
+
184
+ // Save request method for later
185
+ $this->method = $method;
186
+
187
+ // Build request headers
188
+ $path = $uri->getPath();
189
+ if ($uri->getQuery()) $path .= '?' . $uri->getQuery();
190
+ $request = "{$method} {$path} HTTP/{$http_ver}\r\n";
191
+ foreach ($headers as $k => $v) {
192
+ if (is_string($k)) $v = ucfirst($k) . ": $v";
193
+ $request .= "$v\r\n";
194
+ }
195
+
196
+ // Add the request body
197
+ $request .= "\r\n" . $body;
198
+
199
+ // Send the request
200
+ if (! @fwrite($this->socket, $request)) {
201
+ require_once dirname(__FILE__) . '/Exception.php';
202
+ throw new SZend_Http_Client_Adapter_Exception('Error writing request to server');
203
+ }
204
+
205
+ return $request;
206
+ }
207
+
208
+ /**
209
+ * Read response from server
210
+ *
211
+ * @return string
212
+ */
213
+ public function read()
214
+ {
215
+ // First, read headers only
216
+ $response = '';
217
+ $gotStatus = false;
218
+ while ($line = @fgets($this->socket)) {
219
+ $gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false);
220
+ if ($gotStatus) {
221
+ $response .= $line;
222
+ if (!chop($line)) break;
223
+ }
224
+ }
225
+
226
+ // Handle 100 and 101 responses internally by restarting the read again
227
+ if (SZend_Http_Response::extractCode($response) == 100 ||
228
+ SZend_Http_Response::extractCode($response) == 101) return $this->read();
229
+
230
+ // If this was a HEAD request, return after reading the header (no need to read body)
231
+ if ($this->method == SZend_Http_Client::HEAD) return $response;
232
+
233
+ // Check headers to see what kind of connection / transfer encoding we have
234
+ $headers = SZend_Http_Response::extractHeaders($response);
235
+
236
+ // if the connection is set to close, just read until socket closes
237
+ if (isset($headers['connection']) && $headers['connection'] == 'close') {
238
+ while ($buff = @fread($this->socket, 8192)) {
239
+ $response .= $buff;
240
+ }
241
+
242
+ $this->close();
243
+
244
+ // Else, if we got a transfer-encoding header (chunked body)
245
+ } elseif (isset($headers['transfer-encoding'])) {
246
+ if ($headers['transfer-encoding'] == 'chunked') {
247
+ do {
248
+ $chunk = '';
249
+ $line = @fgets($this->socket);
250
+ $chunk .= $line;
251
+
252
+ $hexchunksize = ltrim(chop($line), '0');
253
+ $hexchunksize = strlen($hexchunksize) ? strtolower($hexchunksize) : 0;
254
+
255
+ $chunksize = hexdec(chop($line));
256
+ if (dechex($chunksize) != $hexchunksize) {
257
+ @fclose($this->socket);
258
+ require_once dirname(__FILE__) . '/Exception.php';
259
+ throw new SZend_Http_Client_Adapter_Exception('Invalid chunk size "' .
260
+ $hexchunksize . '" unable to read chunked body');
261
+ }
262
+
263
+ $left_to_read = $chunksize;
264
+ while ($left_to_read > 0) {
265
+ $line = @fread($this->socket, $left_to_read);
266
+ $chunk .= $line;
267
+ $left_to_read -= strlen($line);
268
+ }
269
+
270
+ $chunk .= @fgets($this->socket);
271
+ $response .= $chunk;
272
+ } while ($chunksize > 0);
273
+ } else {
274
+ throw new SZend_Http_Client_Adapter_Exception('Cannot handle "' .
275
+ $headers['transfer-encoding'] . '" transfer encoding');
276
+ }
277
+
278
+ // Else, if we got the content-length header, read this number of bytes
279
+ } elseif (isset($headers['content-length'])) {
280
+ $left_to_read = $headers['content-length'];
281
+ $chunk = '';
282
+ while ($left_to_read > 0) {
283
+ $chunk = @fread($this->socket, $left_to_read);
284
+ $left_to_read -= strlen($chunk);
285
+ $response .= $chunk;
286
+ }
287
+
288
+ // Fallback: just read the response (should not happen)
289
+ } else {
290
+ while ($buff = @fread($this->socket, 8192)) {
291
+ $response .= $buff;
292
+ }
293
+
294
+ $this->close();
295
+ }
296
+
297
+ return $response;
298
+ }
299
+
300
+ /**
301
+ * Close the connection to the server
302
+ *
303
+ */
304
+ public function close()
305
+ {
306
+ if (is_resource($this->socket)) @fclose($this->socket);
307
+ $this->socket = null;
308
+ $this->connected_to = array(null, null);
309
+ }
310
+
311
+ /**
312
+ * Destructor: make sure the socket is disconnected
313
+ *
314
+ */
315
+ public function __destruct()
316
+ {
317
+ if ($this->socket) $this->close();
318
+ }
319
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Http/Client/Adapter/Test.php ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SZend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category SZend
16
+ * @package SZend_Http
17
+ * @subpackage Client_Adapter
18
+ * @version $Id: Test.php 8064 2008-02-16 10:58:39Z thomas $
19
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
20
+ * @license http://framework.zend.com/license/new-bsd New BSD License
21
+ */
22
+
23
+ require_once dirname(__FILE__) . '/../../../Uri/Http.php';
24
+ require_once dirname(__FILE__) . '/../../../Http/Response.php';
25
+ require_once dirname(__FILE__) . '/../../../Http/Client/Adapter/Interface.php';
26
+
27
+ /**
28
+ * A testing-purposes adapter.
29
+ *
30
+ * Should be used to test all components that rely on SZend_Http_Client,
31
+ * without actually performing an HTTP request. You should instantiate this
32
+ * object manually, and then set it as the client's adapter. Then, you can
33
+ * set the expected response using the setResponse() method.
34
+ *
35
+ * @category SZend
36
+ * @package SZend_Http
37
+ * @subpackage Client_Adapter
38
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
39
+ * @license http://framework.zend.com/license/new-bsd New BSD License
40
+ */
41
+ class SZend_Http_Client_Adapter_Test implements SZend_Http_Client_Adapter_Interface
42
+ {
43
+ /**
44
+ * Parameters array
45
+ *
46
+ * @var array
47
+ */
48
+ protected $config = array();
49
+
50
+ /**
51
+ * Buffer of responses to be returned by the read() method. Can be
52
+ * set using setResponse() and addResponse().
53
+ *
54
+ * @var array
55
+ */
56
+ protected $responses = array("HTTP/1.1 400 Bad Request\r\n\r\n");
57
+
58
+ /**
59
+ * Current position in the response buffer
60
+ *
61
+ * @var integer
62
+ */
63
+ protected $responseIndex = 0;
64
+
65
+ /**
66
+ * Adapter constructor, currently empty. Config is set using setConfig()
67
+ *
68
+ */
69
+ public function __construct()
70
+ { }
71
+
72
+ /**
73
+ * Set the configuration array for the adapter
74
+ *
75
+ * @param array $config
76
+ */
77
+ public function setConfig($config = array())
78
+ {
79
+ if (! is_array($config)) {
80
+ require_once 'SZend/Http/Client/Adapter/Exception.php';
81
+ throw new SZend_Http_Client_Adapter_Exception(
82
+ '$config expects an array, ' . gettype($config) . ' recieved.');
83
+ }
84
+
85
+ foreach ($config as $k => $v) {
86
+ $this->config[strtolower($k)] = $v;
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Connect to the remote server
92
+ *
93
+ * @param string $host
94
+ * @param int $port
95
+ * @param boolean $secure
96
+ * @param int $timeout
97
+ */
98
+ public function connect($host, $port = 80, $secure = false)
99
+ { }
100
+
101
+ /**
102
+ * Send request to the remote server
103
+ *
104
+ * @param string $method
105
+ * @param SZend_Uri_Http $uri
106
+ * @param string $http_ver
107
+ * @param array $headers
108
+ * @param string $body
109
+ * @return string Request as string
110
+ */
111
+ public function write($method, $uri, $http_ver = '1.1', $headers = array(), $body = '')
112
+ {
113
+ $host = $uri->getHost();
114
+ $host = (strtolower($uri->getScheme()) == 'https' ? 'sslv2://' . $host : $host);
115
+
116
+ // Build request headers
117
+ $path = $uri->getPath();
118
+ if ($uri->getQuery()) $path .= '?' . $uri->getQuery();
119
+ $request = "{$method} {$path} HTTP/{$http_ver}\r\n";
120
+ foreach ($headers as $k => $v) {
121
+ if (is_string($k)) $v = ucfirst($k) . ": $v";
122
+ $request .= "$v\r\n";
123
+ }
124
+
125
+ // Add the request body
126
+ $request .= "\r\n" . $body;
127
+
128
+ // Do nothing - just return the request as string
129
+
130
+ return $request;
131
+ }
132
+
133
+ /**
134
+ * Return the response set in $this->setResponse()
135
+ *
136
+ * @return string
137
+ */
138
+ public function read()
139
+ {
140
+ if ($this->responseIndex >= count($this->responses)) {
141
+ $this->responseIndex = 0;
142
+ }
143
+ return $this->responses[$this->responseIndex++];
144
+ }
145
+
146
+ /**
147
+ * Close the connection (dummy)
148
+ *
149
+ */
150
+ public function close()
151
+ { }
152
+
153
+ /**
154
+ * Set the HTTP response(s) to be returned by this adapter
155
+ *
156
+ * @param SZend_Http_Response|array|string $response
157
+ */
158
+ public function setResponse($response)
159
+ {
160
+ if ($response instanceof SZend_Http_Response) {
161
+ $response = $response->asString();
162
+ }
163
+
164
+ $this->responses = (array)$response;
165
+ $this->responseIndex = 0;
166
+ }
167
+
168
+ /**
169
+ * Add another response to the response buffer.
170
+ *
171
+ * @param string $response
172
+ */
173
+ public function addResponse($response)
174
+ {
175
+ $this->responses[] = $response;
176
+ }
177
+
178
+ /**
179
+ * Sets the position of the response buffer. Selects which
180
+ * response will be returned on the next call to read().
181
+ *
182
+ * @param integer $index
183
+ */
184
+ public function setResponseIndex($index)
185
+ {
186
+ if ($index < 0 || $index >= count($this->responses)) {
187
+ require_once 'SZend/Http/Client/Adapter/Exception.php';
188
+ throw new SZend_Http_Client_Adapter_Exception(
189
+ 'Index out of range of response buffer size');
190
+ }
191
+ $this->responseIndex = $index;
192
+ }
193
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Http/Client/Exception.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SZend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category SZend
16
+ * @package SZend_Http
17
+ * @subpackage Client_Exception
18
+ * @version $Id: Exception.php 8064 2008-02-16 10:58:39Z thomas $
19
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
20
+ * @license http://framework.zend.com/license/new-bsd New BSD License
21
+ */
22
+
23
+ require_once dirname(__FILE__) . '/../../Http/Exception.php';
24
+
25
+ /**
26
+ * @category SZend
27
+ * @package SZend_Http
28
+ * @subpackage Client
29
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
30
+ * @license http://framework.zend.com/license/new-bsd New BSD License
31
+ */
32
+ class SZend_Http_Client_Exception extends SZend_Http_Exception
33
+ {}
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Http/Exception.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SZend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category SZend
16
+ * @package SZend_Http
17
+ * @subpackage Exception
18
+ * @version $Id: Exception.php 23775 2011-03-01 17:25:24Z ralph $
19
+ * @copyright Copyright (c) 2005-2011 SZend Technologies USA Inc. (http://www.zend.com)
20
+ * @license http://framework.zend.com/license/new-bsd New BSD License
21
+ */
22
+
23
+ /**
24
+ * @see SZend_Exception
25
+ */
26
+ // require_once 'SZend/Exception.php';
27
+
28
+ /**
29
+ * @category SZend
30
+ * @package SZend_Http
31
+ * @subpackage Client
32
+ * @copyright Copyright (c) 2005-2011 SZend Technologies USA Inc. (http://www.zend.com)
33
+ * @license http://framework.zend.com/license/new-bsd New BSD License
34
+ */
35
+ class SZend_Http_Exception extends SZend_Exception
36
+ {}
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Http/Response.php ADDED
@@ -0,0 +1,625 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * SZend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category SZend
17
+ * @package SZend_Http
18
+ * @subpackage Response
19
+ * @version $Id: Response.php 8064 2008-02-16 10:58:39Z thomas $
20
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
21
+ * @license http://framework.zend.com/license/new-bsd New BSD License
22
+ */
23
+
24
+ /**
25
+ * SZend_Http_Response represents an HTTP 1.0 / 1.1 response message. It
26
+ * includes easy access to all the response's different elemts, as well as some
27
+ * convenience methods for parsing and validating HTTP responses.
28
+ *
29
+ * @package SZend_Http
30
+ * @subpackage Response
31
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
32
+ * @license http://framework.zend.com/license/new-bsd New BSD License
33
+ */
34
+ class SZend_Http_Response
35
+ {
36
+ /**
37
+ * List of all known HTTP response codes - used by responseCodeAsText() to
38
+ * translate numeric codes to messages.
39
+ *
40
+ * @var array
41
+ */
42
+ protected static $messages = array(
43
+ // Informational 1xx
44
+ 100 => 'Continue',
45
+ 101 => 'Switching Protocols',
46
+
47
+ // Success 2xx
48
+ 200 => 'OK',
49
+ 201 => 'Created',
50
+ 202 => 'Accepted',
51
+ 203 => 'Non-Authoritative Information',
52
+ 204 => 'No Content',
53
+ 205 => 'Reset Content',
54
+ 206 => 'Partial Content',
55
+
56
+ // Redirection 3xx
57
+ 300 => 'Multiple Choices',
58
+ 301 => 'Moved Permanently',
59
+ 302 => 'Found', // 1.1
60
+ 303 => 'See Other',
61
+ 304 => 'Not Modified',
62
+ 305 => 'Use Proxy',
63
+ // 306 is deprecated but reserved
64
+ 307 => 'Temporary Redirect',
65
+
66
+ // Client Error 4xx
67
+ 400 => 'Bad Request',
68
+ 401 => 'Unauthorized',
69
+ 402 => 'Payment Required',
70
+ 403 => 'Forbidden',
71
+ 404 => 'Not Found',
72
+ 405 => 'Method Not Allowed',
73
+ 406 => 'Not Acceptable',
74
+ 407 => 'Proxy Authentication Required',
75
+ 408 => 'Request Timeout',
76
+ 409 => 'Conflict',
77
+ 410 => 'Gone',
78
+ 411 => 'Length Required',
79
+ 412 => 'Precondition Failed',
80
+ 413 => 'Request Entity Too Large',
81
+ 414 => 'Request-URI Too Long',
82
+ 415 => 'Unsupported Media Type',
83
+ 416 => 'Requested Range Not Satisfiable',
84
+ 417 => 'Expectation Failed',
85
+
86
+ // Server Error 5xx
87
+ 500 => 'Internal Server Error',
88
+ 501 => 'Not Implemented',
89
+ 502 => 'Bad Gateway',
90
+ 503 => 'Service Unavailable',
91
+ 504 => 'Gateway Timeout',
92
+ 505 => 'HTTP Version Not Supported',
93
+ 509 => 'Bandwidth Limit Exceeded'
94
+ );
95
+
96
+ /**
97
+ * The HTTP version (1.0, 1.1)
98
+ *
99
+ * @var string
100
+ */
101
+ protected $version;
102
+
103
+ /**
104
+ * The HTTP response code
105
+ *
106
+ * @var int
107
+ */
108
+ protected $code;
109
+
110
+ /**
111
+ * The HTTP response code as string
112
+ * (e.g. 'Not Found' for 404 or 'Internal Server Error' for 500)
113
+ *
114
+ * @var string
115
+ */
116
+ protected $message;
117
+
118
+ /**
119
+ * The HTTP response headers array
120
+ *
121
+ * @var array
122
+ */
123
+ protected $headers = array();
124
+
125
+ /**
126
+ * The HTTP response body
127
+ *
128
+ * @var string
129
+ */
130
+ protected $body;
131
+
132
+ /**
133
+ * HTTP response constructor
134
+ *
135
+ * In most cases, you would use SZend_Http_Response::fromString to parse an HTTP
136
+ * response string and create a new SZend_Http_Response object.
137
+ *
138
+ * NOTE: The constructor no longer accepts nulls or empty values for the code and
139
+ * headers and will throw an exception if the passed values do not form a valid HTTP
140
+ * responses.
141
+ *
142
+ * If no message is passed, the message will be guessed according to the response code.
143
+ *
144
+ * @param int $code Response code (200, 404, ...)
145
+ * @param array $headers Headers array
146
+ * @param string $body Response body
147
+ * @param string $version HTTP version
148
+ * @param string $message Response code as text
149
+ * @throws SZend_Http_Exception
150
+ */
151
+ public function __construct($code, $headers, $body = null, $version = '1.1', $message = null)
152
+ {
153
+ // Make sure the response code is valid and set it
154
+ if (self::responseCodeAsText($code) === null) {
155
+ require_once 'SZend/Http/Exception.php';
156
+ throw new SZend_Http_Exception("{$code} is not a valid HTTP response code");
157
+ }
158
+
159
+ $this->code = $code;
160
+
161
+ // Make sure we got valid headers and set them
162
+ if (! is_array($headers)) {
163
+ require_once 'SZend/Http/Exception.php';
164
+ throw new SZend_Http_Exception('No valid headers were passed');
165
+ }
166
+
167
+ foreach ($headers as $name => $value) {
168
+ if (is_int($name))
169
+ list($name, $value) = explode(": ", $value, 1);
170
+
171
+ $this->headers[ucwords(strtolower($name))] = $value;
172
+ }
173
+
174
+ // Set the body
175
+ $this->body = $body;
176
+
177
+ // Set the HTTP version
178
+ if (! preg_match('|^\d\.\d$|', $version)) {
179
+ require_once 'SZend/Http/Exception.php';
180
+ throw new SZend_Http_Exception("Invalid HTTP response version: $version");
181
+ }
182
+
183
+ $this->version = $version;
184
+
185
+ // If we got the response message, set it. Else, set it according to
186
+ // the response code
187
+ if (is_string($message)) {
188
+ $this->message = $message;
189
+ } else {
190
+ $this->message = self::responseCodeAsText($code);
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Check whether the response is an error
196
+ *
197
+ * @return boolean
198
+ */
199
+ public function isError()
200
+ {
201
+ $restype = floor($this->code / 100);
202
+ if ($restype == 4 || $restype == 5) {
203
+ return true;
204
+ }
205
+
206
+ return false;
207
+ }
208
+
209
+ /**
210
+ * Check whether the response in successful
211
+ *
212
+ * @return boolean
213
+ */
214
+ public function isSuccessful()
215
+ {
216
+ $restype = floor($this->code / 100);
217
+ if ($restype == 2 || $restype == 1) { // Shouldn't 3xx count as success as well ???
218
+ return true;
219
+ }
220
+
221
+ return false;
222
+ }
223
+
224
+ /**
225
+ * Check whether the response is a redirection
226
+ *
227
+ * @return boolean
228
+ */
229
+ public function isRedirect()
230
+ {
231
+ $restype = floor($this->code / 100);
232
+ if ($restype == 3) {
233
+ return true;
234
+ }
235
+
236
+ return false;
237
+ }
238
+
239
+ /**
240
+ * Get the response body as string
241
+ *
242
+ * This method returns the body of the HTTP response (the content), as it
243
+ * should be in it's readable version - that is, after decoding it (if it
244
+ * was decoded), deflating it (if it was gzip compressed), etc.
245
+ *
246
+ * If you want to get the raw body (as transfered on wire) use
247
+ * $this->getRawBody() instead.
248
+ *
249
+ * @return string
250
+ */
251
+ public function getBody()
252
+ {
253
+ $body = '';
254
+
255
+ // Decode the body if it was transfer-encoded
256
+ switch ($this->getHeader('transfer-encoding')) {
257
+
258
+ // Handle chunked body
259
+ case 'chunked':
260
+ $body = self::decodeChunkedBody($this->body);
261
+ break;
262
+
263
+ // No transfer encoding, or unknown encoding extension:
264
+ // return body as is
265
+ default:
266
+ $body = $this->body;
267
+ break;
268
+ }
269
+
270
+ // Decode any content-encoding (gzip or deflate) if needed
271
+ switch (strtolower($this->getHeader('content-encoding'))) {
272
+
273
+ // Handle gzip encoding
274
+ case 'gzip':
275
+ $body = self::decodeGzip($body);
276
+ break;
277
+
278
+ // Handle deflate encoding
279
+ case 'deflate':
280
+ $body = self::decodeDeflate($body);
281
+ break;
282
+
283
+ default:
284
+ break;
285
+ }
286
+
287
+ return $body;
288
+ }
289
+
290
+ /**
291
+ * Get the raw response body (as transfered "on wire") as string
292
+ *
293
+ * If the body is encoded (with Transfer-Encoding, not content-encoding -
294
+ * IE "chunked" body), gzip compressed, etc. it will not be decoded.
295
+ *
296
+ * @return string
297
+ */
298
+ public function getRawBody()
299
+ {
300
+ return $this->body;
301
+ }
302
+
303
+ /**
304
+ * Get the HTTP version of the response
305
+ *
306
+ * @return string
307
+ */
308
+ public function getVersion()
309
+ {
310
+ return $this->version;
311
+ }
312
+
313
+ /**
314
+ * Get the HTTP response status code
315
+ *
316
+ * @return int
317
+ */
318
+ public function getStatus()
319
+ {
320
+ return $this->code;
321
+ }
322
+
323
+ /**
324
+ * Return a message describing the HTTP response code
325
+ * (Eg. "OK", "Not Found", "Moved Permanently")
326
+ *
327
+ * @return string
328
+ */
329
+ public function getMessage()
330
+ {
331
+ return $this->message;
332
+ }
333
+
334
+ /**
335
+ * Get the response headers
336
+ *
337
+ * @return array
338
+ */
339
+ public function getHeaders()
340
+ {
341
+ return $this->headers;
342
+ }
343
+
344
+ /**
345
+ * Get a specific header as string, or null if it is not set
346
+ *
347
+ * @param string$header
348
+ * @return string|array|null
349
+ */
350
+ public function getHeader($header)
351
+ {
352
+ $header = ucwords(strtolower($header));
353
+ if (! is_string($header) || ! isset($this->headers[$header])) return null;
354
+
355
+ return $this->headers[$header];
356
+ }
357
+
358
+ /**
359
+ * Get all headers as string
360
+ *
361
+ * @param boolean $status_line Whether to return the first status line (IE "HTTP 200 OK")
362
+ * @param string $br Line breaks (eg. "\n", "\r\n", "<br />")
363
+ * @return string
364
+ */
365
+ public function getHeadersAsString($status_line = true, $br = "\n")
366
+ {
367
+ $str = '';
368
+
369
+ if ($status_line) {
370
+ $str = "HTTP/{$this->version} {$this->code} {$this->message}{$br}";
371
+ }
372
+
373
+ // Iterate over the headers and stringify them
374
+ foreach ($this->headers as $name => $value)
375
+ {
376
+ if (is_string($value))
377
+ $str .= "{$name}: {$value}{$br}";
378
+
379
+ elseif (is_array($value)) {
380
+ foreach ($value as $subval) {
381
+ $str .= "{$name}: {$subval}{$br}";
382
+ }
383
+ }
384
+ }
385
+
386
+ return $str;
387
+ }
388
+
389
+ /**
390
+ * Get the entire response as string
391
+ *
392
+ * @param string $br Line breaks (eg. "\n", "\r\n", "<br />")
393
+ * @return string
394
+ */
395
+ public function asString($br = "\n")
396
+ {
397
+ return $this->getHeadersAsString(true, $br) . $br . $this->getBody();
398
+ }
399
+
400
+ /**
401
+ * A convenience function that returns a text representation of
402
+ * HTTP response codes. Returns 'Unknown' for unknown codes.
403
+ * Returns array of all codes, if $code is not specified.
404
+ *
405
+ * Conforms to HTTP/1.1 as defined in RFC 2616 (except for 'Unknown')
406
+ * See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10 for reference
407
+ *
408
+ * @param int $code HTTP response code
409
+ * @param boolean $http11 Use HTTP version 1.1
410
+ * @return string
411
+ */
412
+ public static function responseCodeAsText($code = null, $http11 = true)
413
+ {
414
+ $messages = self::$messages;
415
+ if (! $http11) $messages[302] = 'Moved Temporarily';
416
+
417
+ if ($code === null) {
418
+ return $messages;
419
+ } elseif (isset($messages[$code])) {
420
+ return $messages[$code];
421
+ } else {
422
+ return 'Unknown';
423
+ }
424
+ }
425
+
426
+ /**
427
+ * Extract the response code from a response string
428
+ *
429
+ * @param string $response_str
430
+ * @return int
431
+ */
432
+ public static function extractCode($response_str)
433
+ {
434
+ preg_match("|^HTTP/[\d\.x]+ (\d+)|", $response_str, $m);
435
+
436
+ if (isset($m[1])) {
437
+ return (int) $m[1];
438
+ } else {
439
+ return false;
440
+ }
441
+ }
442
+
443
+ /**
444
+ * Extract the HTTP message from a response
445
+ *
446
+ * @param string $response_str
447
+ * @return string
448
+ */
449
+ public static function extractMessage($response_str)
450
+ {
451
+ preg_match("|^HTTP/[\d\.x]+ \d+ ([^\r\n]+)|", $response_str, $m);
452
+
453
+ if (isset($m[1])) {
454
+ return $m[1];
455
+ } else {
456
+ return false;
457
+ }
458
+ }
459
+
460
+ /**
461
+ * Extract the HTTP version from a response
462
+ *
463
+ * @param string $response_str
464
+ * @return string
465
+ */
466
+ public static function extractVersion($response_str)
467
+ {
468
+ preg_match("|^HTTP/([\d\.x]+) \d+|", $response_str, $m);
469
+
470
+ if (isset($m[1])) {
471
+ return $m[1];
472
+ } else {
473
+ return false;
474
+ }
475
+ }
476
+
477
+ /**
478
+ * Extract the headers from a response string
479
+ *
480
+ * @param string $response_str
481
+ * @return array
482
+ */
483
+ public static function extractHeaders($response_str)
484
+ {
485
+ $headers = array();
486
+
487
+ // First, split body and headers
488
+ $parts = preg_split('|(?:\r?\n){2}|m', $response_str, 2);
489
+ if (! $parts[0]) return $headers;
490
+
491
+ // Split headers part to lines
492
+ $lines = explode("\n", $parts[0]);
493
+ unset($parts);
494
+ $last_header = null;
495
+
496
+ foreach($lines as $line) {
497
+ $line = trim($line, "\r\n");
498
+ if ($line == "") break;
499
+
500
+ if (preg_match("|^([\w-]+):\s+(.+)|", $line, $m)) {
501
+ unset($last_header);
502
+ $h_name = strtolower($m[1]);
503
+ $h_value = $m[2];
504
+
505
+ if (isset($headers[$h_name])) {
506
+ if (! is_array($headers[$h_name])) {
507
+ $headers[$h_name] = array($headers[$h_name]);
508
+ }
509
+
510
+ $headers[$h_name][] = $h_value;
511
+ } else {
512
+ $headers[$h_name] = $h_value;
513
+ }
514
+ $last_header = $h_name;
515
+ } elseif (preg_match("|^\s+(.+)$|", $line, $m) && $last_header !== null) {
516
+ if (is_array($headers[$last_header])) {
517
+ end($headers[$last_header]);
518
+ $last_header_key = key($headers[$last_header]);
519
+ $headers[$last_header][$last_header_key] .= $m[1];
520
+ } else {
521
+ $headers[$last_header] .= $m[1];
522
+ }
523
+ }
524
+ }
525
+
526
+ return $headers;
527
+ }
528
+
529
+ /**
530
+ * Extract the body from a response string
531
+ *
532
+ * @param string $response_str
533
+ * @return string
534
+ */
535
+ public static function extractBody($response_str)
536
+ {
537
+ $parts = preg_split('|(?:\r?\n){2}|m', $response_str, 2);
538
+ if (isset($parts[1])) {
539
+ return $parts[1];
540
+ } else {
541
+ return '';
542
+ }
543
+ }
544
+
545
+ /**
546
+ * Decode a "chunked" transfer-encoded body and return the decoded text
547
+ *
548
+ * @param string $body
549
+ * @return string
550
+ */
551
+ public static function decodeChunkedBody($body)
552
+ {
553
+ $decBody = '';
554
+
555
+ while (trim($body)) {
556
+ if (! preg_match("/^([\da-fA-F]+)[^\r\n]*\r\n/sm", $body, $m)) {
557
+ require_once 'SZend/Http/Exception.php';
558
+ throw new SZend_Http_Exception("Error parsing body - doesn't seem to be a chunked message");
559
+ }
560
+
561
+ $length = hexdec(trim($m[1]));
562
+ $cut = strlen($m[0]);
563
+
564
+ $decBody .= substr($body, $cut, $length);
565
+ $body = substr($body, $cut + $length + 2);
566
+ }
567
+
568
+ return $decBody;
569
+ }
570
+
571
+ /**
572
+ * Decode a gzip encoded message (when Content-encoding = gzip)
573
+ *
574
+ * Currently requires PHP with zlib support
575
+ *
576
+ * @param string $body
577
+ * @return string
578
+ */
579
+ public static function decodeGzip($body)
580
+ {
581
+ if (! function_exists('gzinflate')) {
582
+ require_once 'SZend/Http/Exception.php';
583
+ throw new SZend_Http_Exception('Unable to decode gzipped response ' .
584
+ 'body: perhaps the zlib extension is not loaded?');
585
+ }
586
+
587
+ return gzinflate(substr($body, 10));
588
+ }
589
+
590
+ /**
591
+ * Decode a zlib deflated message (when Content-encoding = deflate)
592
+ *
593
+ * Currently requires PHP with zlib support
594
+ *
595
+ * @param string $body
596
+ * @return string
597
+ */
598
+ public static function decodeDeflate($body)
599
+ {
600
+ if (! function_exists('gzuncompress')) {
601
+ require_once 'SZend/Http/Exception.php';
602
+ throw new SZend_Http_Exception('Unable to decode deflated response ' .
603
+ 'body: perhaps the zlib extension is not loaded?');
604
+ }
605
+
606
+ return gzuncompress($body);
607
+ }
608
+
609
+ /**
610
+ * Create a new SZend_Http_Response object from a string
611
+ *
612
+ * @param string $response_str
613
+ * @return SZend_Http_Response
614
+ */
615
+ public static function fromString($response_str)
616
+ {
617
+ $code = self::extractCode($response_str);
618
+ $headers = self::extractHeaders($response_str);
619
+ $body = self::extractBody($response_str);
620
+ $version = self::extractVersion($response_str);
621
+ $message = self::extractMessage($response_str);
622
+
623
+ return new SZend_Http_Response($code, $headers, $body, $version, $message);
624
+ }
625
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Json.php ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SZend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category SZend
16
+ * @package SZend_Json
17
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ */
20
+
21
+ /**
22
+ * SZend_Json_Exception.
23
+ */
24
+ require_once dirname(__FILE__) . '/Json/Exception.php';
25
+
26
+ /**
27
+ * Class for encoding to and decoding from JSON.
28
+ *
29
+ * @category SZend
30
+ * @package SZend_Json
31
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
32
+ * @license http://framework.zend.com/license/new-bsd New BSD License
33
+ */
34
+ class SZend_Json
35
+ {
36
+ /**
37
+ * How objects should be encoded -- arrays or as StdClass. TYPE_ARRAY is 1
38
+ * so that it is a boolean true value, allowing it to be used with
39
+ * ext/json's functions.
40
+ */
41
+ const TYPE_ARRAY = 1;
42
+ const TYPE_OBJECT = 0;
43
+
44
+ /**
45
+ * To check the allowed nesting depth of the XML tree during xml2json conversion.
46
+ *
47
+ * @var int
48
+ */
49
+ public static $maxRecursionDepthAllowed=25;
50
+
51
+ /**
52
+ * @var bool
53
+ */
54
+ public static $useBuiltinEncoderDecoder = false;
55
+
56
+ /**
57
+ * Decodes the given $encodedValue string which is
58
+ * encoded in the JSON format
59
+ *
60
+ * Uses ext/json's json_decode if available.
61
+ *
62
+ * @param string $encodedValue Encoded in JSON format
63
+ * @param int $objectDecodeType Optional; flag indicating how to decode
64
+ * objects. See {@link ZJsonDecoder::decode()} for details.
65
+ * @return mixed
66
+ */
67
+ public static function decode($encodedValue, $objectDecodeType = SZend_Json::TYPE_ARRAY)
68
+ {
69
+ if (function_exists('json_decode') && self::$useBuiltinEncoderDecoder !== true) {
70
+ return json_decode($encodedValue, $objectDecodeType);
71
+ }
72
+
73
+ require_once 'SZend/Json/Decoder.php';
74
+ return SZend_Json_Decoder::decode($encodedValue, $objectDecodeType);
75
+ }
76
+
77
+
78
+ /**
79
+ * Encode the mixed $valueToEncode into the JSON format
80
+ *
81
+ * Encodes using ext/json's json_encode() if available.
82
+ *
83
+ * NOTE: Object should not contain cycles; the JSON format
84
+ * does not allow object reference.
85
+ *
86
+ * NOTE: Only public variables will be encoded
87
+ *
88
+ * @param mixed $valueToEncode
89
+ * @param boolean $cycleCheck Optional; whether or not to check for object recursion; off by default
90
+ * @return string JSON encoded object
91
+ */
92
+ public static function encode($valueToEncode, $cycleCheck = false)
93
+ {
94
+ if (function_exists('json_encode') && self::$useBuiltinEncoderDecoder !== true) {
95
+ return json_encode($valueToEncode);
96
+ }
97
+
98
+ require_once 'SZend/Json/Encoder.php';
99
+ return SZend_Json_Encoder::encode($valueToEncode, $cycleCheck);
100
+ }
101
+
102
+ /**
103
+ * fromXml - Converts XML to JSON
104
+ *
105
+ * Converts a XML formatted string into a JSON formatted string.
106
+ * The value returned will be a string in JSON format.
107
+ *
108
+ * The caller of this function needs to provide only the first parameter,
109
+ * which is an XML formatted String. The second parameter is optional, which
110
+ * lets the user to select if the XML attributes in the input XML string
111
+ * should be included or ignored in xml2json conversion.
112
+ *
113
+ * This function converts the XML formatted string into a PHP array by
114
+ * calling a recursive (protected static) function in this class. Then, it
115
+ * converts that PHP array into JSON by calling the "encode" static funcion.
116
+ *
117
+ * Throws a SZend_Json_Exception if the input not a XML formatted string.
118
+ *
119
+ * @static
120
+ * @access public
121
+ * @param string $xmlStringContents XML String to be converted
122
+ * @param boolean $ignoreXmlAttributes Include or exclude XML attributes in
123
+ * the xml2json conversion process.
124
+ * @return mixed - JSON formatted string on success
125
+ * @throws SZend_Json_Exception
126
+ */
127
+ public static function fromXml ($xmlStringContents, $ignoreXmlAttributes=true) {
128
+ // Load the XML formatted string into a Simple XML Element object.
129
+ $simpleXmlElementObject = simplexml_load_string($xmlStringContents);
130
+
131
+ // If it is not a valid XML content, throw an exception.
132
+ if ($simpleXmlElementObject == null) {
133
+ throw new SZend_Json_Exception('Function fromXml was called with an invalid XML formatted string.');
134
+ } // End of if ($simpleXmlElementObject == null)
135
+
136
+ $resultArray = null;
137
+
138
+ // Call the recursive function to convert the XML into a PHP array.
139
+ $resultArray = self::_processXml($simpleXmlElementObject, $ignoreXmlAttributes);
140
+
141
+ // Convert the PHP array to JSON using SZend_Json encode method.
142
+ // It is just that simple.
143
+ $jsonStringOutput = self::encode($resultArray);
144
+ return($jsonStringOutput);
145
+ } // End of function fromXml.
146
+
147
+ /**
148
+ * _processXml - Contains the logic for xml2json
149
+ *
150
+ * The logic in this function is a recursive one.
151
+ *
152
+ * The main caller of this function (i.e. fromXml) needs to provide
153
+ * only the first two parameters i.e. the SimpleXMLElement object and
154
+ * the flag for ignoring or not ignoring XML attributes. The third parameter
155
+ * will be used internally within this function during the recursive calls.
156
+ *
157
+ * This function converts the SimpleXMLElement object into a PHP array by
158
+ * calling a recursive (protected static) function in this class. Once all
159
+ * the XML elements are stored in the PHP array, it is returned to the caller.
160
+ *
161
+ * Throws a SZend_Json_Exception if the XML tree is deeper than the allowed limit.
162
+ *
163
+ * @static
164
+ * @access protected
165
+ * @param SimpleXMLElement $simpleXmlElementObject XML element to be converted
166
+ * @param boolean $ignoreXmlAttributes Include or exclude XML attributes in
167
+ * the xml2json conversion process.
168
+ * @param int $recursionDepth Current recursion depth of this function
169
+ * @return mixed - On success, a PHP associative array of traversed XML elements
170
+ * @throws SZend_Json_Exception
171
+ */
172
+ protected static function _processXml ($simpleXmlElementObject, $ignoreXmlAttributes, $recursionDepth=0) {
173
+ // Keep an eye on how deeply we are involved in recursion.
174
+ if ($recursionDepth > self::$maxRecursionDepthAllowed) {
175
+ // XML tree is too deep. Exit now by throwing an exception.
176
+ throw new SZend_Json_Exception(
177
+ "Function _processXml exceeded the allowed recursion depth of " .
178
+ self::$maxRecursionDepthAllowed);
179
+ } // End of if ($recursionDepth > self::$maxRecursionDepthAllowed)
180
+
181
+ if ($recursionDepth == 0) {
182
+ // Store the original SimpleXmlElementObject sent by the caller.
183
+ // We will need it at the very end when we return from here for good.
184
+ $callerProvidedSimpleXmlElementObject = $simpleXmlElementObject;
185
+ } // End of if ($recursionDepth == 0)
186
+
187
+ if ($simpleXmlElementObject instanceof SimpleXMLElement) {
188
+ // Get a copy of the simpleXmlElementObject
189
+ $copyOfSimpleXmlElementObject = $simpleXmlElementObject;
190
+ // Get the object variables in the SimpleXmlElement object for us to iterate.
191
+ $simpleXmlElementObject = get_object_vars($simpleXmlElementObject);
192
+ } // End of if (get_class($simpleXmlElementObject) == "SimpleXMLElement")
193
+
194
+ // It needs to be an array of object variables.
195
+ if (is_array($simpleXmlElementObject)) {
196
+ // Initialize a result array.
197
+ $resultArray = array();
198
+ // Is the input array size 0? Then, we reached the rare CDATA text if any.
199
+ if (count($simpleXmlElementObject) <= 0) {
200
+ // Let us return the lonely CDATA. It could even be
201
+ // an empty element or just filled with whitespaces.
202
+ return (trim(strval($copyOfSimpleXmlElementObject)));
203
+ } // End of if (count($simpleXmlElementObject) <= 0)
204
+
205
+ // Let us walk through the child elements now.
206
+ foreach($simpleXmlElementObject as $key=>$value) {
207
+ // Check if we need to ignore the XML attributes.
208
+ // If yes, you can skip processing the XML attributes.
209
+ // Otherwise, add the XML attributes to the result array.
210
+ if(($ignoreXmlAttributes == true) && (is_string($key)) && ($key == "@attributes")) {
211
+ continue;
212
+ } // End of if(($ignoreXmlAttributes == true) && ($key == "@attributes"))
213
+
214
+ // Let us recursively process the current XML element we just visited.
215
+ // Increase the recursion depth by one.
216
+ $recursionDepth++;
217
+ $resultArray[$key] = self::_processXml ($value, $ignoreXmlAttributes, $recursionDepth);
218
+
219
+ // Decrease the recursion depth by one.
220
+ $recursionDepth--;
221
+ } // End of foreach($simpleXmlElementObject as $key=>$value) {
222
+
223
+ if ($recursionDepth == 0) {
224
+ // That is it. We are heading to the exit now.
225
+ // Set the XML root element name as the root [top-level] key of
226
+ // the associative array that we are going to return to the original
227
+ // caller of this recursive function.
228
+ $tempArray = $resultArray;
229
+ $resultArray = array();
230
+ $resultArray[$callerProvidedSimpleXmlElementObject->getName()] = $tempArray;
231
+ } // End of if ($recursionDepth == 0)
232
+
233
+ return($resultArray);
234
+ } else {
235
+ // We are now looking at either the XML attribute text or
236
+ // the text between the XML tags.
237
+ return (trim(strval($simpleXmlElementObject)));
238
+ } // End of if (is_array($simpleXmlElementObject))
239
+ } // End of function _processXml.
240
+ }
241
+
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Json/Decoder.php ADDED
@@ -0,0 +1,457 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SZend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category SZend
16
+ * @package SZend_Json
17
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ */
20
+
21
+ /**
22
+ * SZend_Json
23
+ */
24
+ require_once dirname(__FILE__) . '/../Json.php';
25
+
26
+ /**
27
+ * SZend_Json_Exception
28
+ */
29
+ require_once dirname(__FILE__) . '/../Json/Exception.php';
30
+
31
+
32
+ /**
33
+ * Decode JSON encoded string to PHP variable constructs
34
+ *
35
+ * @category SZend
36
+ * @package SZend_Json
37
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
38
+ * @license http://framework.zend.com/license/new-bsd New BSD License
39
+ */
40
+ class SZend_Json_Decoder
41
+ {
42
+ /**
43
+ * Parse tokens used to decode the JSON object. These are not
44
+ * for public consumption, they are just used internally to the
45
+ * class.
46
+ */
47
+ const EOF = 0;
48
+ const DATUM = 1;
49
+ const LBRACE = 2;
50
+ const LBRACKET = 3;
51
+ const RBRACE = 4;
52
+ const RBRACKET = 5;
53
+ const COMMA = 6;
54
+ const COLON = 7;
55
+
56
+ /**
57
+ * Use to maintain a "pointer" to the source being decoded
58
+ *
59
+ * @var string
60
+ */
61
+ protected $_source;
62
+
63
+ /**
64
+ * Caches the source length
65
+ *
66
+ * @var int
67
+ */
68
+ protected $_sourceLength;
69
+
70
+ /**
71
+ * The offset within the souce being decoded
72
+ *
73
+ * @var int
74
+ *
75
+ */
76
+ protected $_offset;
77
+
78
+ /**
79
+ * The current token being considered in the parser cycle
80
+ *
81
+ * @var int
82
+ */
83
+ protected $_token;
84
+
85
+ /**
86
+ * Flag indicating how objects should be decoded
87
+ *
88
+ * @var int
89
+ * @access protected
90
+ */
91
+ protected $_decodeType;
92
+
93
+ /**
94
+ * Constructor
95
+ *
96
+ * @param string $source String source to decode
97
+ * @param int $decodeType How objects should be decoded -- see
98
+ * {@link SZend_Json::TYPE_ARRAY} and {@link SZend_Json::TYPE_OBJECT} for
99
+ * valid values
100
+ * @return void
101
+ */
102
+ protected function __construct($source, $decodeType)
103
+ {
104
+ // Set defaults
105
+ $this->_source = $source;
106
+ $this->_sourceLength = strlen($source);
107
+ $this->_token = self::EOF;
108
+ $this->_offset = 0;
109
+
110
+ // Normalize and set $decodeType
111
+ if (!in_array($decodeType, array(SZend_Json::TYPE_ARRAY, SZend_Json::TYPE_OBJECT)))
112
+ {
113
+ $decodeType = SZend_Json::TYPE_ARRAY;
114
+ }
115
+ $this->_decodeType = $decodeType;
116
+
117
+ // Set pointer at first token
118
+ $this->_getNextToken();
119
+ }
120
+
121
+ /**
122
+ * Decode a JSON source string
123
+ *
124
+ * Decodes a JSON encoded string. The value returned will be one of the
125
+ * following:
126
+ * - integer
127
+ * - float
128
+ * - boolean
129
+ * - null
130
+ * - StdClass
131
+ * - array
132
+ * - array of one or more of the above types
133
+ *
134
+ * By default, decoded objects will be returned as associative arrays; to
135
+ * return a StdClass object instead, pass {@link SZend_Json::TYPE_OBJECT} to
136
+ * the $objectDecodeType parameter.
137
+ *
138
+ * Throws a SZend_Json_Exception if the source string is null.
139
+ *
140
+ * @static
141
+ * @access public
142
+ * @param string $source String to be decoded
143
+ * @param int $objectDecodeType How objects should be decoded; should be
144
+ * either or {@link SZend_Json::TYPE_ARRAY} or
145
+ * {@link SZend_Json::TYPE_OBJECT}; defaults to TYPE_ARRAY
146
+ * @return mixed
147
+ * @throws SZend_Json_Exception
148
+ */
149
+ public static function decode($source = null, $objectDecodeType = SZend_Json::TYPE_ARRAY)
150
+ {
151
+ if (null === $source) {
152
+ throw new SZend_Json_Exception('Must specify JSON encoded source for decoding');
153
+ } elseif (!is_string($source)) {
154
+ throw new SZend_Json_Exception('Can only decode JSON encoded strings');
155
+ }
156
+
157
+ $decoder = new self($source, $objectDecodeType);
158
+
159
+ return $decoder->_decodeValue();
160
+ }
161
+
162
+
163
+ /**
164
+ * Recursive driving rountine for supported toplevel tops
165
+ *
166
+ * @return mixed
167
+ */
168
+ protected function _decodeValue()
169
+ {
170
+ switch ($this->_token) {
171
+ case self::DATUM:
172
+ $result = $this->_tokenValue;
173
+ $this->_getNextToken();
174
+ return($result);
175
+ break;
176
+ case self::LBRACE:
177
+ return($this->_decodeObject());
178
+ break;
179
+ case self::LBRACKET:
180
+ return($this->_decodeArray());
181
+ break;
182
+ default:
183
+ return null;
184
+ break;
185
+ }
186
+ }
187
+
188
+ /**
189
+ * Decodes an object of the form:
190
+ * { "attribute: value, "attribute2" : value,...}
191
+ *
192
+ * If ZJsonEnoder or ZJAjax was used to encode the original object
193
+ * then a special attribute called __className which specifies a class
194
+ * name that should wrap the data contained within the encoded source.
195
+ *
196
+ * Decodes to either an array or StdClass object, based on the value of
197
+ * {@link $_decodeType}. If invalid $_decodeType present, returns as an
198
+ * array.
199
+ *
200
+ * @return array|StdClass
201
+ */
202
+ protected function _decodeObject()
203
+ {
204
+ $members = array();
205
+ $tok = $this->_getNextToken();
206
+
207
+ while ($tok && $tok != self::RBRACE) {
208
+ if ($tok != self::DATUM || ! is_string($this->_tokenValue)) {
209
+ throw new SZend_Json_Exception('Missing key in object encoding: ' . $this->_source);
210
+ }
211
+
212
+ $key = $this->_tokenValue;
213
+ $tok = $this->_getNextToken();
214
+
215
+ if ($tok != self::COLON) {
216
+ throw new SZend_Json_Exception('Missing ":" in object encoding: ' . $this->_source);
217
+ }
218
+
219
+ $tok = $this->_getNextToken();
220
+ $members[$key] = $this->_decodeValue();
221
+ $tok = $this->_token;
222
+
223
+ if ($tok == self::RBRACE) {
224
+ break;
225
+ }
226
+
227
+ if ($tok != self::COMMA) {
228
+ throw new SZend_Json_Exception('Missing "," in object encoding: ' . $this->_source);
229
+ }
230
+
231
+ $tok = $this->_getNextToken();
232
+ }
233
+
234
+ switch ($this->_decodeType) {
235
+ case SZend_Json::TYPE_OBJECT:
236
+ // Create new StdClass and populate with $members
237
+ $result = new StdClass();
238
+ foreach ($members as $key => $value) {
239
+ $result->$key = $value;
240
+ }
241
+ break;
242
+ case SZend_Json::TYPE_ARRAY:
243
+ default:
244
+ $result = $members;
245
+ break;
246
+ }
247
+
248
+ $this->_getNextToken();
249
+ return $result;
250
+ }
251
+
252
+ /**
253
+ * Decodes a JSON array format:
254
+ * [element, element2,...,elementN]
255
+ *
256
+ * @return array
257
+ */
258
+ protected function _decodeArray()
259
+ {
260
+ $result = array();
261
+ $starttok = $tok = $this->_getNextToken(); // Move past the '['
262
+ $index = 0;
263
+
264
+ while ($tok && $tok != self::RBRACKET) {
265
+ $result[$index++] = $this->_decodeValue();
266
+
267
+ $tok = $this->_token;
268
+
269
+ if ($tok == self::RBRACKET || !$tok) {
270
+ break;
271
+ }
272
+
273
+ if ($tok != self::COMMA) {
274
+ throw new SZend_Json_Exception('Missing "," in array encoding: ' . $this->_source);
275
+ }
276
+
277
+ $tok = $this->_getNextToken();
278
+ }
279
+
280
+ $this->_getNextToken();
281
+ return($result);
282
+ }
283
+
284
+
285
+ /**
286
+ * Removes whitepsace characters from the source input
287
+ */
288
+ protected function _eatWhitespace()
289
+ {
290
+ if (preg_match(
291
+ '/([\t\b\f\n\r ])*/s',
292
+ $this->_source,
293
+ $matches,
294
+ PREG_OFFSET_CAPTURE,
295
+ $this->_offset)
296
+ && $matches[0][1] == $this->_offset)
297
+ {
298
+ $this->_offset += strlen($matches[0][0]);
299
+ }
300
+ }
301
+
302
+
303
+ /**
304
+ * Retrieves the next token from the source stream
305
+ *
306
+ * @return int Token constant value specified in class definition
307
+ */
308
+ protected function _getNextToken()
309
+ {
310
+ $this->_token = self::EOF;
311
+ $this->_tokenValue = null;
312
+ $this->_eatWhitespace();
313
+
314
+ if ($this->_offset >= $this->_sourceLength) {
315
+ return(self::EOF);
316
+ }
317
+
318
+ $str = $this->_source;
319
+ $str_length = $this->_sourceLength;
320
+ $i = $this->_offset;
321
+ $start = $i;
322
+
323
+ switch ($str{$i}) {
324
+ case '{':
325
+ $this->_token = self::LBRACE;
326
+ break;
327
+ case '}':
328
+ $this->_token = self::RBRACE;
329
+ break;
330
+ case '[':
331
+ $this->_token = self::LBRACKET;
332
+ break;
333
+ case ']':
334
+ $this->_token = self::RBRACKET;
335
+ break;
336
+ case ',':
337
+ $this->_token = self::COMMA;
338
+ break;
339
+ case ':':
340
+ $this->_token = self::COLON;
341
+ break;
342
+ case '"':
343
+ $result = '';
344
+ do {
345
+ $i++;
346
+ if ($i >= $str_length) {
347
+ break;
348
+ }
349
+
350
+ $chr = $str{$i};
351
+ if ($chr == '\\') {
352
+ $i++;
353
+ if ($i >= $str_length) {
354
+ break;
355
+ }
356
+ $chr = $str{$i};
357
+ switch ($chr) {
358
+ case '"' :
359
+ $result .= '"';
360
+ break;
361
+ case '\\':
362
+ $result .= '\\';
363
+ break;
364
+ case '/' :
365
+ $result .= '/';
366
+ break;
367
+ case 'b' :
368
+ $result .= chr(8);
369
+ break;
370
+ case 'f' :
371
+ $result .= chr(12);
372
+ break;
373
+ case 'n' :
374
+ $result .= chr(10);
375
+ break;
376
+ case 'r' :
377
+ $result .= chr(13);
378
+ break;
379
+ case 't' :
380
+ $result .= chr(9);
381
+ break;
382
+ case '\'' :
383
+ $result .= '\'';
384
+ break;
385
+ default:
386
+ throw new SZend_Json_Exception("Illegal escape "
387
+ . "sequence '" . $chr . "'");
388
+ }
389
+ } elseif ($chr == '"') {
390
+ break;
391
+ } else {
392
+ $result .= $chr;
393
+ }
394
+ } while ($i < $str_length);
395
+
396
+ $this->_token = self::DATUM;
397
+ //$this->_tokenValue = substr($str, $start + 1, $i - $start - 1);
398
+ $this->_tokenValue = $result;
399
+ break;
400
+ case 't':
401
+ if (($i+ 3) < $str_length && substr($str, $start, 4) == "true") {
402
+ $this->_token = self::DATUM;
403
+ }
404
+ $this->_tokenValue = true;
405
+ $i += 3;
406
+ break;
407
+ case 'f':
408
+ if (($i+ 4) < $str_length && substr($str, $start, 5) == "false") {
409
+ $this->_token = self::DATUM;
410
+ }
411
+ $this->_tokenValue = false;
412
+ $i += 4;
413
+ break;
414
+ case 'n':
415
+ if (($i+ 3) < $str_length && substr($str, $start, 4) == "null") {
416
+ $this->_token = self::DATUM;
417
+ }
418
+ $this->_tokenValue = NULL;
419
+ $i += 3;
420
+ break;
421
+ }
422
+
423
+ if ($this->_token != self::EOF) {
424
+ $this->_offset = $i + 1; // Consume the last token character
425
+ return($this->_token);
426
+ }
427
+
428
+ $chr = $str{$i};
429
+ if ($chr == '-' || $chr == '.' || ($chr >= '0' && $chr <= '9')) {
430
+ if (preg_match('/-?([0-9])*(\.[0-9]*)?((e|E)((-|\+)?)[0-9]+)?/s',
431
+ $str, $matches, PREG_OFFSET_CAPTURE, $start) && $matches[0][1] == $start) {
432
+
433
+ $datum = $matches[0][0];
434
+
435
+ if (is_numeric($datum)) {
436
+ if (preg_match('/^0\d+$/', $datum)) {
437
+ throw new SZend_Json_Exception("Octal notation not supported by JSON (value: $datum)");
438
+ } else {
439
+ $val = intval($datum);
440
+ $fVal = floatval($datum);
441
+ $this->_tokenValue = ($val == $fVal ? $val : $fVal);
442
+ }
443
+ } else {
444
+ throw new SZend_Json_Exception("Illegal number format: $datum");
445
+ }
446
+
447
+ $this->_token = self::DATUM;
448
+ $this->_offset = $start + strlen($datum);
449
+ }
450
+ } else {
451
+ throw new SZend_Json_Exception('Illegal Token');
452
+ }
453
+
454
+ return($this->_token);
455
+ }
456
+ }
457
+
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Json/Encoder.php ADDED
@@ -0,0 +1,413 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SZend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category SZend
16
+ * @package SZend_Json
17
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ */
20
+
21
+
22
+ /**
23
+ * SZend_Json_Exception
24
+ */
25
+ require_once dirname(__FILE__) . '/../Exception.php';
26
+
27
+
28
+ /**
29
+ * Encode PHP constructs to JSON
30
+ *
31
+ * @category SZend
32
+ * @package SZend_Json
33
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class SZend_Json_Encoder
37
+ {
38
+ /**
39
+ * Whether or not to check for possible cycling
40
+ *
41
+ * @var boolean
42
+ */
43
+ protected $_cycleCheck;
44
+
45
+ /**
46
+ * Array of visited objects; used to prevent cycling.
47
+ *
48
+ * @var array
49
+ */
50
+ protected $_visited = array();
51
+
52
+ /**
53
+ * Constructor
54
+ *
55
+ * @param boolean $cycleCheck Whether or not to check for recursion when encoding
56
+ * @return void
57
+ */
58
+ protected function __construct($cycleCheck = false)
59
+ {
60
+ $this->_cycleCheck = $cycleCheck;
61
+ }
62
+
63
+ /**
64
+ * Use the JSON encoding scheme for the value specified
65
+ *
66
+ * @param mixed $value The value to be encoded
67
+ * @param boolean $cycleCheck Whether or not to check for possible object recursion when encoding
68
+ * @return string The encoded value
69
+ */
70
+ public static function encode($value, $cycleCheck = false)
71
+ {
72
+ $encoder = new self(($cycleCheck) ? true : false);
73
+
74
+ return $encoder->_encodeValue($value);
75
+ }
76
+
77
+ /**
78
+ * Recursive driver which determines the type of value to be encoded
79
+ * and then dispatches to the appropriate method. $values are either
80
+ * - objects (returns from {@link _encodeObject()})
81
+ * - arrays (returns from {@link _encodeArray()})
82
+ * - basic datums (e.g. numbers or strings) (returns from {@link _encodeDatum()})
83
+ *
84
+ * @param $value mixed The value to be encoded
85
+ * @return string Encoded value
86
+ */
87
+ protected function _encodeValue(&$value)
88
+ {
89
+ if (is_object($value)) {
90
+ return $this->_encodeObject($value);
91
+ } else if (is_array($value)) {
92
+ return $this->_encodeArray($value);
93
+ }
94
+
95
+ return $this->_encodeDatum($value);
96
+ }
97
+
98
+
99
+
100
+ /**
101
+ * Encode an object to JSON by encoding each of the public properties
102
+ *
103
+ * A special property is added to the JSON object called '__className'
104
+ * that contains the name of the class of $value. This is used to decode
105
+ * the object on the client into a specific class.
106
+ *
107
+ * @param $value object
108
+ * @return string
109
+ * @throws SZend_Json_Exception If recursive checks are enabled and the object has been serialized previously
110
+ */
111
+ protected function _encodeObject(&$value)
112
+ {
113
+ if ($this->_cycleCheck) {
114
+ if ($this->_wasVisited($value)) {
115
+ throw new SZend_Json_Exception(
116
+ 'Cycles not supported in JSON encoding, cycle introduced by '
117
+ . 'class "' . get_class($value) . '"'
118
+ );
119
+ }
120
+
121
+ $this->_visited[] = $value;
122
+ }
123
+
124
+ $props = '';
125
+ foreach (get_object_vars($value) as $name => $propValue) {
126
+ if (isset($propValue)) {
127
+ $props .= ','
128
+ . $this->_encodeValue($name)
129
+ . ':'
130
+ . $this->_encodeValue($propValue);
131
+ }
132
+ }
133
+
134
+ return '{"__className":"' . get_class($value) . '"'
135
+ . $props . '}';
136
+ }
137
+
138
+
139
+ /**
140
+ * Determine if an object has been serialized already
141
+ *
142
+ * @param mixed $value
143
+ * @return boolean
144
+ */
145
+ protected function _wasVisited(&$value)
146
+ {
147
+ if (in_array($value, $this->_visited, true)) {
148
+ return true;
149
+ }
150
+
151
+ return false;
152
+ }
153
+
154
+
155
+ /**
156
+ * JSON encode an array value
157
+ *
158
+ * Recursively encodes each value of an array and returns a JSON encoded
159
+ * array string.
160
+ *
161
+ * Arrays are defined as integer-indexed arrays starting at index 0, where
162
+ * the last index is (count($array) -1); any deviation from that is
163
+ * considered an associative array, and will be encoded as such.
164
+ *
165
+ * @param $array array
166
+ * @return string
167
+ */
168
+ protected function _encodeArray(&$array)
169
+ {
170
+ $tmpArray = array();
171
+
172
+ // Check for associative array
173
+ if (!empty($array) && (array_keys($array) !== range(0, count($array) - 1))) {
174
+ // Associative array
175
+ $result = '{';
176
+ foreach ($array as $key => $value) {
177
+ $key = (string) $key;
178
+ $tmpArray[] = $this->_encodeString($key)
179
+ . ':'
180
+ . $this->_encodeValue($value);
181
+ }
182
+ $result .= implode(',', $tmpArray);
183
+ $result .= '}';
184
+ } else {
185
+ // Indexed array
186
+ $result = '[';
187
+ $length = count($array);
188
+ for ($i = 0; $i < $length; $i++) {
189
+ $tmpArray[] = $this->_encodeValue($array[$i]);
190
+ }
191
+ $result .= implode(',', $tmpArray);
192
+ $result .= ']';
193
+ }
194
+
195
+ return $result;
196
+ }
197
+
198
+
199
+ /**
200
+ * JSON encode a basic data type (string, number, boolean, null)
201
+ *
202
+ * If value type is not a string, number, boolean, or null, the string
203
+ * 'null' is returned.
204
+ *
205
+ * @param $value mixed
206
+ * @return string
207
+ */
208
+ protected function _encodeDatum(&$value)
209
+ {
210
+ $result = 'null';
211
+
212
+ if (is_int($value) || is_float($value)) {
213
+ $result = (string)$value;
214
+ } elseif (is_string($value)) {
215
+ $result = $this->_encodeString($value);
216
+ } elseif (is_bool($value)) {
217
+ $result = $value ? 'true' : 'false';
218
+ }
219
+
220
+ return $result;
221
+ }
222
+
223
+
224
+ /**
225
+ * JSON encode a string value by escaping characters as necessary
226
+ *
227
+ * @param $value string
228
+ * @return string
229
+ */
230
+ protected function _encodeString(&$string)
231
+ {
232
+ // Escape these characters with a backslash:
233
+ // " \ / \n \r \t \b \f
234
+ $search = array('\\', "\n", "\t", "\r", "\b", "\f", '"');
235
+ $replace = array('\\\\', '\\n', '\\t', '\\r', '\\b', '\\f', '\"');
236
+ $string = str_replace($search, $replace, $string);
237
+
238
+ // Escape certain ASCII characters:
239
+ // 0x08 => \b
240
+ // 0x0c => \f
241
+ $string = str_replace(array(chr(0x08), chr(0x0C)), array('\b', '\f'), $string);
242
+
243
+ return '"' . $string . '"';
244
+ }
245
+
246
+
247
+ /**
248
+ * Encode the constants associated with the ReflectionClass
249
+ * parameter. The encoding format is based on the class2 format
250
+ *
251
+ * @param $cls ReflectionClass
252
+ * @return string Encoded constant block in class2 format
253
+ */
254
+ private static function _encodeConstants(ReflectionClass $cls)
255
+ {
256
+ $result = "constants : {";
257
+ $constants = $cls->getConstants();
258
+
259
+ $tmpArray = array();
260
+ if (!empty($constants)) {
261
+ foreach ($constants as $key => $value) {
262
+ $tmpArray[] = "$key: " . self::encode($value);
263
+ }
264
+
265
+ $result .= implode(', ', $tmpArray);
266
+ }
267
+
268
+ return $result . "}";
269
+ }
270
+
271
+
272
+ /**
273
+ * Encode the public methods of the ReflectionClass in the
274
+ * class2 format
275
+ *
276
+ * @param $cls ReflectionClass
277
+ * @return string Encoded method fragment
278
+ *
279
+ */
280
+ private static function _encodeMethods(ReflectionClass $cls)
281
+ {
282
+ $methods = $cls->getMethods();
283
+ $result = 'methods:{';
284
+
285
+ $started = false;
286
+ foreach ($methods as $method) {
287
+ if (! $method->isPublic() || !$method->isUserDefined()) {
288
+ continue;
289
+ }
290
+
291
+ if ($started) {
292
+ $result .= ',';
293
+ }
294
+ $started = true;
295
+
296
+ $result .= '' . $method->getName(). ':function(';
297
+
298
+ if ('__construct' != $method->getName()) {
299
+ $parameters = $method->getParameters();
300
+ $paramCount = count($parameters);
301
+ $argsStarted = false;
302
+
303
+ $argNames = "var argNames=[";
304
+ foreach ($parameters as $param) {
305
+ if ($argsStarted) {
306
+ $result .= ',';
307
+ }
308
+
309
+ $result .= $param->getName();
310
+
311
+ if ($argsStarted) {
312
+ $argNames .= ',';
313
+ }
314
+
315
+ $argNames .= '"' . $param->getName() . '"';
316
+
317
+ $argsStarted = true;
318
+ }
319
+ $argNames .= "];";
320
+
321
+ $result .= "){"
322
+ . $argNames
323
+ . 'var result = ZAjaxEngine.invokeRemoteMethod('
324
+ . "this, '" . $method->getName()
325
+ . "',argNames,arguments);"
326
+ . 'return(result);}';
327
+ } else {
328
+ $result .= "){}";
329
+ }
330
+ }
331
+
332
+ return $result . "}";
333
+ }
334
+
335
+
336
+ /**
337
+ * Encode the public properties of the ReflectionClass in the class2
338
+ * format.
339
+ *
340
+ * @param $cls ReflectionClass
341
+ * @return string Encode properties list
342
+ *
343
+ */
344
+ private static function _encodeVariables(ReflectionClass $cls)
345
+ {
346
+ $properties = $cls->getProperties();
347
+ $propValues = get_class_vars($cls->getName());
348
+ $result = "variables:{";
349
+ $cnt = 0;
350
+
351
+ $tmpArray = array();
352
+ foreach ($properties as $prop) {
353
+ if (! $prop->isPublic()) {
354
+ continue;
355
+ }
356
+
357
+ $tmpArray[] = $prop->getName()
358
+ . ':'
359
+ . self::encode($propValues[$prop->getName()]);
360
+ }
361
+ $result .= implode(',', $tmpArray);
362
+
363
+ return $result . "}";
364
+ }
365
+
366
+ /**
367
+ * Encodes the given $className into the class2 model of encoding PHP
368
+ * classes into JavaScript class2 classes.
369
+ * NOTE: Currently only public methods and variables are proxied onto
370
+ * the client machine
371
+ *
372
+ * @param $className string The name of the class, the class must be
373
+ * instantiable using a null constructor
374
+ * @param $package string Optional package name appended to JavaScript
375
+ * proxy class name
376
+ * @return string The class2 (JavaScript) encoding of the class
377
+ * @throws SZend_Json_Exception
378
+ */
379
+ public static function encodeClass($className, $package = '')
380
+ {
381
+ $cls = new ReflectionClass($className);
382
+ if (! $cls->isInstantiable()) {
383
+ throw new SZend_Json_Exception("$className must be instantiable");
384
+ }
385
+
386
+ return "Class.create('$package$className',{"
387
+ . self::_encodeConstants($cls) .","
388
+ . self::_encodeMethods($cls) .","
389
+ . self::_encodeVariables($cls) .'});';
390
+ }
391
+
392
+
393
+ /**
394
+ * Encode several classes at once
395
+ *
396
+ * Returns JSON encoded classes, using {@link encodeClass()}.
397
+ *
398
+ * @param array $classNames
399
+ * @param string $package
400
+ * @return string
401
+ */
402
+ public static function encodeClasses(array $classNames, $package = '')
403
+ {
404
+ $result = '';
405
+ foreach ($classNames as $className) {
406
+ $result .= self::encodeClass($className, $package);
407
+ }
408
+
409
+ return $result;
410
+ }
411
+
412
+ }
413
+
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Json/Exception.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SZend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category SZend
16
+ * @package SZend_Json
17
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ */
20
+
21
+
22
+
23
+ /**
24
+ * SZend_Exception
25
+ */
26
+ require_once dirname(__FILE__) . '/../Exception.php';
27
+
28
+
29
+ /**
30
+ * @category SZend
31
+ * @package SZend_Json
32
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
33
+ * @license http://framework.zend.com/license/new-bsd New BSD License
34
+ */
35
+ class SZend_Json_Exception extends SZend_Exception
36
+ {}
37
+
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Loader.php ADDED
@@ -0,0 +1,258 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SZend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category SZend
16
+ * @package SZend_Loader
17
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ * @version $Id: Loader.php 8064 2008-02-16 10:58:39Z thomas $
20
+ */
21
+
22
+ /**
23
+ * Static methods for loading classes and files.
24
+ *
25
+ * @category SZend
26
+ * @package SZend_Loader
27
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
28
+ * @license http://framework.zend.com/license/new-bsd New BSD License
29
+ */
30
+ class SZend_Loader
31
+ {
32
+ /**
33
+ * Loads a class from a PHP file. The filename must be formatted
34
+ * as "$class.php".
35
+ *
36
+ * If $dirs is a string or an array, it will search the directories
37
+ * in the order supplied, and attempt to load the first matching file.
38
+ *
39
+ * If $dirs is null, it will split the class name at underscores to
40
+ * generate a path hierarchy (e.g., "SZend_Example_Class" will map
41
+ * to "SZend/Example/Class.php").
42
+ *
43
+ * If the file was not found in the $dirs, or if no $dirs were specified,
44
+ * it will attempt to load it from PHP's include_path.
45
+ *
46
+ * @param string $class - The full class name of a SZend component.
47
+ * @param string|array $dirs - OPTIONAL Either a path or an array of paths
48
+ * to search.
49
+ * @return void
50
+ * @throws SZend_Exception
51
+ */
52
+ public static function loadClass($class, $dirs = null)
53
+ {
54
+ if (class_exists($class, false) || interface_exists($class, false)) {
55
+ return;
56
+ }
57
+
58
+ if ((null !== $dirs) && !is_string($dirs) && !is_array($dirs)) {
59
+ require_once dirname(__FILE__) . '/Exception.php';
60
+ throw new SZend_Exception('Directory argument must be a string or an array');
61
+ }
62
+
63
+ // autodiscover the path from the class name
64
+ $file = str_replace('SZend', dirname(__FILE__), str_replace('_', DIRECTORY_SEPARATOR, $class)) . '.php';
65
+ if (!empty($dirs)) {
66
+ // use the autodiscovered path
67
+ $dirPath = dirname($file);
68
+ if (is_string($dirs)) {
69
+ $dirs = explode(PATH_SEPARATOR, $dirs);
70
+ }
71
+ foreach ($dirs as $key => $dir) {
72
+ if ($dir == '.') {
73
+ $dirs[$key] = $dirPath;
74
+ } else {
75
+ $dir = rtrim($dir, '\\/');
76
+ $dirs[$key] = $dir . DIRECTORY_SEPARATOR . $dirPath;
77
+ }
78
+ }
79
+ $file = basename($file);
80
+ self::loadFile($file, $dirs, true);
81
+ } else {
82
+ self::_securityCheck($file);
83
+ include_once $file;
84
+ }
85
+
86
+ if (!class_exists($class, false) && !interface_exists($class, false)) {
87
+ require_once dirname(__FILE__) . '/Exception.php';
88
+ throw new SZend_Exception("File \"$file\" was loaded but class \"$class\" was not found in the file");
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Loads a PHP file. This is a wrapper for PHP's include() function.
94
+ *
95
+ * $filename must be the complete filename, including any
96
+ * extension such as ".php". Note that a security check is performed that
97
+ * does not permit extended characters in the filename. This method is
98
+ * intended for loading SZend Framework files.
99
+ *
100
+ * If $dirs is a string or an array, it will search the directories
101
+ * in the order supplied, and attempt to load the first matching file.
102
+ *
103
+ * If the file was not found in the $dirs, or if no $dirs were specified,
104
+ * it will attempt to load it from PHP's include_path.
105
+ *
106
+ * If $once is TRUE, it will use include_once() instead of include().
107
+ *
108
+ * @param string $filename
109
+ * @param string|array $dirs - OPTIONAL either a path or array of paths
110
+ * to search.
111
+ * @param boolean $once
112
+ * @return boolean
113
+ * @throws SZend_Exception
114
+ */
115
+ public static function loadFile($filename, $dirs = null, $once = false)
116
+ {
117
+ self::_securityCheck($filename);
118
+
119
+ /**
120
+ * Search in provided directories, as well as include_path
121
+ */
122
+ $incPath = false;
123
+ if (!empty($dirs) && (is_array($dirs) || is_string($dirs))) {
124
+ if (is_array($dirs)) {
125
+ $dirs = implode(PATH_SEPARATOR, $dirs);
126
+ }
127
+ $incPath = get_include_path();
128
+ set_include_path($dirs . PATH_SEPARATOR . $incPath);
129
+ }
130
+
131
+ /**
132
+ * Try finding for the plain filename in the include_path.
133
+ */
134
+ if ($once) {
135
+ include_once $filename;
136
+ } else {
137
+ include $filename;
138
+ }
139
+
140
+ /**
141
+ * If searching in directories, reset include_path
142
+ */
143
+ if ($incPath) {
144
+ set_include_path($incPath);
145
+ }
146
+
147
+ return true;
148
+ }
149
+
150
+ /**
151
+ * Returns TRUE if the $filename is readable, or FALSE otherwise.
152
+ * This function uses the PHP include_path, where PHP's is_readable()
153
+ * does not.
154
+ *
155
+ * @param string $filename
156
+ * @return boolean
157
+ */
158
+ public static function isReadable($filename)
159
+ {
160
+ if (!$fh = @fopen($filename, 'r', true)) {
161
+ return false;
162
+ }
163
+
164
+ return true;
165
+ }
166
+
167
+ /**
168
+ * spl_autoload() suitable implementation for supporting class autoloading.
169
+ *
170
+ * Attach to spl_autoload() using the following:
171
+ * <code>
172
+ * spl_autoload_register(array('SZend_Loader', 'autoload'));
173
+ * </code>
174
+ *
175
+ * @param string $class
176
+ * @return string|false Class name on success; false on failure
177
+ */
178
+ public static function autoload($class)
179
+ {
180
+ try {
181
+ self::loadClass($class);
182
+ return $class;
183
+ } catch (Exception $e) {
184
+ return false;
185
+ }
186
+ }
187
+
188
+ /**
189
+ * Register {@link autoload()} with spl_autoload()
190
+ *
191
+ * @param string $class (optional)
192
+ * @param boolean $enabled (optional)
193
+ * @return void
194
+ * @throws SZend_Exception if spl_autoload() is not found
195
+ * or if the specified class does not have an autoload() method.
196
+ */
197
+ public static function registerAutoload($class = 'SZend_Loader', $enabled = true)
198
+ {
199
+ if (!function_exists('spl_autoload_register')) {
200
+ require_once dirname(__FILE__) . '/Exception.php';
201
+ throw new SZend_Exception('spl_autoload does not exist in this PHP installation');
202
+ }
203
+
204
+ self::loadClass($class);
205
+ $methods = get_class_methods($class);
206
+ if (!in_array('autoload', (array) $methods)) {
207
+ require_once dirname(__FILE__) . '/Exception.php';
208
+ throw new SZend_Exception("The class \"$class\" does not have an autoload() method");
209
+ }
210
+
211
+ if ($enabled === true) {
212
+ spl_autoload_register(array($class, 'autoload'));
213
+ } else {
214
+ spl_autoload_unregister(array($class, 'autoload'));
215
+ }
216
+ }
217
+
218
+ /**
219
+ * Ensure that filename does not contain exploits
220
+ *
221
+ * @param string $filename
222
+ * @return void
223
+ * @throws SZend_Exception
224
+ */
225
+ protected static function _securityCheck($filename)
226
+ {
227
+ /**
228
+ * Security check
229
+ */
230
+ if (preg_match('/[^a-z0-9\\/\\\\_.-]/i', $filename)) {
231
+ require_once dirname(__FILE__) . '/Exception.php';
232
+ throw new SZend_Exception('Security check: Illegal character in filename');
233
+ }
234
+ }
235
+
236
+ /**
237
+ * Attempt to include() the file.
238
+ *
239
+ * include() is not prefixed with the @ operator because if
240
+ * the file is loaded and contains a parse error, execution
241
+ * will halt silently and this is difficult to debug.
242
+ *
243
+ * Always set display_errors = Off on production servers!
244
+ *
245
+ * @param string $filespec
246
+ * @param boolean $once
247
+ * @return boolean
248
+ * @deprecated Since 1.5.0; use loadFile() instead
249
+ */
250
+ protected static function _includeFile($filespec, $once = false)
251
+ {
252
+ if ($once) {
253
+ return include_once $filespec;
254
+ } else {
255
+ return include $filespec ;
256
+ }
257
+ }
258
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Uri.php ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * SZend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category SZend
17
+ * @package SZend_Uri
18
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Uri.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+ /**
24
+ * @see SZend_Loader
25
+ */
26
+ require_once dirname(__FILE__) . '/Loader.php';
27
+
28
+ /**
29
+ * @category SZend
30
+ * @package SZend_Uri
31
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
32
+ * @license http://framework.zend.com/license/new-bsd New BSD License
33
+ */
34
+ abstract class SZend_Uri
35
+ {
36
+ /**
37
+ * Scheme of this URI (http, ftp, etc.)
38
+ * @var string
39
+ */
40
+ protected $_scheme = '';
41
+
42
+ /**
43
+ * Return a string representation of this URI.
44
+ *
45
+ * @see getUri()
46
+ * @return string
47
+ */
48
+ public function __toString()
49
+ {
50
+ return $this->getUri();
51
+ }
52
+
53
+ /**
54
+ * Convenience function, checks that a $uri string is well-formed
55
+ * by validating it but not returning an object. Returns TRUE if
56
+ * $uri is a well-formed URI, or FALSE otherwise.
57
+ *
58
+ * @param string $uri
59
+ * @return boolean
60
+ */
61
+ public static function check($uri)
62
+ {
63
+ try {
64
+ $uri = self::factory($uri);
65
+ } catch (Exception $e) {
66
+ return false;
67
+ }
68
+
69
+ return $uri->valid();
70
+ }
71
+
72
+ /**
73
+ * Create a new SZend_Uri object for a URI. If building a new URI, then $uri should contain
74
+ * only the scheme (http, ftp, etc). Otherwise, supply $uri with the complete URI.
75
+ *
76
+ * @param string $uri
77
+ * @throws SZend_Uri_Exception
78
+ * @return SZend_Uri
79
+ */
80
+ public static function factory($uri = 'http')
81
+ {
82
+ /**
83
+ * Separate the scheme from the scheme-specific parts
84
+ * @link http://www.faqs.org/rfcs/rfc2396.html
85
+ */
86
+ $uri = explode(':', $uri, 2);
87
+ $scheme = strtolower($uri[0]);
88
+ $schemeSpecific = isset($uri[1]) ? $uri[1] : '';
89
+
90
+ if (!strlen($scheme)) {
91
+ require_once 'SZend/Uri/Exception.php';
92
+ throw new SZend_Uri_Exception('An empty string was supplied for the scheme');
93
+ }
94
+
95
+ // Security check: $scheme is used to load a class file, so only alphanumerics are allowed.
96
+ if (!ctype_alnum($scheme)) {
97
+ require_once 'SZend/Uri/Exception.php';
98
+ throw new SZend_Uri_Exception('Illegal scheme supplied, only alphanumeric characters are permitted');
99
+ }
100
+
101
+ /**
102
+ * Create a new SZend_Uri object for the $uri. If a subclass of SZend_Uri exists for the
103
+ * scheme, return an instance of that class. Otherwise, a SZend_Uri_Exception is thrown.
104
+ */
105
+ switch ($scheme) {
106
+ case 'http':
107
+ case 'https':
108
+ $className = 'SZend_Uri_Http';
109
+ break;
110
+ case 'mailto':
111
+ // @todo
112
+ default:
113
+ require_once 'SZend/Uri/Exception.php';
114
+ throw new SZend_Uri_Exception("Scheme \"$scheme\" is not supported");
115
+ }
116
+ SZend_Loader::loadClass($className);
117
+ return new $className($scheme, $schemeSpecific);
118
+
119
+ }
120
+
121
+ /**
122
+ * Get the URI's scheme
123
+ *
124
+ * @return string|false Scheme or false if no scheme is set.
125
+ */
126
+ public function getScheme()
127
+ {
128
+ if (!empty($this->_scheme)) {
129
+ return $this->_scheme;
130
+ } else {
131
+ return false;
132
+ }
133
+ }
134
+
135
+ /******************************************************************************
136
+ * Abstract Methods
137
+ *****************************************************************************/
138
+
139
+ /**
140
+ * SZend_Uri and its subclasses cannot be instantiated directly.
141
+ * Use SZend_Uri::factory() to return a new SZend_Uri object.
142
+ */
143
+ abstract protected function __construct($scheme, $schemeSpecific = '');
144
+
145
+ /**
146
+ * Return a string representation of this URI.
147
+ *
148
+ * @return string
149
+ */
150
+ abstract public function getUri();
151
+
152
+ /**
153
+ * Returns TRUE if this URI is valid, or FALSE otherwise.
154
+ *
155
+ * @return boolean
156
+ */
157
+ abstract public function valid();
158
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Uri/Exception.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SZend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category SZend
16
+ * @package SZend_Uri
17
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ */
20
+
21
+
22
+ /**
23
+ * SZend_Exception
24
+ */
25
+ require_once dirname(__FILE__) . '/../Exception.php';
26
+
27
+
28
+ /**
29
+ * @category SZend
30
+ * @package SZend_Uri
31
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
32
+ * @license http://framework.zend.com/license/new-bsd New BSD License
33
+ */
34
+ class SZend_Uri_Exception extends SZend_Exception
35
+ {}
36
+
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Uri/Http.php ADDED
@@ -0,0 +1,631 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * SZend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category SZend
17
+ * @package SZend_Uri
18
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Http.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see SZend_Uri
26
+ */
27
+ require_once dirname(__FILE__) . '/../Uri.php';
28
+
29
+
30
+ /**
31
+ * @see SZend_Validate_Hostname
32
+ */
33
+ require_once dirname(__FILE__) . '/../Validate/Hostname.php';
34
+
35
+
36
+ /**
37
+ * @category SZend
38
+ * @package SZend_Uri
39
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
40
+ * @license http://framework.zend.com/license/new-bsd New BSD License
41
+ */
42
+ class SZend_Uri_Http extends SZend_Uri
43
+ {
44
+ /**
45
+ * URI parts are divided among these instance variables
46
+ */
47
+ protected $_username = '';
48
+ protected $_password = '';
49
+ protected $_host = '';
50
+ protected $_port = '';
51
+ protected $_path = '';
52
+ protected $_query = '';
53
+ protected $_fragment = '';
54
+
55
+ /**
56
+ * Regular expression grammar rules for validation; values added by constructor
57
+ */
58
+ protected $_regex = array();
59
+
60
+ /**
61
+ * Constructor accepts a string $scheme (e.g., http, https) and a scheme-specific part of the URI
62
+ * (e.g., example.com/path/to/resource?query=param#fragment)
63
+ *
64
+ * @param string $scheme
65
+ * @param string $schemeSpecific
66
+ * @throws SZend_Uri_Exception
67
+ * @return void
68
+ */
69
+ protected function __construct($scheme, $schemeSpecific = '')
70
+ {
71
+ // Set the scheme
72
+ $this->_scheme = $scheme;
73
+
74
+ // Set up grammar rules for validation via regular expressions. These
75
+ // are to be used with slash-delimited regular expression strings.
76
+ $this->_regex['alphanum'] = '[^\W_]';
77
+ $this->_regex['escaped'] = '(?:%[\da-fA-F]{2})';
78
+ $this->_regex['mark'] = '[-_.!~*\'()\[\]]';
79
+ $this->_regex['reserved'] = '[;\/?:@&=+$,]';
80
+ $this->_regex['unreserved'] = '(?:' . $this->_regex['alphanum'] . '|' . $this->_regex['mark'] . ')';
81
+ $this->_regex['segment'] = '(?:(?:' . $this->_regex['unreserved'] . '|' . $this->_regex['escaped']
82
+ . '|[:@&=+$,;])*)';
83
+ $this->_regex['path'] = '(?:\/' . $this->_regex['segment'] . '?)+';
84
+ $this->_regex['uric'] = '(?:' . $this->_regex['reserved'] . '|' . $this->_regex['unreserved'] . '|'
85
+ . $this->_regex['escaped'] . ')';
86
+ // If no scheme-specific part was supplied, the user intends to create
87
+ // a new URI with this object. No further parsing is required.
88
+ if (strlen($schemeSpecific) == 0) {
89
+ return;
90
+ }
91
+
92
+ // Parse the scheme-specific URI parts into the instance variables.
93
+ $this->_parseUri($schemeSpecific);
94
+
95
+ // Validate the URI
96
+ if (!$this->valid()) {
97
+ require_once 'SZend/Uri/Exception.php';
98
+ throw new SZend_Uri_Exception('Invalid URI supplied');
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Parse the scheme-specific portion of the URI and place its parts into instance variables.
104
+ *
105
+ * @param string $schemeSpecific
106
+ * @throws SZend_Uri_Exception
107
+ * @return void
108
+ */
109
+ protected function _parseUri($schemeSpecific)
110
+ {
111
+ // High-level decomposition parser
112
+ $pattern = '~^((//)([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))?$~';
113
+ $status = @preg_match($pattern, $schemeSpecific, $matches);
114
+ if ($status === false) {
115
+ require_once 'SZend/Uri/Exception.php';
116
+ throw new SZend_Uri_Exception('Internal error: scheme-specific decomposition failed');
117
+ }
118
+
119
+ // Failed decomposition; no further processing needed
120
+ if (!$status) {
121
+ return;
122
+ }
123
+
124
+ // Save URI components that need no further decomposition
125
+ $this->_path = isset($matches[4]) ? $matches[4] : '';
126
+ $this->_query = isset($matches[6]) ? $matches[6] : '';
127
+ $this->_fragment = isset($matches[8]) ? $matches[8] : '';
128
+
129
+ // Additional decomposition to get username, password, host, and port
130
+ $combo = isset($matches[3]) ? $matches[3] : '';
131
+ $pattern = '~^(([^:@]*)(:([^@]*))?@)?([^:]+)(:(.*))?$~';
132
+ $status = @preg_match($pattern, $combo, $matches);
133
+ if ($status === false) {
134
+ require_once 'SZend/Uri/Exception.php';
135
+ throw new SZend_Uri_Exception('Internal error: authority decomposition failed');
136
+ }
137
+
138
+ // Failed decomposition; no further processing needed
139
+ if (!$status) {
140
+ return;
141
+ }
142
+
143
+ // Save remaining URI components
144
+ $this->_username = isset($matches[2]) ? $matches[2] : '';
145
+ $this->_password = isset($matches[4]) ? $matches[4] : '';
146
+ $this->_host = isset($matches[5]) ? $matches[5] : '';
147
+ $this->_port = isset($matches[7]) ? $matches[7] : '';
148
+
149
+ }
150
+
151
+ /**
152
+ * Returns a URI based on current values of the instance variables. If any
153
+ * part of the URI does not pass validation, then an exception is thrown.
154
+ *
155
+ * @throws SZend_Uri_Exception
156
+ * @return string
157
+ */
158
+ public function getUri()
159
+ {
160
+ if (!$this->valid()) {
161
+ require_once 'SZend/Uri/Exception.php';
162
+ throw new SZend_Uri_Exception('One or more parts of the URI are invalid');
163
+ }
164
+ $password = strlen($this->_password) ? ":$this->_password" : '';
165
+ $auth = strlen($this->_username) ? "$this->_username$password@" : '';
166
+ $port = strlen($this->_port) ? ":$this->_port" : '';
167
+ $query = strlen($this->_query) ? "?$this->_query" : '';
168
+ $fragment = strlen($this->_fragment) ? "#$this->_fragment" : '';
169
+ return "$this->_scheme://$auth$this->_host$port$this->_path$query$fragment";
170
+ }
171
+
172
+ /**
173
+ * Validate the current URI from the instance variables. Returns true if and only if all
174
+ * parts pass validation.
175
+ *
176
+ * @return boolean
177
+ */
178
+ public function valid()
179
+ {
180
+ /**
181
+ * Return true if and only if all parts of the URI have passed validation
182
+ */
183
+ return $this->validateUsername()
184
+ && $this->validatePassword()
185
+ && $this->validateHost()
186
+ && $this->validatePort()
187
+ && $this->validatePath()
188
+ && $this->validateQuery()
189
+ && $this->validateFragment();
190
+ }
191
+
192
+ /**
193
+ * Returns the username portion of the URL, or FALSE if none.
194
+ *
195
+ * @return string
196
+ */
197
+ public function getUsername()
198
+ {
199
+ return strlen($this->_username) ? $this->_username : false;
200
+ }
201
+
202
+ /**
203
+ * Returns true if and only if the username passes validation. If no username is passed,
204
+ * then the username contained in the instance variable is used.
205
+ *
206
+ * @param string $username
207
+ * @throws SZend_Uri_Exception
208
+ * @return boolean
209
+ */
210
+ public function validateUsername($username = null)
211
+ {
212
+ if ($username === null) {
213
+ $username = $this->_username;
214
+ }
215
+
216
+ // If the username is empty, then it is considered valid
217
+ if (strlen($username) == 0) {
218
+ return true;
219
+ }
220
+ /**
221
+ * Check the username against the allowed values
222
+ *
223
+ * @link http://www.faqs.org/rfcs/rfc2396.html
224
+ */
225
+ $status = @preg_match('/^(' . $this->_regex['alphanum'] . '|' . $this->_regex['mark'] . '|'
226
+ . $this->_regex['escaped'] . '|[;:&=+$,])+$/', $username);
227
+ if ($status === false) {
228
+ require_once 'SZend/Uri/Exception.php';
229
+ throw new SZend_Uri_Exception('Internal error: username validation failed');
230
+ }
231
+
232
+ return $status == 1;
233
+ }
234
+
235
+ /**
236
+ * Sets the username for the current URI, and returns the old username
237
+ *
238
+ * @param string $username
239
+ * @throws SZend_Uri_Exception
240
+ * @return string
241
+ */
242
+ public function setUsername($username)
243
+ {
244
+ if (!$this->validateUsername($username)) {
245
+ require_once 'SZend/Uri/Exception.php';
246
+ throw new SZend_Uri_Exception("Username \"$username\" is not a valid HTTP username");
247
+ }
248
+ $oldUsername = $this->_username;
249
+ $this->_username = $username;
250
+ return $oldUsername;
251
+ }
252
+
253
+ /**
254
+ * Returns the password portion of the URL, or FALSE if none.
255
+ *
256
+ * @return string
257
+ */
258
+ public function getPassword()
259
+ {
260
+ return strlen($this->_password) ? $this->_password : false;
261
+ }
262
+
263
+ /**
264
+ * Returns true if and only if the password passes validation. If no password is passed,
265
+ * then the password contained in the instance variable is used.
266
+ *
267
+ * @param string $password
268
+ * @throws SZend_Uri_Exception
269
+ * @return boolean
270
+ */
271
+ public function validatePassword($password = null)
272
+ {
273
+ if ($password === null) {
274
+ $password = $this->_password;
275
+ }
276
+
277
+ // If the password is empty, then it is considered valid
278
+ if (strlen($password) == 0) {
279
+ return true;
280
+ }
281
+
282
+ // If the password is nonempty, but there is no username, then it is considered invalid
283
+ if (strlen($password) > 0 && strlen($this->_username) == 0) {
284
+ return false;
285
+ }
286
+
287
+ /**
288
+ * Check the password against the allowed values
289
+ *
290
+ * @link http://www.faqs.org/rfcs/rfc2396.html
291
+ */
292
+ $status = @preg_match('/^(' . $this->_regex['alphanum'] . '|' . $this->_regex['mark'] . '|'
293
+ . $this->_regex['escaped'] . '|[;:&=+$,])+$/', $password);
294
+ if ($status === false) {
295
+ require_once 'SZend/Uri/Exception.php';
296
+ throw new SZend_Uri_Exception('Internal error: password validation failed.');
297
+ }
298
+ return $status == 1;
299
+ }
300
+
301
+ /**
302
+ * Sets the password for the current URI, and returns the old password
303
+ *
304
+ * @param string $password
305
+ * @throws SZend_Uri_Exception
306
+ * @return string
307
+ */
308
+ public function setPassword($password)
309
+ {
310
+ if (!$this->validatePassword($password)) {
311
+ require_once 'SZend/Uri/Exception.php';
312
+ throw new SZend_Uri_Exception("Password \"$password\" is not a valid HTTP password.");
313
+ }
314
+ $oldPassword = $this->_password;
315
+ $this->_password = $password;
316
+ return $oldPassword;
317
+ }
318
+
319
+ /**
320
+ * Returns the domain or host IP portion of the URL, or FALSE if none.
321
+ *
322
+ * @return string
323
+ */
324
+ public function getHost()
325
+ {
326
+ return strlen($this->_host) ? $this->_host : false;
327
+ }
328
+
329
+ /**
330
+ * Returns true if and only if the host string passes validation. If no host is passed,
331
+ * then the host contained in the instance variable is used.
332
+ *
333
+ * @param string $host
334
+ * @return boolean
335
+ * @uses SZend_Filter
336
+ */
337
+ public function validateHost($host = null)
338
+ {
339
+ if ($host === null) {
340
+ $host = $this->_host;
341
+ }
342
+
343
+ /**
344
+ * If the host is empty, then it is considered invalid
345
+ */
346
+ if (strlen($host) == 0) {
347
+ return false;
348
+ }
349
+
350
+ /**
351
+ * Check the host against the allowed values; delegated to SZend_Filter.
352
+ */
353
+ $validate = new SZend_Validate_Hostname(SZend_Validate_Hostname::ALLOW_ALL);
354
+ return $validate->isValid($host);
355
+ }
356
+
357
+ /**
358
+ * Sets the host for the current URI, and returns the old host
359
+ *
360
+ * @param string $host
361
+ * @throws SZend_Uri_Exception
362
+ * @return string
363
+ */
364
+ public function setHost($host)
365
+ {
366
+ if (!$this->validateHost($host)) {
367
+ require_once 'SZend/Uri/Exception.php';
368
+ throw new SZend_Uri_Exception("Host \"$host\" is not a valid HTTP host");
369
+ }
370
+ $oldHost = $this->_host;
371
+ $this->_host = $host;
372
+ return $oldHost;
373
+ }
374
+
375
+ /**
376
+ * Returns the TCP port, or FALSE if none.
377
+ *
378
+ * @return string
379
+ */
380
+ public function getPort()
381
+ {
382
+ return strlen($this->_port) ? $this->_port : false;
383
+ }
384
+
385
+ /**
386
+ * Returns true if and only if the TCP port string passes validation. If no port is passed,
387
+ * then the port contained in the instance variable is used.
388
+ *
389
+ * @param string $port
390
+ * @return boolean
391
+ */
392
+ public function validatePort($port = null)
393
+ {
394
+ if ($port === null) {
395
+ $port = $this->_port;
396
+ }
397
+
398
+ // If the port is empty, then it is considered valid
399
+ if (!strlen($port)) {
400
+ return true;
401
+ }
402
+
403
+ // Check the port against the allowed values
404
+ return ctype_digit((string)$port) && 1 <= $port && $port <= 65535;
405
+ }
406
+
407
+ /**
408
+ * Sets the port for the current URI, and returns the old port
409
+ *
410
+ * @param string $port
411
+ * @throws SZend_Uri_Exception
412
+ * @return string
413
+ */
414
+ public function setPort($port)
415
+ {
416
+ if (!$this->validatePort($port)) {
417
+ require_once 'SZend/Uri/Exception.php';
418
+ throw new SZend_Uri_Exception("Port \"$port\" is not a valid HTTP port.");
419
+ }
420
+ $oldPort = $this->_port;
421
+ $this->_port = $port;
422
+ return $oldPort;
423
+ }
424
+
425
+ /**
426
+ * Returns the path and filename portion of the URL, or FALSE if none.
427
+ *
428
+ * @return string
429
+ */
430
+ public function getPath()
431
+ {
432
+ return strlen($this->_path) ? $this->_path : '/';
433
+ }
434
+
435
+ /**
436
+ * Returns true if and only if the path string passes validation. If no path is passed,
437
+ * then the path contained in the instance variable is used.
438
+ *
439
+ * @param string $path
440
+ * @throws SZend_Uri_Exception
441
+ * @return boolean
442
+ */
443
+ public function validatePath($path = null)
444
+ {
445
+ if ($path === null) {
446
+ $path = $this->_path;
447
+ }
448
+ /**
449
+ * If the path is empty, then it is considered valid
450
+ */
451
+ if (strlen($path) == 0) {
452
+ return true;
453
+ }
454
+ /**
455
+ * Determine whether the path is well-formed
456
+ */
457
+ $pattern = '/^' . $this->_regex['path'] . '$/';
458
+ $status = @preg_match($pattern, $path);
459
+ if ($status === false) {
460
+ require_once 'SZend/Uri/Exception.php';
461
+ throw new SZend_Uri_Exception('Internal error: path validation failed');
462
+ }
463
+ return (boolean) $status;
464
+ }
465
+
466
+ /**
467
+ * Sets the path for the current URI, and returns the old path
468
+ *
469
+ * @param string $path
470
+ * @throws SZend_Uri_Exception
471
+ * @return string
472
+ */
473
+ public function setPath($path)
474
+ {
475
+ if (!$this->validatePath($path)) {
476
+ require_once 'SZend/Uri/Exception.php';
477
+ throw new SZend_Uri_Exception("Path \"$path\" is not a valid HTTP path");
478
+ }
479
+ $oldPath = $this->_path;
480
+ $this->_path = $path;
481
+ return $oldPath;
482
+ }
483
+
484
+ /**
485
+ * Returns the query portion of the URL (after ?), or FALSE if none.
486
+ *
487
+ * @return string
488
+ */
489
+ public function getQuery()
490
+ {
491
+ return strlen($this->_query) ? $this->_query : false;
492
+ }
493
+
494
+ /**
495
+ * Returns true if and only if the query string passes validation. If no query is passed,
496
+ * then the query string contained in the instance variable is used.
497
+ *
498
+ * @param string $query
499
+ * @throws SZend_Uri_Exception
500
+ * @return boolean
501
+ */
502
+ public function validateQuery($query = null)
503
+ {
504
+ if ($query === null) {
505
+ $query = $this->_query;
506
+ }
507
+
508
+ // If query is empty, it is considered to be valid
509
+ if (strlen($query) == 0) {
510
+ return true;
511
+ }
512
+
513
+ /**
514
+ * Determine whether the query is well-formed
515
+ *
516
+ * @link http://www.faqs.org/rfcs/rfc2396.html
517
+ */
518
+ $pattern = '/^' . $this->_regex['uric'] . '*$/';
519
+ $status = @preg_match($pattern, $query);
520
+ if ($status === false) {
521
+ require_once 'SZend/Uri/Exception.php';
522
+ throw new SZend_Uri_Exception('Internal error: query validation failed');
523
+ }
524
+
525
+ return $status == 1;
526
+ }
527
+
528
+ /**
529
+ * Set the query string for the current URI, and return the old query
530
+ * string This method accepts both strings and arrays.
531
+ *
532
+ * @param string|array $query The query string or array
533
+ * @return string Old query string
534
+ */
535
+ public function setQuery($query)
536
+ {
537
+ $oldQuery = $this->_query;
538
+
539
+ // If query is empty, set an empty string
540
+ if (empty($query)) {
541
+ $this->_query = '';
542
+ return $oldQuery;
543
+ }
544
+
545
+ // If query is an array, make a string out of it
546
+ if (is_array($query)) {
547
+ $query = http_build_query($query, '', '&');
548
+
549
+ // If it is a string, make sure it is valid. If not parse and encode it
550
+ } else {
551
+ $query = (string) $query;
552
+ if (! $this->validateQuery($query)) {
553
+ parse_str($query, $query_array);
554
+ $query = http_build_query($query_array, '', '&');
555
+ }
556
+ }
557
+
558
+ // Make sure the query is valid, and set it
559
+ if (! $this->validateQuery($query)) {
560
+ require_once 'SZend/Uri/Exception.php';
561
+ throw new SZend_Uri_Exception("'$query' is not a valid query string");
562
+ }
563
+
564
+ $this->_query = $query;
565
+
566
+ return $oldQuery;
567
+ }
568
+
569
+ /**
570
+ * Returns the fragment portion of the URL (after #), or FALSE if none.
571
+ *
572
+ * @return string|false
573
+ */
574
+ public function getFragment()
575
+ {
576
+ return strlen($this->_fragment) ? $this->_fragment : false;
577
+ }
578
+
579
+ /**
580
+ * Returns true if and only if the fragment passes validation. If no fragment is passed,
581
+ * then the fragment contained in the instance variable is used.
582
+ *
583
+ * @param string $fragment
584
+ * @throws SZend_Uri_Exception
585
+ * @return boolean
586
+ */
587
+ public function validateFragment($fragment = null)
588
+ {
589
+ if ($fragment === null) {
590
+ $fragment = $this->_fragment;
591
+ }
592
+
593
+ // If fragment is empty, it is considered to be valid
594
+ if (strlen($fragment) == 0) {
595
+ return true;
596
+ }
597
+
598
+ /**
599
+ * Determine whether the fragment is well-formed
600
+ *
601
+ * @link http://www.faqs.org/rfcs/rfc2396.html
602
+ */
603
+ $pattern = '/^' . $this->_regex['uric'] . '*$/';
604
+ $status = @preg_match($pattern, $fragment);
605
+ if ($status === false) {
606
+ require_once 'SZend/Uri/Exception.php';
607
+ throw new SZend_Uri_Exception('Internal error: fragment validation failed');
608
+ }
609
+
610
+ return (boolean) $status;
611
+ }
612
+
613
+ /**
614
+ * Sets the fragment for the current URI, and returns the old fragment
615
+ *
616
+ * @param string $fragment
617
+ * @throws SZend_Uri_Exception
618
+ * @return string
619
+ */
620
+ public function setFragment($fragment)
621
+ {
622
+ if (!$this->validateFragment($fragment)) {
623
+ require_once 'SZend/Uri/Exception.php';
624
+ throw new SZend_Uri_Exception("Fragment \"$fragment\" is not a valid HTTP fragment");
625
+ }
626
+ $oldFragment = $this->_fragment;
627
+ $this->_fragment = $fragment;
628
+ return $oldFragment;
629
+ }
630
+ }
631
+
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Abstract.php ADDED
@@ -0,0 +1,337 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * SZend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category SZend
17
+ * @package SZend_Validate
18
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Abstract.php 8113 2008-02-18 13:15:27Z matthew $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see SZend_Validate_Interface
26
+ */
27
+ require_once dirname(__FILE__) . '/Interface.php';
28
+
29
+
30
+ /**
31
+ * @category SZend
32
+ * @package SZend_Validate
33
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ abstract class SZend_Validate_Abstract implements SZend_Validate_Interface
37
+ {
38
+ /**
39
+ * The value to be validated
40
+ *
41
+ * @var mixed
42
+ */
43
+ protected $_value;
44
+
45
+ /**
46
+ * Additional variables available for validation failure messages
47
+ *
48
+ * @var array
49
+ */
50
+ protected $_messageVariables = array();
51
+
52
+ /**
53
+ * Validation failure message template definitions
54
+ *
55
+ * @var array
56
+ */
57
+ protected $_messageTemplates = array();
58
+
59
+ /**
60
+ * Array of validation failure messages
61
+ *
62
+ * @var array
63
+ */
64
+ protected $_messages = array();
65
+
66
+ /**
67
+ * Flag indidcating whether or not value should be obfuscated in error
68
+ * messages
69
+ * @var bool
70
+ */
71
+ protected $_obscureValue = false;
72
+
73
+ /**
74
+ * Array of validation failure message codes
75
+ *
76
+ * @var array
77
+ * @deprecated Since 1.5.0
78
+ */
79
+ protected $_errors = array();
80
+
81
+ /**
82
+ * Translation object
83
+ * @var SZend_Translate
84
+ */
85
+ protected $_translator;
86
+
87
+ /**
88
+ * Default translation object for all validate objects
89
+ * @var SZend_Translate
90
+ */
91
+ protected static $_defaultTranslator;
92
+
93
+ /**
94
+ * Returns array of validation failure messages
95
+ *
96
+ * @return array
97
+ */
98
+ public function getMessages()
99
+ {
100
+ return $this->_messages;
101
+ }
102
+
103
+ /**
104
+ * Returns an array of the names of variables that are used in constructing validation failure messages
105
+ *
106
+ * @return array
107
+ */
108
+ public function getMessageVariables()
109
+ {
110
+ return array_keys($this->_messageVariables);
111
+ }
112
+
113
+ /**
114
+ * Sets the validation failure message template for a particular key
115
+ *
116
+ * @param string $messageString
117
+ * @param string $messageKey OPTIONAL
118
+ * @return SZend_Validate_Abstract Provides a fluent interface
119
+ * @throws SZend_Validate_Exception
120
+ */
121
+ public function setMessage($messageString, $messageKey = null)
122
+ {
123
+ if ($messageKey === null) {
124
+ $keys = array_keys($this->_messageTemplates);
125
+ $messageKey = current($keys);
126
+ }
127
+ if (!isset($this->_messageTemplates[$messageKey])) {
128
+ require_once 'SZend/Validate/Exception.php';
129
+ throw new SZend_Validate_Exception("No message template exists for key '$messageKey'");
130
+ }
131
+ $this->_messageTemplates[$messageKey] = $messageString;
132
+ return $this;
133
+ }
134
+
135
+ /**
136
+ * Sets validation failure message templates given as an array, where the array keys are the message keys,
137
+ * and the array values are the message template strings.
138
+ *
139
+ * @param array $messages
140
+ * @return SZend_Validate_Abstract
141
+ */
142
+ public function setMessages(array $messages)
143
+ {
144
+ foreach ($messages as $key => $message) {
145
+ $this->setMessage($message, $key);
146
+ }
147
+ return $this;
148
+ }
149
+
150
+ /**
151
+ * Magic function returns the value of the requested property, if and only if it is the value or a
152
+ * message variable.
153
+ *
154
+ * @param string $property
155
+ * @return mixed
156
+ * @throws SZend_Validate_Exception
157
+ */
158
+ public function __get($property)
159
+ {
160
+ if ($property == 'value') {
161
+ return $this->_value;
162
+ }
163
+ if (array_key_exists($property, $this->_messageVariables)) {
164
+ return $this->{$this->_messageVariables[$property]};
165
+ }
166
+ /**
167
+ * @see SZend_Validate_Exception
168
+ */
169
+ require_once 'SZend/Validate/Exception.php';
170
+ throw new SZend_Validate_Exception("No property exists by the name '$property'");
171
+ }
172
+
173
+ /**
174
+ * Constructs and returns a validation failure message with the given message key and value.
175
+ *
176
+ * Returns null if and only if $messageKey does not correspond to an existing template.
177
+ *
178
+ * If a translator is available and a translation exists for $messageKey,
179
+ * the translation will be used.
180
+ *
181
+ * @param string $messageKey
182
+ * @param string $value
183
+ * @return string
184
+ */
185
+ protected function _createMessage($messageKey, $value)
186
+ {
187
+ if (!isset($this->_messageTemplates[$messageKey])) {
188
+ return null;
189
+ }
190
+
191
+ $message = $this->_messageTemplates[$messageKey];
192
+
193
+ if (null !== ($translator = $this->getTranslator())) {
194
+ if ($translator->isTranslated($messageKey)) {
195
+ $message = $translator->translate($messageKey);
196
+ }
197
+ }
198
+
199
+ if ($this->getObscureValue()) {
200
+ $value = str_repeat('*', strlen($value));
201
+ }
202
+
203
+ $message = str_replace('%value%', (string) $value, $message);
204
+ foreach ($this->_messageVariables as $ident => $property) {
205
+ $message = str_replace("%$ident%", $this->$property, $message);
206
+ }
207
+ return $message;
208
+ }
209
+
210
+ /**
211
+ * @param string $messageKey OPTIONAL
212
+ * @param string $value OPTIONAL
213
+ * @return void
214
+ */
215
+ protected function _error($messageKey = null, $value = null)
216
+ {
217
+ if ($messageKey === null) {
218
+ $keys = array_keys($this->_messageTemplates);
219
+ $messageKey = current($keys);
220
+ }
221
+ if ($value === null) {
222
+ $value = $this->_value;
223
+ }
224
+ $this->_errors[] = $messageKey;
225
+ $this->_messages[$messageKey] = $this->_createMessage($messageKey, $value);
226
+ }
227
+
228
+ /**
229
+ * Sets the value to be validated and clears the messages and errors arrays
230
+ *
231
+ * @param mixed $value
232
+ * @return void
233
+ */
234
+ protected function _setValue($value)
235
+ {
236
+ $this->_value = $value;
237
+ $this->_messages = array();
238
+ $this->_errors = array();
239
+ }
240
+
241
+ /**
242
+ * Returns array of validation failure message codes
243
+ *
244
+ * @return array
245
+ * @deprecated Since 1.5.0
246
+ */
247
+ public function getErrors()
248
+ {
249
+ return $this->_errors;
250
+ }
251
+
252
+ /**
253
+ * Set flag indicating whether or not value should be obfuscated in messages
254
+ *
255
+ * @param bool $flag
256
+ * @return SZend_Validate_Abstract
257
+ */
258
+ public function setObscureValue($flag)
259
+ {
260
+ $this->_obscureValue = (bool) $flag;
261
+ return $this;
262
+ }
263
+
264
+ /**
265
+ * Retrieve flag indicating whether or not value should be obfuscated in
266
+ * messages
267
+ *
268
+ * @return bool
269
+ */
270
+ public function getObscureValue()
271
+ {
272
+ return $this->_obscureValue;
273
+ }
274
+
275
+ /**
276
+ * Set translation object
277
+ *
278
+ * @param SZend_Translate|SZend_Translate_Adapter|null $translator
279
+ * @return SZend_Validate_Abstract
280
+ */
281
+ public function setTranslator($translator = null)
282
+ {
283
+ if ((null === $translator) || ($translator instanceof SZend_Translate_Adapter)) {
284
+ $this->_translator = $translator;
285
+ } elseif ($translator instanceof SZend_Translate) {
286
+ $this->_translator = $translator->getAdapter();
287
+ } else {
288
+ require_once 'SZend/Validate/Exception.php';
289
+ throw new SZend_Validate_Exception('Invalid translator specified');
290
+ }
291
+ return $this;
292
+ }
293
+
294
+ /**
295
+ * Return translation object
296
+ *
297
+ * @return SZend_Translate_Adapter|null
298
+ */
299
+ public function getTranslator()
300
+ {
301
+ if (null === $this->_translator) {
302
+ return self::getDefaultTranslator();
303
+ }
304
+
305
+ return $this->_translator;
306
+ }
307
+
308
+ /**
309
+ * Set default translation object for all validate objects
310
+ *
311
+ * @param SZend_Translate|SZend_Translate_Adapter|null $translator
312
+ * @return void
313
+ */
314
+ public static function setDefaultTranslator($translator = null)
315
+ {
316
+ if ((null === $translator) || ($translator instanceof SZend_Translate_Adapter)) {
317
+ self::$_defaultTranslator = $translator;
318
+ } elseif ($translator instanceof SZend_Translate) {
319
+ self::$_defaultTranslator = $translator->getAdapter();
320
+ } else {
321
+ require_once 'SZend/Validate/Exception.php';
322
+ throw new SZend_Validate_Exception('Invalid translator specified');
323
+ }
324
+ }
325
+
326
+ /**
327
+ * Get default translation object for all validate objects
328
+ *
329
+ * @return SZend_Translate_Adapter|null
330
+ */
331
+ public static function getDefaultTranslator()
332
+ {
333
+ if (null === self::$_defaultTranslator) {
334
+ }
335
+ return self::$_defaultTranslator;
336
+ }
337
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Hostname.php ADDED
@@ -0,0 +1,444 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * SZend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category SZend
17
+ * @package SZend_Validate
18
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Hostname.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see SZend_Validate_Abstract
26
+ */
27
+ require_once dirname(__FILE__) . '/../Validate/Abstract.php';
28
+
29
+ /**
30
+ * @see SZend_Loader
31
+ */
32
+ require_once dirname(__FILE__) . '/../Loader.php';
33
+
34
+ /**
35
+ * @see SZend_Validate_Ip
36
+ */
37
+ require_once dirname(__FILE__) . '/../Validate/Ip.php';
38
+
39
+ /**
40
+ * Please note there are two standalone test scripts for testing IDN characters due to problems
41
+ * with file encoding.
42
+ *
43
+ * The first is tests/SZend/Validate/HostnameTestStandalone.php which is designed to be run on
44
+ * the command line.
45
+ *
46
+ * The second is tests/SZend/Validate/HostnameTestForm.php which is designed to be run via HTML
47
+ * to allow users to test entering UTF-8 characters in a form.
48
+ *
49
+ * @category SZend
50
+ * @package SZend_Validate
51
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
52
+ * @license http://framework.zend.com/license/new-bsd New BSD License
53
+ */
54
+ class SZend_Validate_Hostname extends SZend_Validate_Abstract
55
+ {
56
+
57
+ const IP_ADDRESS_NOT_ALLOWED = 'hostnameIpAddressNotAllowed';
58
+ const UNKNOWN_TLD = 'hostnameUnknownTld';
59
+ const INVALID_DASH = 'hostnameDashCharacter';
60
+ const INVALID_HOSTNAME_SCHEMA = 'hostnameInvalidHostnameSchema';
61
+ const UNDECIPHERABLE_TLD = 'hostnameUndecipherableTld';
62
+ const INVALID_HOSTNAME = 'hostnameInvalidHostname';
63
+ const INVALID_LOCAL_NAME = 'hostnameInvalidLocalName';
64
+ const LOCAL_NAME_NOT_ALLOWED = 'hostnameLocalNameNotAllowed';
65
+
66
+ /**
67
+ * @var array
68
+ */
69
+ protected $_messageTemplates = array(
70
+ self::IP_ADDRESS_NOT_ALLOWED => "'%value%' appears to be an IP address, but IP addresses are not allowed",
71
+ self::UNKNOWN_TLD => "'%value%' appears to be a DNS hostname but cannot match TLD against known list",
72
+ self::INVALID_DASH => "'%value%' appears to be a DNS hostname but contains a dash (-) in an invalid position",
73
+ self::INVALID_HOSTNAME_SCHEMA => "'%value%' appears to be a DNS hostname but cannot match against hostname schema for TLD '%tld%'",
74
+ self::UNDECIPHERABLE_TLD => "'%value%' appears to be a DNS hostname but cannot extract TLD part",
75
+ self::INVALID_HOSTNAME => "'%value%' does not match the expected structure for a DNS hostname",
76
+ self::INVALID_LOCAL_NAME => "'%value%' does not appear to be a valid local network name",
77
+ self::LOCAL_NAME_NOT_ALLOWED => "'%value%' appears to be a local network name but local network names are not allowed"
78
+ );
79
+
80
+ /**
81
+ * @var array
82
+ */
83
+ protected $_messageVariables = array(
84
+ 'tld' => '_tld'
85
+ );
86
+
87
+ /**
88
+ * Allows Internet domain names (e.g., example.com)
89
+ */
90
+ const ALLOW_DNS = 1;
91
+
92
+ /**
93
+ * Allows IP addresses
94
+ */
95
+ const ALLOW_IP = 2;
96
+
97
+ /**
98
+ * Allows local network names (e.g., localhost, www.localdomain)
99
+ */
100
+ const ALLOW_LOCAL = 4;
101
+
102
+ /**
103
+ * Allows all types of hostnames
104
+ */
105
+ const ALLOW_ALL = 7;
106
+
107
+ /**
108
+ * Whether IDN domains are validated
109
+ *
110
+ * @var boolean
111
+ */
112
+ private $_validateIdn = true;
113
+
114
+ /**
115
+ * Whether TLDs are validated against a known list
116
+ *
117
+ * @var boolean
118
+ */
119
+ private $_validateTld = true;
120
+
121
+ /**
122
+ * Bit field of ALLOW constants; determines which types of hostnames are allowed
123
+ *
124
+ * @var integer
125
+ */
126
+ protected $_allow;
127
+
128
+ /**
129
+ * Bit field of CHECK constants; determines what additional hostname checks to make
130
+ *
131
+ * @var unknown_type
132
+ */
133
+ // protected $_check;
134
+
135
+ /**
136
+ * Array of valid top-level-domains
137
+ *
138
+ * @var array
139
+ * @see ftp://data.iana.org/TLD/tlds-alpha-by-domain.txt List of all TLDs by domain
140
+ */
141
+ protected $_validTlds = array(
142
+ 'ac', 'ad', 'ae', 'aero', 'af', 'ag', 'ai', 'al', 'am', 'an', 'ao',
143
+ 'aq', 'ar', 'arpa', 'as', 'at', 'au', 'aw', 'ax', 'az', 'ba', 'bb',
144
+ 'bd', 'be', 'bf', 'bg', 'bh', 'bi', 'biz', 'bj', 'bm', 'bn', 'bo',
145
+ 'br', 'bs', 'bt', 'bv', 'bw', 'by', 'bz', 'ca', 'cat', 'cc', 'cd',
146
+ 'cf', 'cg', 'ch', 'ci', 'ck', 'cl', 'cm', 'cn', 'co', 'com', 'coop',
147
+ 'cr', 'cu', 'cv', 'cx', 'cy', 'cz', 'de', 'dj', 'dk', 'dm', 'do',
148
+ 'dz', 'ec', 'edu', 'ee', 'eg', 'er', 'es', 'et', 'eu', 'fi', 'fj',
149
+ 'fk', 'fm', 'fo', 'fr', 'ga', 'gb', 'gd', 'ge', 'gf', 'gg', 'gh',
150
+ 'gi', 'gl', 'gm', 'gn', 'gov', 'gp', 'gq', 'gr', 'gs', 'gt', 'gu',
151
+ 'gw', 'gy', 'hk', 'hm', 'hn', 'hr', 'ht', 'hu', 'id', 'ie', 'il',
152
+ 'im', 'in', 'info', 'int', 'io', 'iq', 'ir', 'is', 'it', 'je', 'jm',
153
+ 'jo', 'jobs', 'jp', 'ke', 'kg', 'kh', 'ki', 'km', 'kn', 'kr', 'kw',
154
+ 'ky', 'kz', 'la', 'lb', 'lc', 'li', 'lk', 'lr', 'ls', 'lt', 'lu',
155
+ 'lv', 'ly', 'ma', 'mc', 'md', 'mg', 'mh', 'mil', 'mk', 'ml', 'mm',
156
+ 'mn', 'mo', 'mobi', 'mp', 'mq', 'mr', 'ms', 'mt', 'mu', 'museum', 'mv',
157
+ 'mw', 'mx', 'my', 'mz', 'na', 'name', 'nc', 'ne', 'net', 'nf', 'ng',
158
+ 'ni', 'nl', 'no', 'np', 'nr', 'nu', 'nz', 'om', 'org', 'pa', 'pe',
159
+ 'pf', 'pg', 'ph', 'pk', 'pl', 'pm', 'pn', 'pr', 'pro', 'ps', 'pt',
160
+ 'pw', 'py', 'qa', 're', 'ro', 'ru', 'rw', 'sa', 'sb', 'sc', 'sd',
161
+ 'se', 'sg', 'sh', 'si', 'sj', 'sk', 'sl', 'sm', 'sn', 'so', 'sr',
162
+ 'st', 'su', 'sv', 'sy', 'sz', 'tc', 'td', 'tf', 'tg', 'th', 'tj',
163
+ 'tk', 'tl', 'tm', 'tn', 'to', 'tp', 'tr', 'travel', 'tt', 'tv', 'tw',
164
+ 'tz', 'ua', 'ug', 'uk', 'um', 'us', 'uy', 'uz', 'va', 'vc', 've',
165
+ 'vg', 'vi', 'vn', 'vu', 'wf', 'ws', 'ye', 'yt', 'yu', 'za', 'zm',
166
+ 'zw'
167
+ );
168
+
169
+ /**
170
+ * @var string
171
+ */
172
+ protected $_tld;
173
+
174
+ /**
175
+ * Sets validator options
176
+ *
177
+ * @param integer $allow OPTIONAL Set what types of hostname to allow (default ALLOW_DNS)
178
+ * @param boolean $validateIdn OPTIONAL Set whether IDN domains are validated (default true)
179
+ * @param boolean $validateTld OPTIONAL Set whether the TLD element of a hostname is validated (default true)
180
+ * @param SZend_Validate_Ip $ipValidator OPTIONAL
181
+ * @return void
182
+ * @see http://www.iana.org/cctld/specifications-policies-cctlds-01apr02.htm Technical Specifications for ccTLDs
183
+ */
184
+ public function __construct($allow = self::ALLOW_DNS, $validateIdn = true, $validateTld = true, SZend_Validate_Ip $ipValidator = null)
185
+ {
186
+ // Set allow options
187
+ $this->setAllow($allow);
188
+
189
+ // Set validation options
190
+ $this->_validateIdn = $validateIdn;
191
+ $this->_validateTld = $validateTld;
192
+
193
+ $this->setIpValidator($ipValidator);
194
+ }
195
+
196
+ /**
197
+ * @param SZend_Validate_Ip $ipValidator OPTIONAL
198
+ * @return void;
199
+ */
200
+ public function setIpValidator(SZend_Validate_Ip $ipValidator = null)
201
+ {
202
+ if ($ipValidator === null) {
203
+ $ipValidator = new SZend_Validate_Ip();
204
+ }
205
+ $this->_ipValidator = $ipValidator;
206
+ }
207
+
208
+ /**
209
+ * Returns the allow option
210
+ *
211
+ * @return integer
212
+ */
213
+ public function getAllow()
214
+ {
215
+ return $this->_allow;
216
+ }
217
+
218
+ /**
219
+ * Sets the allow option
220
+ *
221
+ * @param integer $allow
222
+ * @return SZend_Validate_Hostname Provides a fluent interface
223
+ */
224
+ public function setAllow($allow)
225
+ {
226
+ $this->_allow = $allow;
227
+ return $this;
228
+ }
229
+
230
+ /**
231
+ * Set whether IDN domains are validated
232
+ *
233
+ * This only applies when DNS hostnames are validated
234
+ *
235
+ * @param boolean $allowed Set allowed to true to validate IDNs, and false to not validate them
236
+ */
237
+ public function setValidateIdn ($allowed)
238
+ {
239
+ $this->_validateIdn = (bool) $allowed;
240
+ }
241
+
242
+ /**
243
+ * Set whether the TLD element of a hostname is validated
244
+ *
245
+ * This only applies when DNS hostnames are validated
246
+ *
247
+ * @param boolean $allowed Set allowed to true to validate TLDs, and false to not validate them
248
+ */
249
+ public function setValidateTld ($allowed)
250
+ {
251
+ $this->_validateTld = (bool) $allowed;
252
+ }
253
+
254
+ /**
255
+ * Sets the check option
256
+ *
257
+ * @param integer $check
258
+ * @return SZend_Validate_Hostname Provides a fluent interface
259
+ */
260
+ /*
261
+ public function setCheck($check)
262
+ {
263
+ $this->_check = $check;
264
+ return $this;
265
+ }
266
+ */
267
+
268
+ /**
269
+ * Defined by SZend_Validate_Interface
270
+ *
271
+ * Returns true if and only if the $value is a valid hostname with respect to the current allow option
272
+ *
273
+ * @param string $value
274
+ * @throws SZend_Validate_Exception if a fatal error occurs for validation process
275
+ * @return boolean
276
+ */
277
+ public function isValid($value)
278
+ {
279
+ $valueString = (string) $value;
280
+
281
+ $this->_setValue($valueString);
282
+
283
+ // Check input against IP address schema
284
+ if ($this->_ipValidator->isValid($valueString)) {
285
+ if (!($this->_allow & self::ALLOW_IP)) {
286
+ $this->_error(self::IP_ADDRESS_NOT_ALLOWED);
287
+ return false;
288
+ } else{
289
+ return true;
290
+ }
291
+ }
292
+
293
+ // Check input against DNS hostname schema
294
+ $domainParts = explode('.', $valueString);
295
+ if ((count($domainParts) > 1) && (strlen($valueString) >= 4) && (strlen($valueString) <= 254)) {
296
+ $status = false;
297
+
298
+ do {
299
+ // First check TLD
300
+ if (preg_match('/([a-z]{2,10})$/i', end($domainParts), $matches)) {
301
+
302
+ reset($domainParts);
303
+
304
+ // Hostname characters are: *(label dot)(label dot label); max 254 chars
305
+ // label: id-prefix [*ldh{61} id-prefix]; max 63 chars
306
+ // id-prefix: alpha / digit
307
+ // ldh: alpha / digit / dash
308
+
309
+ // Match TLD against known list
310
+ $this->_tld = strtolower($matches[1]);
311
+ if ($this->_validateTld) {
312
+ if (!in_array($this->_tld, $this->_validTlds)) {
313
+ $this->_error(self::UNKNOWN_TLD);
314
+ $status = false;
315
+ break;
316
+ }
317
+ }
318
+
319
+ /**
320
+ * Match against IDN hostnames
321
+ * @see SZend_Validate_Hostname_Interface
322
+ */
323
+ $labelChars = 'a-z0-9';
324
+ $utf8 = false;
325
+ $classFile = 'SZend/Validate/Hostname/' . ucfirst($this->_tld) . '.php';
326
+ if ($this->_validateIdn) {
327
+ if (SZend_Loader::isReadable($classFile)) {
328
+
329
+ // Load additional characters
330
+ $className = 'SZend_Validate_Hostname_' . ucfirst($this->_tld);
331
+ SZend_Loader::loadClass($className);
332
+ $labelChars .= call_user_func(array($className, 'getCharacters'));
333
+ $utf8 = true;
334
+ }
335
+ }
336
+
337
+ // Keep label regex short to avoid issues with long patterns when matching IDN hostnames
338
+ $regexLabel = '/^[' . $labelChars . '\x2d]{1,63}$/i';
339
+ if ($utf8) {
340
+ $regexLabel .= 'u';
341
+ }
342
+
343
+ // Check each hostname part
344
+ $valid = true;
345
+ foreach ($domainParts as $domainPart) {
346
+
347
+ // Check dash (-) does not start, end or appear in 3rd and 4th positions
348
+ if (strpos($domainPart, '-') === 0 ||
349
+ (strlen($domainPart) > 2 && strpos($domainPart, '-', 2) == 2 && strpos($domainPart, '-', 3) == 3) ||
350
+ strrpos($domainPart, '-') === strlen($domainPart) - 1) {
351
+
352
+ $this->_error(self::INVALID_DASH);
353
+ $status = false;
354
+ break 2;
355
+ }
356
+
357
+ // Check each domain part
358
+ $status = @preg_match($regexLabel, $domainPart);
359
+ if ($status === false) {
360
+ /**
361
+ * Regex error
362
+ * @see SZend_Validate_Exception
363
+ */
364
+ require_once 'SZend/Validate/Exception.php';
365
+ throw new SZend_Validate_Exception('Internal error: DNS validation failed');
366
+ } elseif ($status === 0) {
367
+ $valid = false;
368
+ }
369
+ }
370
+
371
+ // If all labels didn't match, the hostname is invalid
372
+ if (!$valid) {
373
+ $this->_error(self::INVALID_HOSTNAME_SCHEMA);
374
+ $status = false;
375
+ }
376
+
377
+ } else {
378
+ // Hostname not long enough
379
+ $this->_error(self::UNDECIPHERABLE_TLD);
380
+ $status = false;
381
+ }
382
+ } while (false);
383
+
384
+ // If the input passes as an Internet domain name, and domain names are allowed, then the hostname
385
+ // passes validation
386
+ if ($status && ($this->_allow & self::ALLOW_DNS)) {
387
+ return true;
388
+ }
389
+ } else {
390
+ $this->_error(self::INVALID_HOSTNAME);
391
+ }
392
+
393
+ // Check input against local network name schema; last chance to pass validation
394
+ $regexLocal = "/^(([a-zA-Z0-9\x2d]{1,63}\x2e)*[a-zA-Z0-9\x2d]{1,63}){1,254}$/";
395
+ $status = @preg_match($regexLocal, $valueString);
396
+ if (false === $status) {
397
+ /**
398
+ * Regex error
399
+ * @see SZend_Validate_Exception
400
+ */
401
+ require_once 'SZend/Validate/Exception.php';
402
+ throw new SZend_Validate_Exception('Internal error: local network name validation failed');
403
+ }
404
+
405
+ // If the input passes as a local network name, and local network names are allowed, then the
406
+ // hostname passes validation
407
+ $allowLocal = $this->_allow & self::ALLOW_LOCAL;
408
+ if ($status && $allowLocal) {
409
+ return true;
410
+ }
411
+
412
+ // If the input does not pass as a local network name, add a message
413
+ if (!$status) {
414
+ $this->_error(self::INVALID_LOCAL_NAME);
415
+ }
416
+
417
+ // If local network names are not allowed, add a message
418
+ if (!$allowLocal) {
419
+ $this->_error(self::LOCAL_NAME_NOT_ALLOWED);
420
+ }
421
+
422
+ return false;
423
+ }
424
+
425
+ /**
426
+ * Throws an exception if a regex for $type does not exist
427
+ *
428
+ * @param string $type
429
+ * @throws SZend_Validate_Exception
430
+ * @return SZend_Validate_Hostname Provides a fluent interface
431
+ */
432
+ /*
433
+ protected function _checkRegexType($type)
434
+ {
435
+ if (!isset($this->_regex[$type])) {
436
+ require_once 'SZend/Validate/Exception.php';
437
+ throw new SZend_Validate_Exception("'$type' must be one of ('" . implode(', ', array_keys($this->_regex))
438
+ . "')");
439
+ }
440
+ return $this;
441
+ }
442
+ */
443
+
444
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Hostname/At.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * SZend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category SZend
17
+ * @package SZend_Validate
18
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: At.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see SZend_Validate_Hostname_Interface
26
+ */
27
+ require_once dirname(__FILE__) . '/../../Validate/Hostname/Interface.php';
28
+
29
+
30
+ /**
31
+ * @category SZend
32
+ * @package SZend_Validate
33
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class SZend_Validate_Hostname_At implements SZend_Validate_Hostname_Interface
37
+ {
38
+
39
+ /**
40
+ * Returns UTF-8 characters allowed in DNS hostnames for the specified Top-Level-Domain
41
+ *
42
+ * @see http://www.nic.at/en/service/technical_information/idn/charset_converter/ Austria (.AT)
43
+ * @return string
44
+ */
45
+ static function getCharacters()
46
+ {
47
+ return '\x{00EO}-\x{00F6}\x{00F8}-\x{00FF}\x{0153}\x{0161}\x{017E}';
48
+ }
49
+
50
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Hostname/Ch.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * SZend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category SZend
17
+ * @package SZend_Validate
18
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Ch.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see SZend_Validate_Hostname_Interface
26
+ */
27
+ require_once dirname(__FILE__) . '/../../Validate/Hostname/Interface.php';
28
+
29
+
30
+ /**
31
+ * @category SZend
32
+ * @package SZend_Validate
33
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class SZend_Validate_Hostname_Ch implements SZend_Validate_Hostname_Interface
37
+ {
38
+
39
+ /**
40
+ * Returns UTF-8 characters allowed in DNS hostnames for the specified Top-Level-Domain
41
+ *
42
+ * @see https://nic.switch.ch/reg/ocView.action?res=EF6GW2JBPVTG67DLNIQXU234MN6SC33JNQQGI7L6#anhang1 Switzerland (.CH)
43
+ * @return string
44
+ */
45
+ static function getCharacters()
46
+ {
47
+ return '\x{00EO}-\x{00F6}\x{00F8}-\x{00FF}\x{0153}';
48
+ }
49
+
50
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Hostname/De.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * SZend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category SZend
17
+ * @package SZend_Validate
18
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: De.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see SZend_Validate_Hostname_Interface
26
+ */
27
+ require_once dirname(__FILE__) . '/../../Validate/Hostname/Interface.php';
28
+
29
+
30
+ /**
31
+ * @category SZend
32
+ * @package SZend_Validate
33
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class SZend_Validate_Hostname_De implements SZend_Validate_Hostname_Interface
37
+ {
38
+
39
+ /**
40
+ * Returns UTF-8 characters allowed in DNS hostnames for the specified Top-Level-Domain
41
+ *
42
+ * @see http://www.denic.de/en/domains/idns/liste.html Germany (.DE) alllowed characters
43
+ * @return string
44
+ */
45
+ static function getCharacters()
46
+ {
47
+ return '\x{00E1}\x{00E0}\x{0103}\x{00E2}\x{00E5}\x{00E4}\x{00E3}\x{0105}\x{0101}\x{00E6}\x{0107}' .
48
+ '\x{0109}\x{010D}\x{010B}\x{00E7}\x{010F}\x{0111}\x{00E9}\x{00E8}\x{0115}\x{00EA}\x{011B}' .
49
+ '\x{00EB}\x{0117}\x{0119}\x{0113}\x{011F}\x{011D}\x{0121}\x{0123}\x{0125}\x{0127}\x{00ED}' .
50
+ '\x{00EC}\x{012D}\x{00EE}\x{00EF}\x{0129}\x{012F}\x{012B}\x{0131}\x{0135}\x{0137}\x{013A}' .
51
+ '\x{013E}\x{013C}\x{0142}\x{0144}\x{0148}\x{00F1}\x{0146}\x{014B}\x{00F3}\x{00F2}\x{014F}' .
52
+ '\x{00F4}\x{00F6}\x{0151}\x{00F5}\x{00F8}\x{014D}\x{0153}\x{0138}\x{0155}\x{0159}\x{0157}' .
53
+ '\x{015B}\x{015D}\x{0161}\x{015F}\x{0165}\x{0163}\x{0167}\x{00FA}\x{00F9}\x{016D}\x{00FB}' .
54
+ '\x{016F}\x{00FC}\x{0171}\x{0169}\x{0173}\x{016B}\x{0175}\x{00FD}\x{0177}\x{00FF}\x{017A}' .
55
+ '\x{017E}\x{017C}\x{00F0}\x{00FE}';
56
+ }
57
+
58
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Hostname/Fi.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * SZend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category SZend
17
+ * @package SZend_Validate
18
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Fi.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see SZend_Validate_Hostname_Interface
26
+ */
27
+ require_once dirname(__FILE__) . '/../../Validate/Hostname/Interface.php';
28
+
29
+
30
+ /**
31
+ * @category SZend
32
+ * @package SZend_Validate
33
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class SZend_Validate_Hostname_Fi implements SZend_Validate_Hostname_Interface
37
+ {
38
+
39
+ /**
40
+ * Returns UTF-8 characters allowed in DNS hostnames for the specified Top-Level-Domain
41
+ *
42
+ * @see http://www.ficora.fi/en/index/palvelut/fiverkkotunnukset/aakkostenkaytto.html Finland (.FI)
43
+ * @return string
44
+ */
45
+ static function getCharacters()
46
+ {
47
+ return '\x{00E5}\x{00E4}\x{00F6}';
48
+ }
49
+
50
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Hostname/Hu.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * SZend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category SZend
17
+ * @package SZend_Validate
18
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Hu.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see SZend_Validate_Hostname_Interface
26
+ */
27
+ require_once dirname(__FILE__) . '/../../Validate/Hostname/Interface.php';
28
+
29
+
30
+ /**
31
+ * @category SZend
32
+ * @package SZend_Validate
33
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class SZend_Validate_Hostname_Hu implements SZend_Validate_Hostname_Interface
37
+ {
38
+
39
+ /**
40
+ * Returns UTF-8 characters allowed in DNS hostnames for the specified Top-Level-Domain
41
+ *
42
+ * @see http://www.domain.hu/domain/English/szabalyzat.html Hungary (.HU)
43
+ * @return string
44
+ */
45
+ static function getCharacters()
46
+ {
47
+ return '\x{00E1}\x{00E9}\x{00ED}\x{00F3}\x{00F6}\x{0151}\x{00FA}\x{00FC}\x{0171}';
48
+ }
49
+
50
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Hostname/Interface.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * SZend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category SZend
17
+ * @package SZend_Validate
18
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Interface.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @category SZend
26
+ * @package SZend_Validate
27
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
28
+ * @license http://framework.zend.com/license/new-bsd New BSD License
29
+ */
30
+ interface SZend_Validate_Hostname_Interface
31
+ {
32
+
33
+ /**
34
+ * Returns UTF-8 characters allowed in DNS hostnames for the specified Top-Level-Domain
35
+ *
36
+ * UTF-8 characters should be written as four character hex codes \x{XXXX}
37
+ * For example é (lowercase e with acute) is represented by the hex code \x{00E9}
38
+ *
39
+ * You only need to include lower-case equivalents of characters since the hostname
40
+ * check is case-insensitive
41
+ *
42
+ * Please document the supported TLDs in the documentation file at:
43
+ * manual/en/module_specs/SZend_Validate-Hostname.xml
44
+ *
45
+ * @see http://en.wikipedia.org/wiki/Internationalized_domain_name
46
+ * @see http://www.iana.org/cctld/ Country-Code Top-Level Domains (TLDs)
47
+ * @see http://www.columbia.edu/kermit/utf8-t1.html UTF-8 characters
48
+ * @return string
49
+ */
50
+ static function getCharacters();
51
+
52
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Hostname/Li.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * SZend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category SZend
17
+ * @package SZend_Validate
18
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Li.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see SZend_Validate_Hostname_Interface
26
+ */
27
+ require_once dirname(__FILE__) . '/../../Validate/Hostname/Interface.php';
28
+
29
+
30
+ /**
31
+ * @category SZend
32
+ * @package SZend_Validate
33
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class SZend_Validate_Hostname_Li implements SZend_Validate_Hostname_Interface
37
+ {
38
+
39
+ /**
40
+ * Returns UTF-8 characters allowed in DNS hostnames for the specified Top-Level-Domain
41
+ *
42
+ * @see https://nic.switch.ch/reg/ocView.action?res=EF6GW2JBPVTG67DLNIQXU234MN6SC33JNQQGI7L6#anhang1 Liechtenstein (.LI)
43
+ * @return string
44
+ */
45
+ static function getCharacters()
46
+ {
47
+ return '\x{00EO}-\x{00F6}\x{00F8}-\x{00FF}\x{0153}';
48
+ }
49
+
50
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Hostname/No.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * SZend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category SZend
17
+ * @package SZend_Validate
18
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: No.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see SZend_Validate_Hostname_Interface
26
+ */
27
+ require_once dirname(__FILE__) . '/../../Validate/Hostname/Interface.php';
28
+
29
+
30
+ /**
31
+ * @category SZend
32
+ * @package SZend_Validate
33
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class SZend_Validate_Hostname_No implements SZend_Validate_Hostname_Interface
37
+ {
38
+
39
+ /**
40
+ * Returns UTF-8 characters allowed in DNS hostnames for the specified Top-Level-Domain
41
+ *
42
+ * @see http://www.norid.no/domeneregistrering/idn/idn_nyetegn.en.html Norway (.NO)
43
+ * @return string
44
+ */
45
+ static function getCharacters()
46
+ {
47
+ return '\x00E1\x00E0\x00E4\x010D\x00E7\x0111\x00E9\x00E8\x00EA\x\x014B' .
48
+ '\x0144\x00F1\x00F3\x00F2\x00F4\x00F6\x0161\x0167\x00FC\x017E\x00E6' .
49
+ '\x00F8\x00E5';
50
+ }
51
+
52
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Hostname/Se.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * SZend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category SZend
17
+ * @package SZend_Validate
18
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Se.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see SZend_Validate_Hostname_Interface
26
+ */
27
+ require_once dirname(__FILE__) . '/../../Validate/Hostname/Interface.php';
28
+
29
+
30
+ /**
31
+ * @category SZend
32
+ * @package SZend_Validate
33
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class SZend_Validate_Hostname_Se implements SZend_Validate_Hostname_Interface
37
+ {
38
+
39
+ /**
40
+ * Returns UTF-8 characters allowed in DNS hostnames for the specified Top-Level-Domain
41
+ *
42
+ * @see http://www.iis.se/english/IDN_campaignsite.shtml?lang=en Sweden (.SE)
43
+ * @return string
44
+ */
45
+ static function getCharacters()
46
+ {
47
+ return '\x{00E5}\x{00E4}\x{00F6}\x{00FC}\x{00E9}';
48
+ }
49
+
50
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Interface.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SZend Framework
4
+ *
5
+ * LICENSE
6
+ *
7
+ * This source file is subject to the new BSD license that is bundled
8
+ * with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://framework.zend.com/license/new-bsd
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@zend.com so we can send you a copy immediately.
14
+ *
15
+ * @category SZend
16
+ * @package SZend_Validate
17
+ * @copyright Copyright (c) 2005-2011 SZend Technologies USA Inc. (http://www.zend.com)
18
+ * @license http://framework.zend.com/license/new-bsd New BSD License
19
+ * @version $Id: Interface.php 23775 2011-03-01 17:25:24Z ralph $
20
+ */
21
+
22
+ /**
23
+ * @category SZend
24
+ * @package SZend_Validate
25
+ * @copyright Copyright (c) 2005-2011 SZend Technologies USA Inc. (http://www.zend.com)
26
+ * @license http://framework.zend.com/license/new-bsd New BSD License
27
+ */
28
+ interface SZend_Validate_Interface
29
+ {
30
+ /**
31
+ * Returns true if and only if $value meets the validation requirements
32
+ *
33
+ * If $value fails validation, then this method returns false, and
34
+ * getMessages() will return an array of messages that explain why the
35
+ * validation failed.
36
+ *
37
+ * @param mixed $value
38
+ * @return boolean
39
+ * @throws SZend_Validate_Exception If validation of $value is impossible
40
+ */
41
+ public function isValid($value);
42
+
43
+ /**
44
+ * Returns an array of messages that explain why the most recent isValid()
45
+ * call returned false. The array keys are validation failure message identifiers,
46
+ * and the array values are the corresponding human-readable message strings.
47
+ *
48
+ * If isValid() was never called or if the most recent isValid() call
49
+ * returned true, then this method returns an empty array.
50
+ *
51
+ * @return array
52
+ */
53
+ public function getMessages();
54
+ }
app/code/local/SPM/ShopyMind/ShopymindClient/src/library/SZend/Validate/Ip.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * SZend Framework
5
+ *
6
+ * LICENSE
7
+ *
8
+ * This source file is subject to the new BSD license that is bundled
9
+ * with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://framework.zend.com/license/new-bsd
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@zend.com so we can send you a copy immediately.
15
+ *
16
+ * @category SZend
17
+ * @package SZend_Validate
18
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
19
+ * @license http://framework.zend.com/license/new-bsd New BSD License
20
+ * @version $Id: Ip.php 8064 2008-02-16 10:58:39Z thomas $
21
+ */
22
+
23
+
24
+ /**
25
+ * @see SZend_Validate_Abstract
26
+ */
27
+ require_once dirname(__FILE__) . '/../Validate/Abstract.php';
28
+
29
+
30
+ /**
31
+ * @category SZend
32
+ * @package SZend_Validate
33
+ * @copyright Copyright (c) 2005-2008 SZend Technologies USA Inc. (http://www.zend.com)
34
+ * @license http://framework.zend.com/license/new-bsd New BSD License
35
+ */
36
+ class SZend_Validate_Ip extends SZend_Validate_Abstract
37
+ {
38
+
39
+ const NOT_IP_ADDRESS = 'notIpAddress';
40
+
41
+ /**
42
+ * @var array
43
+ */
44
+ protected $_messageTemplates = array(
45
+ self::NOT_IP_ADDRESS => "'%value%' does not appear to be a valid IP address"
46
+ );
47
+
48
+ /**
49
+ * Defined by SZend_Validate_Interface
50
+ *
51
+ * Returns true if and only if $value is a valid IP address
52
+ *
53
+ * @param mixed $value
54
+ * @return boolean
55
+ */
56
+ public function isValid($value)
57
+ {
58
+ $valueString = (string) $value;
59
+
60
+ $this->_setValue($valueString);
61
+
62
+ if (ip2long($valueString) === false) {
63
+ $this->_error();
64
+ return false;
65
+ }
66
+
67
+ return true;
68
+ }
69
+
70
+ }
app/code/local/SPM/ShopyMind/controllers/Adminhtml/ConfigurationController.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class SPM_ShopyMind_Adminhtml_ConfigurationController extends Mage_Adminhtml_Controller_Action
4
+ {
5
+ public function indexAction()
6
+ {
7
+ if(!is_writable(Mage::getBaseDir('base').'/app/code/local/SPM/ShopyMind/ShopymindClient/configuration.php')) {
8
+ Mage::getSingleton('adminhtml/session')->addError($this->__('File').' '.realpath(Mage::getBaseDir('base').'/app/code/local/SPM/ShopyMind/ShopymindClient/configuration.php').' '.$this->__('need to be writable'));
9
+ }
10
+ if(!function_exists('curl_init')) {
11
+ Mage::getSingleton('adminhtml/session')->addError($this->__('Shopymind needs the PHP Curl extension, please ask your hosting provider to enable it prior to use this module.'));
12
+ }
13
+ $this->loadLayout()->renderLayout();
14
+ }
15
+
16
+ public function postAction()
17
+ {
18
+ $post = $this->getRequest()->getPost();
19
+ try {
20
+ if (empty($post)) {
21
+ Mage::throwException($this->__('Invalid form data.'));
22
+ }
23
+
24
+ $config = new Mage_Core_Model_Config();
25
+ /* here's your form processing */
26
+ $config->saveConfig('shopymind/configuration/apiidentification', $_POST['SPMForm']['apiIdentification'], 'default', 0 );
27
+ $config->saveConfig('shopymind/configuration/apipassword', $_POST['SPMForm']['apiPassword'], 'default', 0 );
28
+ $config->saveConfig('shopymind/configuration/birthrequired', $_POST['SPMForm']['birthRequired'], 'default', 0 );
29
+ if($_POST['SPMForm']['birthRequired'] == 'yes') {
30
+
31
+ $settings = array (
32
+ 'is_required'=> 1,
33
+ 'is_visible' => true
34
+ );
35
+ $config->saveConfig('customer/address/dob_show', 'req', 'default', 0 );
36
+ }
37
+ else {
38
+ $settings = array (
39
+ 'is_required'=> 0,
40
+ 'is_visible' => true
41
+ );
42
+ $config->saveConfig('customer/address/dob_show', 'opt', 'default', 0 );
43
+ }
44
+ $setup = new Mage_Eav_Model_Entity_Setup('core_setup');
45
+ $AttrCode = 'dob';
46
+ $setup->updateAttribute('1', $AttrCode, $settings);
47
+ $config->reinit();
48
+ Mage::app()->reinitStores();
49
+ if(file_exists(Mage::getBaseDir('base').'/app/code/local/SPM/ShopyMind/ShopymindClient/bin/Configuration.php')) {
50
+ //Include
51
+ include(Mage::getBaseDir('base').'/app/code/local/SPM/ShopyMind/ShopymindClient/bin/Configuration.php');
52
+ //Récupération d'un instance et renseignement des paramètres
53
+ $config = ShopymindClient_Configuration::factory($_POST['SPMForm']['apiIdentification'], $_POST['SPMForm']['apiPassword'], $_POST['SPMForm']['defaultLang'], $_POST['SPMForm']['defaultCurrency'],$_POST['SPMForm']['contactPage'],$_POST['SPMForm']['phoneNumber'],$_POST['SPMForm']['timezone']);
54
+ //Test de la connection au server SPM
55
+ if(!$config->saveConfig()) {
56
+ Mage::throwException($this->__('Error when save config'));
57
+ }
58
+ else {
59
+ //Sauvegarde du fichier de configuration
60
+ if(!$config->testConnection())
61
+ Mage::throwException($this->__('Error when test connection'));
62
+ else {
63
+ //Connexion au serveur et sauvegarde des informations
64
+ $connect = $config->connectServer();
65
+ if($connect !== true) {
66
+ Mage::throwException($this->__('Error when connect to server'));
67
+ }else {
68
+ $message = $this->__('Your form has been submitted successfully.');
69
+ Mage::getSingleton('adminhtml/session')->addSuccess($message);
70
+ }
71
+ }
72
+ }
73
+ }
74
+
75
+ } catch (Exception $e) {
76
+ Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
77
+ }
78
+ $this->_redirect('*/*');
79
+ }
80
+ }
app/code/local/SPM/ShopyMind/etc/config.xml ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <SPM_ShopyMind>
5
+ <version>1.0.2</version>
6
+ </SPM_ShopyMind>
7
+ </modules>
8
+
9
+ <global>
10
+ <resources>
11
+ <shopymind_setup>
12
+ <!-- ajout du setup pour le module. Le dossier SQL du module contiendra un dossier avec ce nom "scriptsql_setup"-->
13
+ <setup>
14
+ <module>SPM_ShopyMind</module>
15
+ </setup>
16
+ <connection> <use>core_setup</use> </connection>
17
+ </shopymind_setup>
18
+ </resources>
19
+ <blocks>
20
+ <shopymind>
21
+ <class>SPM_ShopyMind_Block</class>
22
+ </shopymind>
23
+ </blocks>
24
+ <helpers>
25
+ <shopymind>
26
+ <class>SPM_ShopyMind_Helper</class>
27
+ </shopymind>
28
+ </helpers>
29
+ <models>
30
+ <shopymind>
31
+ <class>SPM_ShopyMind_Model</class>
32
+ </shopymind>
33
+ </models>
34
+ <events>
35
+ <sales_order_invoice_pay>
36
+ <observers>
37
+ <SPM_ShopyMind_Model_Observer>
38
+ <type>singleton</type>
39
+ <class>shopymind/observer</class>
40
+ <method>newOrderObserver</method>
41
+ </SPM_ShopyMind_Model_Observer>
42
+ </observers>
43
+ </sales_order_invoice_pay>
44
+
45
+ <controller_front_init_before>
46
+ <observers>
47
+ <SPM_ShopyMind_Model_Observer>
48
+ <type>singleton</type>
49
+ <class>shopymind/observer</class>
50
+ <method>checkIsSPMUser</method>
51
+ </SPM_ShopyMind_Model_Observer>
52
+ </observers>
53
+ </controller_front_init_before>
54
+ <controller_action_layout_generate_blocks_before>
55
+ <observers>
56
+ <SPM_ShopyMind_Model_Observer>
57
+ <type>singleton</type>
58
+ <class>shopymind/observer</class>
59
+ <method>frontCheck</method>
60
+ </SPM_ShopyMind_Model_Observer>
61
+ </observers>
62
+ </controller_action_layout_generate_blocks_before>
63
+ </events>
64
+ </global>
65
+
66
+ <admin>
67
+ <routers>
68
+ <shopymind>
69
+ <use>admin</use>
70
+ <args>
71
+ <module>SPM_ShopyMind</module>
72
+ <frontName>shopymind</frontName>
73
+ </args>
74
+ </shopymind>
75
+ </routers>
76
+ </admin>
77
+
78
+ <adminhtml>
79
+ <translate>
80
+ <modules>
81
+ <spm_adminhtml>
82
+ <files>
83
+ <shopymind>SPM_ShopyMind.csv</shopymind>
84
+ </files>
85
+ </spm_adminhtml>
86
+ </modules>
87
+ </translate>
88
+
89
+ <menu>
90
+ <shopymind_adminform translate="title" module="shopymind">
91
+ <title>ShopyMind</title>
92
+ <sort_order>100</sort_order>
93
+ <action>shopymind/adminhtml_configuration</action>
94
+ </shopymind_adminform>
95
+ </menu>
96
+
97
+ <acl>
98
+ <resources>
99
+ <admin>
100
+ <children>
101
+ <catalog>
102
+ <children>
103
+ <shopymind_adminform>
104
+ <title>My Form</title>
105
+ </shopymind_adminform>
106
+ </children>
107
+ </catalog>
108
+ </children>
109
+ </admin>
110
+ </resources>
111
+ </acl>
112
+
113
+ <layout>
114
+ <updates>
115
+ <shopymind>
116
+ <file>shopymind.xml</file>
117
+ </shopymind>
118
+ </updates>
119
+ </layout>
120
+ </adminhtml>
121
+ <frontend>
122
+ <layout>
123
+ <updates>
124
+ <shopymind>
125
+ <file>shopymind.xml</file>
126
+ </shopymind>
127
+ </updates>
128
+ </layout>
129
+ </frontend>
130
+ </config>
app/code/local/SPM/ShopyMind/sql/shopymind_setup/mysql4-install-1.0.2.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $installer = $this;
3
+ $installer->startSetup();
4
+ $installer->run ( "CREATE TABLE IF NOT EXISTS {$this->getTable('spmcartoorder')} (`id_cart` int(10) unsigned NOT NULL,`id_customer` int(10) unsigned NOT NULL DEFAULT '0',`id_order` int(10) unsigned NOT NULL DEFAULT '0',`spm_key` varchar(40) COLLATE utf8_bin NOT NULL DEFAULT '',`is_converted` tinyint(1) unsigned NOT NULL DEFAULT '0',`date_add` datetime NOT NULL,`date_upd` datetime NOT NULL,PRIMARY KEY (`spm_key`),KEY `is_converted` (`is_converted`),KEY `date_upd` (`date_upd`),KEY `date_add` (`date_add`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;" );
5
+ $installer->getConnection()->addColumn(
6
+ $installer->getTable('spmcartoorder'),
7
+ 'email',
8
+ array(
9
+ 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
10
+ 'length' => 255,
11
+ 'unsigned' => true,
12
+ 'nullable' => true,
13
+ 'comment' => 'Customer email'
14
+ )
15
+ );
16
+ $installer->getConnection()->addIndex($installer->getTable('spmcartoorder'), 'email', 'email');
17
+
18
+ $installer->getConnection()->addColumn(
19
+ $installer->getTable('spmcartoorder'),
20
+ 'voucher_number',
21
+ array(
22
+ 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
23
+ 'length' => 20,
24
+ 'unsigned' => true,
25
+ 'nullable' => true,
26
+ 'comment' => 'Voucher used'
27
+ )
28
+ );
29
+ $installer->getConnection()->addIndex($installer->getTable('spmcartoorder'), 'voucher_number', 'voucher_number');
30
+ $installer->endSetup();
31
+ ?>
app/code/local/SPM/ShopyMind/sql/shopymind_setup/upgrade-1.0.1-1.0.2.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $installer = $this;
3
+ $installer->startSetup();
4
+ $installer->run ( "CREATE TABLE IF NOT EXISTS {$this->getTable('spmcartoorder')} (`id_cart` int(10) unsigned NOT NULL,`id_customer` int(10) unsigned NOT NULL DEFAULT '0',`id_order` int(10) unsigned NOT NULL DEFAULT '0',`spm_key` varchar(40) COLLATE utf8_bin NOT NULL DEFAULT '',`is_converted` tinyint(1) unsigned NOT NULL DEFAULT '0',`date_add` datetime NOT NULL,`date_upd` datetime NOT NULL,PRIMARY KEY (`spm_key`),KEY `is_converted` (`is_converted`),KEY `date_upd` (`date_upd`),KEY `date_add` (`date_add`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;" );
5
+ $installer->getConnection()->addColumn(
6
+ $installer->getTable('spmcartoorder'),
7
+ 'email',
8
+ array(
9
+ 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
10
+ 'length' => 255,
11
+ 'unsigned' => true,
12
+ 'nullable' => true,
13
+ 'comment' => 'Customer email'
14
+ )
15
+ );
16
+ $installer->getConnection()->addIndex($installer->getTable('spmcartoorder'), 'email', 'email');
17
+
18
+ $installer->getConnection()->addColumn(
19
+ $installer->getTable('spmcartoorder'),
20
+ 'voucher_number',
21
+ array(
22
+ 'type' => Varien_Db_Ddl_Table::TYPE_TEXT,
23
+ 'length' => 20,
24
+ 'unsigned' => true,
25
+ 'nullable' => true,
26
+ 'comment' => 'Voucher used'
27
+ )
28
+ );
29
+ $installer->getConnection()->addIndex($installer->getTable('spmcartoorder'), 'voucher_number', 'voucher_number');
30
+ $installer->endSetup();
31
+ ?>
app/design/adminhtml/default/default/layout/shopymind.xml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <layout>
3
+ <shopymind_adminhtml_configuration_index>
4
+ <update handle="shopymind_configuration_index"/>
5
+ <reference name="content">
6
+ <block type="adminhtml/template" name="configuration" template="shopymind/configuration.phtml"/>
7
+ </reference>
8
+ </shopymind_adminhtml_configuration_index>
9
+ </layout>
app/design/adminhtml/default/default/template/shopymind/configuration.phtml ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <br /><br /><div style="text-align:center;"><a href="http://www.shopymind.com/" target="_blank"><img src="http://media.shopymind.com/img/logo.png" /></a></div><br /><br /><ul class="messages"><li class="notice-msg"><?=$this->__('Afin d\'utiliser shopymind, vous devez créer un compte gratuitement');?> <a href="http://client.shopymind.com/registration/speed" target="_blank"><?=$this->__('en cliquant ici');?></a></li></ul>
2
+ <div class="content-header">
3
+ <table cellspacing="0" class="grid-header">
4
+ <tr>
5
+ <td><h3><?=$this->__('ShopyMind Configuration')?></h3></td>
6
+ <td class="a-right">
7
+ <button onclick="editForm.submit()" class="scalable save" type="button"><span><?=$this->__('Send')?></span></button>
8
+ </td>
9
+ </tr>
10
+ </table>
11
+ </div>
12
+ <div class="entry-edit">
13
+
14
+ <form id="edit_form" name="edit_form" method="post" action="<?=$this->getUrl('*/*/post')?>">
15
+ <input name="form_key" type="hidden" value="<?php echo Mage::getSingleton('core/session')->getFormKey() ?>" />
16
+ <input name="SPMForm[defaultLang]" type="hidden" value="<?php echo substr(Mage::app()->getLocale()->getDefaultLocale(),0,2) ?>" />
17
+ <input name="SPMForm[defaultCurrency]" type="hidden" value="<?php echo Mage::app()->getStore()->getDefaultCurrencyCode() ?>" />
18
+ <input name="SPMForm[contactPage]" type="hidden" value="<?php echo Mage::getUrl('contacts') ?>" />
19
+ <input name="SPMForm[phoneNumber]" type="hidden" value="<?php echo Mage::getStoreConfig('general/store_information/phone') ?>" />
20
+ <input name="SPMForm[timezone]" type="hidden" value="<?php echo Mage::getStoreConfig('general/locale/timezone') ?>" />
21
+ <h4 class="icon-head head-edit-form fieldset-legend"><?=$this->__('Login Information')?></h4>
22
+ <fieldset id="spm_login">
23
+ <table cellspacing="0" class="form-list">
24
+ <tr>
25
+ <td class="label"><?=$this->__('API key')?> <span class="required">*</span></td>
26
+ <td class="value"><input class="input-text required-entry" name="SPMForm[apiIdentification]" value="<?=htmlentities(Mage::getStoreConfig('shopymind/configuration/apiidentification'),ENT_COMPAT,'UTF-8');?>" /></td>
27
+ </tr>
28
+ <tr>
29
+ <td class="label"><?=$this->__('API password')?> <span class="required">*</span></td>
30
+ <td class="value"><input type="password" class="input-text required-entry" name="SPMForm[apiPassword]" value="<?=htmlentities(Mage::getStoreConfig('shopymind/configuration/apipassword'),ENT_COMPAT,'UTF-8');?>" /></td>
31
+ </tr>
32
+ </table>
33
+ </fieldset>
34
+ <h4 class="icon-head head-edit-form fieldset-legend"><?=$this->__('Configuration')?></h4>
35
+ <fieldset id="spm_login">
36
+ <table cellspacing="0" class="form-list">
37
+ <tr>
38
+ <td class="label"><?=$this->__('Make the field date of birth required')?></td>
39
+ <td class="value"><select class="select required-entry" name="SPMForm[birthRequired]"><option value="no"<?=(Mage::getStoreConfig('shopymind/configuration/birthrequired') == 'no'? ' selected="selected"':'')?>><?=$this->__('No')?></option><option value="yes"<?=(!Mage::getStoreConfig('shopymind/configuration/birthrequired') || Mage::getStoreConfig('shopymind/configuration/birthrequired') == 'yes'? ' selected="selected"':'')?>><?=$this->__('Yes')?></option></select>
40
+ <p class="note"><span><strong style="color:red"><?=$this->__('Recommended')?></strong></span></p>
41
+ </td>
42
+ </tr>
43
+ </table>
44
+ </fieldset>
45
+ </form>
46
+ </div>
47
+ <script type="text/javascript">
48
+ var editForm = new varienForm('edit_form');
49
+ </script>
app/design/frontend/base/default/layout/shopymind.xml ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Magento
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Open Software License (OSL 3.0)
9
+ * that is bundled with this package in the file LICENSE.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/osl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@magentocommerce.com so we can send you a copy immediately.
15
+ *
16
+ * @category design
17
+ * @package base_default
18
+ * @copyright Copyright (c) 2011 Phoenix Medien GmbH & Co. KG (http://www.phoenix-medien.de)
19
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
20
+ */
21
+
22
+ -->
23
+ <layout version="0.1.0">
24
+ <default>
25
+ <reference name="footer">
26
+ <action method="unsetData"><key>cache_lifetime</key></action>
27
+ <action method="unsetData"><key>cache_tags</key></action>
28
+ <block type="core/template" name="shopymind_footer" template="shopymind/footer.phtml" />
29
+ </reference>
30
+ </default>
31
+ </layout>
app/design/frontend/base/default/template/shopymind/footer.phtml ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if(Mage::getSingleton('customer/session')->isLoggedIn()) {
3
+ $cookie = Mage::app()->getCookie();
4
+
5
+ $email = Mage::getSingleton('customer/session')->getCustomer()->getEmail();
6
+ $subscriber = Mage::getModel('newsletter/subscriber')->loadByEmail($email);
7
+ if($subscriber->isSubscribed()) {
8
+ $customer = Mage::helper('customer')->getCustomer()->getData();
9
+ $params = array(
10
+ 'last_name' => @$customer['lastname'],
11
+ 'first_name' => @$customer['firstname'],
12
+ 'email_address' => @$customer['email'],
13
+ 'birthday' => @$customer['dob'],
14
+ 'locale' => self::getUserLocale($customer['entity_id'],$customer['store_id']),
15
+ 'gender' => @$customer['gender'],
16
+ 'ip' => Mage::helper('core/http')->getRemoteAddr()
17
+ );
18
+ $signature = sha1(serialize($params));
19
+ if($cookie->get('spmoptinchecksum') != '' && $cookie->get('spmoptinchecksum') == $signature) {
20
+ return;
21
+ }
22
+ $optinkey = ShopymindClient_Notify::addOptInClient($params);
23
+ if($optinkey) {
24
+ $cookie->set('spmoptinchecksum', $signature, ((3600*24)*365));
25
+ echo '<img src="http://client.shopymind.com/optin/'.$optinkey.'.png" style="display:none;" />';
26
+ }
27
+ }
28
+ }
29
+
30
+ ?>
app/etc/modules/SPM_ShopyMind.xml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <SPM_ShopyMind>
5
+ <active>true</active>
6
+ <codePool>local</codePool>
7
+ </SPM_ShopyMind>
8
+ </modules>
9
+ </config>
package.xml ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>shopymind</name>
4
+ <version>1.0.2</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://opensource.org/licenses/GPL-3.0">GPL v3.0</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Connecteur pour le service d'email marketing ShopyMind</summary>
10
+ <description>Connecteur pour le service d'email marketing ShopyMind</description>
11
+ <notes>Compatibilit&#xE9; guest order&#xD;
12
+ Prise en charge fonctionnalit&#xE9;s de segmentation avanc&#xE9;es</notes>
13
+ <authors><author><name>Jean-S&#xE9;bastien</name><user>shopymind</user><email>contact@shopymind.com</email></author></authors>
14
+ <date>2014-04-07</date>
15
+ <time>15:57:45</time>
16
+ <contents><target name="magelocal"><dir name="SPM"><dir name="ShopyMind"><dir name="Block"><file name="Configuration.php" hash="d41d8cd98f00b204e9800998ecf8427e"/></dir><dir name="Helper"><file name="Data.php" hash="233ff6d4066636dfe76a6d0fcc3837ea"/></dir><dir name="Model"><file name="Observer.php" hash="e301e143c0484d7398c8e4602a4841f0"/></dir><dir name="ShopymindClient"><dir name="bin"><file name="Configuration.php" hash="f3d0cef466e2394cb822ac27e003951e"/><file name="Notify.php" hash="1c1d359da754b2abe0ab874ef43e535b"/><file name="RequestServer.php" hash="98f6647a822f8c3b81fa5b1e1b9befee"/></dir><file name="call.php" hash="42e156192ce1399a3304918e0e399898"/><file name="callback.php" hash="79c59da98f597a08c003c196b291b736"/><file name="configuration.php" hash="8bceaafd452353a9d354ecd1edb197b3"/><dir name="doc"><file name="CHANGELOG.md" hash="83e5eac956d477a6d375c39a7f2d786f"/><file name="README.md" hash="fb69c4a24b741a83ce6d52f737e27188"/></dir><dir name="src"><file name="Client.php" hash="dd15a8676a86cd2b43085a57ce97b696"/><dir name="Reminders"><file name="Abstract.php" hash="50931470009af2fa17b8ed0f0cbda115"/><file name="BirthdayClients.php" hash="83ade73e1b70e8b7e6534890f6929d52"/><file name="DroppedOutCart.php" hash="6534d4a827131294a29389addf7eb0fa"/><file name="GoodClientsByAmount.php" hash="dd2d1d7fd57bfb04cc3ecf2d0b81edf9"/><file name="GoodClientsByNumberOrders.php" hash="7a7a8e82e4527efb7c582edd0441abbd"/><file name="MissingClients.php" hash="eaef3516c7e02c5f60fba29234f81fb4"/><file name="OrdersByStatus.php" hash="998d5a9a571cc50d839c0d5fd313731a"/><file name="VoucherUnused.php" hash="64c1258b19d80cf5d444875c194dcb27"/></dir><file name="Server.php" hash="16454422468e0e4ef20dc52638f0e3f5"/><file name="definitions.php" hash="fc658b642d678ba252304cd073652fe4"/><dir name="library"><dir name="SZend"><dir name="Controller"><file name="Exception.php" hash="f1237afdaffbd144257b107770618eac"/><dir name="Request"><file name="Abstract.php" hash="54596831d5dc5fda331e393b8a478379"/><file name="Exception.php" hash="cc838555e9115befa50dc1af49b17577"/><file name="Http.php" hash="4dd5b595b9fc44e815040e2e6ba689ba"/></dir></dir><file name="Exception.php" hash="2bf61e21546b8f0aa3b2769355f2dc7e"/><dir name="Http"><dir name="Client"><dir name="Adapter"><file name="Exception.php" hash="2537f0b6f539f8e48c038324a0d628e8"/><file name="Interface.php" hash="d999c7f241a1f19af0e8865cb9b5d10d"/><file name="Proxy.php" hash="4981dc0fcd46adb3a43af4eac257d8e9"/><file name="Socket.php" hash="9ebca7242be11891ebd9bc49209ff09b"/><file name="Test.php" hash="176910209997f08742c9b01bbc3d5a7c"/></dir><file name="Exception.php" hash="6e1996a825c541b3b88e3d85e85a20ba"/></dir><file name="Client.php" hash="f2242e7dd86105a877ad5aa0d12e4f50"/><file name="Exception.php" hash="1fa7eabe51eecc8296610f3767215413"/><file name="Response.php" hash="fb8acaa8d9c3993ecc01efce0b372ae6"/></dir><dir name="Json"><file name="Decoder.php" hash="5d93754ec797bad1a110728389c3ee8c"/><file name="Encoder.php" hash="a84449a2792fad49e7d1aa7d783ec174"/><file name="Exception.php" hash="96e6fefe64b68c5ef4848af6d0bb4e82"/></dir><file name="Json.php" hash="0695e495093dbfa46fb57e7ad9579aac"/><file name="Loader.php" hash="5e3ae1b4235fcb6aad2a67ea98f3d2b8"/><dir name="Uri"><file name="Exception.php" hash="3883d68acc73300df64e1c985c57cf75"/><file name="Http.php" hash="e956bd37f9ec96b19d3429fbe8d50f09"/></dir><file name="Uri.php" hash="8a04b4728ad7b609143e9060e110e1d1"/><dir name="Validate"><file name="Abstract.php" hash="c5e7fafa362afe2809abfd63a481d46b"/><dir name="Hostname"><file name="At.php" hash="0e553eeab4854d0acc2b278a83e6ae4d"/><file name="Ch.php" hash="56959ede41ad28062c0a02c35a6325bd"/><file name="De.php" hash="860ad7d2c007980dcc9935ffafdfb47f"/><file name="Fi.php" hash="46b399d55d8f6d60eace39a9d04a0a20"/><file name="Hu.php" hash="aace5a75ab79a6b3730cdcd500b9cfbb"/><file name="Interface.php" hash="5e04ae45e72d695d45d19d4893722718"/><file name="Li.php" hash="ea875839c91646e73ef3e75a2da27a2e"/><file name="No.php" hash="42f57854fe2f265c48d131b999535a4c"/><file name="Se.php" hash="3ab64c0f1c4a8d404c2b92f40d8b9c49"/></dir><file name="Hostname.php" hash="2d8942bfa2d462f712c16e9bbbd7a637"/><file name="Interface.php" hash="2269e3299d88d13b1e73ba3f0b8c9619"/><file name="Ip.php" hash="3f12e46be79290359362e65f829ff52d"/></dir></dir></dir></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="ConfigurationController.php" hash="30e6fdc25bf5ebc63d332173fa3341e7"/></dir></dir><dir name="etc"><file name="config.xml" hash="49bd477f361d7d3ec7d2e8a2f83d34b1"/></dir><dir name="sql"><dir name="shopymind_setup"><file name="mysql4-install-1.0.2.php" hash="8c0be5e2d86533c6789f59571ae35295"/><file name="upgrade-1.0.0-1.0.1.php" hash=""/><file name="upgrade-1.0.1-1.0.2.php" hash="8c0be5e2d86533c6789f59571ae35295"/></dir></dir><file name=".htaccess" hash="a04a22aa9c4e19789afcc2d4f1b23fce"/></dir></dir></target><target name="mageetc"><dir name="modules"><file name="SPM_ShopyMind.xml" hash="33bac8c042bc58f7d15565e8e95a8d25"/></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="shopymind.xml" hash="cf7214ff0b2df43a38908b53e8ab92ff"/></dir><dir name="template"><dir name="shopymind"><file name="configuration.phtml" hash="177d33849e46e5700f157a121331d7a3"/></dir></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="shopymind.xml" hash="707507d1f3dca58ba918eb2dec3a276f"/></dir><dir name="template"><dir name="shopymind"><file name="footer.phtml" hash="3538f2a0052c65aeb1e7887fe47fe828"/></dir></dir></dir></dir></dir></target></contents>
17
+ <compatible/>
18
+ <dependencies><required><php><min>5.0.0</min><max>6.0.0</max></php></required></dependencies>
19
+ </package>