Version Notes
- Translation service improvement - display international pages under the domestic store domain
Download this release
Release Info
Developer | Webinterpret |
Extension | Webinterpret_Connector |
Version | 1.3.0.0 |
Comparing to | |
See all releases |
Code changes from version 1.2.7.7 to 1.3.0.0
- app/code/community/Webinterpret/Connector/Helper/Data.php +53 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Browser.php +195 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Client/AbstractClient.php +73 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Client/AbstractCurl.php +232 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Client/AbstractStream.php +45 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Client/BatchClientInterface.php +27 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Client/ClientInterface.php +20 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Client/Curl.php +60 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Client/FileGetContents.php +51 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Client/MultiCurl.php +114 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Exception/ClientException.php +10 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Exception/ExceptionInterface.php +10 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Exception/InvalidArgumentException.php +10 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Exception/LogicException.php +10 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Exception/RequestException.php +32 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Exception/RuntimeException.php +7 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Listener/BasicAuthListener.php +27 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Listener/CallbackListener.php +49 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Listener/CookieListener.php +50 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Listener/DigestAuthListener.php +837 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Listener/History/Entry.php +42 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Listener/History/Journal.php +76 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Listener/HistoryListener.php +33 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Listener/ListenerChain.php +40 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Listener/ListenerInterface.php +12 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Listener/LoggerListener.php +36 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Message/AbstractMessage.php +154 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Message/Factory/Factory.php +26 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Message/Factory/FactoryInterface.php +12 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Message/Form/FormRequest.php +187 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Message/Form/FormRequestInterface.php +27 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Message/Form/FormUpload.php +118 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Message/Form/FormUploadInterface.php +13 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Message/MessageInterface.php +74 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Message/Request.php +174 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Message/RequestInterface.php +75 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Message/Response.php +193 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Util/Cookie.php +216 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Util/CookieJar.php +79 -0
- app/code/community/Webinterpret/Connector/Lib/Buzz/Util/Url.php +190 -0
- app/code/community/Webinterpret/Connector/Model/StoreExtender.php +198 -0
- app/code/community/Webinterpret/Connector/controllers/IndexController.php +12 -0
- app/code/community/Webinterpret/Connector/etc/config.xml +33 -2
- app/design/frontend/base/default/template/webinterpret/connector/product_view.phtml +1 -0
- package.xml +5 -8
app/code/community/Webinterpret/Connector/Helper/Data.php
CHANGED
@@ -133,6 +133,11 @@ class Webinterpret_Connector_Helper_Data extends Mage_Core_Helper_Abstract
|
|
133 |
return (bool)Mage::getStoreConfig('webinterpret_connector/global_notifications_enabled');
|
134 |
}
|
135 |
|
|
|
|
|
|
|
|
|
|
|
136 |
public function isFooterEnabled()
|
137 |
{
|
138 |
$module = $this->isEnabled();
|
@@ -452,4 +457,52 @@ class Webinterpret_Connector_Helper_Data extends Mage_Core_Helper_Abstract
|
|
452 |
{
|
453 |
return (string) Mage::getConfig()->getNode()->modules->Webinterpret_Connector->version;
|
454 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
455 |
}
|
133 |
return (bool)Mage::getStoreConfig('webinterpret_connector/global_notifications_enabled');
|
134 |
}
|
135 |
|
136 |
+
public function isStoreExtenderEnabled()
|
137 |
+
{
|
138 |
+
return (bool)Mage::getStoreConfig('webinterpret_connector/store_extender_enabled');
|
139 |
+
}
|
140 |
+
|
141 |
public function isFooterEnabled()
|
142 |
{
|
143 |
$module = $this->isEnabled();
|
457 |
{
|
458 |
return (string) Mage::getConfig()->getNode()->modules->Webinterpret_Connector->version;
|
459 |
}
|
460 |
+
|
461 |
+
/**
|
462 |
+
* @return bool
|
463 |
+
* @throws \Exception
|
464 |
+
*/
|
465 |
+
public function verifyRequest() {
|
466 |
+
if (!function_exists( 'openssl_verify')) {
|
467 |
+
throw new \Exception('OpenSSL is required.');
|
468 |
+
}
|
469 |
+
|
470 |
+
$requestId = $_SERVER['HTTP_WEBINTERPRET_REQUEST_ID'];
|
471 |
+
$signature = $_SERVER['HTTP_WEBINTERPRET_SIGNATURE'];
|
472 |
+
$signature = base64_decode( $signature );
|
473 |
+
|
474 |
+
$version = $_SERVER['HTTP_WEBINTERPRET_SIGNATURE_VERSION'];
|
475 |
+
if (empty( $version )) {
|
476 |
+
$version = 1;
|
477 |
+
}
|
478 |
+
|
479 |
+
// Data
|
480 |
+
$data = $requestId;
|
481 |
+
if ($version == 2) {
|
482 |
+
// Query data
|
483 |
+
$queryArray = $_GET;
|
484 |
+
ksort($queryArray);
|
485 |
+
$queryData = serialize($queryArray);
|
486 |
+
|
487 |
+
// Post data
|
488 |
+
$postData = $_POST;
|
489 |
+
ksort($postData);
|
490 |
+
$postData = serialize($postData);
|
491 |
+
|
492 |
+
$data = $requestId . $queryData . $postData;
|
493 |
+
}
|
494 |
+
|
495 |
+
// Verify signature
|
496 |
+
$public_key = Mage::getStoreConfig('webinterpret_connector/public_key');
|
497 |
+
$ok = openssl_verify($data, $signature, $public_key, OPENSSL_ALGO_SHA1);
|
498 |
+
|
499 |
+
if ($ok == 1) {
|
500 |
+
return true;
|
501 |
+
}
|
502 |
+
if ($ok == 0) {
|
503 |
+
throw new \Exception('Incorrect signature.');
|
504 |
+
}
|
505 |
+
|
506 |
+
throw new \Exception('Error checking signature');
|
507 |
+
}
|
508 |
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Browser.php
ADDED
@@ -0,0 +1,195 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Client\ClientInterface;
|
6 |
+
use WebinterpretConnector\Buzz\Client\FileGetContents;
|
7 |
+
use WebinterpretConnector\Buzz\Listener\ListenerChain;
|
8 |
+
use WebinterpretConnector\Buzz\Listener\ListenerInterface;
|
9 |
+
use WebinterpretConnector\Buzz\Message\Factory\Factory;
|
10 |
+
use WebinterpretConnector\Buzz\Message\Factory\FactoryInterface;
|
11 |
+
use WebinterpretConnector\Buzz\Message\MessageInterface;
|
12 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
13 |
+
use WebinterpretConnector\Buzz\Util\Url;
|
14 |
+
|
15 |
+
class Browser
|
16 |
+
{
|
17 |
+
private $client;
|
18 |
+
private $factory;
|
19 |
+
private $listener;
|
20 |
+
private $lastRequest;
|
21 |
+
private $lastResponse;
|
22 |
+
|
23 |
+
public function __construct(ClientInterface $client = null, FactoryInterface $factory = null)
|
24 |
+
{
|
25 |
+
$this->client = $client ?: new FileGetContents();
|
26 |
+
$this->factory = $factory ?: new Factory();
|
27 |
+
}
|
28 |
+
|
29 |
+
public function get($url, $headers = array())
|
30 |
+
{
|
31 |
+
return $this->call($url, RequestInterface::METHOD_GET, $headers);
|
32 |
+
}
|
33 |
+
|
34 |
+
public function post($url, $headers = array(), $content = '')
|
35 |
+
{
|
36 |
+
return $this->call($url, RequestInterface::METHOD_POST, $headers, $content);
|
37 |
+
}
|
38 |
+
|
39 |
+
public function head($url, $headers = array())
|
40 |
+
{
|
41 |
+
return $this->call($url, RequestInterface::METHOD_HEAD, $headers);
|
42 |
+
}
|
43 |
+
|
44 |
+
public function patch($url, $headers = array(), $content = '')
|
45 |
+
{
|
46 |
+
return $this->call($url, RequestInterface::METHOD_PATCH, $headers, $content);
|
47 |
+
}
|
48 |
+
|
49 |
+
public function put($url, $headers = array(), $content = '')
|
50 |
+
{
|
51 |
+
return $this->call($url, RequestInterface::METHOD_PUT, $headers, $content);
|
52 |
+
}
|
53 |
+
|
54 |
+
public function delete($url, $headers = array(), $content = '')
|
55 |
+
{
|
56 |
+
return $this->call($url, RequestInterface::METHOD_DELETE, $headers, $content);
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Sends a request.
|
61 |
+
*
|
62 |
+
* @param string $url The URL to call
|
63 |
+
* @param string $method The request method to use
|
64 |
+
* @param array $headers An array of request headers
|
65 |
+
* @param string $content The request content
|
66 |
+
*
|
67 |
+
* @return MessageInterface The response object
|
68 |
+
*/
|
69 |
+
public function call($url, $method, $headers = array(), $content = '')
|
70 |
+
{
|
71 |
+
$request = $this->factory->createRequest($method);
|
72 |
+
|
73 |
+
if (!$url instanceof Url) {
|
74 |
+
$url = new Url($url);
|
75 |
+
}
|
76 |
+
|
77 |
+
$url->applyToRequest($request);
|
78 |
+
|
79 |
+
$request->addHeaders($headers);
|
80 |
+
$request->setContent($content);
|
81 |
+
|
82 |
+
return $this->send($request);
|
83 |
+
}
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Sends a form request.
|
87 |
+
*
|
88 |
+
* @param string $url The URL to submit to
|
89 |
+
* @param array $fields An array of fields
|
90 |
+
* @param string $method The request method to use
|
91 |
+
* @param array $headers An array of request headers
|
92 |
+
*
|
93 |
+
* @return MessageInterface The response object
|
94 |
+
*/
|
95 |
+
public function submit($url, array $fields, $method = RequestInterface::METHOD_POST, $headers = array())
|
96 |
+
{
|
97 |
+
$request = $this->factory->createFormRequest();
|
98 |
+
|
99 |
+
if (!$url instanceof Url) {
|
100 |
+
$url = new Url($url);
|
101 |
+
}
|
102 |
+
|
103 |
+
$url->applyToRequest($request);
|
104 |
+
|
105 |
+
$request->addHeaders($headers);
|
106 |
+
$request->setMethod($method);
|
107 |
+
$request->setFields($fields);
|
108 |
+
|
109 |
+
return $this->send($request);
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Sends a request.
|
114 |
+
*
|
115 |
+
* @param RequestInterface $request A request object
|
116 |
+
* @param MessageInterface $response A response object
|
117 |
+
*
|
118 |
+
* @return MessageInterface The response
|
119 |
+
*/
|
120 |
+
public function send(RequestInterface $request, MessageInterface $response = null)
|
121 |
+
{
|
122 |
+
if (null === $response) {
|
123 |
+
$response = $this->factory->createResponse();
|
124 |
+
}
|
125 |
+
|
126 |
+
if ($this->listener) {
|
127 |
+
$this->listener->preSend($request);
|
128 |
+
}
|
129 |
+
|
130 |
+
$this->client->send($request, $response);
|
131 |
+
|
132 |
+
$this->lastRequest = $request;
|
133 |
+
$this->lastResponse = $response;
|
134 |
+
|
135 |
+
if ($this->listener) {
|
136 |
+
$this->listener->postSend($request, $response);
|
137 |
+
}
|
138 |
+
|
139 |
+
return $response;
|
140 |
+
}
|
141 |
+
|
142 |
+
public function getLastRequest()
|
143 |
+
{
|
144 |
+
return $this->lastRequest;
|
145 |
+
}
|
146 |
+
|
147 |
+
public function getLastResponse()
|
148 |
+
{
|
149 |
+
return $this->lastResponse;
|
150 |
+
}
|
151 |
+
|
152 |
+
public function setClient(ClientInterface $client)
|
153 |
+
{
|
154 |
+
$this->client = $client;
|
155 |
+
}
|
156 |
+
|
157 |
+
public function getClient()
|
158 |
+
{
|
159 |
+
return $this->client;
|
160 |
+
}
|
161 |
+
|
162 |
+
public function setMessageFactory(FactoryInterface $factory)
|
163 |
+
{
|
164 |
+
$this->factory = $factory;
|
165 |
+
}
|
166 |
+
|
167 |
+
public function getMessageFactory()
|
168 |
+
{
|
169 |
+
return $this->factory;
|
170 |
+
}
|
171 |
+
|
172 |
+
public function setListener(ListenerInterface $listener)
|
173 |
+
{
|
174 |
+
$this->listener = $listener;
|
175 |
+
}
|
176 |
+
|
177 |
+
public function getListener()
|
178 |
+
{
|
179 |
+
return $this->listener;
|
180 |
+
}
|
181 |
+
|
182 |
+
public function addListener(ListenerInterface $listener)
|
183 |
+
{
|
184 |
+
if (!$this->listener) {
|
185 |
+
$this->listener = $listener;
|
186 |
+
} elseif ($this->listener instanceof ListenerChain) {
|
187 |
+
$this->listener->addListener($listener);
|
188 |
+
} else {
|
189 |
+
$this->listener = new ListenerChain(array(
|
190 |
+
$this->listener,
|
191 |
+
$listener,
|
192 |
+
));
|
193 |
+
}
|
194 |
+
}
|
195 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Client/AbstractClient.php
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Client;
|
4 |
+
|
5 |
+
abstract class AbstractClient implements ClientInterface
|
6 |
+
{
|
7 |
+
protected $ignoreErrors = true;
|
8 |
+
protected $maxRedirects = 5;
|
9 |
+
protected $timeout = 5;
|
10 |
+
protected $verifyPeer = true;
|
11 |
+
protected $verifyHost = 2;
|
12 |
+
protected $proxy;
|
13 |
+
|
14 |
+
public function setIgnoreErrors($ignoreErrors)
|
15 |
+
{
|
16 |
+
$this->ignoreErrors = $ignoreErrors;
|
17 |
+
}
|
18 |
+
|
19 |
+
public function getIgnoreErrors()
|
20 |
+
{
|
21 |
+
return $this->ignoreErrors;
|
22 |
+
}
|
23 |
+
|
24 |
+
public function setMaxRedirects($maxRedirects)
|
25 |
+
{
|
26 |
+
$this->maxRedirects = $maxRedirects;
|
27 |
+
}
|
28 |
+
|
29 |
+
public function getMaxRedirects()
|
30 |
+
{
|
31 |
+
return $this->maxRedirects;
|
32 |
+
}
|
33 |
+
|
34 |
+
public function setTimeout($timeout)
|
35 |
+
{
|
36 |
+
$this->timeout = $timeout;
|
37 |
+
}
|
38 |
+
|
39 |
+
public function getTimeout()
|
40 |
+
{
|
41 |
+
return $this->timeout;
|
42 |
+
}
|
43 |
+
|
44 |
+
public function setVerifyPeer($verifyPeer)
|
45 |
+
{
|
46 |
+
$this->verifyPeer = $verifyPeer;
|
47 |
+
}
|
48 |
+
|
49 |
+
public function getVerifyPeer()
|
50 |
+
{
|
51 |
+
return $this->verifyPeer;
|
52 |
+
}
|
53 |
+
|
54 |
+
public function getVerifyHost()
|
55 |
+
{
|
56 |
+
return $this->verifyHost;
|
57 |
+
}
|
58 |
+
|
59 |
+
public function setVerifyHost($verifyHost)
|
60 |
+
{
|
61 |
+
$this->verifyHost = $verifyHost;
|
62 |
+
}
|
63 |
+
|
64 |
+
public function setProxy($proxy)
|
65 |
+
{
|
66 |
+
$this->proxy = $proxy;
|
67 |
+
}
|
68 |
+
|
69 |
+
public function getProxy()
|
70 |
+
{
|
71 |
+
return $this->proxy;
|
72 |
+
}
|
73 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Client/AbstractCurl.php
ADDED
@@ -0,0 +1,232 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Client;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\Form\FormRequestInterface;
|
6 |
+
use WebinterpretConnector\Buzz\Message\Form\FormUploadInterface;
|
7 |
+
use WebinterpretConnector\Buzz\Message\MessageInterface;
|
8 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
9 |
+
use WebinterpretConnector\Buzz\Exception\ClientException;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Base client class with helpers for working with cURL.
|
13 |
+
*/
|
14 |
+
abstract class AbstractCurl extends AbstractClient
|
15 |
+
{
|
16 |
+
protected $options = array();
|
17 |
+
|
18 |
+
public function __construct()
|
19 |
+
{
|
20 |
+
if (defined('CURLOPT_PROTOCOLS')) {
|
21 |
+
$this->options = array(
|
22 |
+
CURLOPT_PROTOCOLS => CURLPROTO_HTTP | CURLPROTO_HTTPS,
|
23 |
+
CURLOPT_REDIR_PROTOCOLS => CURLPROTO_HTTP | CURLPROTO_HTTPS,
|
24 |
+
);
|
25 |
+
}
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Creates a new cURL resource.
|
30 |
+
*
|
31 |
+
* @see curl_init()
|
32 |
+
*
|
33 |
+
* @return resource A new cURL resource
|
34 |
+
*
|
35 |
+
* @throws ClientException If unable to create a cURL resource
|
36 |
+
*/
|
37 |
+
protected static function createCurlHandle()
|
38 |
+
{
|
39 |
+
if (false === $curl = curl_init()) {
|
40 |
+
throw new ClientException('Unable to create a new cURL handle');
|
41 |
+
}
|
42 |
+
|
43 |
+
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
44 |
+
curl_setopt($curl, CURLOPT_HEADER, true);
|
45 |
+
|
46 |
+
return $curl;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Populates a response object.
|
51 |
+
*
|
52 |
+
* @param resource $curl A cURL resource
|
53 |
+
* @param string $raw The raw response string
|
54 |
+
* @param MessageInterface $response The response object
|
55 |
+
*/
|
56 |
+
protected static function populateResponse($curl, $raw, MessageInterface $response)
|
57 |
+
{
|
58 |
+
// fixes bug https://sourceforge.net/p/curl/bugs/1204/
|
59 |
+
$version = curl_version();
|
60 |
+
if (version_compare($version['version'], '7.30.0', '<')) {
|
61 |
+
$pos = strlen($raw) - curl_getinfo($curl, CURLINFO_SIZE_DOWNLOAD);
|
62 |
+
} else {
|
63 |
+
$pos = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
|
64 |
+
}
|
65 |
+
|
66 |
+
$response->setHeaders(static::getLastHeaders(rtrim(substr($raw, 0, $pos))));
|
67 |
+
$response->setContent(strlen($raw) > $pos ? substr($raw, $pos) : '');
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Sets options on a cURL resource based on a request.
|
72 |
+
*/
|
73 |
+
private static function setOptionsFromRequest($curl, RequestInterface $request)
|
74 |
+
{
|
75 |
+
$options = array(
|
76 |
+
CURLOPT_HTTP_VERSION => $request->getProtocolVersion() == 1.0 ? CURL_HTTP_VERSION_1_0 : CURL_HTTP_VERSION_1_1,
|
77 |
+
CURLOPT_CUSTOMREQUEST => $request->getMethod(),
|
78 |
+
CURLOPT_URL => $request->getHost().$request->getResource(),
|
79 |
+
CURLOPT_HTTPHEADER => $request->getHeaders(),
|
80 |
+
);
|
81 |
+
|
82 |
+
switch ($request->getMethod()) {
|
83 |
+
case RequestInterface::METHOD_HEAD:
|
84 |
+
$options[CURLOPT_NOBODY] = true;
|
85 |
+
break;
|
86 |
+
|
87 |
+
case RequestInterface::METHOD_GET:
|
88 |
+
$options[CURLOPT_HTTPGET] = true;
|
89 |
+
break;
|
90 |
+
|
91 |
+
case RequestInterface::METHOD_POST:
|
92 |
+
case RequestInterface::METHOD_PUT:
|
93 |
+
case RequestInterface::METHOD_DELETE:
|
94 |
+
case RequestInterface::METHOD_PATCH:
|
95 |
+
case RequestInterface::METHOD_OPTIONS:
|
96 |
+
$options[CURLOPT_POSTFIELDS] = $fields = static::getPostFields($request);
|
97 |
+
|
98 |
+
// remove the content-type header
|
99 |
+
if (is_array($fields)) {
|
100 |
+
$options[CURLOPT_HTTPHEADER] = array_filter($options[CURLOPT_HTTPHEADER], function($header) {
|
101 |
+
return 0 !== stripos($header, 'Content-Type: ');
|
102 |
+
});
|
103 |
+
}
|
104 |
+
|
105 |
+
break;
|
106 |
+
}
|
107 |
+
|
108 |
+
curl_setopt_array($curl, $options);
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Returns a value for the CURLOPT_POSTFIELDS option.
|
113 |
+
*
|
114 |
+
* @return string|array A post fields value
|
115 |
+
*/
|
116 |
+
private static function getPostFields(RequestInterface $request)
|
117 |
+
{
|
118 |
+
if (!$request instanceof FormRequestInterface) {
|
119 |
+
return $request->getContent();
|
120 |
+
}
|
121 |
+
|
122 |
+
$fields = $request->getFields();
|
123 |
+
$multipart = false;
|
124 |
+
|
125 |
+
foreach ($fields as $name => $value) {
|
126 |
+
if (!$value instanceof FormUploadInterface) {
|
127 |
+
continue;
|
128 |
+
}
|
129 |
+
|
130 |
+
if (!$file = $value->getFile()) {
|
131 |
+
return $request->getContent();
|
132 |
+
}
|
133 |
+
|
134 |
+
$multipart = true;
|
135 |
+
|
136 |
+
if (version_compare(PHP_VERSION, '5.5', '>=')) {
|
137 |
+
$curlFile = new \CURLFile($file);
|
138 |
+
if ($contentType = $value->getContentType()) {
|
139 |
+
$curlFile->setMimeType($contentType);
|
140 |
+
}
|
141 |
+
|
142 |
+
if (basename($file) != $value->getFilename()) {
|
143 |
+
$curlFile->setPostFilename($value->getFilename());
|
144 |
+
}
|
145 |
+
|
146 |
+
$fields[$name] = $curlFile;
|
147 |
+
} else {
|
148 |
+
// replace value with upload string
|
149 |
+
$fields[$name] = '@'.$file;
|
150 |
+
|
151 |
+
if ($contentType = $value->getContentType()) {
|
152 |
+
$fields[$name] .= ';type='.$contentType;
|
153 |
+
}
|
154 |
+
if (basename($file) != $value->getFilename()) {
|
155 |
+
$fields[$name] .= ';filename='.$value->getFilename();
|
156 |
+
}
|
157 |
+
}
|
158 |
+
}
|
159 |
+
|
160 |
+
return $multipart ? $fields : http_build_query($fields, '', '&');
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* A helper for getting the last set of headers.
|
165 |
+
*
|
166 |
+
* @param string $raw A string of many header chunks
|
167 |
+
*
|
168 |
+
* @return array An array of header lines
|
169 |
+
*/
|
170 |
+
private static function getLastHeaders($raw)
|
171 |
+
{
|
172 |
+
$headers = array();
|
173 |
+
foreach (preg_split('/(\\r?\\n)/', $raw) as $header) {
|
174 |
+
if ($header) {
|
175 |
+
$headers[] = $header;
|
176 |
+
} else {
|
177 |
+
$headers = array();
|
178 |
+
}
|
179 |
+
}
|
180 |
+
|
181 |
+
return $headers;
|
182 |
+
}
|
183 |
+
|
184 |
+
/**
|
185 |
+
* Stashes a cURL option to be set on send, when the resource is created.
|
186 |
+
*
|
187 |
+
* If the supplied value it set to null the option will be removed.
|
188 |
+
*
|
189 |
+
* @param integer $option The option
|
190 |
+
* @param mixed $value The value
|
191 |
+
*
|
192 |
+
* @see curl_setopt()
|
193 |
+
*/
|
194 |
+
public function setOption($option, $value)
|
195 |
+
{
|
196 |
+
if (null === $value) {
|
197 |
+
unset($this->options[$option]);
|
198 |
+
} else {
|
199 |
+
$this->options[$option] = $value;
|
200 |
+
}
|
201 |
+
}
|
202 |
+
|
203 |
+
/**
|
204 |
+
* Prepares a cURL resource to send a request.
|
205 |
+
*/
|
206 |
+
protected function prepare($curl, RequestInterface $request, array $options = array())
|
207 |
+
{
|
208 |
+
static::setOptionsFromRequest($curl, $request);
|
209 |
+
|
210 |
+
// apply settings from client
|
211 |
+
if ($this->getTimeout() < 1) {
|
212 |
+
curl_setopt($curl, CURLOPT_TIMEOUT_MS, $this->getTimeout() * 1000);
|
213 |
+
} else {
|
214 |
+
curl_setopt($curl, CURLOPT_TIMEOUT, $this->getTimeout());
|
215 |
+
}
|
216 |
+
|
217 |
+
if ($this->proxy) {
|
218 |
+
curl_setopt($curl, CURLOPT_PROXY, $this->proxy);
|
219 |
+
}
|
220 |
+
|
221 |
+
$canFollow = !ini_get('safe_mode') && !ini_get('open_basedir');
|
222 |
+
|
223 |
+
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, $canFollow && $this->getMaxRedirects() > 0);
|
224 |
+
curl_setopt($curl, CURLOPT_MAXREDIRS, $canFollow ? $this->getMaxRedirects() : 0);
|
225 |
+
curl_setopt($curl, CURLOPT_FAILONERROR, !$this->getIgnoreErrors());
|
226 |
+
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->getVerifyPeer());
|
227 |
+
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, $this->getVerifyHost());
|
228 |
+
|
229 |
+
// apply additional options
|
230 |
+
curl_setopt_array($curl, $options + $this->options);
|
231 |
+
}
|
232 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Client/AbstractStream.php
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Client;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
6 |
+
|
7 |
+
abstract class AbstractStream extends AbstractClient
|
8 |
+
{
|
9 |
+
/**
|
10 |
+
* Converts a request into an array for stream_context_create().
|
11 |
+
*
|
12 |
+
* @param RequestInterface $request A request object
|
13 |
+
*
|
14 |
+
* @return array An array for stream_context_create()
|
15 |
+
*/
|
16 |
+
public function getStreamContextArray(RequestInterface $request)
|
17 |
+
{
|
18 |
+
$options = array(
|
19 |
+
'http' => array(
|
20 |
+
// values from the request
|
21 |
+
'method' => $request->getMethod(),
|
22 |
+
'header' => implode("\r\n", $request->getHeaders()),
|
23 |
+
'content' => $request->getContent(),
|
24 |
+
'protocol_version' => $request->getProtocolVersion(),
|
25 |
+
|
26 |
+
// values from the current client
|
27 |
+
'ignore_errors' => $this->getIgnoreErrors(),
|
28 |
+
'follow_location' => $this->getMaxRedirects() > 0,
|
29 |
+
'max_redirects' => $this->getMaxRedirects() + 1,
|
30 |
+
'timeout' => $this->getTimeout(),
|
31 |
+
),
|
32 |
+
'ssl' => array(
|
33 |
+
'verify_peer' => $this->getVerifyPeer(),
|
34 |
+
'verify_host' => $this->getVerifyHost(),
|
35 |
+
),
|
36 |
+
);
|
37 |
+
|
38 |
+
if ($this->proxy) {
|
39 |
+
$options['http']['proxy'] = $this->proxy;
|
40 |
+
$options['http']['request_fulluri'] = true;
|
41 |
+
}
|
42 |
+
|
43 |
+
return $options;
|
44 |
+
}
|
45 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Client/BatchClientInterface.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Client;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Exception\ClientException;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* A client capable of running batches of requests.
|
9 |
+
*
|
10 |
+
* The Countable implementation should return the number of queued requests.
|
11 |
+
*/
|
12 |
+
interface BatchClientInterface extends ClientInterface, \Countable
|
13 |
+
{
|
14 |
+
/**
|
15 |
+
* Processes all queued requests.
|
16 |
+
*
|
17 |
+
* @throws ClientException If something goes wrong
|
18 |
+
*/
|
19 |
+
public function flush();
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Processes zero or more queued requests.
|
23 |
+
*
|
24 |
+
* @throws ClientException If something goes wrong
|
25 |
+
*/
|
26 |
+
public function proceed();
|
27 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Client/ClientInterface.php
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Client;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Exception\ClientException;
|
6 |
+
use WebinterpretConnector\Buzz\Message\MessageInterface;
|
7 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
8 |
+
|
9 |
+
interface ClientInterface
|
10 |
+
{
|
11 |
+
/**
|
12 |
+
* Populates the supplied response with the response for the supplied request.
|
13 |
+
*
|
14 |
+
* @param RequestInterface $request A request object
|
15 |
+
* @param MessageInterface $response A response object
|
16 |
+
*
|
17 |
+
* @throws ClientException If something goes wrong
|
18 |
+
*/
|
19 |
+
public function send(RequestInterface $request, MessageInterface $response);
|
20 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Client/Curl.php
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Client;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Exception\RequestException;
|
6 |
+
use WebinterpretConnector\Buzz\Message\MessageInterface;
|
7 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
8 |
+
use WebinterpretConnector\Buzz\Exception\LogicException;
|
9 |
+
|
10 |
+
class Curl extends AbstractCurl
|
11 |
+
{
|
12 |
+
private $lastCurl;
|
13 |
+
|
14 |
+
public function send(RequestInterface $request, MessageInterface $response, array $options = array())
|
15 |
+
{
|
16 |
+
if (is_resource($this->lastCurl)) {
|
17 |
+
curl_close($this->lastCurl);
|
18 |
+
}
|
19 |
+
|
20 |
+
$this->lastCurl = static::createCurlHandle();
|
21 |
+
$this->prepare($this->lastCurl, $request, $options);
|
22 |
+
|
23 |
+
$data = curl_exec($this->lastCurl);
|
24 |
+
|
25 |
+
if (false === $data) {
|
26 |
+
$errorMsg = curl_error($this->lastCurl);
|
27 |
+
$errorNo = curl_errno($this->lastCurl);
|
28 |
+
|
29 |
+
$e = new RequestException($errorMsg, $errorNo);
|
30 |
+
$e->setRequest($request);
|
31 |
+
|
32 |
+
throw $e;
|
33 |
+
}
|
34 |
+
|
35 |
+
static::populateResponse($this->lastCurl, $data, $response);
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Introspects the last cURL request.
|
40 |
+
*
|
41 |
+
* @see curl_getinfo()
|
42 |
+
*
|
43 |
+
* @throws LogicException If there is no cURL resource
|
44 |
+
*/
|
45 |
+
public function getInfo($opt = 0)
|
46 |
+
{
|
47 |
+
if (!is_resource($this->lastCurl)) {
|
48 |
+
throw new LogicException('There is no cURL resource');
|
49 |
+
}
|
50 |
+
|
51 |
+
return 0 === $opt ? curl_getinfo($this->lastCurl) : curl_getinfo($this->lastCurl, $opt);
|
52 |
+
}
|
53 |
+
|
54 |
+
public function __destruct()
|
55 |
+
{
|
56 |
+
if (is_resource($this->lastCurl)) {
|
57 |
+
curl_close($this->lastCurl);
|
58 |
+
}
|
59 |
+
}
|
60 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Client/FileGetContents.php
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Client;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Exception\RequestException;
|
6 |
+
use WebinterpretConnector\Buzz\Message\MessageInterface;
|
7 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
8 |
+
|
9 |
+
use WebinterpretConnector\Buzz\Exception\ClientException;
|
10 |
+
|
11 |
+
class FileGetContents extends AbstractStream
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* @see ClientInterface
|
15 |
+
*
|
16 |
+
* @throws ClientException If file_get_contents() fires an error
|
17 |
+
*/
|
18 |
+
public function send(RequestInterface $request, MessageInterface $response)
|
19 |
+
{
|
20 |
+
$context = stream_context_create($this->getStreamContextArray($request));
|
21 |
+
$url = $request->getHost().$request->getResource();
|
22 |
+
|
23 |
+
$level = error_reporting(0);
|
24 |
+
$content = file_get_contents($url, 0, $context);
|
25 |
+
error_reporting($level);
|
26 |
+
if (false === $content) {
|
27 |
+
$error = error_get_last();
|
28 |
+
$e = new RequestException($error['message']);
|
29 |
+
$e->setRequest($request);
|
30 |
+
|
31 |
+
throw $e;
|
32 |
+
}
|
33 |
+
|
34 |
+
$response->setHeaders($this->filterHeaders((array) $http_response_header));
|
35 |
+
$response->setContent($content);
|
36 |
+
}
|
37 |
+
|
38 |
+
private function filterHeaders(array $headers)
|
39 |
+
{
|
40 |
+
$filtered = array();
|
41 |
+
foreach ($headers as $header) {
|
42 |
+
if (0 === stripos($header, 'http/')) {
|
43 |
+
$filtered = array();
|
44 |
+
}
|
45 |
+
|
46 |
+
$filtered[] = $header;
|
47 |
+
}
|
48 |
+
|
49 |
+
return $filtered;
|
50 |
+
}
|
51 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Client/MultiCurl.php
ADDED
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Client;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\MessageInterface;
|
6 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
7 |
+
use WebinterpretConnector\Buzz\Exception\ClientException;
|
8 |
+
|
9 |
+
class MultiCurl extends AbstractCurl implements BatchClientInterface
|
10 |
+
{
|
11 |
+
private $queue = array();
|
12 |
+
private $curlm;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Populates the supplied response with the response for the supplied request.
|
16 |
+
*
|
17 |
+
* The array of options will be passed to curl_setopt_array().
|
18 |
+
*
|
19 |
+
* If a "callback" option is supplied, its value will be called when the
|
20 |
+
* request completes. The callable should have the following signature:
|
21 |
+
*
|
22 |
+
* $callback = function($client, $request, $response, $options, $error) {
|
23 |
+
* if (!$error) {
|
24 |
+
* // success
|
25 |
+
* } else {
|
26 |
+
* // error ($error is one of the CURLE_* constants)
|
27 |
+
* }
|
28 |
+
* };
|
29 |
+
*
|
30 |
+
* @param RequestInterface $request A request object
|
31 |
+
* @param MessageInterface $response A response object
|
32 |
+
* @param array $options An array of options
|
33 |
+
*/
|
34 |
+
public function send(RequestInterface $request, MessageInterface $response, array $options = array())
|
35 |
+
{
|
36 |
+
$this->queue[] = array($request, $response, $options);
|
37 |
+
}
|
38 |
+
|
39 |
+
public function count()
|
40 |
+
{
|
41 |
+
return count($this->queue);
|
42 |
+
}
|
43 |
+
|
44 |
+
public function flush()
|
45 |
+
{
|
46 |
+
while ($this->queue) {
|
47 |
+
$this->proceed();
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
public function proceed()
|
52 |
+
{
|
53 |
+
if (!$this->queue) {
|
54 |
+
return;
|
55 |
+
}
|
56 |
+
|
57 |
+
if (!$this->curlm && false === $this->curlm = curl_multi_init()) {
|
58 |
+
throw new ClientException('Unable to create a new cURL multi handle');
|
59 |
+
}
|
60 |
+
|
61 |
+
foreach (array_keys($this->queue) as $i) {
|
62 |
+
if (3 == count($this->queue[$i])) {
|
63 |
+
// prepare curl handle
|
64 |
+
list($request, , $options) = $this->queue[$i];
|
65 |
+
$curl = static::createCurlHandle();
|
66 |
+
|
67 |
+
// remove custom option
|
68 |
+
unset($options['callback']);
|
69 |
+
|
70 |
+
$this->prepare($curl, $request, $options);
|
71 |
+
$this->queue[$i][] = $curl;
|
72 |
+
curl_multi_add_handle($this->curlm, $curl);
|
73 |
+
}
|
74 |
+
}
|
75 |
+
|
76 |
+
// process outstanding perform
|
77 |
+
$active = null;
|
78 |
+
do {
|
79 |
+
$mrc = curl_multi_exec($this->curlm, $active);
|
80 |
+
} while ($active && CURLM_CALL_MULTI_PERFORM == $mrc);
|
81 |
+
|
82 |
+
// handle any completed requests
|
83 |
+
while ($done = curl_multi_info_read($this->curlm)) {
|
84 |
+
foreach (array_keys($this->queue) as $i) {
|
85 |
+
list($request, $response, $options, $curl) = $this->queue[$i];
|
86 |
+
|
87 |
+
if ($curl !== $done['handle']) {
|
88 |
+
continue;
|
89 |
+
}
|
90 |
+
|
91 |
+
// populate the response object
|
92 |
+
if (CURLE_OK === $done['result']) {
|
93 |
+
static::populateResponse($curl, curl_multi_getcontent($curl), $response);
|
94 |
+
}
|
95 |
+
|
96 |
+
// remove from queue
|
97 |
+
curl_multi_remove_handle($this->curlm, $curl);
|
98 |
+
curl_close($curl);
|
99 |
+
unset($this->queue[$i]);
|
100 |
+
|
101 |
+
// callback
|
102 |
+
if (isset($options['callback'])) {
|
103 |
+
call_user_func($options['callback'], $this, $request, $response, $options, $done['result']);
|
104 |
+
}
|
105 |
+
}
|
106 |
+
}
|
107 |
+
|
108 |
+
// cleanup
|
109 |
+
if (!$this->queue) {
|
110 |
+
curl_multi_close($this->curlm);
|
111 |
+
$this->curlm = null;
|
112 |
+
}
|
113 |
+
}
|
114 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Exception/ClientException.php
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Exception;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Thrown whenever a client process fails.
|
7 |
+
*/
|
8 |
+
class ClientException extends RuntimeException
|
9 |
+
{
|
10 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Exception/ExceptionInterface.php
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Exception;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Marker interface to denote exceptions thrown from the Buzz context.
|
7 |
+
*/
|
8 |
+
interface ExceptionInterface
|
9 |
+
{
|
10 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Exception/InvalidArgumentException.php
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Exception;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Thrown when an invalid argument is provided.
|
7 |
+
*/
|
8 |
+
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
|
9 |
+
{
|
10 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Exception/LogicException.php
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Exception;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Thrown whenever a required call-flow is not respected.
|
7 |
+
*/
|
8 |
+
class LogicException extends \LogicException implements ExceptionInterface
|
9 |
+
{
|
10 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Exception/RequestException.php
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Exception;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
6 |
+
|
7 |
+
class RequestException extends ClientException
|
8 |
+
{
|
9 |
+
/**
|
10 |
+
* Request object
|
11 |
+
*
|
12 |
+
* @var RequestInterface
|
13 |
+
*/
|
14 |
+
private $request;
|
15 |
+
|
16 |
+
/**
|
17 |
+
* @return RequestInterface
|
18 |
+
*/
|
19 |
+
public function getRequest()
|
20 |
+
{
|
21 |
+
return $this->request;
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @param RequestInterface $request
|
26 |
+
*/
|
27 |
+
public function setRequest(RequestInterface $request)
|
28 |
+
{
|
29 |
+
$this->request = $request;
|
30 |
+
}
|
31 |
+
|
32 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Exception/RuntimeException.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Exception;
|
4 |
+
|
5 |
+
class RuntimeException extends \RuntimeException implements ExceptionInterface
|
6 |
+
{
|
7 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Listener/BasicAuthListener.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Listener;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\MessageInterface;
|
6 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
7 |
+
|
8 |
+
class BasicAuthListener implements ListenerInterface
|
9 |
+
{
|
10 |
+
private $username;
|
11 |
+
private $password;
|
12 |
+
|
13 |
+
public function __construct($username, $password)
|
14 |
+
{
|
15 |
+
$this->username = $username;
|
16 |
+
$this->password = $password;
|
17 |
+
}
|
18 |
+
|
19 |
+
public function preSend(RequestInterface $request)
|
20 |
+
{
|
21 |
+
$request->addHeader('Authorization: Basic '.base64_encode($this->username.':'.$this->password));
|
22 |
+
}
|
23 |
+
|
24 |
+
public function postSend(RequestInterface $request, MessageInterface $response)
|
25 |
+
{
|
26 |
+
}
|
27 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Listener/CallbackListener.php
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Listener;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\MessageInterface;
|
6 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
7 |
+
use WebinterpretConnector\Buzz\Exception\InvalidArgumentException;
|
8 |
+
|
9 |
+
class CallbackListener implements ListenerInterface
|
10 |
+
{
|
11 |
+
private $callable;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Constructor.
|
15 |
+
*
|
16 |
+
* The callback should expect either one or two arguments, depending on
|
17 |
+
* whether it is receiving a pre or post send notification.
|
18 |
+
*
|
19 |
+
* $listener = new CallbackListener(function($request, $response = null) {
|
20 |
+
* if ($response) {
|
21 |
+
* // postSend
|
22 |
+
* } else {
|
23 |
+
* // preSend
|
24 |
+
* }
|
25 |
+
* });
|
26 |
+
*
|
27 |
+
* @param mixed $callable A PHP callable
|
28 |
+
*
|
29 |
+
* @throws InvalidArgumentException If the argument is not callable
|
30 |
+
*/
|
31 |
+
public function __construct($callable)
|
32 |
+
{
|
33 |
+
if (!is_callable($callable)) {
|
34 |
+
throw new InvalidArgumentException('The argument is not callable.');
|
35 |
+
}
|
36 |
+
|
37 |
+
$this->callable = $callable;
|
38 |
+
}
|
39 |
+
|
40 |
+
public function preSend(RequestInterface $request)
|
41 |
+
{
|
42 |
+
call_user_func($this->callable, $request);
|
43 |
+
}
|
44 |
+
|
45 |
+
public function postSend(RequestInterface $request, MessageInterface $response)
|
46 |
+
{
|
47 |
+
call_user_func($this->callable, $request, $response);
|
48 |
+
}
|
49 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Listener/CookieListener.php
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Listener;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
6 |
+
use WebinterpretConnector\Buzz\Message\MessageInterface;
|
7 |
+
|
8 |
+
use WebinterpretConnector\Buzz\Util\Cookie;
|
9 |
+
use WebinterpretConnector\Buzz\Util\CookieJar;
|
10 |
+
|
11 |
+
class CookieListener implements ListenerInterface
|
12 |
+
{
|
13 |
+
private $cookieJar;
|
14 |
+
|
15 |
+
public function __construct()
|
16 |
+
{
|
17 |
+
$this->cookieJar = new CookieJar();
|
18 |
+
}
|
19 |
+
|
20 |
+
public function setCookies($cookies)
|
21 |
+
{
|
22 |
+
$this->cookieJar->setCookies($cookies);
|
23 |
+
}
|
24 |
+
|
25 |
+
public function getCookies()
|
26 |
+
{
|
27 |
+
return $this->cookieJar->getCookies();
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Adds a cookie to the current cookie jar.
|
32 |
+
*
|
33 |
+
* @param Cookie $cookie A cookie object
|
34 |
+
*/
|
35 |
+
public function addCookie(Cookie $cookie)
|
36 |
+
{
|
37 |
+
$this->cookieJar->addCookie($cookie);
|
38 |
+
}
|
39 |
+
|
40 |
+
public function preSend(RequestInterface $request)
|
41 |
+
{
|
42 |
+
$this->cookieJar->clearExpiredCookies();
|
43 |
+
$this->cookieJar->addCookieHeaders($request);
|
44 |
+
}
|
45 |
+
|
46 |
+
public function postSend(RequestInterface $request, MessageInterface $response)
|
47 |
+
{
|
48 |
+
$this->cookieJar->processSetCookieHeaders($request, $response);
|
49 |
+
}
|
50 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Listener/DigestAuthListener.php
ADDED
@@ -0,0 +1,837 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Listener;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\MessageInterface;
|
6 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
7 |
+
|
8 |
+
class DigestAuthListener implements ListenerInterface
|
9 |
+
{
|
10 |
+
private $username;
|
11 |
+
private $password;
|
12 |
+
private $realm;
|
13 |
+
|
14 |
+
private $algorithm;
|
15 |
+
private $authenticationMethod;
|
16 |
+
private $clientNonce;
|
17 |
+
private $domain;
|
18 |
+
private $entityBody;
|
19 |
+
private $method;
|
20 |
+
private $nonce;
|
21 |
+
private $nonceCount;
|
22 |
+
private $opaque;
|
23 |
+
private $uri;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* QOP options: Only one of the following can be set at any time. setOptions will throw an exception otherwise.
|
27 |
+
* OPTION_QOP_AUTH_INT - Always use auth-int (if available)
|
28 |
+
* OPTION_QOP_AUTH - Always use auth (even if auth-int available)
|
29 |
+
*/
|
30 |
+
const OPTION_QOP_AUTH_INT = 1;
|
31 |
+
const OPTION_QOP_AUTH = 2;
|
32 |
+
/**
|
33 |
+
* Ignore server request to downgrade authentication from Digest to Basic.
|
34 |
+
* Breaks RFC compatibility, but ensures passwords are never sent using base64 which is trivial for an attacker to decode.
|
35 |
+
*/
|
36 |
+
const OPTION_IGNORE_DOWNGRADE_REQUEST = 4;
|
37 |
+
/**
|
38 |
+
* Discard Client Nonce on each request.
|
39 |
+
*/
|
40 |
+
const OPTION_DISCARD_CLIENT_NONCE = 8;
|
41 |
+
|
42 |
+
private $options;
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Set OPTION_QOP_BEST_AVAILABLE and OPTION_DISCARD_CLIENT_NONCE by default.
|
46 |
+
*/
|
47 |
+
public function __construct($username = null, $password = null, $realm = null)
|
48 |
+
{
|
49 |
+
$this->setUsername($username);
|
50 |
+
$this->setPassword($password);
|
51 |
+
$this->setRealm($realm);
|
52 |
+
$this->setOptions(DigestAuthListener::OPTION_QOP_AUTH_INT & DigestAuthListener::OPTION_DISCARD_CLIENT_NONCE);
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Passes the returned server headers to parseServerHeaders() to check if any authentication variables need to be set.
|
57 |
+
* Inteprets the returned status code and attempts authentication if status is 401 (Authentication Required) by resending
|
58 |
+
* the last request with an Authentication header.
|
59 |
+
*
|
60 |
+
* @param RequestInterface $request A request object
|
61 |
+
* @param MessageInterface $response A response object
|
62 |
+
*/
|
63 |
+
public function postSend(RequestInterface $request, MessageInterface $response)
|
64 |
+
{
|
65 |
+
$statusCode = $response->getStatusCode();
|
66 |
+
$this->parseServerHeaders($response->getHeaders(), $statusCode);
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Populates uri, method and entityBody used to generate the Authentication header using the specified request object.
|
71 |
+
* Appends the Authentication header if it is present and has been able to be calculated.
|
72 |
+
*
|
73 |
+
* @param RequestInterface $request A request object
|
74 |
+
*/
|
75 |
+
public function preSend(RequestInterface $request)
|
76 |
+
{
|
77 |
+
$this->setUri($request->getResource());
|
78 |
+
$this->setMethod($request->getMethod());
|
79 |
+
$this->setEntityBody($request->getContent());
|
80 |
+
|
81 |
+
$header = $this->getHeader();
|
82 |
+
if($header) {
|
83 |
+
$request->addHeader($header);
|
84 |
+
}
|
85 |
+
}
|
86 |
+
|
87 |
+
/**
|
88 |
+
* Sets the password to be used to authenticate the client.
|
89 |
+
*
|
90 |
+
* @param string $password The password
|
91 |
+
*
|
92 |
+
* @return void
|
93 |
+
*/
|
94 |
+
public function setPassword($password)
|
95 |
+
{
|
96 |
+
$this->password = $password;
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Sets the realm to be used to authenticate the client.
|
101 |
+
*
|
102 |
+
* @param string $realm The realm
|
103 |
+
*
|
104 |
+
* @return void
|
105 |
+
*/
|
106 |
+
public function setRealm($realm)
|
107 |
+
{
|
108 |
+
$this->realm = $realm;
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Sets the username to be used to authenticate the client.
|
113 |
+
*
|
114 |
+
* @param string $username The username
|
115 |
+
*
|
116 |
+
* @return void
|
117 |
+
*/
|
118 |
+
public function setUsername($username)
|
119 |
+
{
|
120 |
+
$this->username = $username;
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Sets the options to be used by this class.
|
125 |
+
*
|
126 |
+
* @param int $options A bitmask of the constants defined in this class.
|
127 |
+
*
|
128 |
+
* @return void
|
129 |
+
*/
|
130 |
+
public function setOptions($options)
|
131 |
+
{
|
132 |
+
if(($options & DigestAuthListener::OPTION_QOP_AUTH_INT) === true) {
|
133 |
+
if(($options & DigestAuthListener::OPTION_QOP_AUTH) === true) {
|
134 |
+
throw new \InvalidArgumentException('DigestAuthListener: Only one value of OPTION_QOP_AUTH_INT or OPTION_QOP_AUTH may be set.');
|
135 |
+
}
|
136 |
+
$this->options = $this->options | DigestAuthListener::OPTION_QOP_AUTH_INT;
|
137 |
+
} else {
|
138 |
+
if(($options & DigestAuthListener::OPTION_QOP_AUTH) === true) {
|
139 |
+
$this->options = $this->options | DigestAuthListener::OPTION_QOP_AUTH;
|
140 |
+
}
|
141 |
+
}
|
142 |
+
|
143 |
+
if(($options & DigestAuthListener::OPTION_IGNORE_DOWNGRADE_REQUEST) === true) {
|
144 |
+
$this->options = $this->options | DigestAuthListener::OPTION_IGNORE_DOWNGRADE_REQUEST;
|
145 |
+
}
|
146 |
+
|
147 |
+
if(($options & DigestAuthListener::OPTION_DISCARD_CLIENT_NONCE) === true) {
|
148 |
+
$this->options = $this->options | DigestAuthListener::OPTION_DISCARD_CLIENT_NONCE;
|
149 |
+
}
|
150 |
+
}
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Discards the Client Nonce forcing the generation of a new Client Nonce on the next request.
|
154 |
+
*
|
155 |
+
* @return void
|
156 |
+
*/
|
157 |
+
private function discardClientNonce()
|
158 |
+
{
|
159 |
+
$this->clientNonce = null;
|
160 |
+
}
|
161 |
+
|
162 |
+
/**
|
163 |
+
* Returns the hashing algorithm to be used to generate the digest value. Currently only returns MD5.
|
164 |
+
*
|
165 |
+
* @return string The hashing algorithm to be used.
|
166 |
+
*/
|
167 |
+
private function getAlgorithm()
|
168 |
+
{
|
169 |
+
if($this->algorithm == null) {
|
170 |
+
$this->algorithm = 'MD5';
|
171 |
+
}
|
172 |
+
return $this->algorithm;
|
173 |
+
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Returns the authentication method requested by the server.
|
177 |
+
* If OPTION_IGNORE_DOWNGRADE_REQUEST is set this will always return "Digest"
|
178 |
+
*
|
179 |
+
* @return string Returns either "Digest" or "Basic".
|
180 |
+
*/
|
181 |
+
private function getAuthenticationMethod()
|
182 |
+
{
|
183 |
+
if(($this->options & DigestAuthListener::OPTION_IGNORE_DOWNGRADE_REQUEST) === true) {
|
184 |
+
return "Digest";
|
185 |
+
}
|
186 |
+
return $this->authenticationMethod;
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* Returns either the current value of clientNonce or generates a new value if clientNonce is null.
|
191 |
+
* Also increments nonceCount.
|
192 |
+
*
|
193 |
+
* @return string Returns either the current value of clientNonce the newly generated clientNonce;
|
194 |
+
*/
|
195 |
+
private function getClientNonce()
|
196 |
+
{
|
197 |
+
if($this->clientNonce == null) {
|
198 |
+
$this->clientNonce = uniqid();
|
199 |
+
|
200 |
+
if($this->nonceCount == null) {
|
201 |
+
// If nonceCount is not set then set it to 00000001.
|
202 |
+
$this->nonceCount = '00000001';
|
203 |
+
} else {
|
204 |
+
// If it is set then increment it.
|
205 |
+
$this->nonceCount++;
|
206 |
+
// Ensure nonceCount is zero-padded at the start of the string to a length of 8
|
207 |
+
while(strlen($this->nonceCount) < 8) {
|
208 |
+
$this->nonceCount = '0' . $this->nonceCount;
|
209 |
+
}
|
210 |
+
}
|
211 |
+
}
|
212 |
+
return $this->clientNonce;
|
213 |
+
}
|
214 |
+
|
215 |
+
/**
|
216 |
+
* Returns a space separated list of uris that the server nonce can be used to generate an authentication response against.
|
217 |
+
*
|
218 |
+
* @return string Space separated list of uris.
|
219 |
+
*/
|
220 |
+
private function getDomain()
|
221 |
+
{
|
222 |
+
return $this->domain;
|
223 |
+
}
|
224 |
+
|
225 |
+
/**
|
226 |
+
* Returns the entity body of the current request.
|
227 |
+
* The entity body is the request before it has been encoded with the content-encoding and minus the request headers.
|
228 |
+
*
|
229 |
+
* @return string The full entity-body.
|
230 |
+
*/
|
231 |
+
private function getEntityBody()
|
232 |
+
{
|
233 |
+
return (string)$this->entityBody;
|
234 |
+
}
|
235 |
+
|
236 |
+
/**
|
237 |
+
* Calculates the value of HA1 according to RFC 2617 and RFC 2069.
|
238 |
+
*
|
239 |
+
* @return string The value of HA1
|
240 |
+
*/
|
241 |
+
private function getHA1()
|
242 |
+
{
|
243 |
+
$username = $this->getUsername();
|
244 |
+
$password = $this->getPassword();
|
245 |
+
$realm = $this->getRealm();
|
246 |
+
|
247 |
+
if(($username) AND ($password) AND ($realm)) {
|
248 |
+
$algorithm = $this->getAlgorithm();
|
249 |
+
|
250 |
+
if(!isset($algorithm) OR ($algorithm == "MD5")) {
|
251 |
+
|
252 |
+
$A1 = "{$username}:{$realm}:{$password}";
|
253 |
+
}
|
254 |
+
if($this->algorithm == "MD5-sess") {
|
255 |
+
|
256 |
+
$nonce = $this->getNonce();
|
257 |
+
$cnonce = $this->getClientNonce();
|
258 |
+
if(($nonce) AND ($cnonce)) {
|
259 |
+
$A1 = $this->hash("{$username}:{$realm}:{$password}") . ":{$nonce}:{$cnonce}";
|
260 |
+
}
|
261 |
+
}
|
262 |
+
if(isset($A1)) {
|
263 |
+
$HA1 = $this->hash($A1);
|
264 |
+
return $HA1;
|
265 |
+
}
|
266 |
+
}
|
267 |
+
return null;
|
268 |
+
}
|
269 |
+
|
270 |
+
/**
|
271 |
+
* Calculates the value of HA2 according to RFC 2617 and RFC 2069.
|
272 |
+
*
|
273 |
+
* @return string The value of HA2
|
274 |
+
*/
|
275 |
+
private function getHA2()
|
276 |
+
{
|
277 |
+
$method = $this->getMethod();
|
278 |
+
$uri = $this->getUri();
|
279 |
+
|
280 |
+
if(($method) AND ($uri)) {
|
281 |
+
$qop = $this->getQOP();
|
282 |
+
|
283 |
+
if(!isset($qop) OR ($qop == 'auth')) {
|
284 |
+
$A2 = "{$method}:{$uri}";
|
285 |
+
}
|
286 |
+
if($qop == 'auth-int') {
|
287 |
+
$entityBody = $this->getEntityBody();
|
288 |
+
$A2 = "{$method}:{$uri}:" . $this->hash($entityBody);
|
289 |
+
}
|
290 |
+
|
291 |
+
if(isset($A2)) {
|
292 |
+
$HA2 = $this->hash($A2);
|
293 |
+
return $HA2;
|
294 |
+
}
|
295 |
+
}
|
296 |
+
return null;
|
297 |
+
}
|
298 |
+
|
299 |
+
/**
|
300 |
+
* Returns the full Authentication header for use in authenticating the client with either Digest or Basic authentication.
|
301 |
+
*
|
302 |
+
* @return string The Authentication header to be sent to the server.
|
303 |
+
*/
|
304 |
+
private function getHeader()
|
305 |
+
{
|
306 |
+
if($this->getAuthenticationMethod() == 'Digest') {
|
307 |
+
$username = $this->getUsername();
|
308 |
+
$realm = $this->getRealm();
|
309 |
+
$nonce = $this->getNonce();
|
310 |
+
$response = $this->getResponse();
|
311 |
+
if(($username) AND ($realm) AND ($nonce) AND ($response)) {
|
312 |
+
$uri = $this->getUri();
|
313 |
+
$opaque = $this->getOpaque();
|
314 |
+
$domain = $this->getDomain();
|
315 |
+
$qop = $this->getQOP();
|
316 |
+
|
317 |
+
$header = "Authorization: Digest";
|
318 |
+
$header .= " username=\"" . $username . "\",";
|
319 |
+
$header .= " realm=\"" . $realm . "\",";
|
320 |
+
$header .= " nonce=\"" . $nonce . "\",";
|
321 |
+
$header .= " response=\"" . $response . "\",";
|
322 |
+
|
323 |
+
if($uri) {
|
324 |
+
$header .= " uri=\"" . $uri . "\",";
|
325 |
+
}
|
326 |
+
if($opaque) {
|
327 |
+
$header .= " opaque=\"" . $opaque . "\",";
|
328 |
+
}
|
329 |
+
|
330 |
+
if($qop) {
|
331 |
+
$header .= " qop=" . $qop . ",";
|
332 |
+
|
333 |
+
$cnonce = $this->getClientNonce();
|
334 |
+
$nc = $this->getNonceCount();
|
335 |
+
|
336 |
+
if($cnonce) {
|
337 |
+
$header .= " nc=" . $nc . ",";
|
338 |
+
}
|
339 |
+
if($cnonce) {
|
340 |
+
$header .= " cnonce=\"" . $cnonce . "\",";
|
341 |
+
}
|
342 |
+
}
|
343 |
+
|
344 |
+
// Remove the last comma from the header
|
345 |
+
$header = substr($header, 0, strlen($header) - 1);
|
346 |
+
// Discard the Client Nonce if OPTION_DISCARD_CLIENT_NONCE is set.
|
347 |
+
if(($this->options & DigestAuthListener::OPTION_DISCARD_CLIENT_NONCE) === true) {
|
348 |
+
$this->discardClientNonce();
|
349 |
+
}
|
350 |
+
return $header;
|
351 |
+
}
|
352 |
+
}
|
353 |
+
if($this->getAuthenticationMethod() == 'Basic') {
|
354 |
+
$username = $this->getUsername();
|
355 |
+
$password = $this->getPassword();
|
356 |
+
if(($username) AND ($password)) {
|
357 |
+
$header = 'Authorization: Basic ' . base64_encode("{$username}:{$password}");
|
358 |
+
return $header;
|
359 |
+
}
|
360 |
+
}
|
361 |
+
return null;
|
362 |
+
}
|
363 |
+
|
364 |
+
/**
|
365 |
+
* Returns the HTTP method used in the current request.
|
366 |
+
*
|
367 |
+
* @return string One of GET,POST,PUT,DELETE or HEAD.
|
368 |
+
*/
|
369 |
+
private function getMethod()
|
370 |
+
{
|
371 |
+
return $this->method;
|
372 |
+
}
|
373 |
+
|
374 |
+
/**
|
375 |
+
* Returns the value of nonce we have received in the server headers.
|
376 |
+
*
|
377 |
+
* @return string The value of the server nonce.
|
378 |
+
*/
|
379 |
+
private function getNonce()
|
380 |
+
{
|
381 |
+
return $this->nonce;
|
382 |
+
}
|
383 |
+
|
384 |
+
/**
|
385 |
+
* Returns the current nonce counter for the client nonce.
|
386 |
+
*
|
387 |
+
* @return string An eight digit zero-padded string which reflects the number of times the clientNonce has been generated.
|
388 |
+
*/
|
389 |
+
private function getNonceCount()
|
390 |
+
{
|
391 |
+
return $this->nonceCount;
|
392 |
+
}
|
393 |
+
|
394 |
+
/**
|
395 |
+
* Returns the opaque value that was sent to us from the server.
|
396 |
+
*
|
397 |
+
* @return string The value of opaque.
|
398 |
+
*/
|
399 |
+
private function getOpaque()
|
400 |
+
{
|
401 |
+
return $this->opaque;
|
402 |
+
}
|
403 |
+
|
404 |
+
/**
|
405 |
+
* Returns the plaintext password for the client.
|
406 |
+
*
|
407 |
+
* @return string The value of password.
|
408 |
+
*/
|
409 |
+
private function getPassword()
|
410 |
+
{
|
411 |
+
return $this->password;
|
412 |
+
}
|
413 |
+
|
414 |
+
/**
|
415 |
+
* Returns either the realm specified by the client, or the realm specified by the server.
|
416 |
+
* If the server set the value of realm then anything set by our client is overwritten.
|
417 |
+
*
|
418 |
+
* @return string The value of realm.
|
419 |
+
*/
|
420 |
+
private function getRealm()
|
421 |
+
{
|
422 |
+
return $this->realm;
|
423 |
+
}
|
424 |
+
|
425 |
+
/**
|
426 |
+
* Calculates the value of response according to RFC 2617 and RFC 2069.
|
427 |
+
*
|
428 |
+
* @return string The value of response
|
429 |
+
*/
|
430 |
+
private function getResponse()
|
431 |
+
{
|
432 |
+
$HA1 = $this->getHA1();
|
433 |
+
$nonce = $this->getNonce();
|
434 |
+
$HA2 = $this->getHA2();
|
435 |
+
|
436 |
+
if(($HA1) AND ($nonce) AND ($HA2)) {
|
437 |
+
$qop = $this->getQOP();
|
438 |
+
|
439 |
+
if(!isset($qop)) {
|
440 |
+
$response = $this->hash("{$HA1}:{$nonce}:{$HA2}");
|
441 |
+
return $response;
|
442 |
+
} else {
|
443 |
+
$cnonce = $this->getClientNonce();
|
444 |
+
$nc = $this->getNonceCount();
|
445 |
+
if(($cnonce) AND ($nc)) {
|
446 |
+
$response = $this->hash("{$HA1}:{$nonce}:{$nc}:{$cnonce}:{$qop}:{$HA2}");
|
447 |
+
return $response;
|
448 |
+
}
|
449 |
+
}
|
450 |
+
}
|
451 |
+
return null;
|
452 |
+
}
|
453 |
+
|
454 |
+
/**
|
455 |
+
* Returns the Quality of Protection to be used when authenticating with the server.
|
456 |
+
*
|
457 |
+
* @return string This will either be auth-int or auth.
|
458 |
+
*/
|
459 |
+
private function getQOP()
|
460 |
+
{
|
461 |
+
// Has the server specified any options for Quality of Protection
|
462 |
+
if(isset($this->qop) AND count($this->qop)) {
|
463 |
+
if(($this->options & DigestAuthListener::OPTION_QOP_AUTH_INT) === true) {
|
464 |
+
if(in_array('auth-int', $this->qop)) {
|
465 |
+
return 'auth-int';
|
466 |
+
}
|
467 |
+
if(in_array('auth', $this->qop)) {
|
468 |
+
return 'auth';
|
469 |
+
}
|
470 |
+
}
|
471 |
+
if(($this->options & DigestAuthListener::OPTION_QOP_AUTH) === true) {
|
472 |
+
if(in_array('auth', $this->qop)) {
|
473 |
+
return 'auth';
|
474 |
+
}
|
475 |
+
if(in_array('auth-int', $this->qop)) {
|
476 |
+
return 'auth-int';
|
477 |
+
}
|
478 |
+
}
|
479 |
+
}
|
480 |
+
// Server has not specified any value for Quality of Protection so return null
|
481 |
+
return null;
|
482 |
+
}
|
483 |
+
|
484 |
+
/**
|
485 |
+
* Returns the username set by the client to authenticate with the server.
|
486 |
+
*
|
487 |
+
* @return string The value of username
|
488 |
+
*/
|
489 |
+
private function getUsername()
|
490 |
+
{
|
491 |
+
return $this->username;
|
492 |
+
}
|
493 |
+
|
494 |
+
/**
|
495 |
+
* Returns the uri that we are requesting access to.
|
496 |
+
*
|
497 |
+
* @return string The value of uri
|
498 |
+
*/
|
499 |
+
private function getUri()
|
500 |
+
{
|
501 |
+
return $this->uri;
|
502 |
+
}
|
503 |
+
|
504 |
+
/**
|
505 |
+
* Calculates the hash for a given value using the algorithm specified by the server.
|
506 |
+
*
|
507 |
+
* @param string $value The value to be hashed
|
508 |
+
*
|
509 |
+
* @return string The hashed value.
|
510 |
+
*/
|
511 |
+
private function hash($value)
|
512 |
+
{
|
513 |
+
$algorithm = $this->getAlgorithm();
|
514 |
+
if(($algorithm == 'MD5') OR ($algorithm == 'MD5-sess')) {
|
515 |
+
return hash('md5', $value);
|
516 |
+
}
|
517 |
+
return null;
|
518 |
+
}
|
519 |
+
|
520 |
+
/**
|
521 |
+
* Parses the Authentication-Info header received from the server and calls the relevant setter method on each variable received.
|
522 |
+
*
|
523 |
+
* @param string $authenticationInfo The full Authentication-Info header.
|
524 |
+
*
|
525 |
+
* @return void
|
526 |
+
*/
|
527 |
+
private function parseAuthenticationInfoHeader($authenticationInfo)
|
528 |
+
{
|
529 |
+
// Remove "Authentication-Info: " from start of header
|
530 |
+
$wwwAuthenticate = substr($wwwAuthenticate, 21, strlen($wwwAuthenticate) - 21);
|
531 |
+
|
532 |
+
$nameValuePairs = $this->parseNameValuePairs($wwwAuthenticate);
|
533 |
+
foreach($nameValuePairs as $name => $value) {
|
534 |
+
switch($name) {
|
535 |
+
case 'message-qop':
|
536 |
+
|
537 |
+
break;
|
538 |
+
case 'nextnonce':
|
539 |
+
// This function needs to only set the Nonce once the rspauth has been verified.
|
540 |
+
$this->setNonce($value);
|
541 |
+
break;
|
542 |
+
case 'rspauth':
|
543 |
+
// Check server rspauth value
|
544 |
+
break;
|
545 |
+
}
|
546 |
+
}
|
547 |
+
}
|
548 |
+
|
549 |
+
/**
|
550 |
+
* Parses a string of name=value pairs separated by commas and returns and array with the name as the index.
|
551 |
+
*
|
552 |
+
* @param string $nameValuePairs The string containing the name=value pairs.
|
553 |
+
*
|
554 |
+
* @return array An array with the name used as the index and the values stored within.
|
555 |
+
*/
|
556 |
+
private function parseNameValuePairs($nameValuePairs)
|
557 |
+
{
|
558 |
+
$parsedNameValuePairs = array();
|
559 |
+
$nameValuePairs = explode(',', $nameValuePairs);
|
560 |
+
foreach($nameValuePairs as $nameValuePair) {
|
561 |
+
// Trim the Whitespace from the start and end of the name value pair string
|
562 |
+
$nameValuePair = trim($nameValuePair);
|
563 |
+
// Split $nameValuePair (name=value) into $name and $value
|
564 |
+
list($name, $value) = explode('=', $nameValuePair, 2);
|
565 |
+
// Remove quotes if the string is quoted
|
566 |
+
$value = $this->unquoteString($value);
|
567 |
+
// Add pair to array[name] => value
|
568 |
+
$parsedNameValuePairs[$name] = $value;
|
569 |
+
}
|
570 |
+
return $parsedNameValuePairs;
|
571 |
+
}
|
572 |
+
|
573 |
+
/**
|
574 |
+
* Parses the server headers received and checks for WWW-Authenticate and Authentication-Info headers.
|
575 |
+
* Calls parseWwwAuthenticateHeader() and parseAuthenticationInfoHeader() respectively if either of these headers are present.
|
576 |
+
*
|
577 |
+
* @param array $headers An array of the headers received by the client.
|
578 |
+
*
|
579 |
+
* @return void
|
580 |
+
*/
|
581 |
+
private function parseServerHeaders(array $headers)
|
582 |
+
{
|
583 |
+
foreach($headers as $header) {
|
584 |
+
// Check to see if the WWW-Authenticate header is present and if so set $authHeader
|
585 |
+
if(strtolower(substr($header, 0, 18)) == 'www-authenticate: ') {
|
586 |
+
$wwwAuthenticate = $header;
|
587 |
+
$this->parseWwwAuthenticateHeader($wwwAuthenticate);
|
588 |
+
}
|
589 |
+
// Check to see if the Authentication-Info header is present and if so set $authInfo
|
590 |
+
if(strtolower(substr($header, 0, 21)) == 'authentication-info: ') {
|
591 |
+
$authenticationInfo = $header;
|
592 |
+
$this->parseAuthenticationInfoHeader($wwwAuthenticate);
|
593 |
+
}
|
594 |
+
}
|
595 |
+
}
|
596 |
+
|
597 |
+
/**
|
598 |
+
* Parses the WWW-Authenticate header received from the server and calls the relevant setter method on each variable received.
|
599 |
+
*
|
600 |
+
* @param string $wwwAuthenticate The full WWW-Authenticate header.
|
601 |
+
*
|
602 |
+
* @return void
|
603 |
+
*/
|
604 |
+
private function parseWwwAuthenticateHeader($wwwAuthenticate)
|
605 |
+
{
|
606 |
+
// Remove "WWW-Authenticate: " from start of header
|
607 |
+
$wwwAuthenticate = substr($wwwAuthenticate, 18, strlen($wwwAuthenticate) - 18);
|
608 |
+
if(substr($wwwAuthenticate, 0, 7) == 'Digest ') {
|
609 |
+
$this->setAuthenticationMethod('Digest');
|
610 |
+
// Remove "Digest " from start of header
|
611 |
+
$wwwAuthenticate = substr($wwwAuthenticate, 7, strlen($wwwAuthenticate) - 7);
|
612 |
+
|
613 |
+
$nameValuePairs = $this->parseNameValuePairs($wwwAuthenticate);
|
614 |
+
|
615 |
+
foreach($nameValuePairs as $name => $value) {
|
616 |
+
switch($name) {
|
617 |
+
case 'algorithm':
|
618 |
+
$this->setAlgorithm($value);
|
619 |
+
break;
|
620 |
+
case 'domain':
|
621 |
+
$this->setDomain($value);
|
622 |
+
break;
|
623 |
+
case 'nonce':
|
624 |
+
$this->setNonce($value);
|
625 |
+
break;
|
626 |
+
case 'realm':
|
627 |
+
$this->setRealm($value);
|
628 |
+
break;
|
629 |
+
case 'opaque':
|
630 |
+
$this->setOpaque($value);
|
631 |
+
break;
|
632 |
+
case 'qop':
|
633 |
+
$this->setQOP(explode(',', $value));
|
634 |
+
break;
|
635 |
+
}
|
636 |
+
}
|
637 |
+
}
|
638 |
+
if (substr($wwwAuthenticate, 0, 6) == 'Basic ') {
|
639 |
+
$this->setAuthenticationMethod('Basic');
|
640 |
+
// Remove "Basic " from start of header
|
641 |
+
$wwwAuthenticate = substr($wwwAuthenticate, 6, strlen($wwwAuthenticate) - 6);
|
642 |
+
|
643 |
+
$nameValuePairs = $this->parseNameValuePairs($wwwAuthenticate);
|
644 |
+
|
645 |
+
foreach($nameValuePairs as $name => $value) {
|
646 |
+
switch($name) {
|
647 |
+
case 'realm':
|
648 |
+
$this->setRealm($value);
|
649 |
+
break;
|
650 |
+
}
|
651 |
+
}
|
652 |
+
}
|
653 |
+
}
|
654 |
+
|
655 |
+
/**
|
656 |
+
* Sets the hashing algorithm to be used. Currently only uses MD5 specified by either MD5 or MD5-sess.
|
657 |
+
* RFCs are currently in draft stage for the proposal of SHA-256 and SHA-512-256.
|
658 |
+
* Support will be added once the RFC leaves the draft stage.
|
659 |
+
*
|
660 |
+
* @param string $algorithm The algorithm the server has requested to use.
|
661 |
+
*
|
662 |
+
* @throws \InvalidArgumentException If $algorithm is set to anything other than MD5 or MD5-sess.
|
663 |
+
*
|
664 |
+
* @return void
|
665 |
+
*/
|
666 |
+
private function setAlgorithm($algorithm)
|
667 |
+
{
|
668 |
+
if(($algorithm == 'MD5') OR ($algorithm == 'MD5-sess')) {
|
669 |
+
$this->algorithm = $algorithm;
|
670 |
+
} else {
|
671 |
+
throw new \InvalidArgumentException('DigestAuthListener: Only MD5 and MD5-sess algorithms are currently supported.');
|
672 |
+
}
|
673 |
+
}
|
674 |
+
|
675 |
+
/**
|
676 |
+
* Sets authentication method to be used. Options are "Digest" and "Basic".
|
677 |
+
* If the server and the client are unable to authenticate using Digest then the RFCs state that the server should attempt
|
678 |
+
* to authenticate the client using Basic authentication. This ensures that we adhere to that behaviour.
|
679 |
+
* This does however create the possibilty of a downgrade attack so it may be an idea to add a way of disabling this functionality
|
680 |
+
* as Basic authentication is trivial to decrypt and exposes the username/password to a man-in-the-middle attack.
|
681 |
+
*
|
682 |
+
* @param string $authenticationMethod The authentication method requested by the server.
|
683 |
+
*
|
684 |
+
* @throws \InvalidArgumentException If $authenticationMethod is set to anything other than Digest or Basic
|
685 |
+
*
|
686 |
+
* @return void
|
687 |
+
*/
|
688 |
+
private function setAuthenticationMethod($authenticationMethod)
|
689 |
+
{
|
690 |
+
if(($authenticationMethod == 'Digest') OR ($authenticationMethod == 'Basic')) {
|
691 |
+
$this->authenticationMethod = $authenticationMethod;
|
692 |
+
} else {
|
693 |
+
throw new \InvalidArgumentException('DigestAuthListener: Only Digest and Basic authentication methods are currently supported.');
|
694 |
+
}
|
695 |
+
}
|
696 |
+
|
697 |
+
/**
|
698 |
+
* Sets the domain to be authenticated against. THIS IS NOT TO BE CONFUSED WITH THE HOSTNAME/DOMAIN.
|
699 |
+
* This is specified by the RFC to be a list of uris separated by spaces that the client will be allowed to access.
|
700 |
+
* An RFC in draft stage is proposing the removal of this functionality, it does not seem to be in widespread use.
|
701 |
+
*
|
702 |
+
* @param string $domain The list of uris separated by spaces that the client will be able to access upon successful authentication.
|
703 |
+
*
|
704 |
+
* @return void
|
705 |
+
*/
|
706 |
+
private function setDomain($value)
|
707 |
+
{
|
708 |
+
$this->domain = $value;
|
709 |
+
}
|
710 |
+
|
711 |
+
/**
|
712 |
+
* Sets the Entity Body of the Request for use with qop=auth-int
|
713 |
+
*
|
714 |
+
* @param string $entityBody The body of the entity (The unencoded request minus the headers).
|
715 |
+
*
|
716 |
+
* @return void
|
717 |
+
*/
|
718 |
+
private function setEntityBody($entityBody = null)
|
719 |
+
{
|
720 |
+
$this->entityBody = $entityBody;
|
721 |
+
}
|
722 |
+
|
723 |
+
/**
|
724 |
+
* Sets the HTTP method being used for the request
|
725 |
+
*
|
726 |
+
* @param string $method The HTTP method
|
727 |
+
*
|
728 |
+
* @throws \InvalidArgumentException If $method is set to anything other than GET,POST,PUT,DELETE or HEAD.
|
729 |
+
*
|
730 |
+
* @return void
|
731 |
+
*/
|
732 |
+
private function setMethod($method = null)
|
733 |
+
{
|
734 |
+
if($method == 'GET') {
|
735 |
+
$this->method = 'GET';
|
736 |
+
return;
|
737 |
+
}
|
738 |
+
if($method == 'POST') {
|
739 |
+
$this->method = 'POST';
|
740 |
+
return;
|
741 |
+
}
|
742 |
+
if($method == 'PUT') {
|
743 |
+
$this->method = 'PUT';
|
744 |
+
return;
|
745 |
+
}
|
746 |
+
if($method == 'DELETE') {
|
747 |
+
$this->method = 'DELETE';
|
748 |
+
return;
|
749 |
+
}
|
750 |
+
if($method == 'HEAD') {
|
751 |
+
$this->method = 'HEAD';
|
752 |
+
return;
|
753 |
+
}
|
754 |
+
throw new \InvalidArgumentException('DigestAuthListener: Only GET,POST,PUT,DELETE,HEAD HTTP methods are currently supported.');
|
755 |
+
}
|
756 |
+
|
757 |
+
/**
|
758 |
+
* Sets the value of nonce
|
759 |
+
*
|
760 |
+
* @param string $opaque The server nonce value
|
761 |
+
*
|
762 |
+
* @return void
|
763 |
+
*/
|
764 |
+
private function setNonce($nonce = null)
|
765 |
+
{
|
766 |
+
$this->nonce = $nonce;
|
767 |
+
}
|
768 |
+
|
769 |
+
/**
|
770 |
+
* Sets the value of opaque
|
771 |
+
*
|
772 |
+
* @param string $opaque The opaque value
|
773 |
+
*
|
774 |
+
* @return void
|
775 |
+
*/
|
776 |
+
private function setOpaque($opaque)
|
777 |
+
{
|
778 |
+
$this->opaque = $opaque;
|
779 |
+
}
|
780 |
+
|
781 |
+
/**
|
782 |
+
* Sets the acceptable value(s) for the quality of protection used by the server. Supported values are auth and auth-int.
|
783 |
+
* TODO: This method should give precedence to using qop=auth-int first as this offers integrity protection.
|
784 |
+
*
|
785 |
+
* @param array $qop An array with the values of qop that the server has specified it will accept.
|
786 |
+
*
|
787 |
+
* @throws \InvalidArgumentException If $qop contains any values other than auth-int or auth.
|
788 |
+
*
|
789 |
+
* @return void
|
790 |
+
*/
|
791 |
+
private function setQOP(array $qop = array())
|
792 |
+
{
|
793 |
+
$this->qop = array();
|
794 |
+
foreach($qop as $protection) {
|
795 |
+
$protection = trim($protection);
|
796 |
+
if($protection == 'auth-int') {
|
797 |
+
$this->qop[] = 'auth-int';
|
798 |
+
} elseif($protection == 'auth') {
|
799 |
+
$this->qop[] = 'auth';
|
800 |
+
} else {
|
801 |
+
throw new \InvalidArgumentException('DigestAuthListener: Only auth-int and auth are supported Quality of Protection mechanisms.');
|
802 |
+
}
|
803 |
+
}
|
804 |
+
}
|
805 |
+
|
806 |
+
/**
|
807 |
+
* Sets the value of uri
|
808 |
+
*
|
809 |
+
* @param string $uri The uri
|
810 |
+
*
|
811 |
+
* @return void
|
812 |
+
*/
|
813 |
+
private function setUri($uri = null)
|
814 |
+
{
|
815 |
+
$this->uri = $uri;
|
816 |
+
}
|
817 |
+
|
818 |
+
/**
|
819 |
+
* If a string contains quotation marks at either end this function will strip them. Otherwise it will remain unchanged.
|
820 |
+
*
|
821 |
+
* @param string $str The string to be stripped of quotation marks.
|
822 |
+
*
|
823 |
+
* @return string Returns the original string without the quotation marks at either end.
|
824 |
+
*/
|
825 |
+
private function unquoteString($str = null)
|
826 |
+
{
|
827 |
+
if($str) {
|
828 |
+
if(substr($str, 0, 1) == '"') {
|
829 |
+
$str = substr($str, 1, strlen($str) - 1);
|
830 |
+
}
|
831 |
+
if(substr($str, strlen($str) - 1, 1) == '"') {
|
832 |
+
$str = substr($str, 0, strlen($str) - 1);
|
833 |
+
}
|
834 |
+
}
|
835 |
+
return $str;
|
836 |
+
}
|
837 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Listener/History/Entry.php
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Listener\History;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\MessageInterface;
|
6 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
7 |
+
|
8 |
+
class Entry
|
9 |
+
{
|
10 |
+
private $request;
|
11 |
+
private $response;
|
12 |
+
private $duration;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Constructor.
|
16 |
+
*
|
17 |
+
* @param RequestInterface $request The request
|
18 |
+
* @param MessageInterface $response The response
|
19 |
+
* @param integer $duration The duration in seconds
|
20 |
+
*/
|
21 |
+
public function __construct(RequestInterface $request, MessageInterface $response, $duration = null)
|
22 |
+
{
|
23 |
+
$this->request = $request;
|
24 |
+
$this->response = $response;
|
25 |
+
$this->duration = $duration;
|
26 |
+
}
|
27 |
+
|
28 |
+
public function getRequest()
|
29 |
+
{
|
30 |
+
return $this->request;
|
31 |
+
}
|
32 |
+
|
33 |
+
public function getResponse()
|
34 |
+
{
|
35 |
+
return $this->response;
|
36 |
+
}
|
37 |
+
|
38 |
+
public function getDuration()
|
39 |
+
{
|
40 |
+
return $this->duration;
|
41 |
+
}
|
42 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Listener/History/Journal.php
ADDED
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Listener\History;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\MessageInterface;
|
6 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
7 |
+
|
8 |
+
class Journal implements \Countable, \IteratorAggregate
|
9 |
+
{
|
10 |
+
private $entries = array();
|
11 |
+
private $limit = 10;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Records an entry in the journal.
|
15 |
+
*
|
16 |
+
* @param RequestInterface $request The request
|
17 |
+
* @param MessageInterface $response The response
|
18 |
+
* @param integer $duration The duration in seconds
|
19 |
+
*/
|
20 |
+
public function record(RequestInterface $request, MessageInterface $response, $duration = null)
|
21 |
+
{
|
22 |
+
$this->addEntry(new Entry($request, $response, $duration));
|
23 |
+
}
|
24 |
+
|
25 |
+
public function addEntry(Entry $entry)
|
26 |
+
{
|
27 |
+
array_push($this->entries, $entry);
|
28 |
+
$this->entries = array_slice($this->entries, $this->getLimit() * -1);
|
29 |
+
end($this->entries);
|
30 |
+
}
|
31 |
+
|
32 |
+
public function getEntries()
|
33 |
+
{
|
34 |
+
return $this->entries;
|
35 |
+
}
|
36 |
+
|
37 |
+
public function getLast()
|
38 |
+
{
|
39 |
+
return end($this->entries);
|
40 |
+
}
|
41 |
+
|
42 |
+
public function getLastRequest()
|
43 |
+
{
|
44 |
+
return $this->getLast()->getRequest();
|
45 |
+
}
|
46 |
+
|
47 |
+
public function getLastResponse()
|
48 |
+
{
|
49 |
+
return $this->getLast()->getResponse();
|
50 |
+
}
|
51 |
+
|
52 |
+
public function clear()
|
53 |
+
{
|
54 |
+
$this->entries = array();
|
55 |
+
}
|
56 |
+
|
57 |
+
public function count()
|
58 |
+
{
|
59 |
+
return count($this->entries);
|
60 |
+
}
|
61 |
+
|
62 |
+
public function setLimit($limit)
|
63 |
+
{
|
64 |
+
$this->limit = $limit;
|
65 |
+
}
|
66 |
+
|
67 |
+
public function getLimit()
|
68 |
+
{
|
69 |
+
return $this->limit;
|
70 |
+
}
|
71 |
+
|
72 |
+
public function getIterator()
|
73 |
+
{
|
74 |
+
return new \ArrayIterator(array_reverse($this->entries));
|
75 |
+
}
|
76 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Listener/HistoryListener.php
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Listener;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Listener\History\Journal;
|
6 |
+
use WebinterpretConnector\Buzz\Message\MessageInterface;
|
7 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
8 |
+
|
9 |
+
class HistoryListener implements ListenerInterface
|
10 |
+
{
|
11 |
+
private $journal;
|
12 |
+
private $startTime;
|
13 |
+
|
14 |
+
public function __construct(Journal $journal)
|
15 |
+
{
|
16 |
+
$this->journal = $journal;
|
17 |
+
}
|
18 |
+
|
19 |
+
public function getJournal()
|
20 |
+
{
|
21 |
+
return $this->journal;
|
22 |
+
}
|
23 |
+
|
24 |
+
public function preSend(RequestInterface $request)
|
25 |
+
{
|
26 |
+
$this->startTime = microtime(true);
|
27 |
+
}
|
28 |
+
|
29 |
+
public function postSend(RequestInterface $request, MessageInterface $response)
|
30 |
+
{
|
31 |
+
$this->journal->record($request, $response, microtime(true) - $this->startTime);
|
32 |
+
}
|
33 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Listener/ListenerChain.php
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Listener;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\MessageInterface;
|
6 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
7 |
+
|
8 |
+
class ListenerChain implements ListenerInterface
|
9 |
+
{
|
10 |
+
private $listeners;
|
11 |
+
|
12 |
+
public function __construct(array $listeners = array())
|
13 |
+
{
|
14 |
+
$this->listeners = $listeners;
|
15 |
+
}
|
16 |
+
|
17 |
+
public function addListener(ListenerInterface $listener)
|
18 |
+
{
|
19 |
+
$this->listeners[] = $listener;
|
20 |
+
}
|
21 |
+
|
22 |
+
public function getListeners()
|
23 |
+
{
|
24 |
+
return $this->listeners;
|
25 |
+
}
|
26 |
+
|
27 |
+
public function preSend(RequestInterface $request)
|
28 |
+
{
|
29 |
+
foreach ($this->listeners as $listener) {
|
30 |
+
$listener->preSend($request);
|
31 |
+
}
|
32 |
+
}
|
33 |
+
|
34 |
+
public function postSend(RequestInterface $request, MessageInterface $response)
|
35 |
+
{
|
36 |
+
foreach ($this->listeners as $listener) {
|
37 |
+
$listener->postSend($request, $response);
|
38 |
+
}
|
39 |
+
}
|
40 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Listener/ListenerInterface.php
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Listener;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\MessageInterface;
|
6 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
7 |
+
|
8 |
+
interface ListenerInterface
|
9 |
+
{
|
10 |
+
public function preSend(RequestInterface $request);
|
11 |
+
public function postSend(RequestInterface $request, MessageInterface $response);
|
12 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Listener/LoggerListener.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Listener;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\MessageInterface;
|
6 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
7 |
+
use WebinterpretConnector\Buzz\Exception\InvalidArgumentException;
|
8 |
+
|
9 |
+
class LoggerListener implements ListenerInterface
|
10 |
+
{
|
11 |
+
private $logger;
|
12 |
+
private $prefix;
|
13 |
+
private $startTime;
|
14 |
+
|
15 |
+
public function __construct($logger, $prefix = null)
|
16 |
+
{
|
17 |
+
if (!is_callable($logger)) {
|
18 |
+
throw new InvalidArgumentException('The logger must be a callable.');
|
19 |
+
}
|
20 |
+
|
21 |
+
$this->logger = $logger;
|
22 |
+
$this->prefix = $prefix;
|
23 |
+
}
|
24 |
+
|
25 |
+
public function preSend(RequestInterface $request)
|
26 |
+
{
|
27 |
+
$this->startTime = microtime(true);
|
28 |
+
}
|
29 |
+
|
30 |
+
public function postSend(RequestInterface $request, MessageInterface $response)
|
31 |
+
{
|
32 |
+
$seconds = microtime(true) - $this->startTime;
|
33 |
+
|
34 |
+
call_user_func($this->logger, sprintf('%sSent "%s %s%s" in %dms', $this->prefix, $request->getMethod(), $request->getHost(), $request->getResource(), round($seconds * 1000)));
|
35 |
+
}
|
36 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Message/AbstractMessage.php
ADDED
@@ -0,0 +1,154 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Message;
|
4 |
+
|
5 |
+
abstract class AbstractMessage implements MessageInterface
|
6 |
+
{
|
7 |
+
private $headers = array();
|
8 |
+
private $content;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Returns the value of a header.
|
12 |
+
*
|
13 |
+
* @param string $name
|
14 |
+
* @param string|boolean $glue Glue for implode, or false to return an array
|
15 |
+
*
|
16 |
+
* @return string|array|null
|
17 |
+
*/
|
18 |
+
public function getHeader($name, $glue = "\r\n")
|
19 |
+
{
|
20 |
+
$needle = $name.':';
|
21 |
+
|
22 |
+
$values = array();
|
23 |
+
foreach ($this->getHeaders() as $header) {
|
24 |
+
if (0 === stripos($header, $needle)) {
|
25 |
+
$values[] = trim(substr($header, strlen($needle)));
|
26 |
+
}
|
27 |
+
}
|
28 |
+
|
29 |
+
if (false === $glue) {
|
30 |
+
return $values;
|
31 |
+
} else {
|
32 |
+
return count($values) ? implode($glue, $values) : null;
|
33 |
+
}
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Returns a header's attributes.
|
38 |
+
*
|
39 |
+
* @param string $name A header name
|
40 |
+
*
|
41 |
+
* @return array An associative array of attributes
|
42 |
+
*/
|
43 |
+
public function getHeaderAttributes($name)
|
44 |
+
{
|
45 |
+
$attributes = array();
|
46 |
+
foreach ($this->getHeader($name, false) as $header) {
|
47 |
+
if (false !== strpos($header, ';')) {
|
48 |
+
// remove header value
|
49 |
+
list(, $header) = explode(';', $header, 2);
|
50 |
+
|
51 |
+
// loop through attribute key=value pairs
|
52 |
+
foreach (array_map('trim', explode(';', trim($header))) as $pair) {
|
53 |
+
list($key, $value) = explode('=', $pair);
|
54 |
+
$attributes[$key] = $value;
|
55 |
+
}
|
56 |
+
}
|
57 |
+
}
|
58 |
+
|
59 |
+
return $attributes;
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Returns the value of a particular header attribute.
|
64 |
+
*
|
65 |
+
* @param string $header A header name
|
66 |
+
* @param string $attribute An attribute name
|
67 |
+
*
|
68 |
+
* @return string|null The value of the attribute or null if it isn't set
|
69 |
+
*/
|
70 |
+
public function getHeaderAttribute($header, $attribute)
|
71 |
+
{
|
72 |
+
$attributes = $this->getHeaderAttributes($header);
|
73 |
+
|
74 |
+
if (isset($attributes[$attribute])) {
|
75 |
+
return $attributes[$attribute];
|
76 |
+
}
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Returns the current message as a DOMDocument.
|
81 |
+
*
|
82 |
+
* @return \DOMDocument
|
83 |
+
*/
|
84 |
+
public function toDomDocument()
|
85 |
+
{
|
86 |
+
$revert = libxml_use_internal_errors(true);
|
87 |
+
|
88 |
+
$document = new \DOMDocument('1.0', $this->getHeaderAttribute('Content-Type', 'charset') ?: 'UTF-8');
|
89 |
+
if (0 === strpos($this->getHeader('Content-Type'), 'text/xml')) {
|
90 |
+
$document->loadXML($this->getContent());
|
91 |
+
} else {
|
92 |
+
$document->loadHTML($this->getContent());
|
93 |
+
}
|
94 |
+
|
95 |
+
libxml_use_internal_errors($revert);
|
96 |
+
|
97 |
+
return $document;
|
98 |
+
}
|
99 |
+
|
100 |
+
public function setHeaders(array $headers)
|
101 |
+
{
|
102 |
+
$this->headers = $this->flattenHeaders($headers);
|
103 |
+
}
|
104 |
+
|
105 |
+
public function addHeader($header)
|
106 |
+
{
|
107 |
+
$this->headers[] = $header;
|
108 |
+
}
|
109 |
+
|
110 |
+
public function addHeaders(array $headers)
|
111 |
+
{
|
112 |
+
$this->headers = array_merge($this->headers, $this->flattenHeaders($headers));
|
113 |
+
}
|
114 |
+
|
115 |
+
public function getHeaders()
|
116 |
+
{
|
117 |
+
return $this->headers;
|
118 |
+
}
|
119 |
+
|
120 |
+
public function setContent($content)
|
121 |
+
{
|
122 |
+
$this->content = $content;
|
123 |
+
}
|
124 |
+
|
125 |
+
public function getContent()
|
126 |
+
{
|
127 |
+
return $this->content;
|
128 |
+
}
|
129 |
+
|
130 |
+
public function __toString()
|
131 |
+
{
|
132 |
+
$string = implode("\r\n", $this->getHeaders())."\r\n";
|
133 |
+
|
134 |
+
if ($content = $this->getContent()) {
|
135 |
+
$string .= "\r\n$content\r\n";
|
136 |
+
}
|
137 |
+
|
138 |
+
return $string;
|
139 |
+
}
|
140 |
+
|
141 |
+
protected function flattenHeaders(array $headers)
|
142 |
+
{
|
143 |
+
$flattened = array();
|
144 |
+
foreach ($headers as $key => $header) {
|
145 |
+
if (is_int($key)) {
|
146 |
+
$flattened[] = $header;
|
147 |
+
} else {
|
148 |
+
$flattened[] = $key.': '.$header;
|
149 |
+
}
|
150 |
+
}
|
151 |
+
|
152 |
+
return $flattened;
|
153 |
+
}
|
154 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Message/Factory/Factory.php
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Message\Factory;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\Form\FormRequest;
|
6 |
+
use WebinterpretConnector\Buzz\Message\Request;
|
7 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
8 |
+
use WebinterpretConnector\Buzz\Message\Response;
|
9 |
+
|
10 |
+
class Factory implements FactoryInterface
|
11 |
+
{
|
12 |
+
public function createRequest($method = RequestInterface::METHOD_GET, $resource = '/', $host = null)
|
13 |
+
{
|
14 |
+
return new Request($method, $resource, $host);
|
15 |
+
}
|
16 |
+
|
17 |
+
public function createFormRequest($method = RequestInterface::METHOD_POST, $resource = '/', $host = null)
|
18 |
+
{
|
19 |
+
return new FormRequest($method, $resource, $host);
|
20 |
+
}
|
21 |
+
|
22 |
+
public function createResponse()
|
23 |
+
{
|
24 |
+
return new Response();
|
25 |
+
}
|
26 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Message/Factory/FactoryInterface.php
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Message\Factory;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
6 |
+
|
7 |
+
interface FactoryInterface
|
8 |
+
{
|
9 |
+
public function createRequest($method = RequestInterface::METHOD_GET, $resource = '/', $host = null);
|
10 |
+
public function createFormRequest($method = RequestInterface::METHOD_POST, $resource = '/', $host = null);
|
11 |
+
public function createResponse();
|
12 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Message/Form/FormRequest.php
ADDED
@@ -0,0 +1,187 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Message\Form;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\Request;
|
6 |
+
use WebinterpretConnector\Buzz\Exception\LogicException;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* FormRequest.
|
10 |
+
*
|
11 |
+
* $request = new FormRequest();
|
12 |
+
* $request->setField('user[name]', 'Kris Wallsmith');
|
13 |
+
* $request->setField('user[image]', new FormUpload('/path/to/image.jpg'));
|
14 |
+
*
|
15 |
+
* @author Marc Weistroff <marc.weistroff@sensio.com>
|
16 |
+
* @author Kris Wallsmith <kris.wallsmith@gmail.com>
|
17 |
+
*/
|
18 |
+
class FormRequest extends Request implements FormRequestInterface
|
19 |
+
{
|
20 |
+
private $fields = array();
|
21 |
+
private $boundary;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Constructor.
|
25 |
+
*
|
26 |
+
* Defaults to POST rather than GET.
|
27 |
+
*/
|
28 |
+
public function __construct($method = self::METHOD_POST, $resource = '/', $host = null)
|
29 |
+
{
|
30 |
+
parent::__construct($method, $resource, $host);
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Sets the value of a form field.
|
35 |
+
*
|
36 |
+
* If the value is an array it will be flattened and one field value will
|
37 |
+
* be added for each leaf.
|
38 |
+
*/
|
39 |
+
public function setField($name, $value)
|
40 |
+
{
|
41 |
+
if (is_array($value)) {
|
42 |
+
$this->addFields(array($name => $value));
|
43 |
+
|
44 |
+
return;
|
45 |
+
}
|
46 |
+
|
47 |
+
if ('[]' == substr($name, -2)) {
|
48 |
+
$this->fields[substr($name, 0, -2)][] = $value;
|
49 |
+
} else {
|
50 |
+
$this->fields[$name] = $value;
|
51 |
+
}
|
52 |
+
}
|
53 |
+
|
54 |
+
public function addFields(array $fields)
|
55 |
+
{
|
56 |
+
foreach ($this->flattenArray($fields) as $name => $value) {
|
57 |
+
$this->setField($name, $value);
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
public function setFields(array $fields)
|
62 |
+
{
|
63 |
+
$this->fields = array();
|
64 |
+
$this->addFields($fields);
|
65 |
+
}
|
66 |
+
|
67 |
+
public function getFields()
|
68 |
+
{
|
69 |
+
return $this->fields;
|
70 |
+
}
|
71 |
+
|
72 |
+
public function getResource()
|
73 |
+
{
|
74 |
+
$resource = parent::getResource();
|
75 |
+
|
76 |
+
if (!$this->isSafe() || !$this->fields) {
|
77 |
+
return $resource;
|
78 |
+
}
|
79 |
+
|
80 |
+
// append the query string
|
81 |
+
$resource .= false === strpos($resource, '?') ? '?' : '&';
|
82 |
+
$resource .= http_build_query($this->fields);
|
83 |
+
|
84 |
+
return $resource;
|
85 |
+
}
|
86 |
+
|
87 |
+
public function setContent($content)
|
88 |
+
{
|
89 |
+
throw new \BadMethodCallException('It is not permitted to set the content.');
|
90 |
+
}
|
91 |
+
|
92 |
+
public function getHeaders()
|
93 |
+
{
|
94 |
+
$headers = parent::getHeaders();
|
95 |
+
|
96 |
+
if ($this->isSafe()) {
|
97 |
+
return $headers;
|
98 |
+
}
|
99 |
+
|
100 |
+
if ($this->isMultipart()) {
|
101 |
+
$headers[] = 'Content-Type: multipart/form-data; boundary='.$this->getBoundary();
|
102 |
+
} else {
|
103 |
+
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
|
104 |
+
}
|
105 |
+
|
106 |
+
return $headers;
|
107 |
+
}
|
108 |
+
|
109 |
+
public function getContent()
|
110 |
+
{
|
111 |
+
if ($this->isSafe()) {
|
112 |
+
return;
|
113 |
+
}
|
114 |
+
|
115 |
+
if (!$this->isMultipart()) {
|
116 |
+
return http_build_query($this->fields, '', '&');
|
117 |
+
}
|
118 |
+
|
119 |
+
$content = '';
|
120 |
+
|
121 |
+
foreach ($this->fields as $name => $values) {
|
122 |
+
$content .= '--'.$this->getBoundary()."\r\n";
|
123 |
+
if ($values instanceof FormUploadInterface) {
|
124 |
+
if (!$values->getFilename()) {
|
125 |
+
throw new LogicException(sprintf('Form upload at "%s" does not include a filename.', $name));
|
126 |
+
}
|
127 |
+
|
128 |
+
$values->setName($name);
|
129 |
+
$content .= (string) $values;
|
130 |
+
} else {
|
131 |
+
foreach (is_array($values) ? $values : array($values) as $value) {
|
132 |
+
$content .= "Content-Disposition: form-data; name=\"$name\"\r\n";
|
133 |
+
$content .= "\r\n";
|
134 |
+
$content .= $value."\r\n";
|
135 |
+
}
|
136 |
+
}
|
137 |
+
}
|
138 |
+
|
139 |
+
$content .= '--'.$this->getBoundary().'--';
|
140 |
+
|
141 |
+
return $content;
|
142 |
+
}
|
143 |
+
|
144 |
+
// private
|
145 |
+
|
146 |
+
private function flattenArray(array $values, $prefix = '', $format = '%s')
|
147 |
+
{
|
148 |
+
$flat = array();
|
149 |
+
|
150 |
+
foreach ($values as $name => $value) {
|
151 |
+
$flatName = $prefix.sprintf($format, $name);
|
152 |
+
|
153 |
+
if (is_array($value)) {
|
154 |
+
$flat += $this->flattenArray($value, $flatName, '[%s]');
|
155 |
+
} else {
|
156 |
+
$flat[$flatName] = $value;
|
157 |
+
}
|
158 |
+
}
|
159 |
+
|
160 |
+
return $flat;
|
161 |
+
}
|
162 |
+
|
163 |
+
private function isSafe()
|
164 |
+
{
|
165 |
+
return in_array($this->getMethod(), array(self::METHOD_GET, self::METHOD_HEAD));
|
166 |
+
}
|
167 |
+
|
168 |
+
private function isMultipart()
|
169 |
+
{
|
170 |
+
foreach ($this->fields as $name => $value) {
|
171 |
+
if (is_object($value) && $value instanceof FormUploadInterface) {
|
172 |
+
return true;
|
173 |
+
}
|
174 |
+
}
|
175 |
+
|
176 |
+
return false;
|
177 |
+
}
|
178 |
+
|
179 |
+
private function getBoundary()
|
180 |
+
{
|
181 |
+
if (!$this->boundary) {
|
182 |
+
$this->boundary = sha1(rand(11111, 99999).time().uniqid());
|
183 |
+
}
|
184 |
+
|
185 |
+
return $this->boundary;
|
186 |
+
}
|
187 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Message/Form/FormRequestInterface.php
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Message\Form;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* An HTTP request message sent by a web form.
|
9 |
+
*
|
10 |
+
* @author Kris Wallsmith <kris.wallsmith@gmail.com>
|
11 |
+
*/
|
12 |
+
interface FormRequestInterface extends RequestInterface
|
13 |
+
{
|
14 |
+
/**
|
15 |
+
* Returns an array of field names and values.
|
16 |
+
*
|
17 |
+
* @return array A array of names and values
|
18 |
+
*/
|
19 |
+
public function getFields();
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Sets the form fields for the current request.
|
23 |
+
*
|
24 |
+
* @param array $fields An array of field names and values
|
25 |
+
*/
|
26 |
+
public function setFields(array $fields);
|
27 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Message/Form/FormUpload.php
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Message\Form;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\AbstractMessage;
|
6 |
+
|
7 |
+
class FormUpload extends AbstractMessage implements FormUploadInterface
|
8 |
+
{
|
9 |
+
private $name;
|
10 |
+
private $filename;
|
11 |
+
private $contentType;
|
12 |
+
private $file;
|
13 |
+
|
14 |
+
public function __construct($file = null, $contentType = null)
|
15 |
+
{
|
16 |
+
if ($file) {
|
17 |
+
$this->loadContent($file);
|
18 |
+
}
|
19 |
+
|
20 |
+
$this->contentType = $contentType;
|
21 |
+
}
|
22 |
+
|
23 |
+
public function getName()
|
24 |
+
{
|
25 |
+
return $this->name;
|
26 |
+
}
|
27 |
+
|
28 |
+
public function setName($name)
|
29 |
+
{
|
30 |
+
$this->name = $name;
|
31 |
+
}
|
32 |
+
|
33 |
+
public function getFilename()
|
34 |
+
{
|
35 |
+
if ($this->filename) {
|
36 |
+
return $this->filename;
|
37 |
+
} elseif ($this->file) {
|
38 |
+
return basename($this->file);
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
public function setFilename($filename)
|
43 |
+
{
|
44 |
+
$this->filename = $filename;
|
45 |
+
}
|
46 |
+
|
47 |
+
public function getContentType()
|
48 |
+
{
|
49 |
+
return $this->contentType ?: $this->detectContentType() ?: 'application/octet-stream';
|
50 |
+
}
|
51 |
+
|
52 |
+
public function setContentType($contentType)
|
53 |
+
{
|
54 |
+
$this->contentType = $contentType;
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Prepends Content-Disposition and Content-Type headers.
|
59 |
+
*/
|
60 |
+
public function getHeaders()
|
61 |
+
{
|
62 |
+
$headers = array('Content-Disposition: form-data');
|
63 |
+
|
64 |
+
if ($name = $this->getName()) {
|
65 |
+
$headers[0] .= sprintf('; name="%s"', $name);
|
66 |
+
}
|
67 |
+
|
68 |
+
if ($filename = $this->getFilename()) {
|
69 |
+
$headers[0] .= sprintf('; filename="%s"', $filename);
|
70 |
+
}
|
71 |
+
|
72 |
+
if ($contentType = $this->getContentType()) {
|
73 |
+
$headers[] = 'Content-Type: '.$contentType;
|
74 |
+
}
|
75 |
+
|
76 |
+
return array_merge($headers, parent::getHeaders());
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Loads the content from a file.
|
81 |
+
*/
|
82 |
+
public function loadContent($file)
|
83 |
+
{
|
84 |
+
$this->file = $file;
|
85 |
+
|
86 |
+
parent::setContent(null);
|
87 |
+
}
|
88 |
+
|
89 |
+
public function setContent($content)
|
90 |
+
{
|
91 |
+
parent::setContent($content);
|
92 |
+
|
93 |
+
$this->file = null;
|
94 |
+
}
|
95 |
+
|
96 |
+
public function getFile()
|
97 |
+
{
|
98 |
+
return $this->file;
|
99 |
+
}
|
100 |
+
|
101 |
+
public function getContent()
|
102 |
+
{
|
103 |
+
return $this->file ? file_get_contents($this->file) : parent::getContent();
|
104 |
+
}
|
105 |
+
|
106 |
+
// private
|
107 |
+
|
108 |
+
private function detectContentType()
|
109 |
+
{
|
110 |
+
if (!class_exists('finfo', false)) {
|
111 |
+
return false;
|
112 |
+
}
|
113 |
+
|
114 |
+
$finfo = new \finfo(FILEINFO_MIME_TYPE);
|
115 |
+
|
116 |
+
return $this->file ? $finfo->file($this->file) : $finfo->buffer(parent::getContent());
|
117 |
+
}
|
118 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Message/Form/FormUploadInterface.php
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Message\Form;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\MessageInterface;
|
6 |
+
|
7 |
+
interface FormUploadInterface extends MessageInterface
|
8 |
+
{
|
9 |
+
public function setName($name);
|
10 |
+
public function getFile();
|
11 |
+
public function getFilename();
|
12 |
+
public function getContentType();
|
13 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Message/MessageInterface.php
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Message;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* An HTTP message.
|
7 |
+
*
|
8 |
+
* @author Kris Wallsmith <kris.wallsmith@gmail.com>
|
9 |
+
*/
|
10 |
+
interface MessageInterface
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Returns a header value.
|
14 |
+
*
|
15 |
+
* @param string $name A header name
|
16 |
+
* @param string|boolean $glue Glue for implode, or false to return an array
|
17 |
+
*
|
18 |
+
* @return string|array|null The header value(s)
|
19 |
+
*/
|
20 |
+
public function getHeader($name, $glue = "\r\n");
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Returns an array of header lines.
|
24 |
+
*
|
25 |
+
* @return array An array of header lines (integer indexes, e.g. ["Header: value"])
|
26 |
+
*/
|
27 |
+
public function getHeaders();
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Sets all headers on the current message.
|
31 |
+
*
|
32 |
+
* Headers can be complete ["Header: value"] pairs or an associative array ["Header" => "value"]
|
33 |
+
*
|
34 |
+
* @param array $headers An array of header lines
|
35 |
+
*/
|
36 |
+
public function setHeaders(array $headers);
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Adds a header to this message.
|
40 |
+
*
|
41 |
+
* @param string $header A header line
|
42 |
+
*/
|
43 |
+
public function addHeader($header);
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Adds a set of headers to this message.
|
47 |
+
*
|
48 |
+
* Headers can be complete ["Header: value"] pairs or an associative array ["Header" => "value"]
|
49 |
+
*
|
50 |
+
* @param array $headers Headers
|
51 |
+
*/
|
52 |
+
public function addHeaders(array $headers);
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Returns the content of the message.
|
56 |
+
*
|
57 |
+
* @return string The message content
|
58 |
+
*/
|
59 |
+
public function getContent();
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Sets the content of the message.
|
63 |
+
*
|
64 |
+
* @param string $content The message content
|
65 |
+
*/
|
66 |
+
public function setContent($content);
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Returns the message document.
|
70 |
+
*
|
71 |
+
* @return string The message
|
72 |
+
*/
|
73 |
+
public function __toString();
|
74 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Message/Request.php
ADDED
@@ -0,0 +1,174 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Message;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Util\Url;
|
6 |
+
|
7 |
+
class Request extends AbstractMessage implements RequestInterface
|
8 |
+
{
|
9 |
+
private $method;
|
10 |
+
private $resource;
|
11 |
+
private $host;
|
12 |
+
private $protocolVersion = 1.1;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Constructor.
|
16 |
+
*
|
17 |
+
* @param string $method
|
18 |
+
* @param string $resource
|
19 |
+
* @param string $host
|
20 |
+
*/
|
21 |
+
public function __construct($method = self::METHOD_GET, $resource = '/', $host = null)
|
22 |
+
{
|
23 |
+
$this->method = strtoupper($method);
|
24 |
+
$this->resource = $resource;
|
25 |
+
$this->host = $host;
|
26 |
+
}
|
27 |
+
|
28 |
+
public function setHeaders(array $headers)
|
29 |
+
{
|
30 |
+
parent::setHeaders(array());
|
31 |
+
|
32 |
+
foreach ($this->flattenHeaders($headers) as $header) {
|
33 |
+
$this->addHeader($header);
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
public function addHeader($header)
|
38 |
+
{
|
39 |
+
if (0 === stripos(substr($header, -8), 'HTTP/1.') && 3 == count($parts = explode(' ', $header))) {
|
40 |
+
list($method, $resource, $protocolVersion) = $parts;
|
41 |
+
|
42 |
+
$this->setMethod($method);
|
43 |
+
$this->setResource($resource);
|
44 |
+
$this->setProtocolVersion((float) substr($protocolVersion, 5));
|
45 |
+
} else {
|
46 |
+
parent::addHeader($header);
|
47 |
+
}
|
48 |
+
}
|
49 |
+
|
50 |
+
public function setMethod($method)
|
51 |
+
{
|
52 |
+
$this->method = strtoupper($method);
|
53 |
+
}
|
54 |
+
|
55 |
+
public function getMethod()
|
56 |
+
{
|
57 |
+
return $this->method;
|
58 |
+
}
|
59 |
+
|
60 |
+
public function setResource($resource)
|
61 |
+
{
|
62 |
+
$this->resource = $resource;
|
63 |
+
}
|
64 |
+
|
65 |
+
public function getResource()
|
66 |
+
{
|
67 |
+
return $this->resource;
|
68 |
+
}
|
69 |
+
|
70 |
+
public function setHost($host)
|
71 |
+
{
|
72 |
+
$this->host = $host;
|
73 |
+
}
|
74 |
+
|
75 |
+
public function getHost()
|
76 |
+
{
|
77 |
+
return $this->host;
|
78 |
+
}
|
79 |
+
|
80 |
+
public function setProtocolVersion($protocolVersion)
|
81 |
+
{
|
82 |
+
$this->protocolVersion = $protocolVersion;
|
83 |
+
}
|
84 |
+
|
85 |
+
public function getProtocolVersion()
|
86 |
+
{
|
87 |
+
return $this->protocolVersion;
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* A convenience method for getting the full URL of the current request.
|
92 |
+
*
|
93 |
+
* @return string
|
94 |
+
*/
|
95 |
+
public function getUrl()
|
96 |
+
{
|
97 |
+
return $this->getHost().$this->getResource();
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* A convenience method for populating the current request from a URL.
|
102 |
+
*
|
103 |
+
* @param Url|string $url An URL
|
104 |
+
*/
|
105 |
+
public function fromUrl($url)
|
106 |
+
{
|
107 |
+
if (!$url instanceof Url) {
|
108 |
+
$url = new Url($url);
|
109 |
+
}
|
110 |
+
|
111 |
+
$url->applyToRequest($this);
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Returns true if the current request is secure.
|
116 |
+
*
|
117 |
+
* @return boolean
|
118 |
+
*/
|
119 |
+
public function isSecure()
|
120 |
+
{
|
121 |
+
return 'https' == parse_url($this->getHost(), PHP_URL_SCHEME);
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Merges cookie headers on the way out.
|
126 |
+
*/
|
127 |
+
public function getHeaders()
|
128 |
+
{
|
129 |
+
return $this->mergeCookieHeaders(parent::getHeaders());
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* Returns a string representation of the current request.
|
134 |
+
*
|
135 |
+
* @return string
|
136 |
+
*/
|
137 |
+
public function __toString()
|
138 |
+
{
|
139 |
+
$string = sprintf("%s %s HTTP/%.1f\r\n", $this->getMethod(), $this->getResource(), $this->getProtocolVersion());
|
140 |
+
|
141 |
+
if ($host = $this->getHost()) {
|
142 |
+
$string .= 'Host: '.$host."\r\n";
|
143 |
+
}
|
144 |
+
|
145 |
+
if ($parent = trim(parent::__toString())) {
|
146 |
+
$string .= $parent."\r\n";
|
147 |
+
}
|
148 |
+
|
149 |
+
return $string;
|
150 |
+
}
|
151 |
+
|
152 |
+
// private
|
153 |
+
|
154 |
+
private function mergeCookieHeaders(array $headers)
|
155 |
+
{
|
156 |
+
$cookieHeader = null;
|
157 |
+
$needle = 'Cookie:';
|
158 |
+
|
159 |
+
foreach ($headers as $i => $header) {
|
160 |
+
if (0 !== stripos($header, $needle)) {
|
161 |
+
continue;
|
162 |
+
}
|
163 |
+
|
164 |
+
if (null === $cookieHeader) {
|
165 |
+
$cookieHeader = $i;
|
166 |
+
} else {
|
167 |
+
$headers[$cookieHeader] .= '; '.trim(substr($header, strlen($needle)));
|
168 |
+
unset($headers[$i]);
|
169 |
+
}
|
170 |
+
}
|
171 |
+
|
172 |
+
return array_values($headers);
|
173 |
+
}
|
174 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Message/RequestInterface.php
ADDED
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Message;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* An HTTP request message.
|
7 |
+
*
|
8 |
+
* @author Kris Wallsmith <kris.wallsmith@gmail.com>
|
9 |
+
*/
|
10 |
+
interface RequestInterface extends MessageInterface
|
11 |
+
{
|
12 |
+
const METHOD_OPTIONS = 'OPTIONS';
|
13 |
+
const METHOD_GET = 'GET';
|
14 |
+
const METHOD_HEAD = 'HEAD';
|
15 |
+
const METHOD_POST = 'POST';
|
16 |
+
const METHOD_PUT = 'PUT';
|
17 |
+
const METHOD_DELETE = 'DELETE';
|
18 |
+
const METHOD_PATCH = 'PATCH';
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Returns the HTTP method of the current request.
|
22 |
+
*
|
23 |
+
* @return string An HTTP method
|
24 |
+
*/
|
25 |
+
public function getMethod();
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Sets the HTTP method of the current request.
|
29 |
+
*
|
30 |
+
* @param string $method The request method
|
31 |
+
*/
|
32 |
+
public function setMethod($method);
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Returns the resource portion of the request line.
|
36 |
+
*
|
37 |
+
* @return string The resource requested
|
38 |
+
*/
|
39 |
+
public function getResource();
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Sets the resource for the current request.
|
43 |
+
*
|
44 |
+
* @param string $resource The resource being requested
|
45 |
+
*/
|
46 |
+
public function setResource($resource);
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Returns the protocol version of the current request.
|
50 |
+
*
|
51 |
+
* @return float The protocol version
|
52 |
+
*/
|
53 |
+
public function getProtocolVersion();
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Returns the value of the host header.
|
57 |
+
*
|
58 |
+
* @return string|null The host
|
59 |
+
*/
|
60 |
+
public function getHost();
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Sets the host for the current request.
|
64 |
+
*
|
65 |
+
* @param string $host The host
|
66 |
+
*/
|
67 |
+
public function setHost($host);
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Checks if the current request is secure.
|
71 |
+
*
|
72 |
+
* @return Boolean True if the request is secure
|
73 |
+
*/
|
74 |
+
public function isSecure();
|
75 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Message/Response.php
ADDED
@@ -0,0 +1,193 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Message;
|
4 |
+
|
5 |
+
class Response extends AbstractMessage
|
6 |
+
{
|
7 |
+
private $protocolVersion;
|
8 |
+
private $statusCode;
|
9 |
+
private $reasonPhrase;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Returns the protocol version of the current response.
|
13 |
+
*
|
14 |
+
* @return float
|
15 |
+
*/
|
16 |
+
public function getProtocolVersion()
|
17 |
+
{
|
18 |
+
if (null === $this->protocolVersion) {
|
19 |
+
$this->parseStatusLine();
|
20 |
+
}
|
21 |
+
|
22 |
+
return $this->protocolVersion ?: null;
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Returns the status code of the current response.
|
27 |
+
*
|
28 |
+
* @return integer
|
29 |
+
*/
|
30 |
+
public function getStatusCode()
|
31 |
+
{
|
32 |
+
if (null === $this->statusCode) {
|
33 |
+
$this->parseStatusLine();
|
34 |
+
}
|
35 |
+
|
36 |
+
return $this->statusCode ?: null;
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Returns the reason phrase for the current response.
|
41 |
+
*
|
42 |
+
* @return string
|
43 |
+
*/
|
44 |
+
public function getReasonPhrase()
|
45 |
+
{
|
46 |
+
if (null === $this->reasonPhrase) {
|
47 |
+
$this->parseStatusLine();
|
48 |
+
}
|
49 |
+
|
50 |
+
return $this->reasonPhrase ?: null;
|
51 |
+
}
|
52 |
+
|
53 |
+
public function setHeaders(array $headers)
|
54 |
+
{
|
55 |
+
parent::setHeaders($headers);
|
56 |
+
|
57 |
+
$this->resetStatusLine();
|
58 |
+
}
|
59 |
+
|
60 |
+
public function addHeader($header)
|
61 |
+
{
|
62 |
+
parent::addHeader($header);
|
63 |
+
|
64 |
+
$this->resetStatusLine();
|
65 |
+
}
|
66 |
+
|
67 |
+
public function addHeaders(array $headers)
|
68 |
+
{
|
69 |
+
parent::addHeaders($headers);
|
70 |
+
|
71 |
+
$this->resetStatusLine();
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Is response invalid?
|
76 |
+
*
|
77 |
+
* @return Boolean
|
78 |
+
*/
|
79 |
+
public function isInvalid()
|
80 |
+
{
|
81 |
+
return $this->getStatusCode() < 100 || $this->getStatusCode() >= 600;
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Is response informative?
|
86 |
+
*
|
87 |
+
* @return Boolean
|
88 |
+
*/
|
89 |
+
public function isInformational()
|
90 |
+
{
|
91 |
+
return $this->getStatusCode() >= 100 && $this->getStatusCode() < 200;
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Is response successful?
|
96 |
+
*
|
97 |
+
* @return Boolean
|
98 |
+
*/
|
99 |
+
public function isSuccessful()
|
100 |
+
{
|
101 |
+
return $this->getStatusCode() >= 200 && $this->getStatusCode() < 300;
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Is the response a redirect?
|
106 |
+
*
|
107 |
+
* @return Boolean
|
108 |
+
*/
|
109 |
+
public function isRedirection()
|
110 |
+
{
|
111 |
+
return $this->getStatusCode() >= 300 && $this->getStatusCode() < 400;
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Is there a client error?
|
116 |
+
*
|
117 |
+
* @return Boolean
|
118 |
+
*/
|
119 |
+
public function isClientError()
|
120 |
+
{
|
121 |
+
return $this->getStatusCode() >= 400 && $this->getStatusCode() < 500;
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Was there a server side error?
|
126 |
+
*
|
127 |
+
* @return Boolean
|
128 |
+
*/
|
129 |
+
public function isServerError()
|
130 |
+
{
|
131 |
+
return $this->getStatusCode() >= 500 && $this->getStatusCode() < 600;
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Is the response OK?
|
136 |
+
*
|
137 |
+
* @return Boolean
|
138 |
+
*/
|
139 |
+
public function isOk()
|
140 |
+
{
|
141 |
+
return 200 === $this->getStatusCode();
|
142 |
+
}
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Is the reponse forbidden?
|
146 |
+
*
|
147 |
+
* @return Boolean
|
148 |
+
*/
|
149 |
+
public function isForbidden()
|
150 |
+
{
|
151 |
+
return 403 === $this->getStatusCode();
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* Is the response a not found error?
|
156 |
+
*
|
157 |
+
* @return Boolean
|
158 |
+
*/
|
159 |
+
public function isNotFound()
|
160 |
+
{
|
161 |
+
return 404 === $this->getStatusCode();
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* Is the response empty?
|
166 |
+
*
|
167 |
+
* @return Boolean
|
168 |
+
*/
|
169 |
+
public function isEmpty()
|
170 |
+
{
|
171 |
+
return in_array($this->getStatusCode(), array(201, 204, 304));
|
172 |
+
}
|
173 |
+
|
174 |
+
// private
|
175 |
+
|
176 |
+
private function parseStatusLine()
|
177 |
+
{
|
178 |
+
$headers = $this->getHeaders();
|
179 |
+
|
180 |
+
if (isset($headers[0]) && 3 == count($parts = explode(' ', $headers[0], 3))) {
|
181 |
+
$this->protocolVersion = (float) substr($parts[0], 5);
|
182 |
+
$this->statusCode = (integer) $parts[1];
|
183 |
+
$this->reasonPhrase = $parts[2];
|
184 |
+
} else {
|
185 |
+
$this->protocolVersion = $this->statusCode = $this->reasonPhrase = false;
|
186 |
+
}
|
187 |
+
}
|
188 |
+
|
189 |
+
private function resetStatusLine()
|
190 |
+
{
|
191 |
+
$this->protocolVersion = $this->statusCode = $this->reasonPhrase = null;
|
192 |
+
}
|
193 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Util/Cookie.php
ADDED
@@ -0,0 +1,216 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Util;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
6 |
+
|
7 |
+
class Cookie
|
8 |
+
{
|
9 |
+
const ATTR_DOMAIN = 'domain';
|
10 |
+
const ATTR_PATH = 'path';
|
11 |
+
const ATTR_SECURE = 'secure';
|
12 |
+
const ATTR_MAX_AGE = 'max-age';
|
13 |
+
const ATTR_EXPIRES = 'expires';
|
14 |
+
|
15 |
+
protected $name;
|
16 |
+
protected $value;
|
17 |
+
protected $attributes = array();
|
18 |
+
protected $createdAt;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Constructor.
|
22 |
+
*/
|
23 |
+
public function __construct()
|
24 |
+
{
|
25 |
+
$this->createdAt = time();
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Returns true if the current cookie matches the supplied request.
|
30 |
+
*
|
31 |
+
* @return boolean
|
32 |
+
*/
|
33 |
+
public function matchesRequest(RequestInterface $request)
|
34 |
+
{
|
35 |
+
// domain
|
36 |
+
if (!$this->matchesDomain(parse_url($request->getHost(), PHP_URL_HOST))) {
|
37 |
+
return false;
|
38 |
+
}
|
39 |
+
|
40 |
+
// path
|
41 |
+
if (!$this->matchesPath($request->getResource())) {
|
42 |
+
return false;
|
43 |
+
}
|
44 |
+
|
45 |
+
// secure
|
46 |
+
if ($this->hasAttribute(static::ATTR_SECURE) && !$request->isSecure()) {
|
47 |
+
return false;
|
48 |
+
}
|
49 |
+
|
50 |
+
return true;
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Returns true of the current cookie has expired.
|
55 |
+
*
|
56 |
+
* Checks the max-age and expires attributes.
|
57 |
+
*
|
58 |
+
* @return boolean Whether the current cookie has expired
|
59 |
+
*/
|
60 |
+
public function isExpired()
|
61 |
+
{
|
62 |
+
$maxAge = $this->getAttribute(static::ATTR_MAX_AGE);
|
63 |
+
if ($maxAge && time() - $this->getCreatedAt() > $maxAge) {
|
64 |
+
return true;
|
65 |
+
}
|
66 |
+
|
67 |
+
$expires = $this->getAttribute(static::ATTR_EXPIRES);
|
68 |
+
if ($expires && strtotime($expires) < time()) {
|
69 |
+
return true;
|
70 |
+
}
|
71 |
+
|
72 |
+
return false;
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Returns true if the current cookie matches the supplied domain.
|
77 |
+
*
|
78 |
+
* @param string $domain A domain hostname
|
79 |
+
*
|
80 |
+
* @return boolean
|
81 |
+
*/
|
82 |
+
public function matchesDomain($domain)
|
83 |
+
{
|
84 |
+
$cookieDomain = $this->getAttribute(static::ATTR_DOMAIN);
|
85 |
+
|
86 |
+
if (0 === strpos($cookieDomain, '.')) {
|
87 |
+
$pattern = '/\b'.preg_quote(substr($cookieDomain, 1), '/').'$/i';
|
88 |
+
|
89 |
+
return (boolean) preg_match($pattern, $domain);
|
90 |
+
} else {
|
91 |
+
return 0 == strcasecmp($cookieDomain, $domain);
|
92 |
+
}
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Returns true if the current cookie matches the supplied path.
|
97 |
+
*
|
98 |
+
* @param string $path A path
|
99 |
+
*
|
100 |
+
* @return boolean
|
101 |
+
*/
|
102 |
+
public function matchesPath($path)
|
103 |
+
{
|
104 |
+
$needle = $this->getAttribute(static::ATTR_PATH);
|
105 |
+
|
106 |
+
return null === $needle || 0 === strpos($path, $needle);
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* Populates the current cookie with data from the supplied Set-Cookie header.
|
111 |
+
*
|
112 |
+
* @param string $header A Set-Cookie header
|
113 |
+
* @param string $issuingDomain The domain that issued the header
|
114 |
+
*/
|
115 |
+
public function fromSetCookieHeader($header, $issuingDomain)
|
116 |
+
{
|
117 |
+
list($this->name, $header) = explode('=', $header, 2);
|
118 |
+
if (false === strpos($header, ';')) {
|
119 |
+
$this->value = $header;
|
120 |
+
$header = null;
|
121 |
+
} else {
|
122 |
+
list($this->value, $header) = explode(';', $header, 2);
|
123 |
+
}
|
124 |
+
|
125 |
+
$this->clearAttributes();
|
126 |
+
foreach (array_map('trim', explode(';', trim($header))) as $pair) {
|
127 |
+
if (false === strpos($pair, '=')) {
|
128 |
+
$name = $pair;
|
129 |
+
$value = null;
|
130 |
+
} else {
|
131 |
+
list($name, $value) = explode('=', $pair);
|
132 |
+
}
|
133 |
+
|
134 |
+
$this->setAttribute($name, $value);
|
135 |
+
}
|
136 |
+
|
137 |
+
if (!$this->getAttribute(static::ATTR_DOMAIN)) {
|
138 |
+
$this->setAttribute(static::ATTR_DOMAIN, $issuingDomain);
|
139 |
+
}
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Formats a Cookie header for the current cookie.
|
144 |
+
*
|
145 |
+
* @return string An HTTP request Cookie header
|
146 |
+
*/
|
147 |
+
public function toCookieHeader()
|
148 |
+
{
|
149 |
+
return 'Cookie: '.$this->getName().'='.$this->getValue();
|
150 |
+
}
|
151 |
+
|
152 |
+
public function setName($name)
|
153 |
+
{
|
154 |
+
$this->name = $name;
|
155 |
+
}
|
156 |
+
|
157 |
+
public function getName()
|
158 |
+
{
|
159 |
+
return $this->name;
|
160 |
+
}
|
161 |
+
|
162 |
+
public function setValue($value)
|
163 |
+
{
|
164 |
+
$this->value = $value;
|
165 |
+
}
|
166 |
+
|
167 |
+
public function getValue()
|
168 |
+
{
|
169 |
+
return $this->value;
|
170 |
+
}
|
171 |
+
|
172 |
+
public function setAttributes(array $attributes)
|
173 |
+
{
|
174 |
+
// attributes are case insensitive
|
175 |
+
$this->attributes = array_change_key_case($attributes);
|
176 |
+
}
|
177 |
+
|
178 |
+
public function setAttribute($name, $value)
|
179 |
+
{
|
180 |
+
$this->attributes[strtolower($name)] = $value;
|
181 |
+
}
|
182 |
+
|
183 |
+
public function getAttributes()
|
184 |
+
{
|
185 |
+
return $this->attributes;
|
186 |
+
}
|
187 |
+
|
188 |
+
public function getAttribute($name)
|
189 |
+
{
|
190 |
+
$name = strtolower($name);
|
191 |
+
|
192 |
+
if (isset($this->attributes[$name])) {
|
193 |
+
return $this->attributes[$name];
|
194 |
+
}
|
195 |
+
}
|
196 |
+
|
197 |
+
public function hasAttribute($name)
|
198 |
+
{
|
199 |
+
return array_key_exists($name, $this->attributes);
|
200 |
+
}
|
201 |
+
|
202 |
+
public function clearAttributes()
|
203 |
+
{
|
204 |
+
$this->setAttributes(array());
|
205 |
+
}
|
206 |
+
|
207 |
+
public function setCreatedAt($createdAt)
|
208 |
+
{
|
209 |
+
$this->createdAt = $createdAt;
|
210 |
+
}
|
211 |
+
|
212 |
+
public function getCreatedAt()
|
213 |
+
{
|
214 |
+
return $this->createdAt;
|
215 |
+
}
|
216 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Util/CookieJar.php
ADDED
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Util;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\MessageInterface;
|
6 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
7 |
+
|
8 |
+
class CookieJar
|
9 |
+
{
|
10 |
+
protected $cookies = array();
|
11 |
+
|
12 |
+
public function setCookies($cookies)
|
13 |
+
{
|
14 |
+
$this->cookies = array();
|
15 |
+
foreach ($cookies as $cookie) {
|
16 |
+
$this->addCookie($cookie);
|
17 |
+
}
|
18 |
+
}
|
19 |
+
|
20 |
+
public function getCookies()
|
21 |
+
{
|
22 |
+
return $this->cookies;
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Adds a cookie to the current cookie jar.
|
27 |
+
*
|
28 |
+
* @param Cookie $cookie A cookie object
|
29 |
+
*/
|
30 |
+
public function addCookie(Cookie $cookie)
|
31 |
+
{
|
32 |
+
$this->cookies[] = $cookie;
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Adds Cookie headers to the supplied request.
|
37 |
+
*
|
38 |
+
* @param RequestInterface $request A request object
|
39 |
+
*/
|
40 |
+
public function addCookieHeaders(RequestInterface $request)
|
41 |
+
{
|
42 |
+
foreach ($this->cookies as $cookie) {
|
43 |
+
if ($cookie->matchesRequest($request)) {
|
44 |
+
$request->addHeader($cookie->toCookieHeader());
|
45 |
+
}
|
46 |
+
}
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Processes Set-Cookie headers from a request/response pair.
|
51 |
+
*
|
52 |
+
* @param RequestInterface $request A request object
|
53 |
+
* @param MessageInterface $response A response object
|
54 |
+
*/
|
55 |
+
public function processSetCookieHeaders(RequestInterface $request, MessageInterface $response)
|
56 |
+
{
|
57 |
+
foreach ($response->getHeader('Set-Cookie', false) as $header) {
|
58 |
+
$cookie = new Cookie();
|
59 |
+
$cookie->fromSetCookieHeader($header, parse_url($request->getHost(), PHP_URL_HOST));
|
60 |
+
|
61 |
+
$this->addCookie($cookie);
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Removes expired cookies.
|
67 |
+
*/
|
68 |
+
public function clearExpiredCookies()
|
69 |
+
{
|
70 |
+
foreach ($this->cookies as $i => $cookie) {
|
71 |
+
if ($cookie->isExpired()) {
|
72 |
+
unset($this->cookies[$i]);
|
73 |
+
}
|
74 |
+
}
|
75 |
+
|
76 |
+
// reset array keys
|
77 |
+
$this->cookies = array_values($this->cookies);
|
78 |
+
}
|
79 |
+
}
|
app/code/community/Webinterpret/Connector/Lib/Buzz/Util/Url.php
ADDED
@@ -0,0 +1,190 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WebinterpretConnector\Buzz\Util;
|
4 |
+
|
5 |
+
use WebinterpretConnector\Buzz\Message\RequestInterface;
|
6 |
+
use WebinterpretConnector\Buzz\Exception\InvalidArgumentException;
|
7 |
+
|
8 |
+
class Url
|
9 |
+
{
|
10 |
+
private static $defaultPorts = array(
|
11 |
+
'http' => 80,
|
12 |
+
'https' => 443,
|
13 |
+
);
|
14 |
+
|
15 |
+
private $url;
|
16 |
+
private $components;
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Constructor.
|
20 |
+
*
|
21 |
+
* @param string $url The URL
|
22 |
+
*
|
23 |
+
* @throws InvalidArgumentException If the URL is invalid
|
24 |
+
*/
|
25 |
+
public function __construct($url)
|
26 |
+
{
|
27 |
+
$components = parse_url($url);
|
28 |
+
|
29 |
+
if (false === $components) {
|
30 |
+
throw new InvalidArgumentException(sprintf('The URL "%s" is invalid.', $url));
|
31 |
+
}
|
32 |
+
|
33 |
+
// support scheme-less URLs
|
34 |
+
if (!isset($components['host']) && isset($components['path'])) {
|
35 |
+
$pos = strpos($components['path'], '/');
|
36 |
+
if (false === $pos) {
|
37 |
+
$components['host'] = $components['path'];
|
38 |
+
unset($components['path']);
|
39 |
+
} elseif (0 !== $pos) {
|
40 |
+
list($host, $path) = explode('/', $components['path'], 2);
|
41 |
+
$components['host'] = $host;
|
42 |
+
$components['path'] = '/'.$path;
|
43 |
+
}
|
44 |
+
}
|
45 |
+
|
46 |
+
// default port
|
47 |
+
if (isset($components['scheme']) && !isset($components['port']) && isset(self::$defaultPorts[$components['scheme']])) {
|
48 |
+
$components['port'] = self::$defaultPorts[$components['scheme']];
|
49 |
+
}
|
50 |
+
|
51 |
+
$this->url = $url;
|
52 |
+
$this->components = $components;
|
53 |
+
}
|
54 |
+
|
55 |
+
public function getScheme()
|
56 |
+
{
|
57 |
+
return $this->parseUrl('scheme');
|
58 |
+
}
|
59 |
+
|
60 |
+
public function getHostname()
|
61 |
+
{
|
62 |
+
return $this->parseUrl('host');
|
63 |
+
}
|
64 |
+
|
65 |
+
public function getPort()
|
66 |
+
{
|
67 |
+
return $this->parseUrl('port');
|
68 |
+
}
|
69 |
+
|
70 |
+
public function getUser()
|
71 |
+
{
|
72 |
+
return $this->parseUrl('user');
|
73 |
+
}
|
74 |
+
|
75 |
+
public function getPassword()
|
76 |
+
{
|
77 |
+
return $this->parseUrl('pass');
|
78 |
+
}
|
79 |
+
|
80 |
+
public function getPath()
|
81 |
+
{
|
82 |
+
return $this->parseUrl('path');
|
83 |
+
}
|
84 |
+
|
85 |
+
public function getQueryString()
|
86 |
+
{
|
87 |
+
return $this->parseUrl('query');
|
88 |
+
}
|
89 |
+
|
90 |
+
public function getFragment()
|
91 |
+
{
|
92 |
+
return $this->parseUrl('fragment');
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Returns a host string that combines scheme, hostname and port.
|
97 |
+
*
|
98 |
+
* @return string A host value for an HTTP message
|
99 |
+
*/
|
100 |
+
public function getHost()
|
101 |
+
{
|
102 |
+
if ($hostname = $this->parseUrl('host')) {
|
103 |
+
$host = $scheme = $this->parseUrl('scheme', 'http');
|
104 |
+
$host .= '://';
|
105 |
+
$host .= $hostname;
|
106 |
+
|
107 |
+
$port = $this->parseUrl('port');
|
108 |
+
if ($port && (!isset(self::$defaultPorts[$scheme]) || self::$defaultPorts[$scheme] != $port)) {
|
109 |
+
$host .= ':'.$port;
|
110 |
+
}
|
111 |
+
|
112 |
+
return $host;
|
113 |
+
}
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Returns a resource string that combines path and query string.
|
118 |
+
*
|
119 |
+
* @return string A resource value for an HTTP message
|
120 |
+
*/
|
121 |
+
public function getResource()
|
122 |
+
{
|
123 |
+
$resource = $this->parseUrl('path', '/');
|
124 |
+
|
125 |
+
if ($query = $this->parseUrl('query')) {
|
126 |
+
$resource .= '?'.$query;
|
127 |
+
}
|
128 |
+
|
129 |
+
return $resource;
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* Returns a formatted URL.
|
134 |
+
*/
|
135 |
+
public function format($pattern)
|
136 |
+
{
|
137 |
+
static $map = array(
|
138 |
+
's' => 'getScheme',
|
139 |
+
'u' => 'getUser',
|
140 |
+
'a' => 'getPassword',
|
141 |
+
'h' => 'getHostname',
|
142 |
+
'o' => 'getPort',
|
143 |
+
'p' => 'getPath',
|
144 |
+
'q' => 'getQueryString',
|
145 |
+
'f' => 'getFragment',
|
146 |
+
'H' => 'getHost',
|
147 |
+
'R' => 'getResource',
|
148 |
+
);
|
149 |
+
|
150 |
+
$url = '';
|
151 |
+
|
152 |
+
$parts = str_split($pattern);
|
153 |
+
while ($part = current($parts)) {
|
154 |
+
if (isset($map[$part])) {
|
155 |
+
$method = $map[$part];
|
156 |
+
$url .= $this->$method();
|
157 |
+
} elseif ('\\' == $part) {
|
158 |
+
$url .= next($parts);
|
159 |
+
} elseif (!ctype_alpha($part)) {
|
160 |
+
$url .= $part;
|
161 |
+
} else {
|
162 |
+
throw new InvalidArgumentException(sprintf('The format character "%s" is invalid.', $part));
|
163 |
+
}
|
164 |
+
|
165 |
+
next($parts);
|
166 |
+
}
|
167 |
+
|
168 |
+
return $url;
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* Applies the current URL to the supplied request.
|
173 |
+
*/
|
174 |
+
public function applyToRequest(RequestInterface $request)
|
175 |
+
{
|
176 |
+
$request->setResource($this->getResource());
|
177 |
+
$request->setHost($this->getHost());
|
178 |
+
}
|
179 |
+
|
180 |
+
private function parseUrl($component = null, $default = null)
|
181 |
+
{
|
182 |
+
if (null === $component) {
|
183 |
+
return $this->components;
|
184 |
+
} elseif (isset($this->components[$component])) {
|
185 |
+
return $this->components[$component];
|
186 |
+
} else {
|
187 |
+
return $default;
|
188 |
+
}
|
189 |
+
}
|
190 |
+
}
|
app/code/community/Webinterpret/Connector/Model/StoreExtender.php
ADDED
@@ -0,0 +1,198 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
use WebinterpretConnector\Buzz\Browser;
|
4 |
+
use WebinterpretConnector\Buzz\Client\Curl;
|
5 |
+
use WebinterpretConnector\Buzz\Client\FileGetContents;
|
6 |
+
use WebinterpretConnector\Buzz\Exception\ClientException;
|
7 |
+
use WebinterpretConnector\Buzz\Message\Response;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* StoreExtender
|
11 |
+
*
|
12 |
+
* @category Webinterpret
|
13 |
+
* @package Webinterpret_Connector
|
14 |
+
* @author Webinterpret Team <info@webinterpret.com>
|
15 |
+
* @license http://opensource.org/licenses/osl-3.0.php
|
16 |
+
*/
|
17 |
+
class Webinterpret_Connector_Model_StoreExtender extends Varien_object
|
18 |
+
{
|
19 |
+
/**
|
20 |
+
* @var string Prefix for cookies that should be forwarded to store extender proxy
|
21 |
+
*/
|
22 |
+
private $cookiePrefix = 'wi_ws_store_ext_';
|
23 |
+
|
24 |
+
public function __construct()
|
25 |
+
{
|
26 |
+
spl_autoload_register(array($this, 'loadStoreExtenderDependencies'), true, true);
|
27 |
+
}
|
28 |
+
|
29 |
+
public static function loadStoreExtenderDependencies($class)
|
30 |
+
{
|
31 |
+
if (preg_match( '/^WebinterpretConnector\\\\/', $class)) {
|
32 |
+
$path = Mage::getModuleDir('', 'Webinterpret_Connector');
|
33 |
+
$libClassName = str_replace('\\', '/', substr($class, strlen('WebinterpretConnector\\')));
|
34 |
+
require_once($path . '/Lib/' . $libClassName . '.php');
|
35 |
+
}
|
36 |
+
}
|
37 |
+
|
38 |
+
public function parseRequest()
|
39 |
+
{
|
40 |
+
$storeExtenderUrl = Mage::getStoreConfig('webinterpret_connector/store_extender_url');
|
41 |
+
$storeExtenderUrl .= '?originalUrl=' . urlencode(Mage::helper('core/url')->getCurrentUrl());
|
42 |
+
|
43 |
+
$browser = new Browser($this->getBrowserClient());
|
44 |
+
$browser->getClient()->setMaxRedirects(0);
|
45 |
+
|
46 |
+
$method = $_SERVER['REQUEST_METHOD'];
|
47 |
+
|
48 |
+
try {
|
49 |
+
$response = $browser->call(
|
50 |
+
$storeExtenderUrl,
|
51 |
+
$_SERVER['REQUEST_METHOD'],
|
52 |
+
$this->getRequestHeaders(),
|
53 |
+
$this->getRequestContent($method)
|
54 |
+
);
|
55 |
+
} catch (ClientException $e) {
|
56 |
+
// fallback - redirect to base store URL if there is problem with proxy
|
57 |
+
header('Location: ' . Mage::getBaseUrl());
|
58 |
+
die();
|
59 |
+
}
|
60 |
+
|
61 |
+
$this->outputResponseCode($response->getStatusCode());
|
62 |
+
$this->outputHeaders($this->parseResponseHeadersToArray($response));
|
63 |
+
echo $response->getContent();
|
64 |
+
die;
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* @param $method
|
69 |
+
* @return string
|
70 |
+
*/
|
71 |
+
private function getRequestContent($method)
|
72 |
+
{
|
73 |
+
$content = '';
|
74 |
+
|
75 |
+
if (in_array($method, array('PUT', 'PATCH', 'DELETE'))) {
|
76 |
+
$content = file_get_contents("php://input");
|
77 |
+
} elseif ($method === 'POST') {
|
78 |
+
$content = http_build_query($_POST);
|
79 |
+
}
|
80 |
+
return $content;
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* @return array
|
85 |
+
*/
|
86 |
+
private function getRequestHeaders()
|
87 |
+
{
|
88 |
+
$headers = array();
|
89 |
+
|
90 |
+
$supportedHeaders = array(
|
91 |
+
'HTTP_X_REQUESTED_WITH' => 'X-Requested-With',
|
92 |
+
'HTTP_CONTENT_TYPE' => 'Content-Type',
|
93 |
+
'HTTP_CONNECTION' => 'Connection',
|
94 |
+
'HTTP_CACHE_CONTROL' => 'Cache-Control',
|
95 |
+
'HTTP_USER_AGENT' => 'User-Agent',
|
96 |
+
'HTTP_ACCEPT' => 'Accept',
|
97 |
+
'HTTP_ACCEPT_LANGUAGE' => 'Accept-Language',
|
98 |
+
);
|
99 |
+
|
100 |
+
foreach ($supportedHeaders as $supportedHeader => $supportedHeaderKey) {
|
101 |
+
if (isset($_SERVER[$supportedHeader])) {
|
102 |
+
$headers[$supportedHeaderKey] = $_SERVER[$supportedHeader];
|
103 |
+
}
|
104 |
+
}
|
105 |
+
|
106 |
+
$cookies = $this->parseRequestCookies();
|
107 |
+
if (!empty($cookies)) {
|
108 |
+
$headers['Cookie'] = $cookies;
|
109 |
+
}
|
110 |
+
|
111 |
+
return $headers;
|
112 |
+
}
|
113 |
+
|
114 |
+
private function parseRequestCookies()
|
115 |
+
{
|
116 |
+
$cookies = array();
|
117 |
+
if (isset($_SERVER['HTTP_COOKIE'])) {
|
118 |
+
$cookies = array_map('trim', explode(';', $_SERVER['HTTP_COOKIE']));
|
119 |
+
$cookiePrefix = $this->cookiePrefix;
|
120 |
+
$cookies = array_filter($cookies, function($cookie) use ($cookiePrefix) {
|
121 |
+
return (strpos($cookie, $cookiePrefix) === 0);
|
122 |
+
});
|
123 |
+
}
|
124 |
+
|
125 |
+
return implode('; ', $cookies);
|
126 |
+
}
|
127 |
+
|
128 |
+
/**
|
129 |
+
* @param \WebinterpretConnector\Buzz\Message\Response $response
|
130 |
+
* @return array
|
131 |
+
*/
|
132 |
+
private function parseResponseHeadersToArray(Response $response)
|
133 |
+
{
|
134 |
+
$supportedHeaders = array(
|
135 |
+
'Date',
|
136 |
+
'Content-Type',
|
137 |
+
'Content-Length',
|
138 |
+
'Connection',
|
139 |
+
'Keep-Alive',
|
140 |
+
'Location',
|
141 |
+
'Set-Cookie',
|
142 |
+
);
|
143 |
+
|
144 |
+
//reformat response headers
|
145 |
+
$responseHeaders = array();
|
146 |
+
|
147 |
+
foreach ($response->getHeaders() as $header) {
|
148 |
+
list($headerName, $headerValue) = explode(':', $header, 2);
|
149 |
+
if ($headerValue) {
|
150 |
+
$responseHeaders[$headerName] = trim($headerValue);
|
151 |
+
}
|
152 |
+
}
|
153 |
+
|
154 |
+
foreach ($responseHeaders as $header => $contents) {
|
155 |
+
if (in_array($header, $supportedHeaders)) {
|
156 |
+
$responseHeaders[] = $header . ': ' . $contents;
|
157 |
+
}
|
158 |
+
unset($responseHeaders[$header]);
|
159 |
+
}
|
160 |
+
|
161 |
+
return $responseHeaders;
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* @param array $responseHeaders
|
166 |
+
*/
|
167 |
+
private function outputHeaders($responseHeaders)
|
168 |
+
{
|
169 |
+
// remove previously set headers
|
170 |
+
header_remove();
|
171 |
+
|
172 |
+
foreach ($responseHeaders as $responseHeader) {
|
173 |
+
header($responseHeader);
|
174 |
+
}
|
175 |
+
}
|
176 |
+
|
177 |
+
/**
|
178 |
+
* @param $code
|
179 |
+
*/
|
180 |
+
private function outputResponseCode($code)
|
181 |
+
{
|
182 |
+
if (function_exists( 'http_response_code')) {
|
183 |
+
http_response_code($code);
|
184 |
+
} else {
|
185 |
+
// X-PHP-Response-Code is a fake header name, we rely on the webserver to handle the 3rd parameter accordingly
|
186 |
+
header('X-PHP-Response-Code: ' . $code, true, $code);
|
187 |
+
}
|
188 |
+
}
|
189 |
+
|
190 |
+
private function getBrowserClient()
|
191 |
+
{
|
192 |
+
if (function_exists('curl_version')) {
|
193 |
+
return new Curl();
|
194 |
+
} else {
|
195 |
+
return new FileGetContents();
|
196 |
+
}
|
197 |
+
}
|
198 |
+
}
|
app/code/community/Webinterpret/Connector/controllers/IndexController.php
CHANGED
@@ -11,6 +11,18 @@ class Webinterpret_Connector_IndexController extends Mage_Core_Controller_Front_
|
|
11 |
{
|
12 |
public function indexAction()
|
13 |
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
try {
|
15 |
$dir = Mage::helper('webinterpret_connector')->getModuleBridgeDir();
|
16 |
$path = $dir . DS . 'bridge.php';
|
11 |
{
|
12 |
public function indexAction()
|
13 |
{
|
14 |
+
// Handle glopal request
|
15 |
+
$module = Mage::app()->getRequest()->getModuleName();
|
16 |
+
if ($module === 'glopal') {
|
17 |
+
if (!Mage::helper('webinterpret_connector')->isStoreExtenderEnabled()) {
|
18 |
+
$this->_forward('defaultNoRoute');
|
19 |
+
return;
|
20 |
+
}
|
21 |
+
$storeExtender = Mage::getModel('webinterpret_connector/storeExtender');
|
22 |
+
$storeExtender->parseRequest();
|
23 |
+
die();
|
24 |
+
}
|
25 |
+
|
26 |
try {
|
27 |
$dir = Mage::helper('webinterpret_connector')->getModuleBridgeDir();
|
28 |
$path = $dir . DS . 'bridge.php';
|
app/code/community/Webinterpret/Connector/etc/config.xml
CHANGED
@@ -8,7 +8,7 @@
|
|
8 |
<config>
|
9 |
<modules>
|
10 |
<Webinterpret_Connector>
|
11 |
-
<version>1.
|
12 |
</Webinterpret_Connector>
|
13 |
</modules>
|
14 |
<global>
|
@@ -58,9 +58,17 @@
|
|
58 |
</events>
|
59 |
<request>
|
60 |
<direct_front_name>
|
61 |
-
<webinterpret_connector/>
|
|
|
62 |
</direct_front_name>
|
63 |
</request>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
</global>
|
65 |
<frontend>
|
66 |
<routers>
|
@@ -71,6 +79,13 @@
|
|
71 |
<frontName>webinterpret_connector</frontName>
|
72 |
</args>
|
73 |
</webinterpret_connector>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
</routers>
|
75 |
<layout>
|
76 |
<updates>
|
@@ -102,6 +117,22 @@
|
|
102 |
<installation_mode><![CDATA[1]]></installation_mode>
|
103 |
<global_notifications_enabled><![CDATA[1]]></global_notifications_enabled>
|
104 |
<automatic_updates_enabled><![CDATA[1]]></automatic_updates_enabled>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
</webinterpret_connector>
|
106 |
</default>
|
107 |
</config>
|
8 |
<config>
|
9 |
<modules>
|
10 |
<Webinterpret_Connector>
|
11 |
+
<version>1.3.0.0</version>
|
12 |
</Webinterpret_Connector>
|
13 |
</modules>
|
14 |
<global>
|
58 |
</events>
|
59 |
<request>
|
60 |
<direct_front_name>
|
61 |
+
<webinterpret_connector />
|
62 |
+
<glopal />
|
63 |
</direct_front_name>
|
64 |
</request>
|
65 |
+
<rewrite>
|
66 |
+
<glopal_url>
|
67 |
+
<from><![CDATA[/glopal\/(.+)/]]></from>
|
68 |
+
<to><![CDATA[glopal/index/index/$1]]></to>
|
69 |
+
<complete>1</complete>
|
70 |
+
</glopal_url>
|
71 |
+
</rewrite>
|
72 |
</global>
|
73 |
<frontend>
|
74 |
<routers>
|
79 |
<frontName>webinterpret_connector</frontName>
|
80 |
</args>
|
81 |
</webinterpret_connector>
|
82 |
+
<glopal>
|
83 |
+
<use>standard</use>
|
84 |
+
<args>
|
85 |
+
<module>Webinterpret_Connector</module>
|
86 |
+
<frontName>glopal</frontName>
|
87 |
+
</args>
|
88 |
+
</glopal>
|
89 |
</routers>
|
90 |
<layout>
|
91 |
<updates>
|
117 |
<installation_mode><![CDATA[1]]></installation_mode>
|
118 |
<global_notifications_enabled><![CDATA[1]]></global_notifications_enabled>
|
119 |
<automatic_updates_enabled><![CDATA[1]]></automatic_updates_enabled>
|
120 |
+
<store_extender_enabled><![CDATA[0]]></store_extender_enabled>
|
121 |
+
<store_extender_url><![CDATA[https://wi-ws-store-ext.glopal.com/index.php]]></store_extender_url>
|
122 |
+
<public_key>-----BEGIN PUBLIC KEY-----
|
123 |
+
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA6YW1LitbxWceRjvGZnwd
|
124 |
+
h7/NH0Gbmnt+jEpC99KJuu4wPV+AyByUV3KxOwo6fUWozsts2tSgg3hgxnTEwjwF
|
125 |
+
XqFdft5pE794YLRtYnBMaMYkcAyl9nZTYimKT+fz+MfKceMIkFmvOVh8IMPjHLV+
|
126 |
+
7GOjBnrUxUl2/z/ohE9wUyxhP7Zo4HpHNDyDsHCBpANWVoRs9n5sBBb4cnBVIXBl
|
127 |
+
AJuWmf5c0NkMim6Sj5mM3fKb0vDhykU9IXIbQMn5cw5+g4Qy6ldcrXNm+M3+4JzW
|
128 |
+
XGqwtKrXbKLJTlA+H57szT4wYOBT1HGeDD9vFDOwTq2AjNN3mcOJawMbkiZ3sJG3
|
129 |
+
/rHMptZtE6ToMbdC/PW2neLcalpgclxafoSoD9byIYA3qWYN3GAEDGJa4UHIcZpv
|
130 |
+
nUxdL5qUgJAz2q/rk7blCSIRwLv85jQtArlfsdoxp3F3iaahjz9sB/VX1xZ6YOJH
|
131 |
+
uZGGd1aUimDOAgVfmqeFOvTEBQFYTpGg9W7TyMIqvfAqPUtOxDmzB6fNxPd45W3s
|
132 |
+
azayJumvfHBOs53t6fI/a52CfQ2I4jaz3eHI0hpHyZVxvsAj5NbFXBYzQ+mOoTEa
|
133 |
+
38d6cBHbci6rLRJ0PdaP6ZABz9OI3UE8VCz5n5BZEJ0QWmXmnn2YnWq8p3Si53KK
|
134 |
+
tQMgSP58oPZ6Nq6qM6KrlmkCAwEAAQ==
|
135 |
+
-----END PUBLIC KEY-----</public_key>
|
136 |
</webinterpret_connector>
|
137 |
</default>
|
138 |
</config>
|
app/design/frontend/base/default/template/webinterpret/connector/product_view.phtml
CHANGED
@@ -17,6 +17,7 @@ _webinterpret.plugin_version = '<?php echo $this->getPluginVersion() ?>';
|
|
17 |
_webinterpret.store_locale = '<?php echo $this->getLocaleCode() ?>';
|
18 |
_webinterpret.store_url = '<?php echo $this->getStoreUrl() ?>';
|
19 |
_webinterpret.product_id = '<?php echo $this->getProductId() ?>';
|
|
|
20 |
//]]>
|
21 |
</script>
|
22 |
<?php endif; ?>
|
17 |
_webinterpret.store_locale = '<?php echo $this->getLocaleCode() ?>';
|
18 |
_webinterpret.store_url = '<?php echo $this->getStoreUrl() ?>';
|
19 |
_webinterpret.product_id = '<?php echo $this->getProductId() ?>';
|
20 |
+
_webinterpret.store_ext_available = '<?php echo Mage::helper('webinterpret_connector')->isStoreExtenderEnabled() ? 'yes' : 'no' ?>';
|
21 |
//]]>
|
22 |
</script>
|
23 |
<?php endif; ?>
|
package.xml
CHANGED
@@ -1,21 +1,18 @@
|
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>Webinterpret_Connector</name>
|
4 |
-
<version>1.
|
5 |
<stability>stable</stability>
|
6 |
<license uri="http://www.opensource.org/licenses/osl-3.0.php">OSL v3.0</license>
|
7 |
<channel>community</channel>
|
8 |
<extends/>
|
9 |
<summary>Integrate Magento with Webinterpret.</summary>
|
10 |
<description>Translate and market your products internationally with Webinterpret. This is the official Magento extension for integrating with Webinterpret.</description>
|
11 |
-
<notes>-
|
12 |
-
- Simplified installation process
|
13 |
-

|
14 |
-
</notes>
|
15 |
<authors><author><name>Webinterpret</name><user>webinterpret</user><email>info@webinterpret.com</email></author></authors>
|
16 |
-
<date>2016-
|
17 |
-
<time>
|
18 |
-
<contents><target name="magecommunity"><dir name="Webinterpret"><dir name="Connector"><dir name="Block"><dir name="Adminhtml"><file name="Notifications.php" hash="5e1935e32f1b5d10f0b76fee427a23a6"/><dir name="System"><dir name="Config"><dir name="Fieldset"><file name="Status.php" hash="99b95c7991e91a4d4d98efdaf8007b88"/></dir></dir></dir></dir><file name="Footer.php" hash="160f03e528d7e9411e85d524919fd280"/><file name="Head.php" hash="1261ad40df9f0dc708178d78d63158d8"/><dir name="Product"><file name="View.php" hash="3b3b40108b53d326c0dcff0e45fa8407"/></dir></dir><dir name="Helper"><file name="Data.php" hash="
|
19 |
<compatible/>
|
20 |
<dependencies><required><php><min>5.3.0</min><max>7.0.0</max></php></required></dependencies>
|
21 |
</package>
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>Webinterpret_Connector</name>
|
4 |
+
<version>1.3.0.0</version>
|
5 |
<stability>stable</stability>
|
6 |
<license uri="http://www.opensource.org/licenses/osl-3.0.php">OSL v3.0</license>
|
7 |
<channel>community</channel>
|
8 |
<extends/>
|
9 |
<summary>Integrate Magento with Webinterpret.</summary>
|
10 |
<description>Translate and market your products internationally with Webinterpret. This is the official Magento extension for integrating with Webinterpret.</description>
|
11 |
+
<notes>- Translation service improvement - display international pages under the domestic store domain</notes>
|
|
|
|
|
|
|
12 |
<authors><author><name>Webinterpret</name><user>webinterpret</user><email>info@webinterpret.com</email></author></authors>
|
13 |
+
<date>2016-08-18</date>
|
14 |
+
<time>08:54:47</time>
|
15 |
+
<contents><target name="magecommunity"><dir><dir name="Webinterpret"><dir name="Connector"><dir><dir name="Block"><dir name="Adminhtml"><file name="Notifications.php" hash="5e1935e32f1b5d10f0b76fee427a23a6"/><dir name="System"><dir name="Config"><dir name="Fieldset"><file name="Status.php" hash="99b95c7991e91a4d4d98efdaf8007b88"/></dir></dir></dir></dir><file name="Footer.php" hash="160f03e528d7e9411e85d524919fd280"/><file name="Head.php" hash="1261ad40df9f0dc708178d78d63158d8"/><dir name="Product"><file name="View.php" hash="3b3b40108b53d326c0dcff0e45fa8407"/></dir></dir><dir name="Helper"><file name="Data.php" hash="bdce8c1bef0471de67c3893b24abe69d"/></dir><dir name="Lib"><dir name="Buzz"><file name="Browser.php" hash="faa5485f0fa3ca4958890052fe90ac92"/><dir name="Client"><file name="AbstractClient.php" hash="e35ab76a0453cd49d25eb677fdfb1cfb"/><file name="AbstractCurl.php" hash="39b85ceac150c234ab7ac9855f5b4afd"/><file name="AbstractStream.php" hash="651db2b755b301ad8b5f8dba6172b800"/><file name="BatchClientInterface.php" hash="3f8ddac0208efa3c8abe2b1025cb2b9c"/><file name="ClientInterface.php" hash="42583838ba59397e693e4d34db056ade"/><file name="Curl.php" hash="7002d06681911925bc67196a64be5e48"/><file name="FileGetContents.php" hash="e9a64db88683338e0a720f0046e413c2"/><file name="MultiCurl.php" hash="5c956bda37ffa542c93cb0582cd51e52"/></dir><dir name="Exception"><file name="ClientException.php" hash="b03c3fc142011180b155916db3016d19"/><file name="ExceptionInterface.php" hash="6dd392e9121db19fc6ee2faf50163175"/><file name="InvalidArgumentException.php" hash="715735e6313fe5d5cc846277ff2635cb"/><file name="LogicException.php" hash="0fb322aa30d4fcf0691471866b1378fb"/><file name="RequestException.php" hash="5ba0bb7e029fd5405f5cdd8b7e247a86"/><file name="RuntimeException.php" hash="8780764e1f114d7ae3f106a656c12a4f"/></dir><dir name="Listener"><file name="BasicAuthListener.php" hash="d3b4bf91414e52137b1bc66a97914da3"/><file name="CallbackListener.php" hash="2b3e473fb154fb424718dcf318c92553"/><file name="CookieListener.php" hash="0dc12bbbafa865701836cb5f1772581e"/><file name="DigestAuthListener.php" hash="991db4773e9d40253e61b2bc9e44ca68"/><dir name="History"><file name="Entry.php" hash="73650b956104e7db6889a373ed3c2522"/><file name="Journal.php" hash="6898357c87dd0d1490b3c004a72fa7a1"/></dir><file name="HistoryListener.php" hash="39f3fd76c57ab4aa7ffebaf49347a078"/><file name="ListenerChain.php" hash="efaa53a20164fae43ea57797b3da3e1f"/><file name="ListenerInterface.php" hash="778bdbf3aa80c34cfab26e5ce3663e96"/><file name="LoggerListener.php" hash="7709c2dfe5c7273dc7e6df8da2b7276e"/></dir><dir name="Message"><file name="AbstractMessage.php" hash="b8fbd6ecb218f09736a21b2396fc93c7"/><dir name="Factory"><file name="Factory.php" hash="19505683584eb8d9aab014288f21ace9"/><file name="FactoryInterface.php" hash="0f5d14dbc1a7b7e99826e33a6bd9b1c7"/></dir><dir name="Form"><file name="FormRequest.php" hash="335bcc0fb762fa3934883165c5f103f9"/><file name="FormRequestInterface.php" hash="cdce91424c9287a154cd53637c2142c4"/><file name="FormUpload.php" hash="3ffdbacf5d22643cab4afca459444a93"/><file name="FormUploadInterface.php" hash="7e0ca9ae5cc0c3b0bfef3717033d36bc"/></dir><file name="MessageInterface.php" hash="e755508e39647ebc9278d9d1b77c9f5a"/><file name="Request.php" hash="2d805ac034a28d4bd04c1275cef06234"/><file name="RequestInterface.php" hash="d5259b58d09230aa97227e798c5334ee"/><file name="Response.php" hash="a6b32fbae2a6b380d5f7bc68cbffea61"/></dir><dir name="Util"><file name="Cookie.php" hash="b08275dc28e7ce1923dc1f16a0500b77"/><file name="CookieJar.php" hash="c6eb7bb4958cac7a8b334e0843cb7b4a"/><file name="Url.php" hash="1825c6e2ff3e1e230c6dde833dbf655d"/></dir></dir></dir><dir name="Model"><file name="Notification.php" hash="a62c3b7ff11cd2d1082c0d959d8eb295"/><file name="Observer.php" hash="b3cb7f22f5bc376b6f834a211a7c205b"/><file name="StoreExtender.php" hash="c5fd0294f6b36c05d1293ca899deb152"/></dir><dir name="bridge2cart"><file name="bridge.php" hash="cdd197a1af1a05082a8836ea24922dad"/><file name="config.php" hash="0fb8e12c8d9c293354eb4fb96a713608"/><file name="helper.php" hash="afb5e2141259c580285ac85d0c180144"/><file name="preloader.php" hash="8a8ada3537394687defdc28d4b6077e8"/></dir><dir name="controllers"><file name="HelperController.php" hash="73fb01f035db7d75eb1ee0a3d535fd0b"/><file name="IndexController.php" hash="a76fb36d3f6fa4c370b766ed9ba818ed"/></dir><dir name="etc"><file name="adminhtml.xml" hash="07e287503c40ce7c588efe7863c05002"/><file name="config.xml" hash="f9eeac722631b966f1231b8ee8cd9712"/><file name="system.xml" hash="cfe59ca34ebfef69b900f4ad275a809a"/></dir></dir></dir></dir></dir></target><target name="magedesign"><dir><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><dir name="webinterpret"><file name="connector.xml" hash="867fafe49fa978668f6e5d7027c57aa6"/></dir></dir><dir name="template"><dir name="webinterpret"><dir name="system"><dir name="config"><file name="activate.phtml" hash="5ef389ad58cb1be9cc666fecd8379fbf"/><dir name="fieldset"><file name="banner.phtml" hash="921b677bd3e52d9c86172bdf26ab4a37"/><file name="status.phtml" hash="412bd1ea314a7f0c8897e6a9225c3551"/></dir></dir></dir></dir></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><dir name="webinterpret"><file name="connector.xml" hash="1226a298ca08a92008293ba4e8c09eab"/></dir></dir><dir name="template"><dir name="webinterpret"><dir name="connector"><file name="footer.phtml" hash="bd48d0e36dea0936b9f28fbdada3b8c1"/><file name="head.phtml" hash="107312871a7b2730532db8d986de5726"/><file name="product_view.phtml" hash="2036bc444284b99f4cc8228fa4751777"/></dir></dir></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Webinterpret_Connector.xml" hash="087c2742f6bcb89ed6a77921e6493feb"/></dir></target><target name="magelocale"><dir><dir name="de_DE"><file name="Webinterpret_Connector.csv" hash="91312fd3bd2645b88e3b3643b6b614a9"/></dir><dir name="en_US"><file name="Webinterpret_Connector.csv" hash="c382db753974630198cf029cf90b5d27"/></dir></dir></target></contents>
|
16 |
<compatible/>
|
17 |
<dependencies><required><php><min>5.3.0</min><max>7.0.0</max></php></required></dependencies>
|
18 |
</package>
|