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>
|
