mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-25 18:19:22 +03:00
v1.2.7.415
This commit is contained in:
parent
5c1e7bc676
commit
54e2645fcf
436 changed files with 407 additions and 347 deletions
195
rainloop/v/1.2.7.415/app/libraries/Buzz/Browser.php
Normal file
195
rainloop/v/1.2.7.415/app/libraries/Buzz/Browser.php
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz;
|
||||
|
||||
use Buzz\Client\ClientInterface;
|
||||
use Buzz\Client\FileGetContents;
|
||||
use Buzz\Listener\ListenerChain;
|
||||
use Buzz\Listener\ListenerInterface;
|
||||
use Buzz\Message\Factory\Factory;
|
||||
use Buzz\Message\Factory\FactoryInterface;
|
||||
use Buzz\Message\MessageInterface;
|
||||
use Buzz\Message\RequestInterface;
|
||||
use Buzz\Util\Url;
|
||||
|
||||
class Browser
|
||||
{
|
||||
private $client;
|
||||
private $factory;
|
||||
private $listener;
|
||||
private $lastRequest;
|
||||
private $lastResponse;
|
||||
|
||||
public function __construct(ClientInterface $client = null, FactoryInterface $factory = null)
|
||||
{
|
||||
$this->client = $client ?: new FileGetContents();
|
||||
$this->factory = $factory ?: new Factory();
|
||||
}
|
||||
|
||||
public function get($url, $headers = array())
|
||||
{
|
||||
return $this->call($url, RequestInterface::METHOD_GET, $headers);
|
||||
}
|
||||
|
||||
public function post($url, $headers = array(), $content = '')
|
||||
{
|
||||
return $this->call($url, RequestInterface::METHOD_POST, $headers, $content);
|
||||
}
|
||||
|
||||
public function head($url, $headers = array())
|
||||
{
|
||||
return $this->call($url, RequestInterface::METHOD_HEAD, $headers);
|
||||
}
|
||||
|
||||
public function patch($url, $headers = array(), $content = '')
|
||||
{
|
||||
return $this->call($url, RequestInterface::METHOD_PATCH, $headers, $content);
|
||||
}
|
||||
|
||||
public function put($url, $headers = array(), $content = '')
|
||||
{
|
||||
return $this->call($url, RequestInterface::METHOD_PUT, $headers, $content);
|
||||
}
|
||||
|
||||
public function delete($url, $headers = array(), $content = '')
|
||||
{
|
||||
return $this->call($url, RequestInterface::METHOD_DELETE, $headers, $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a request.
|
||||
*
|
||||
* @param string $url The URL to call
|
||||
* @param string $method The request method to use
|
||||
* @param array $headers An array of request headers
|
||||
* @param string $content The request content
|
||||
*
|
||||
* @return MessageInterface The response object
|
||||
*/
|
||||
public function call($url, $method, $headers = array(), $content = '')
|
||||
{
|
||||
$request = $this->factory->createRequest($method);
|
||||
|
||||
if (!$url instanceof Url) {
|
||||
$url = new Url($url);
|
||||
}
|
||||
|
||||
$url->applyToRequest($request);
|
||||
|
||||
$request->addHeaders($headers);
|
||||
$request->setContent($content);
|
||||
|
||||
return $this->send($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a form request.
|
||||
*
|
||||
* @param string $url The URL to submit to
|
||||
* @param array $fields An array of fields
|
||||
* @param string $method The request method to use
|
||||
* @param array $headers An array of request headers
|
||||
*
|
||||
* @return MessageInterface The response object
|
||||
*/
|
||||
public function submit($url, array $fields, $method = RequestInterface::METHOD_POST, $headers = array())
|
||||
{
|
||||
$request = $this->factory->createFormRequest();
|
||||
|
||||
if (!$url instanceof Url) {
|
||||
$url = new Url($url);
|
||||
}
|
||||
|
||||
$url->applyToRequest($request);
|
||||
|
||||
$request->addHeaders($headers);
|
||||
$request->setMethod($method);
|
||||
$request->setFields($fields);
|
||||
|
||||
return $this->send($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a request.
|
||||
*
|
||||
* @param RequestInterface $request A request object
|
||||
* @param MessageInterface $response A response object
|
||||
*
|
||||
* @return MessageInterface The response
|
||||
*/
|
||||
public function send(RequestInterface $request, MessageInterface $response = null)
|
||||
{
|
||||
if (null === $response) {
|
||||
$response = $this->factory->createResponse();
|
||||
}
|
||||
|
||||
if ($this->listener) {
|
||||
$this->listener->preSend($request);
|
||||
}
|
||||
|
||||
$this->client->send($request, $response);
|
||||
|
||||
$this->lastRequest = $request;
|
||||
$this->lastResponse = $response;
|
||||
|
||||
if ($this->listener) {
|
||||
$this->listener->postSend($request, $response);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function getLastRequest()
|
||||
{
|
||||
return $this->lastRequest;
|
||||
}
|
||||
|
||||
public function getLastResponse()
|
||||
{
|
||||
return $this->lastResponse;
|
||||
}
|
||||
|
||||
public function setClient(ClientInterface $client)
|
||||
{
|
||||
$this->client = $client;
|
||||
}
|
||||
|
||||
public function getClient()
|
||||
{
|
||||
return $this->client;
|
||||
}
|
||||
|
||||
public function setMessageFactory(FactoryInterface $factory)
|
||||
{
|
||||
$this->factory = $factory;
|
||||
}
|
||||
|
||||
public function getMessageFactory()
|
||||
{
|
||||
return $this->factory;
|
||||
}
|
||||
|
||||
public function setListener(ListenerInterface $listener)
|
||||
{
|
||||
$this->listener = $listener;
|
||||
}
|
||||
|
||||
public function getListener()
|
||||
{
|
||||
return $this->listener;
|
||||
}
|
||||
|
||||
public function addListener(ListenerInterface $listener)
|
||||
{
|
||||
if (!$this->listener) {
|
||||
$this->listener = $listener;
|
||||
} elseif ($this->listener instanceof ListenerChain) {
|
||||
$this->listener->addListener($listener);
|
||||
} else {
|
||||
$this->listener = new ListenerChain(array(
|
||||
$this->listener,
|
||||
$listener,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Client;
|
||||
|
||||
abstract class AbstractClient implements ClientInterface
|
||||
{
|
||||
protected $ignoreErrors = true;
|
||||
protected $maxRedirects = 5;
|
||||
protected $timeout = 5;
|
||||
protected $verifyPeer = true;
|
||||
protected $proxy;
|
||||
|
||||
public function setIgnoreErrors($ignoreErrors)
|
||||
{
|
||||
$this->ignoreErrors = $ignoreErrors;
|
||||
}
|
||||
|
||||
public function getIgnoreErrors()
|
||||
{
|
||||
return $this->ignoreErrors;
|
||||
}
|
||||
|
||||
public function setMaxRedirects($maxRedirects)
|
||||
{
|
||||
$this->maxRedirects = $maxRedirects;
|
||||
}
|
||||
|
||||
public function getMaxRedirects()
|
||||
{
|
||||
return $this->maxRedirects;
|
||||
}
|
||||
|
||||
public function setTimeout($timeout)
|
||||
{
|
||||
$this->timeout = $timeout;
|
||||
}
|
||||
|
||||
public function getTimeout()
|
||||
{
|
||||
return $this->timeout;
|
||||
}
|
||||
|
||||
public function setVerifyPeer($verifyPeer)
|
||||
{
|
||||
$this->verifyPeer = $verifyPeer;
|
||||
}
|
||||
|
||||
public function getVerifyPeer()
|
||||
{
|
||||
return $this->verifyPeer;
|
||||
}
|
||||
|
||||
public function setProxy($proxy)
|
||||
{
|
||||
$this->proxy = $proxy;
|
||||
}
|
||||
|
||||
public function getProxy()
|
||||
{
|
||||
return $this->proxy;
|
||||
}
|
||||
}
|
||||
201
rainloop/v/1.2.7.415/app/libraries/Buzz/Client/AbstractCurl.php
Normal file
201
rainloop/v/1.2.7.415/app/libraries/Buzz/Client/AbstractCurl.php
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Client;
|
||||
|
||||
use Buzz\Message\Form\FormRequestInterface;
|
||||
use Buzz\Message\Form\FormUploadInterface;
|
||||
use Buzz\Message\MessageInterface;
|
||||
use Buzz\Message\RequestInterface;
|
||||
use Buzz\Exception\ClientException;
|
||||
|
||||
/**
|
||||
* Base client class with helpers for working with cURL.
|
||||
*/
|
||||
abstract class AbstractCurl extends AbstractClient
|
||||
{
|
||||
protected $options = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
if (defined('CURLOPT_PROTOCOLS')) {
|
||||
$this->options = array(
|
||||
CURLOPT_PROTOCOLS => CURLPROTO_HTTP | CURLPROTO_HTTPS,
|
||||
CURLOPT_REDIR_PROTOCOLS => CURLPROTO_HTTP | CURLPROTO_HTTPS,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new cURL resource.
|
||||
*
|
||||
* @see curl_init()
|
||||
*
|
||||
* @return resource A new cURL resource
|
||||
*/
|
||||
protected static function createCurlHandle()
|
||||
{
|
||||
if (false === $curl = curl_init()) {
|
||||
throw new ClientException('Unable to create a new cURL handle');
|
||||
}
|
||||
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($curl, CURLOPT_HEADER, true);
|
||||
|
||||
return $curl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates a response object.
|
||||
*
|
||||
* @param resource $curl A cURL resource
|
||||
* @param string $raw The raw response string
|
||||
* @param MessageInterface $response The response object
|
||||
*/
|
||||
protected static function populateResponse($curl, $raw, MessageInterface $response)
|
||||
{
|
||||
$pos = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
|
||||
|
||||
$response->setHeaders(static::getLastHeaders(rtrim(substr($raw, 0, $pos))));
|
||||
$response->setContent(substr($raw, $pos));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets options on a cURL resource based on a request.
|
||||
*/
|
||||
private static function setOptionsFromRequest($curl, RequestInterface $request)
|
||||
{
|
||||
$options = array(
|
||||
CURLOPT_CUSTOMREQUEST => $request->getMethod(),
|
||||
CURLOPT_URL => $request->getHost().$request->getResource(),
|
||||
CURLOPT_HTTPHEADER => $request->getHeaders(),
|
||||
);
|
||||
|
||||
switch ($request->getMethod()) {
|
||||
case RequestInterface::METHOD_HEAD:
|
||||
$options[CURLOPT_NOBODY] = true;
|
||||
break;
|
||||
|
||||
case RequestInterface::METHOD_GET:
|
||||
$options[CURLOPT_HTTPGET] = true;
|
||||
break;
|
||||
|
||||
case RequestInterface::METHOD_POST:
|
||||
case RequestInterface::METHOD_PUT:
|
||||
case RequestInterface::METHOD_DELETE:
|
||||
case RequestInterface::METHOD_PATCH:
|
||||
$options[CURLOPT_POSTFIELDS] = $fields = static::getPostFields($request);
|
||||
|
||||
// remove the content-type header
|
||||
if (is_array($fields)) {
|
||||
$options[CURLOPT_HTTPHEADER] = array_filter($options[CURLOPT_HTTPHEADER], function($header) {
|
||||
return 0 !== stripos($header, 'Content-Type: ');
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
curl_setopt_array($curl, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a value for the CURLOPT_POSTFIELDS option.
|
||||
*
|
||||
* @return string|array A post fields value
|
||||
*/
|
||||
private static function getPostFields(RequestInterface $request)
|
||||
{
|
||||
if (!$request instanceof FormRequestInterface) {
|
||||
return $request->getContent();
|
||||
}
|
||||
|
||||
$fields = $request->getFields();
|
||||
$multipart = false;
|
||||
|
||||
foreach ($fields as $name => $value) {
|
||||
if ($value instanceof FormUploadInterface) {
|
||||
$multipart = true;
|
||||
|
||||
if ($file = $value->getFile()) {
|
||||
// replace value with upload string
|
||||
$fields[$name] = '@'.$file;
|
||||
|
||||
if ($contentType = $value->getContentType()) {
|
||||
$fields[$name] .= ';type='.$contentType;
|
||||
}
|
||||
} else {
|
||||
return $request->getContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $multipart ? $fields : http_build_query($fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper for getting the last set of headers.
|
||||
*
|
||||
* @param string $raw A string of many header chunks
|
||||
*
|
||||
* @return array An array of header lines
|
||||
*/
|
||||
private static function getLastHeaders($raw)
|
||||
{
|
||||
$headers = array();
|
||||
foreach (preg_split('/(\\r?\\n)/', $raw) as $header) {
|
||||
if ($header) {
|
||||
$headers[] = $header;
|
||||
} else {
|
||||
$headers = array();
|
||||
}
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stashes a cURL option to be set on send, when the resource is created.
|
||||
*
|
||||
* If the supplied value it set to null the option will be removed.
|
||||
*
|
||||
* @param integer $option The option
|
||||
* @param mixed $value The value
|
||||
*
|
||||
* @see curl_setopt()
|
||||
*/
|
||||
public function setOption($option, $value)
|
||||
{
|
||||
if (null === $value) {
|
||||
unset($this->options[$option]);
|
||||
} else {
|
||||
$this->options[$option] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a cURL resource to send a request.
|
||||
*/
|
||||
protected function prepare($curl, RequestInterface $request, array $options = array())
|
||||
{
|
||||
static::setOptionsFromRequest($curl, $request);
|
||||
|
||||
// apply settings from client
|
||||
if ($this->getTimeout() < 1) {
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT_MS, $this->getTimeout() * 1000);
|
||||
} else {
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, $this->getTimeout());
|
||||
}
|
||||
|
||||
if ($this->proxy) {
|
||||
curl_setopt($curl, CURLOPT_PROXY, $this->proxy);
|
||||
}
|
||||
|
||||
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 0 < $this->getMaxRedirects());
|
||||
curl_setopt($curl, CURLOPT_MAXREDIRS, $this->getMaxRedirects());
|
||||
curl_setopt($curl, CURLOPT_FAILONERROR, !$this->getIgnoreErrors());
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->getVerifyPeer());
|
||||
|
||||
// apply additional options
|
||||
curl_setopt_array($curl, $options + $this->options);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Client;
|
||||
|
||||
use Buzz\Message\RequestInterface;
|
||||
|
||||
abstract class AbstractStream extends AbstractClient
|
||||
{
|
||||
/**
|
||||
* Converts a request into an array for stream_context_create().
|
||||
*
|
||||
* @param RequestInterface $request A request object
|
||||
*
|
||||
* @return array An array for stream_context_create()
|
||||
*/
|
||||
public function getStreamContextArray(RequestInterface $request)
|
||||
{
|
||||
$options = array(
|
||||
'http' => array(
|
||||
// values from the request
|
||||
'method' => $request->getMethod(),
|
||||
'header' => implode("\r\n", $request->getHeaders()),
|
||||
'content' => $request->getContent(),
|
||||
'protocol_version' => $request->getProtocolVersion(),
|
||||
|
||||
// values from the current client
|
||||
'ignore_errors' => $this->getIgnoreErrors(),
|
||||
'max_redirects' => $this->getMaxRedirects(),
|
||||
'timeout' => $this->getTimeout(),
|
||||
),
|
||||
'ssl' => array(
|
||||
'verify_peer' => $this->getVerifyPeer(),
|
||||
),
|
||||
);
|
||||
|
||||
if ($this->proxy) {
|
||||
$options['http']['proxy'] = $this->proxy;
|
||||
$options['http']['request_fulluri'] = true;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Client;
|
||||
|
||||
interface BatchClientInterface extends ClientInterface
|
||||
{
|
||||
/**
|
||||
* Processes the queued requests.
|
||||
*/
|
||||
public function flush();
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Client;
|
||||
|
||||
use Buzz\Message\MessageInterface;
|
||||
use Buzz\Message\RequestInterface;
|
||||
|
||||
interface ClientInterface
|
||||
{
|
||||
/**
|
||||
* Populates the supplied response with the response for the supplied request.
|
||||
*
|
||||
* @param RequestInterface $request A request object
|
||||
* @param MessageInterface $response A response object
|
||||
*/
|
||||
public function send(RequestInterface $request, MessageInterface $response);
|
||||
}
|
||||
55
rainloop/v/1.2.7.415/app/libraries/Buzz/Client/Curl.php
Normal file
55
rainloop/v/1.2.7.415/app/libraries/Buzz/Client/Curl.php
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Client;
|
||||
|
||||
use Buzz\Message\MessageInterface;
|
||||
use Buzz\Message\RequestInterface;
|
||||
use Buzz\Exception\ClientException;
|
||||
use Buzz\Exception\LogicException;
|
||||
|
||||
class Curl extends AbstractCurl
|
||||
{
|
||||
private $lastCurl;
|
||||
|
||||
public function send(RequestInterface $request, MessageInterface $response, array $options = array())
|
||||
{
|
||||
if (is_resource($this->lastCurl)) {
|
||||
curl_close($this->lastCurl);
|
||||
}
|
||||
|
||||
$this->lastCurl = static::createCurlHandle();
|
||||
$this->prepare($this->lastCurl, $request, $options);
|
||||
|
||||
$data = curl_exec($this->lastCurl);
|
||||
|
||||
if (false === $data) {
|
||||
$errorMsg = curl_error($this->lastCurl);
|
||||
$errorNo = curl_errno($this->lastCurl);
|
||||
|
||||
throw new ClientException($errorMsg, $errorNo);
|
||||
}
|
||||
|
||||
static::populateResponse($this->lastCurl, $data, $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Introspects the last cURL request.
|
||||
*
|
||||
* @see curl_getinfo()
|
||||
*/
|
||||
public function getInfo($opt = 0)
|
||||
{
|
||||
if (!is_resource($this->lastCurl)) {
|
||||
throw new LogicException('There is no cURL resource');
|
||||
}
|
||||
|
||||
return curl_getinfo($this->lastCurl, $opt);
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if (is_resource($this->lastCurl)) {
|
||||
curl_close($this->lastCurl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Client;
|
||||
|
||||
use Buzz\Message\MessageInterface;
|
||||
use Buzz\Message\RequestInterface;
|
||||
use Buzz\Util\CookieJar;
|
||||
use Buzz\Exception\ClientException;
|
||||
|
||||
class FileGetContents extends AbstractStream
|
||||
{
|
||||
/**
|
||||
* @var CookieJar
|
||||
*/
|
||||
protected $cookieJar;
|
||||
|
||||
/**
|
||||
* @param CookieJar|null $cookieJar
|
||||
*/
|
||||
public function __construct(CookieJar $cookieJar = null)
|
||||
{
|
||||
if ($cookieJar) {
|
||||
$this->setCookieJar($cookieJar);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CookieJar $cookieJar
|
||||
*/
|
||||
public function setCookieJar(CookieJar $cookieJar)
|
||||
{
|
||||
$this->cookieJar = $cookieJar;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CookieJar
|
||||
*/
|
||||
public function getCookieJar()
|
||||
{
|
||||
return $this->cookieJar;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see ClientInterface
|
||||
*
|
||||
* @throws ClientException If file_get_contents() fires an error
|
||||
*/
|
||||
public function send(RequestInterface $request, MessageInterface $response)
|
||||
{
|
||||
if ($cookieJar = $this->getCookieJar()) {
|
||||
$cookieJar->clearExpiredCookies();
|
||||
$cookieJar->addCookieHeaders($request);
|
||||
}
|
||||
|
||||
$context = stream_context_create($this->getStreamContextArray($request));
|
||||
$url = $request->getHost().$request->getResource();
|
||||
|
||||
$level = error_reporting(0);
|
||||
$content = file_get_contents($url, 0, $context);
|
||||
error_reporting($level);
|
||||
if (false === $content) {
|
||||
$error = error_get_last();
|
||||
throw new ClientException($error['message']);
|
||||
}
|
||||
|
||||
$response->setHeaders($this->filterHeaders((array) $http_response_header));
|
||||
$response->setContent($content);
|
||||
|
||||
if ($cookieJar) {
|
||||
$cookieJar->processSetCookieHeaders($request, $response);
|
||||
}
|
||||
}
|
||||
|
||||
private function filterHeaders(array $headers)
|
||||
{
|
||||
$filtered = array();
|
||||
foreach ($headers as $header) {
|
||||
if (0 === stripos($header, 'http/')) {
|
||||
$filtered = array();
|
||||
}
|
||||
|
||||
$filtered[] = $header;
|
||||
}
|
||||
|
||||
return $filtered;
|
||||
}
|
||||
}
|
||||
53
rainloop/v/1.2.7.415/app/libraries/Buzz/Client/MultiCurl.php
Normal file
53
rainloop/v/1.2.7.415/app/libraries/Buzz/Client/MultiCurl.php
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Client;
|
||||
|
||||
use Buzz\Message\MessageInterface;
|
||||
use Buzz\Message\RequestInterface;
|
||||
use Buzz\Exception\ClientException;
|
||||
|
||||
class MultiCurl extends AbstractCurl implements BatchClientInterface
|
||||
{
|
||||
private $queue = array();
|
||||
|
||||
public function send(RequestInterface $request, MessageInterface $response, array $options = array())
|
||||
{
|
||||
$this->queue[] = array($request, $response, $options);
|
||||
}
|
||||
|
||||
public function flush()
|
||||
{
|
||||
if (false === $curlm = curl_multi_init()) {
|
||||
throw new ClientException('Unable to create a new cURL multi handle');
|
||||
}
|
||||
|
||||
// prepare a cURL handle for each entry in the queue
|
||||
foreach ($this->queue as $i => &$queue) {
|
||||
list($request, $response, $options) = $queue;
|
||||
$curl = $queue[] = static::createCurlHandle();
|
||||
$this->prepare($curl, $request, $options);
|
||||
curl_multi_add_handle($curlm, $curl);
|
||||
}
|
||||
|
||||
$active = null;
|
||||
do {
|
||||
$mrc = curl_multi_exec($curlm, $active);
|
||||
} while (CURLM_CALL_MULTI_PERFORM == $mrc);
|
||||
|
||||
while ($active && CURLM_OK == $mrc) {
|
||||
if (-1 != curl_multi_select($curlm)) {
|
||||
do {
|
||||
$mrc = curl_multi_exec($curlm, $active);
|
||||
} while (CURLM_CALL_MULTI_PERFORM == $mrc);
|
||||
}
|
||||
}
|
||||
|
||||
// populate the responses
|
||||
while (list($request, $response, $options, $curl) = array_shift($this->queue)) {
|
||||
static::populateResponse($curl, curl_multi_getcontent($curl), $response);
|
||||
curl_multi_remove_handle($curlm, $curl);
|
||||
}
|
||||
|
||||
curl_multi_close($curlm);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Exception;
|
||||
|
||||
/**
|
||||
* Thrown whenever a client process fails.
|
||||
*/
|
||||
class ClientException extends RuntimeException
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Exception;
|
||||
|
||||
/**
|
||||
* Marker interface to denote exceptions thrown from the Buzz context.
|
||||
*/
|
||||
interface ExceptionInterface
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Exception;
|
||||
|
||||
/**
|
||||
* Thrown when an invalid argument is provided.
|
||||
*/
|
||||
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Exception;
|
||||
|
||||
/**
|
||||
* Thrown whenever a required call-flow is not respected.
|
||||
*/
|
||||
class LogicException extends \LogicException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Exception;
|
||||
|
||||
class RuntimeException extends \RuntimeException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Listener;
|
||||
|
||||
use Buzz\Message\MessageInterface;
|
||||
use Buzz\Message\RequestInterface;
|
||||
|
||||
class BasicAuthListener implements ListenerInterface
|
||||
{
|
||||
private $username;
|
||||
private $password;
|
||||
|
||||
public function __construct($username, $password)
|
||||
{
|
||||
$this->username = $username;
|
||||
$this->password = $password;
|
||||
}
|
||||
|
||||
public function preSend(RequestInterface $request)
|
||||
{
|
||||
$request->addHeader('Authorization: Basic '.base64_encode($this->username.':'.$this->password));
|
||||
}
|
||||
|
||||
public function postSend(RequestInterface $request, MessageInterface $response)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Listener;
|
||||
|
||||
use Buzz\Message\MessageInterface;
|
||||
use Buzz\Message\RequestInterface;
|
||||
use Buzz\Exception\InvalidArgumentException;
|
||||
|
||||
class CallbackListener implements ListenerInterface
|
||||
{
|
||||
private $callable;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* The callback should expect either one or two arguments, depending on
|
||||
* whether it is receiving a pre or post send notification.
|
||||
*
|
||||
* $listener = new CallbackListener(function($request, $response = null) {
|
||||
* if ($response) {
|
||||
* // postSend
|
||||
* } else {
|
||||
* // preSend
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* @param mixed $callable A PHP callable
|
||||
*
|
||||
* @throws InvalidArgumentException If the argument is not callable
|
||||
*/
|
||||
public function __construct($callable)
|
||||
{
|
||||
if (!is_callable($callable)) {
|
||||
throw new InvalidArgumentException('The argument is not callable.');
|
||||
}
|
||||
|
||||
$this->callable = $callable;
|
||||
}
|
||||
|
||||
public function preSend(RequestInterface $request)
|
||||
{
|
||||
call_user_func($this->callable, $request);
|
||||
}
|
||||
|
||||
public function postSend(RequestInterface $request, MessageInterface $response)
|
||||
{
|
||||
call_user_func($this->callable, $request, $response);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Listener\History;
|
||||
|
||||
use Buzz\Message\MessageInterface;
|
||||
use Buzz\Message\RequestInterface;
|
||||
|
||||
class Entry
|
||||
{
|
||||
private $request;
|
||||
private $response;
|
||||
private $duration;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param RequestInterface $request The request
|
||||
* @param MessageInterface $response The response
|
||||
* @param integer $duration The duration in seconds
|
||||
*/
|
||||
public function __construct(RequestInterface $request, MessageInterface $response, $duration = null)
|
||||
{
|
||||
$this->request = $request;
|
||||
$this->response = $response;
|
||||
$this->duration = $duration;
|
||||
}
|
||||
|
||||
public function getRequest()
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
|
||||
public function getResponse()
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
public function getDuration()
|
||||
{
|
||||
return $this->duration;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Listener\History;
|
||||
|
||||
use Buzz\Message\MessageInterface;
|
||||
use Buzz\Message\RequestInterface;
|
||||
|
||||
class Journal implements \Countable, \IteratorAggregate
|
||||
{
|
||||
private $entries = array();
|
||||
private $limit = 10;
|
||||
|
||||
/**
|
||||
* Records an entry in the journal.
|
||||
*
|
||||
* @param RequestInterface $request The request
|
||||
* @param MessageInterface $response The response
|
||||
* @param integer $duration The duration in seconds
|
||||
*/
|
||||
public function record(RequestInterface $request, MessageInterface $response, $duration = null)
|
||||
{
|
||||
$this->addEntry(new Entry($request, $response, $duration));
|
||||
}
|
||||
|
||||
public function addEntry(Entry $entry)
|
||||
{
|
||||
array_push($this->entries, $entry);
|
||||
$this->entries = array_slice($this->entries, $this->getLimit() * -1);
|
||||
end($this->entries);
|
||||
}
|
||||
|
||||
public function getEntries()
|
||||
{
|
||||
return $this->entries;
|
||||
}
|
||||
|
||||
public function getLast()
|
||||
{
|
||||
return end($this->entries);
|
||||
}
|
||||
|
||||
public function getLastRequest()
|
||||
{
|
||||
return $this->getLast()->getRequest();
|
||||
}
|
||||
|
||||
public function getLastResponse()
|
||||
{
|
||||
return $this->getLast()->getResponse();
|
||||
}
|
||||
|
||||
public function clear()
|
||||
{
|
||||
$this->entries = array();
|
||||
}
|
||||
|
||||
public function count()
|
||||
{
|
||||
return count($this->entries);
|
||||
}
|
||||
|
||||
public function setLimit($limit)
|
||||
{
|
||||
$this->limit = $limit;
|
||||
}
|
||||
|
||||
public function getLimit()
|
||||
{
|
||||
return $this->limit;
|
||||
}
|
||||
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator(array_reverse($this->entries));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Listener;
|
||||
|
||||
use Buzz\Listener\History\Journal;
|
||||
use Buzz\Message\MessageInterface;
|
||||
use Buzz\Message\RequestInterface;
|
||||
|
||||
class HistoryListener implements ListenerInterface
|
||||
{
|
||||
private $journal;
|
||||
private $startTime;
|
||||
|
||||
public function __construct(Journal $journal)
|
||||
{
|
||||
$this->journal = $journal;
|
||||
}
|
||||
|
||||
public function getJournal()
|
||||
{
|
||||
return $this->journal;
|
||||
}
|
||||
|
||||
public function preSend(RequestInterface $request)
|
||||
{
|
||||
$this->startTime = microtime(true);
|
||||
}
|
||||
|
||||
public function postSend(RequestInterface $request, MessageInterface $response)
|
||||
{
|
||||
$this->journal->record($request, $response, microtime(true) - $this->startTime);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Listener;
|
||||
|
||||
use Buzz\Message\MessageInterface;
|
||||
use Buzz\Message\RequestInterface;
|
||||
|
||||
class ListenerChain implements ListenerInterface
|
||||
{
|
||||
private $listeners;
|
||||
|
||||
public function __construct(array $listeners = array())
|
||||
{
|
||||
$this->listeners = $listeners;
|
||||
}
|
||||
|
||||
public function addListener(ListenerInterface $listener)
|
||||
{
|
||||
$this->listeners[] = $listener;
|
||||
}
|
||||
|
||||
public function getListeners()
|
||||
{
|
||||
return $this->listeners;
|
||||
}
|
||||
|
||||
public function preSend(RequestInterface $request)
|
||||
{
|
||||
foreach ($this->listeners as $listener) {
|
||||
$listener->preSend($request);
|
||||
}
|
||||
}
|
||||
|
||||
public function postSend(RequestInterface $request, MessageInterface $response)
|
||||
{
|
||||
foreach ($this->listeners as $listener) {
|
||||
$listener->postSend($request, $response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Listener;
|
||||
|
||||
use Buzz\Message\MessageInterface;
|
||||
use Buzz\Message\RequestInterface;
|
||||
|
||||
interface ListenerInterface
|
||||
{
|
||||
public function preSend(RequestInterface $request);
|
||||
public function postSend(RequestInterface $request, MessageInterface $response);
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Listener;
|
||||
|
||||
use Buzz\Message\MessageInterface;
|
||||
use Buzz\Message\RequestInterface;
|
||||
use Buzz\Exception\InvalidArgumentException;
|
||||
|
||||
class LoggerListener implements ListenerInterface
|
||||
{
|
||||
private $logger;
|
||||
private $prefix;
|
||||
private $startTime;
|
||||
|
||||
public function __construct($logger, $prefix = null)
|
||||
{
|
||||
if (!is_callable($logger)) {
|
||||
throw new InvalidArgumentException('The logger must be a callable.');
|
||||
}
|
||||
|
||||
$this->logger = $logger;
|
||||
$this->prefix = $prefix;
|
||||
}
|
||||
|
||||
public function preSend(RequestInterface $request)
|
||||
{
|
||||
$this->startTime = microtime(true);
|
||||
}
|
||||
|
||||
public function postSend(RequestInterface $request, MessageInterface $response)
|
||||
{
|
||||
$seconds = microtime(true) - $this->startTime;
|
||||
|
||||
call_user_func($this->logger, sprintf('%sSent "%s %s%s" in %dms', $this->prefix, $request->getMethod(), $request->getHost(), $request->getResource(), round($seconds * 1000)));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Message;
|
||||
|
||||
abstract class AbstractMessage implements MessageInterface
|
||||
{
|
||||
private $headers = array();
|
||||
private $content;
|
||||
|
||||
/**
|
||||
* Returns the value of a header.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string|boolean $glue Glue for implode, or false to return an array
|
||||
*
|
||||
* @return string|array|null
|
||||
*/
|
||||
public function getHeader($name, $glue = "\r\n")
|
||||
{
|
||||
$needle = $name.':';
|
||||
|
||||
$values = array();
|
||||
foreach ($this->getHeaders() as $header) {
|
||||
if (0 === stripos($header, $needle)) {
|
||||
$values[] = trim(substr($header, strlen($needle)));
|
||||
}
|
||||
}
|
||||
|
||||
if (false === $glue) {
|
||||
return $values;
|
||||
} else {
|
||||
return count($values) ? implode($glue, $values) : null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a header's attributes.
|
||||
*
|
||||
* @param string $name A header name
|
||||
*
|
||||
* @return array An associative array of attributes
|
||||
*/
|
||||
public function getHeaderAttributes($name)
|
||||
{
|
||||
$attributes = array();
|
||||
foreach ($this->getHeader($name, false) as $header) {
|
||||
if (false !== strpos($header, ';')) {
|
||||
// remove header value
|
||||
list(, $header) = explode(';', $header, 2);
|
||||
|
||||
// loop through attribute key=value pairs
|
||||
foreach (array_map('trim', explode(';', trim($header))) as $pair) {
|
||||
list($key, $value) = explode('=', $pair);
|
||||
$attributes[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a particular header attribute.
|
||||
*
|
||||
* @param string $header A header name
|
||||
* @param string $attribute An attribute name
|
||||
*
|
||||
* @return string|null The value of the attribute or null if it isn't set
|
||||
*/
|
||||
public function getHeaderAttribute($header, $attribute)
|
||||
{
|
||||
$attributes = $this->getHeaderAttributes($header);
|
||||
|
||||
if (isset($attributes[$attribute])) {
|
||||
return $attributes[$attribute];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current message as a DOMDocument.
|
||||
*
|
||||
* @return \DOMDocument
|
||||
*/
|
||||
public function toDomDocument()
|
||||
{
|
||||
$revert = libxml_use_internal_errors(true);
|
||||
|
||||
$document = new \DOMDocument('1.0', $this->getHeaderAttribute('Content-Type', 'charset') ?: 'UTF-8');
|
||||
if (0 === strpos($this->getHeader('Content-Type'), 'text/xml')) {
|
||||
$document->loadXML($this->getContent());
|
||||
} else {
|
||||
$document->loadHTML($this->getContent());
|
||||
}
|
||||
|
||||
libxml_use_internal_errors($revert);
|
||||
|
||||
return $document;
|
||||
}
|
||||
|
||||
public function setHeaders(array $headers)
|
||||
{
|
||||
$this->headers = $this->flattenHeaders($headers);
|
||||
}
|
||||
|
||||
public function addHeader($header)
|
||||
{
|
||||
$this->headers[] = $header;
|
||||
}
|
||||
|
||||
public function addHeaders(array $headers)
|
||||
{
|
||||
$this->headers = array_merge($this->headers, $this->flattenHeaders($headers));
|
||||
}
|
||||
|
||||
public function getHeaders()
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
public function setContent($content)
|
||||
{
|
||||
$this->content = $content;
|
||||
}
|
||||
|
||||
public function getContent()
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
$string = implode("\r\n", $this->getHeaders())."\r\n";
|
||||
|
||||
if ($content = $this->getContent()) {
|
||||
$string .= "\r\n$content\r\n";
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
protected function flattenHeaders(array $headers)
|
||||
{
|
||||
$flattened = array();
|
||||
foreach ($headers as $key => $header) {
|
||||
if (is_int($key)) {
|
||||
$flattened[] = $header;
|
||||
} else {
|
||||
$flattened[] = $key.': '.$header;
|
||||
}
|
||||
}
|
||||
|
||||
return $flattened;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Message\Factory;
|
||||
|
||||
use Buzz\Message\Form\FormRequest;
|
||||
use Buzz\Message\Request;
|
||||
use Buzz\Message\RequestInterface;
|
||||
use Buzz\Message\Response;
|
||||
|
||||
class Factory implements FactoryInterface
|
||||
{
|
||||
public function createRequest($method = RequestInterface::METHOD_GET, $resource = '/', $host = null)
|
||||
{
|
||||
return new Request($method, $resource, $host);
|
||||
}
|
||||
|
||||
public function createFormRequest($method = RequestInterface::METHOD_POST, $resource = '/', $host = null)
|
||||
{
|
||||
return new FormRequest($method, $resource, $host);
|
||||
}
|
||||
|
||||
public function createResponse()
|
||||
{
|
||||
return new Response();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Message\Factory;
|
||||
|
||||
use Buzz\Message\RequestInterface;
|
||||
|
||||
interface FactoryInterface
|
||||
{
|
||||
public function createRequest($method = RequestInterface::METHOD_GET, $resource = '/', $host = null);
|
||||
public function createFormRequest($method = RequestInterface::METHOD_POST, $resource = '/', $host = null);
|
||||
public function createResponse();
|
||||
}
|
||||
|
|
@ -0,0 +1,187 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Message\Form;
|
||||
|
||||
use Buzz\Message\Request;
|
||||
use Buzz\Exception\LogicException;
|
||||
|
||||
/**
|
||||
* FormRequest.
|
||||
*
|
||||
* $request = new FormRequest();
|
||||
* $request->setField('user[name]', 'Kris Wallsmith');
|
||||
* $request->setField('user[image]', new FormUpload('/path/to/image.jpg'));
|
||||
*
|
||||
* @author Marc Weistroff <marc.weistroff@sensio.com>
|
||||
* @author Kris Wallsmith <kris.wallsmith@gmail.com>
|
||||
*/
|
||||
class FormRequest extends Request implements FormRequestInterface
|
||||
{
|
||||
private $fields = array();
|
||||
private $boundary;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Defaults to POST rather than GET.
|
||||
*/
|
||||
public function __construct($method = self::METHOD_POST, $resource = '/', $host = null)
|
||||
{
|
||||
parent::__construct($method, $resource, $host);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of a form field.
|
||||
*
|
||||
* If the value is an array it will be flattened and one field value will
|
||||
* be added for each leaf.
|
||||
*/
|
||||
public function setField($name, $value)
|
||||
{
|
||||
if (is_array($value)) {
|
||||
$this->addFields(array($name => $value));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ('[]' == substr($name, -2)) {
|
||||
$this->fields[substr($name, 0, -2)][] = $value;
|
||||
} else {
|
||||
$this->fields[$name] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
public function addFields(array $fields)
|
||||
{
|
||||
foreach ($this->flattenArray($fields) as $name => $value) {
|
||||
$this->setField($name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
public function setFields(array $fields)
|
||||
{
|
||||
$this->fields = array();
|
||||
$this->addFields($fields);
|
||||
}
|
||||
|
||||
public function getFields()
|
||||
{
|
||||
return $this->fields;
|
||||
}
|
||||
|
||||
public function getResource()
|
||||
{
|
||||
$resource = parent::getResource();
|
||||
|
||||
if (!$this->isSafe() || !$this->fields) {
|
||||
return $resource;
|
||||
}
|
||||
|
||||
// append the query string
|
||||
$resource .= false === strpos($resource, '?') ? '?' : '&';
|
||||
$resource .= http_build_query($this->fields);
|
||||
|
||||
return $resource;
|
||||
}
|
||||
|
||||
public function setContent($content)
|
||||
{
|
||||
throw new \BadMethodCallException('It is not permitted to set the content.');
|
||||
}
|
||||
|
||||
public function getHeaders()
|
||||
{
|
||||
$headers = parent::getHeaders();
|
||||
|
||||
if ($this->isSafe()) {
|
||||
return $headers;
|
||||
}
|
||||
|
||||
if ($this->isMultipart()) {
|
||||
$headers[] = 'Content-Type: multipart/form-data; boundary='.$this->getBoundary();
|
||||
} else {
|
||||
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
public function getContent()
|
||||
{
|
||||
if ($this->isSafe()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->isMultipart()) {
|
||||
return http_build_query($this->fields);
|
||||
}
|
||||
|
||||
$content = '';
|
||||
|
||||
foreach ($this->fields as $name => $values) {
|
||||
$content .= '--'.$this->getBoundary()."\r\n";
|
||||
if ($values instanceof FormUploadInterface) {
|
||||
if (!$values->getFilename()) {
|
||||
throw new LogicException(sprintf('Form upload at "%s" does not include a filename.', $name));
|
||||
}
|
||||
|
||||
$values->setName($name);
|
||||
$content .= (string) $values;
|
||||
} else {
|
||||
foreach (is_array($values) ? $values : array($values) as $value) {
|
||||
$content .= "Content-Disposition: form-data; name=\"$name\"\r\n";
|
||||
$content .= "\r\n";
|
||||
$content .= $value."\r\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$content .= '--'.$this->getBoundary().'--';
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
// private
|
||||
|
||||
private function flattenArray(array $values, $prefix = '', $format = '%s')
|
||||
{
|
||||
$flat = array();
|
||||
|
||||
foreach ($values as $name => $value) {
|
||||
$flatName = $prefix.sprintf($format, $name);
|
||||
|
||||
if (is_array($value)) {
|
||||
$flat += $this->flattenArray($value, $flatName, '[%s]');
|
||||
} else {
|
||||
$flat[$flatName] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $flat;
|
||||
}
|
||||
|
||||
private function isSafe()
|
||||
{
|
||||
return in_array($this->getMethod(), array(self::METHOD_GET, self::METHOD_HEAD));
|
||||
}
|
||||
|
||||
private function isMultipart()
|
||||
{
|
||||
foreach ($this->fields as $name => $value) {
|
||||
if (is_object($value) && $value instanceof FormUploadInterface) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getBoundary()
|
||||
{
|
||||
if (!$this->boundary) {
|
||||
$this->boundary = sha1(rand(11111, 99999).time().uniqid());
|
||||
}
|
||||
|
||||
return $this->boundary;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Message\Form;
|
||||
|
||||
use Buzz\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* An HTTP request message sent by a web form.
|
||||
*
|
||||
* @author Kris Wallsmith <kris.wallsmith@gmail.com>
|
||||
*/
|
||||
interface FormRequestInterface extends RequestInterface
|
||||
{
|
||||
/**
|
||||
* Returns an array of field names and values.
|
||||
*
|
||||
* @return array A array of names and values
|
||||
*/
|
||||
public function getFields();
|
||||
|
||||
/**
|
||||
* Sets the form fields for the current request.
|
||||
*
|
||||
* @param array $fields An array of field names and values
|
||||
*/
|
||||
public function setFields(array $fields);
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Message\Form;
|
||||
|
||||
use Buzz\Message\AbstractMessage;
|
||||
|
||||
class FormUpload extends AbstractMessage implements FormUploadInterface
|
||||
{
|
||||
private $name;
|
||||
private $filename;
|
||||
private $contentType;
|
||||
private $file;
|
||||
|
||||
public function __construct($file = null, $contentType = null)
|
||||
{
|
||||
if ($file) {
|
||||
$this->loadContent($file);
|
||||
}
|
||||
|
||||
$this->contentType = $contentType;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function getFilename()
|
||||
{
|
||||
if ($this->filename) {
|
||||
return $this->filename;
|
||||
} elseif ($this->file) {
|
||||
return basename($this->file);
|
||||
}
|
||||
}
|
||||
|
||||
public function setFilename($filename)
|
||||
{
|
||||
$this->filename = $filename;
|
||||
}
|
||||
|
||||
public function getContentType()
|
||||
{
|
||||
return $this->contentType ?: $this->detectContentType() ?: 'application/octet-stream';
|
||||
}
|
||||
|
||||
public function setContentType($contentType)
|
||||
{
|
||||
$this->contentType = $contentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepends Content-Disposition and Content-Type headers.
|
||||
*/
|
||||
public function getHeaders()
|
||||
{
|
||||
$headers = array('Content-Disposition: form-data');
|
||||
|
||||
if ($name = $this->getName()) {
|
||||
$headers[0] .= sprintf('; name="%s"', $name);
|
||||
}
|
||||
|
||||
if ($filename = $this->getFilename()) {
|
||||
$headers[0] .= sprintf('; filename="%s"', $filename);
|
||||
}
|
||||
|
||||
if ($contentType = $this->getContentType()) {
|
||||
$headers[] = 'Content-Type: '.$contentType;
|
||||
}
|
||||
|
||||
return array_merge($headers, parent::getHeaders());
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the content from a file.
|
||||
*/
|
||||
public function loadContent($file)
|
||||
{
|
||||
$this->file = $file;
|
||||
|
||||
parent::setContent(null);
|
||||
}
|
||||
|
||||
public function setContent($content)
|
||||
{
|
||||
parent::setContent($content);
|
||||
|
||||
$this->file = null;
|
||||
}
|
||||
|
||||
public function getFile()
|
||||
{
|
||||
return $this->file;
|
||||
}
|
||||
|
||||
public function getContent()
|
||||
{
|
||||
return $this->file ? file_get_contents($this->file) : parent::getContent();
|
||||
}
|
||||
|
||||
// private
|
||||
|
||||
private function detectContentType()
|
||||
{
|
||||
if (!class_exists('finfo', false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$finfo = new \finfo(FILEINFO_MIME_TYPE);
|
||||
|
||||
return $this->file ? $finfo->file($this->file) : $finfo->buffer(parent::getContent());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Message\Form;
|
||||
|
||||
use Buzz\Message\MessageInterface;
|
||||
|
||||
interface FormUploadInterface extends MessageInterface
|
||||
{
|
||||
public function setName($name);
|
||||
public function getFile();
|
||||
public function getFilename();
|
||||
public function getContentType();
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Message;
|
||||
|
||||
/**
|
||||
* An HTTP message.
|
||||
*
|
||||
* @author Kris Wallsmith <kris.wallsmith@gmail.com>
|
||||
*/
|
||||
interface MessageInterface
|
||||
{
|
||||
/**
|
||||
* Returns a header value.
|
||||
*
|
||||
* @param string $name A header name
|
||||
* @param string|boolean $glue Glue for implode, or false to return an array
|
||||
*
|
||||
* @return string|array|null The header value(s)
|
||||
*/
|
||||
public function getHeader($name, $glue = "\r\n");
|
||||
|
||||
/**
|
||||
* Returns an array of header lines.
|
||||
*
|
||||
* @return array An array of header lines (integer indexes, e.g. ["Header: value"])
|
||||
*/
|
||||
public function getHeaders();
|
||||
|
||||
/**
|
||||
* Sets all headers on the current message.
|
||||
*
|
||||
* Headers can be complete ["Header: value"] pairs or an associative array ["Header" => "value"]
|
||||
*
|
||||
* @param array $headers An array of header lines
|
||||
*/
|
||||
public function setHeaders(array $headers);
|
||||
|
||||
/**
|
||||
* Adds a header to this message.
|
||||
*
|
||||
* @param string $header A header line
|
||||
*/
|
||||
public function addHeader($header);
|
||||
|
||||
/**
|
||||
* Adds a set of headers to this message.
|
||||
*
|
||||
* Headers can be complete ["Header: value"] pairs or an associative array ["Header" => "value"]
|
||||
*
|
||||
* @param array $headers Headers
|
||||
*/
|
||||
public function addHeaders(array $headers);
|
||||
|
||||
/**
|
||||
* Returns the content of the message.
|
||||
*
|
||||
* @return string The message content
|
||||
*/
|
||||
public function getContent();
|
||||
|
||||
/**
|
||||
* Sets the content of the message.
|
||||
*
|
||||
* @param string $content The message content
|
||||
*/
|
||||
public function setContent($content);
|
||||
|
||||
/**
|
||||
* Returns the message document.
|
||||
*
|
||||
* @return string The message
|
||||
*/
|
||||
public function __toString();
|
||||
}
|
||||
174
rainloop/v/1.2.7.415/app/libraries/Buzz/Message/Request.php
Normal file
174
rainloop/v/1.2.7.415/app/libraries/Buzz/Message/Request.php
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Message;
|
||||
|
||||
use Buzz\Util\Url;
|
||||
|
||||
class Request extends AbstractMessage implements RequestInterface
|
||||
{
|
||||
private $method;
|
||||
private $resource;
|
||||
private $host;
|
||||
private $protocolVersion = 1.0;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $method
|
||||
* @param string $resource
|
||||
* @param string $host
|
||||
*/
|
||||
public function __construct($method = self::METHOD_GET, $resource = '/', $host = null)
|
||||
{
|
||||
$this->method = strtoupper($method);
|
||||
$this->resource = $resource;
|
||||
$this->host = $host;
|
||||
}
|
||||
|
||||
public function setHeaders(array $headers)
|
||||
{
|
||||
parent::setHeaders(array());
|
||||
|
||||
foreach ($this->flattenHeaders($headers) as $header) {
|
||||
$this->addHeader($header);
|
||||
}
|
||||
}
|
||||
|
||||
public function addHeader($header)
|
||||
{
|
||||
if (0 === stripos(substr($header, -8), 'HTTP/1.') && 3 == count($parts = explode(' ', $header))) {
|
||||
list($method, $resource, $protocolVersion) = $parts;
|
||||
|
||||
$this->setMethod($method);
|
||||
$this->setResource($resource);
|
||||
$this->setProtocolVersion((float) substr($protocolVersion, 5));
|
||||
} else {
|
||||
parent::addHeader($header);
|
||||
}
|
||||
}
|
||||
|
||||
public function setMethod($method)
|
||||
{
|
||||
$this->method = strtoupper($method);
|
||||
}
|
||||
|
||||
public function getMethod()
|
||||
{
|
||||
return $this->method;
|
||||
}
|
||||
|
||||
public function setResource($resource)
|
||||
{
|
||||
$this->resource = $resource;
|
||||
}
|
||||
|
||||
public function getResource()
|
||||
{
|
||||
return $this->resource;
|
||||
}
|
||||
|
||||
public function setHost($host)
|
||||
{
|
||||
$this->host = $host;
|
||||
}
|
||||
|
||||
public function getHost()
|
||||
{
|
||||
return $this->host;
|
||||
}
|
||||
|
||||
public function setProtocolVersion($protocolVersion)
|
||||
{
|
||||
$this->protocolVersion = $protocolVersion;
|
||||
}
|
||||
|
||||
public function getProtocolVersion()
|
||||
{
|
||||
return $this->protocolVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method for getting the full URL of the current request.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUrl()
|
||||
{
|
||||
return $this->getHost().$this->getResource();
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method for populating the current request from a URL.
|
||||
*
|
||||
* @param Url|string $url An URL
|
||||
*/
|
||||
public function fromUrl($url)
|
||||
{
|
||||
if (!$url instanceof Url) {
|
||||
$url = new Url($url);
|
||||
}
|
||||
|
||||
$url->applyToRequest($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current request is secure.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isSecure()
|
||||
{
|
||||
return 'https' == parse_url($this->getHost(), PHP_URL_SCHEME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges cookie headers on the way out.
|
||||
*/
|
||||
public function getHeaders()
|
||||
{
|
||||
return $this->mergeCookieHeaders(parent::getHeaders());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the current request.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$string = sprintf("%s %s HTTP/%.1f\r\n", $this->getMethod(), $this->getResource(), $this->getProtocolVersion());
|
||||
|
||||
if ($host = $this->getHost()) {
|
||||
$string .= 'Host: '.$host."\r\n";
|
||||
}
|
||||
|
||||
if ($parent = trim(parent::__toString())) {
|
||||
$string .= $parent."\r\n";
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
// private
|
||||
|
||||
private function mergeCookieHeaders(array $headers)
|
||||
{
|
||||
$cookieHeader = null;
|
||||
$needle = 'Cookie:';
|
||||
|
||||
foreach ($headers as $i => $header) {
|
||||
if (0 !== stripos($header, $needle)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (null === $cookieHeader) {
|
||||
$cookieHeader = $i;
|
||||
} else {
|
||||
$headers[$cookieHeader] .= '; '.trim(substr($header, strlen($needle)));
|
||||
unset($headers[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
return array_values($headers);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Message;
|
||||
|
||||
/**
|
||||
* An HTTP request message.
|
||||
*
|
||||
* @author Kris Wallsmith <kris.wallsmith@gmail.com>
|
||||
*/
|
||||
interface RequestInterface extends MessageInterface
|
||||
{
|
||||
const METHOD_OPTIONS = 'OPTIONS';
|
||||
const METHOD_GET = 'GET';
|
||||
const METHOD_HEAD = 'HEAD';
|
||||
const METHOD_POST = 'POST';
|
||||
const METHOD_PUT = 'PUT';
|
||||
const METHOD_DELETE = 'DELETE';
|
||||
const METHOD_PATCH = 'PATCH';
|
||||
|
||||
/**
|
||||
* Returns the HTTP method of the current request.
|
||||
*
|
||||
* @return string An HTTP method
|
||||
*/
|
||||
public function getMethod();
|
||||
|
||||
/**
|
||||
* Sets the HTTP method of the current request.
|
||||
*
|
||||
* @param string $method The request method
|
||||
*/
|
||||
public function setMethod($method);
|
||||
|
||||
/**
|
||||
* Returns the resource portion of the request line.
|
||||
*
|
||||
* @return string The resource requested
|
||||
*/
|
||||
public function getResource();
|
||||
|
||||
/**
|
||||
* Sets the resource for the current request.
|
||||
*
|
||||
* @param string $resource The resource being requested
|
||||
*/
|
||||
public function setResource($resource);
|
||||
|
||||
/**
|
||||
* Returns the protocol version of the current request.
|
||||
*
|
||||
* @return float The protocol version
|
||||
*/
|
||||
public function getProtocolVersion();
|
||||
|
||||
/**
|
||||
* Returns the value of the host header.
|
||||
*
|
||||
* @return string|null The host
|
||||
*/
|
||||
public function getHost();
|
||||
|
||||
/**
|
||||
* Sets the host for the current request.
|
||||
*
|
||||
* @param string $host The host
|
||||
*/
|
||||
public function setHost($host);
|
||||
|
||||
/**
|
||||
* Checks if the current request is secure.
|
||||
*
|
||||
* @return Boolean True if the request is secure
|
||||
*/
|
||||
public function isSecure();
|
||||
}
|
||||
193
rainloop/v/1.2.7.415/app/libraries/Buzz/Message/Response.php
Normal file
193
rainloop/v/1.2.7.415/app/libraries/Buzz/Message/Response.php
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Message;
|
||||
|
||||
class Response extends AbstractMessage
|
||||
{
|
||||
private $protocolVersion;
|
||||
private $statusCode;
|
||||
private $reasonPhrase;
|
||||
|
||||
/**
|
||||
* Returns the protocol version of the current response.
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getProtocolVersion()
|
||||
{
|
||||
if (null === $this->protocolVersion) {
|
||||
$this->parseStatusLine();
|
||||
}
|
||||
|
||||
return $this->protocolVersion ?: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the status code of the current response.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getStatusCode()
|
||||
{
|
||||
if (null === $this->statusCode) {
|
||||
$this->parseStatusLine();
|
||||
}
|
||||
|
||||
return $this->statusCode ?: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reason phrase for the current response.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getReasonPhrase()
|
||||
{
|
||||
if (null === $this->reasonPhrase) {
|
||||
$this->parseStatusLine();
|
||||
}
|
||||
|
||||
return $this->reasonPhrase ?: null;
|
||||
}
|
||||
|
||||
public function setHeaders(array $headers)
|
||||
{
|
||||
parent::setHeaders($headers);
|
||||
|
||||
$this->resetStatusLine();
|
||||
}
|
||||
|
||||
public function addHeader($header)
|
||||
{
|
||||
parent::addHeader($header);
|
||||
|
||||
$this->resetStatusLine();
|
||||
}
|
||||
|
||||
public function addHeaders(array $headers)
|
||||
{
|
||||
parent::addHeaders($headers);
|
||||
|
||||
$this->resetStatusLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is response invalid?
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public function isInvalid()
|
||||
{
|
||||
return $this->getStatusCode() < 100 || $this->getStatusCode() >= 600;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is response informative?
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public function isInformational()
|
||||
{
|
||||
return $this->getStatusCode() >= 100 && $this->getStatusCode() < 200;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is response successful?
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public function isSuccessful()
|
||||
{
|
||||
return $this->getStatusCode() >= 200 && $this->getStatusCode() < 300;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the response a redirect?
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public function isRedirection()
|
||||
{
|
||||
return $this->getStatusCode() >= 300 && $this->getStatusCode() < 400;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there a client error?
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public function isClientError()
|
||||
{
|
||||
return $this->getStatusCode() >= 400 && $this->getStatusCode() < 500;
|
||||
}
|
||||
|
||||
/**
|
||||
* Was there a server side error?
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public function isServerError()
|
||||
{
|
||||
return $this->getStatusCode() >= 500 && $this->getStatusCode() < 600;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the response OK?
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public function isOk()
|
||||
{
|
||||
return 200 === $this->getStatusCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the reponse forbidden?
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public function isForbidden()
|
||||
{
|
||||
return 403 === $this->getStatusCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the response a not found error?
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public function isNotFound()
|
||||
{
|
||||
return 404 === $this->getStatusCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the response empty?
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public function isEmpty()
|
||||
{
|
||||
return in_array($this->getStatusCode(), array(201, 204, 304));
|
||||
}
|
||||
|
||||
// private
|
||||
|
||||
private function parseStatusLine()
|
||||
{
|
||||
$headers = $this->getHeaders();
|
||||
|
||||
if (isset($headers[0]) && 3 == count($parts = explode(' ', $headers[0], 3))) {
|
||||
$this->protocolVersion = (float) $parts[0];
|
||||
$this->statusCode = (integer) $parts[1];
|
||||
$this->reasonPhrase = $parts[2];
|
||||
} else {
|
||||
$this->protocolVersion = $this->statusCode = $this->reasonPhrase = false;
|
||||
}
|
||||
}
|
||||
|
||||
private function resetStatusLine()
|
||||
{
|
||||
$this->protocolVersion = $this->statusCode = $this->reasonPhrase = null;
|
||||
}
|
||||
}
|
||||
216
rainloop/v/1.2.7.415/app/libraries/Buzz/Util/Cookie.php
Normal file
216
rainloop/v/1.2.7.415/app/libraries/Buzz/Util/Cookie.php
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Util;
|
||||
|
||||
use Buzz\Message\RequestInterface;
|
||||
|
||||
class Cookie
|
||||
{
|
||||
const ATTR_DOMAIN = 'domain';
|
||||
const ATTR_PATH = 'path';
|
||||
const ATTR_SECURE = 'secure';
|
||||
const ATTR_MAX_AGE = 'max-age';
|
||||
const ATTR_EXPIRES = 'expires';
|
||||
|
||||
protected $name;
|
||||
protected $value;
|
||||
protected $attributes = array();
|
||||
protected $createdAt;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->createdAt = time();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current cookie matches the supplied request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function matchesRequest(RequestInterface $request)
|
||||
{
|
||||
// domain
|
||||
if (!$this->matchesDomain(parse_url($request->getHost(), PHP_URL_HOST))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// path
|
||||
if (!$this->matchesPath($request->getResource())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// secure
|
||||
if ($this->hasAttribute(static::ATTR_SECURE) && !$request->isSecure()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true of the current cookie has expired.
|
||||
*
|
||||
* Checks the max-age and expires attributes.
|
||||
*
|
||||
* @return boolean Whether the current cookie has expired
|
||||
*/
|
||||
public function isExpired()
|
||||
{
|
||||
$maxAge = $this->getAttribute(static::ATTR_MAX_AGE);
|
||||
if ($maxAge && time() - $this->getCreatedAt() > $maxAge) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$expires = $this->getAttribute(static::ATTR_EXPIRES);
|
||||
if ($expires && strtotime($expires) < time()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current cookie matches the supplied domain.
|
||||
*
|
||||
* @param string $domain A domain hostname
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function matchesDomain($domain)
|
||||
{
|
||||
$cookieDomain = $this->getAttribute(static::ATTR_DOMAIN);
|
||||
|
||||
if (0 === strpos($cookieDomain, '.')) {
|
||||
$pattern = '/\b'.preg_quote(substr($cookieDomain, 1), '/').'$/i';
|
||||
|
||||
return (boolean) preg_match($pattern, $domain);
|
||||
} else {
|
||||
return 0 == strcasecmp($cookieDomain, $domain);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the current cookie matches the supplied path.
|
||||
*
|
||||
* @param string $path A path
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function matchesPath($path)
|
||||
{
|
||||
$needle = $this->getAttribute(static::ATTR_PATH);
|
||||
|
||||
return null === $needle || 0 === strpos($path, $needle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the current cookie with data from the supplied Set-Cookie header.
|
||||
*
|
||||
* @param string $header A Set-Cookie header
|
||||
* @param string $issuingDomain The domain that issued the header
|
||||
*/
|
||||
public function fromSetCookieHeader($header, $issuingDomain)
|
||||
{
|
||||
list($this->name, $header) = explode('=', $header, 2);
|
||||
if (false === strpos($header, ';')) {
|
||||
$this->value = $header;
|
||||
$header = null;
|
||||
} else {
|
||||
list($this->value, $header) = explode(';', $header, 2);
|
||||
}
|
||||
|
||||
$this->clearAttributes();
|
||||
foreach (array_map('trim', explode(';', trim($header))) as $pair) {
|
||||
if (false === strpos($pair, '=')) {
|
||||
$name = $pair;
|
||||
$value = null;
|
||||
} else {
|
||||
list($name, $value) = explode('=', $pair);
|
||||
}
|
||||
|
||||
$this->setAttribute($name, $value);
|
||||
}
|
||||
|
||||
if (!$this->getAttribute(static::ATTR_DOMAIN)) {
|
||||
$this->setAttribute(static::ATTR_DOMAIN, $issuingDomain);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a Cookie header for the current cookie.
|
||||
*
|
||||
* @return string An HTTP request Cookie header
|
||||
*/
|
||||
public function toCookieHeader()
|
||||
{
|
||||
return 'Cookie: '.$this->getName().'='.$this->getValue();
|
||||
}
|
||||
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setValue($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
public function setAttributes(array $attributes)
|
||||
{
|
||||
// attributes are case insensitive
|
||||
$this->attributes = array_change_key_case($attributes);
|
||||
}
|
||||
|
||||
public function setAttribute($name, $value)
|
||||
{
|
||||
$this->attributes[strtolower($name)] = $value;
|
||||
}
|
||||
|
||||
public function getAttributes()
|
||||
{
|
||||
return $this->attributes;
|
||||
}
|
||||
|
||||
public function getAttribute($name)
|
||||
{
|
||||
$name = strtolower($name);
|
||||
|
||||
if (isset($this->attributes[$name])) {
|
||||
return $this->attributes[$name];
|
||||
}
|
||||
}
|
||||
|
||||
public function hasAttribute($name)
|
||||
{
|
||||
return array_key_exists($name, $this->attributes);
|
||||
}
|
||||
|
||||
public function clearAttributes()
|
||||
{
|
||||
$this->setAttributes(array());
|
||||
}
|
||||
|
||||
public function setCreatedAt($createdAt)
|
||||
{
|
||||
$this->createdAt = $createdAt;
|
||||
}
|
||||
|
||||
public function getCreatedAt()
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
}
|
||||
79
rainloop/v/1.2.7.415/app/libraries/Buzz/Util/CookieJar.php
Normal file
79
rainloop/v/1.2.7.415/app/libraries/Buzz/Util/CookieJar.php
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Util;
|
||||
|
||||
use Buzz\Message\MessageInterface;
|
||||
use Buzz\Message\RequestInterface;
|
||||
|
||||
class CookieJar
|
||||
{
|
||||
protected $cookies = array();
|
||||
|
||||
public function setCookies($cookies)
|
||||
{
|
||||
$this->cookies = array();
|
||||
foreach ($cookies as $cookie) {
|
||||
$this->addCookie($cookie);
|
||||
}
|
||||
}
|
||||
|
||||
public function getCookies()
|
||||
{
|
||||
return $this->cookies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a cookie to the current cookie jar.
|
||||
*
|
||||
* @param Cookie $cookie A cookie object
|
||||
*/
|
||||
public function addCookie(Cookie $cookie)
|
||||
{
|
||||
$this->cookies[] = $cookie;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds Cookie headers to the supplied request.
|
||||
*
|
||||
* @param RequestInterface $request A request object
|
||||
*/
|
||||
public function addCookieHeaders(RequestInterface $request)
|
||||
{
|
||||
foreach ($this->cookies as $cookie) {
|
||||
if ($cookie->matchesRequest($request)) {
|
||||
$request->addHeader($cookie->toCookieHeader());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes Set-Cookie headers from a request/response pair.
|
||||
*
|
||||
* @param RequestInterface $request A request object
|
||||
* @param MessageInterface $response A response object
|
||||
*/
|
||||
public function processSetCookieHeaders(RequestInterface $request, MessageInterface $response)
|
||||
{
|
||||
foreach ($response->getHeader('Set-Cookie', false) as $header) {
|
||||
$cookie = new Cookie();
|
||||
$cookie->fromSetCookieHeader($header, parse_url($request->getHost(), PHP_URL_HOST));
|
||||
|
||||
$this->addCookie($cookie);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes expired cookies.
|
||||
*/
|
||||
public function clearExpiredCookies()
|
||||
{
|
||||
foreach ($this->cookies as $i => $cookie) {
|
||||
if ($cookie->isExpired()) {
|
||||
unset($this->cookies[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
// reset array keys
|
||||
$this->cookies = array_values($this->cookies);
|
||||
}
|
||||
}
|
||||
190
rainloop/v/1.2.7.415/app/libraries/Buzz/Util/Url.php
Normal file
190
rainloop/v/1.2.7.415/app/libraries/Buzz/Util/Url.php
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
<?php
|
||||
|
||||
namespace Buzz\Util;
|
||||
|
||||
use Buzz\Message\RequestInterface;
|
||||
use Buzz\Exception\InvalidArgumentException;
|
||||
|
||||
class Url
|
||||
{
|
||||
private static $defaultPorts = array(
|
||||
'http' => 80,
|
||||
'https' => 443,
|
||||
);
|
||||
|
||||
private $url;
|
||||
private $components;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $url The URL
|
||||
*
|
||||
* @throws InvalidArgumentException If the URL is invalid
|
||||
*/
|
||||
public function __construct($url)
|
||||
{
|
||||
$components = parse_url($url);
|
||||
|
||||
if (false === $components) {
|
||||
throw new InvalidArgumentException(sprintf('The URL "%s" is invalid.', $url));
|
||||
}
|
||||
|
||||
// support scheme-less URLs
|
||||
if (!isset($components['host']) && isset($components['path'])) {
|
||||
$pos = strpos($components['path'], '/');
|
||||
if (false === $pos) {
|
||||
$components['host'] = $components['path'];
|
||||
unset($components['path']);
|
||||
} elseif (0 !== $pos) {
|
||||
list($host, $path) = explode('/', $components['path'], 2);
|
||||
$components['host'] = $host;
|
||||
$components['path'] = '/'.$path;
|
||||
}
|
||||
}
|
||||
|
||||
// default port
|
||||
if (isset($components['scheme']) && !isset($components['port']) && isset(self::$defaultPorts[$components['scheme']])) {
|
||||
$components['port'] = self::$defaultPorts[$components['scheme']];
|
||||
}
|
||||
|
||||
$this->url = $url;
|
||||
$this->components = $components;
|
||||
}
|
||||
|
||||
public function getScheme()
|
||||
{
|
||||
return $this->parseUrl('scheme');
|
||||
}
|
||||
|
||||
public function getHostname()
|
||||
{
|
||||
return $this->parseUrl('host');
|
||||
}
|
||||
|
||||
public function getPort()
|
||||
{
|
||||
return $this->parseUrl('port');
|
||||
}
|
||||
|
||||
public function getUser()
|
||||
{
|
||||
return $this->parseUrl('user');
|
||||
}
|
||||
|
||||
public function getPassword()
|
||||
{
|
||||
return $this->parseUrl('pass');
|
||||
}
|
||||
|
||||
public function getPath()
|
||||
{
|
||||
return $this->parseUrl('path');
|
||||
}
|
||||
|
||||
public function getQueryString()
|
||||
{
|
||||
return $this->parseUrl('query');
|
||||
}
|
||||
|
||||
public function getFragment()
|
||||
{
|
||||
return $this->parseUrl('fragment');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a host string that combines scheme, hostname and port.
|
||||
*
|
||||
* @return string A host value for an HTTP message
|
||||
*/
|
||||
public function getHost()
|
||||
{
|
||||
if ($hostname = $this->parseUrl('host')) {
|
||||
$host = $scheme = $this->parseUrl('scheme', 'http');
|
||||
$host .= '://';
|
||||
$host .= $hostname;
|
||||
|
||||
$port = $this->parseUrl('port');
|
||||
if ($port && (!isset(self::$defaultPorts[$scheme]) || self::$defaultPorts[$scheme] != $port)) {
|
||||
$host .= ':'.$port;
|
||||
}
|
||||
|
||||
return $host;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a resource string that combines path and query string.
|
||||
*
|
||||
* @return string A resource value for an HTTP message
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
$resource = $this->parseUrl('path', '/');
|
||||
|
||||
if ($query = $this->parseUrl('query')) {
|
||||
$resource .= '?'.$query;
|
||||
}
|
||||
|
||||
return $resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a formatted URL.
|
||||
*/
|
||||
public function format($pattern)
|
||||
{
|
||||
static $map = array(
|
||||
's' => 'getScheme',
|
||||
'u' => 'getUser',
|
||||
'a' => 'getPassword',
|
||||
'h' => 'getHostname',
|
||||
'o' => 'getPort',
|
||||
'p' => 'getPath',
|
||||
'q' => 'getQueryString',
|
||||
'f' => 'getFragment',
|
||||
'H' => 'getHost',
|
||||
'R' => 'getResource',
|
||||
);
|
||||
|
||||
$url = '';
|
||||
|
||||
$parts = str_split($pattern);
|
||||
while ($part = current($parts)) {
|
||||
if (isset($map[$part])) {
|
||||
$method = $map[$part];
|
||||
$url .= $this->$method();
|
||||
} elseif ('\\' == $part) {
|
||||
$url .= next($parts);
|
||||
} elseif (!ctype_alpha($part)) {
|
||||
$url .= $part;
|
||||
} else {
|
||||
throw new InvalidArgumentException(sprintf('The format character "%s" is invalid.', $part));
|
||||
}
|
||||
|
||||
next($parts);
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the current URL to the supplied request.
|
||||
*/
|
||||
public function applyToRequest(RequestInterface $request)
|
||||
{
|
||||
$request->setResource($this->getResource());
|
||||
$request->setHost($this->getHost());
|
||||
}
|
||||
|
||||
private function parseUrl($component = null, $default = null)
|
||||
{
|
||||
if (null === $component) {
|
||||
return $this->components;
|
||||
} elseif (isset($this->components[$component])) {
|
||||
return $this->components[$component];
|
||||
} else {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue