Commits

Jacob Moen  committed 36a3a60

php-github-api and buzz

  • Participants
  • Parent commits a101cd7
  • Branches boosted

Comments (0)

Files changed (182)

File common/vendors/buzz/LICENSE

+Copyright (c) 2010-2011 Kris Wallsmith
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

File common/vendors/buzz/README.md

+[![Build Status](https://secure.travis-ci.org/kriswallsmith/Buzz.png?branch=master)](http://travis-ci.org/kriswallsmith/Buzz)
+
+Buzz is a lightweight PHP 5.3 library for issuing HTTP requests.
+
+```php
+<?php
+
+$browser = new Buzz\Browser();
+$response = $browser->get('http://www.google.com');
+
+echo $browser->getLastRequest()."\n";
+echo $response;
+```
+
+You can also use the low-level HTTP classes directly.
+
+```php
+<?php
+
+$request = new Buzz\Message\Request('HEAD', '/', 'http://google.com');
+$response = new Buzz\Message\Response();
+
+$client = new Buzz\Client\FileGetContents();
+$client->send($request, $response);
+
+echo $request;
+echo $response;
+```

File common/vendors/buzz/lib/Buzz/Browser.php

+<?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 Response 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 Response 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,
+            ));
+        }
+    }
+}

File common/vendors/buzz/lib/Buzz/Client/AbstractClient.php

+<?php
+
+namespace Buzz\Client;
+
+abstract class AbstractClient
+{
+    protected $ignoreErrors = true;
+    protected $maxRedirects = 5;
+    protected $timeout = 5;
+    protected $verifyPeer = true;
+
+    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;
+    }
+}

File common/vendors/buzz/lib/Buzz/Client/AbstractCurl.php

+<?php
+
+namespace Buzz\Client;
+
+use Buzz\Message\Form\FormRequestInterface;
+use Buzz\Message\Form\FormUploadInterface;
+use Buzz\Message\MessageInterface;
+use Buzz\Message\RequestInterface;
+
+/**
+ * Base client class with helpers for working with cURL.
+ */
+abstract class AbstractCurl extends AbstractClient
+{
+    protected $options = array();
+
+    /**
+     * Creates a new cURL resource.
+     *
+     * @see curl_init()
+     *
+     * @return resource A new cURL resource
+     */
+    static protected function createCurlHandle()
+    {
+        if (false === $curl = curl_init()) {
+            throw new \RuntimeException('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
+     */
+    static protected 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.
+     */
+    static private 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
+     */
+    static private 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
+     */
+    static private 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
+        curl_setopt($curl, CURLOPT_TIMEOUT, $this->getTimeout());
+        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);
+    }
+}

File common/vendors/buzz/lib/Buzz/Client/AbstractStream.php

+<?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)
+    {
+        return 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(),
+            ),
+        );
+    }
+}

File common/vendors/buzz/lib/Buzz/Client/BatchClientInterface.php

+<?php
+
+namespace Buzz\Client;
+
+interface BatchClientInterface extends ClientInterface
+{
+    /**
+     * Processes the queued requests.
+     */
+    function flush();
+}

File common/vendors/buzz/lib/Buzz/Client/ClientInterface.php

+<?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
+     */
+    function send(RequestInterface $request, MessageInterface $response);
+}

File common/vendors/buzz/lib/Buzz/Client/Curl.php

+<?php
+
+namespace Buzz\Client;
+
+use Buzz\Message\MessageInterface;
+use Buzz\Message\RequestInterface;
+
+class Curl extends AbstractCurl implements ClientInterface
+{
+    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 \RuntimeException($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);
+        }
+    }
+}

File common/vendors/buzz/lib/Buzz/Client/FileGetContents.php

+<?php
+
+namespace Buzz\Client;
+
+use Buzz\Message\MessageInterface;
+use Buzz\Message\RequestInterface;
+use Buzz\Util\CookieJar;
+
+class FileGetContents extends AbstractStream implements ClientInterface
+{
+    protected $cookieJar;
+
+    public function __construct(CookieJar $cookieJar = null)
+    {
+        if ($cookieJar) {
+            $this->setCookieJar($cookieJar);
+        }
+    }
+
+    public function setCookieJar(CookieJar $cookieJar)
+    {
+        $this->cookieJar = $cookieJar;
+    }
+
+    public function getCookieJar()
+    {
+        return $this->cookieJar;
+    }
+
+    /**
+     * @see ClientInterface
+     *
+     * @throws RuntimeException 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 \RuntimeException($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;
+    }
+}

File common/vendors/buzz/lib/Buzz/Client/MultiCurl.php

+<?php
+
+namespace Buzz\Client;
+
+use Buzz\Message\MessageInterface;
+use Buzz\Message\RequestInterface;
+
+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 \RuntimeException('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);
+    }
+}

File common/vendors/buzz/lib/Buzz/Listener/BasicAuthListener.php

+<?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)
+    {
+    }
+}

File common/vendors/buzz/lib/Buzz/Listener/CallbackListener.php

+<?php
+
+namespace Buzz\Listener;
+
+use Buzz\Message\MessageInterface;
+use Buzz\Message\RequestInterface;
+
+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);
+    }
+}

File common/vendors/buzz/lib/Buzz/Listener/History/Entry.php

+<?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;
+    }
+}

File common/vendors/buzz/lib/Buzz/Listener/History/Journal.php

+<?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));
+    }
+}

File common/vendors/buzz/lib/Buzz/Listener/HistoryListener.php

+<?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);
+    }
+}

File common/vendors/buzz/lib/Buzz/Listener/ListenerChain.php

+<?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);
+        }
+    }
+}

File common/vendors/buzz/lib/Buzz/Listener/ListenerInterface.php

+<?php
+
+namespace Buzz\Listener;
+
+use Buzz\Message\MessageInterface;
+use Buzz\Message\RequestInterface;
+
+interface ListenerInterface
+{
+    function preSend(RequestInterface $request);
+    function postSend(RequestInterface $request, MessageInterface $response);
+}

File common/vendors/buzz/lib/Buzz/Listener/LoggerListener.php

+<?php
+
+namespace Buzz\Listener;
+
+use Buzz\Message\MessageInterface;
+use Buzz\Message\RequestInterface;
+
+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)));
+    }
+}

File common/vendors/buzz/lib/Buzz/Message/AbstractMessage.php

+<?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');
+        $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;
+    }
+}

File common/vendors/buzz/lib/Buzz/Message/Factory/Factory.php

+<?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();
+    }
+}

File common/vendors/buzz/lib/Buzz/Message/Factory/FactoryInterface.php

+<?php
+
+namespace Buzz\Message\Factory;
+
+use Buzz\Message\RequestInterface;
+
+interface FactoryInterface
+{
+    function createRequest($method = RequestInterface::METHOD_GET, $resource = '/', $host = null);
+    function createFormRequest($method = RequestInterface::METHOD_POST, $resource = '/', $host = null);
+    function createResponse();
+}

File common/vendors/buzz/lib/Buzz/Message/Form/FormRequest.php

+<?php
+
+namespace Buzz\Message\Form;
+
+use Buzz\Message\Request;
+
+/**
+ * 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;
+    }
+}

File common/vendors/buzz/lib/Buzz/Message/Form/FormRequestInterface.php

+<?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
+     */
+    function getFields();
+
+    /**
+     * Sets the form fields for the current request.
+     *
+     * @param array $fields An array of field names and values
+     */
+    function setFields(array $fields);
+}

File common/vendors/buzz/lib/Buzz/Message/Form/FormUpload.php

+<?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());
+    }
+}

File common/vendors/buzz/lib/Buzz/Message/Form/FormUploadInterface.php

+<?php
+
+namespace Buzz\Message\Form;
+
+use Buzz\Message\MessageInterface;
+
+interface FormUploadInterface extends MessageInterface
+{
+    function setName($name);
+    function getFile();
+    function getFilename();
+    function getContentType();
+}

File common/vendors/buzz/lib/Buzz/Message/MessageInterface.php

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