summaryrefslogtreecommitdiffstats
path: root/vendor/ringcentral
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 11:31:45 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 11:31:45 +0000
commit4e393913a4b1f06509da4341f0f58a41adac9117 (patch)
tree9c27e3eb77d109dff5fd031502311c5616adab04 /vendor/ringcentral
parentInitial commit. (diff)
downloadicinga-php-thirdparty-4e393913a4b1f06509da4341f0f58a41adac9117.tar.xz
icinga-php-thirdparty-4e393913a4b1f06509da4341f0f58a41adac9117.zip
Adding upstream version 0.12.1+ds.upstream/0.12.1+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/ringcentral')
-rw-r--r--vendor/ringcentral/psr7/.travis.yml21
-rw-r--r--vendor/ringcentral/psr7/CHANGELOG.md28
-rw-r--r--vendor/ringcentral/psr7/Dockerfile5
-rw-r--r--vendor/ringcentral/psr7/LICENSE19
-rw-r--r--vendor/ringcentral/psr7/Makefile21
-rw-r--r--vendor/ringcentral/psr7/README.md587
-rw-r--r--vendor/ringcentral/psr7/composer.json35
-rw-r--r--vendor/ringcentral/psr7/phpunit.xml.dist17
-rw-r--r--vendor/ringcentral/psr7/src/AppendStream.php233
-rw-r--r--vendor/ringcentral/psr7/src/BufferStream.php137
-rw-r--r--vendor/ringcentral/psr7/src/CachingStream.php135
-rw-r--r--vendor/ringcentral/psr7/src/DroppingStream.php41
-rw-r--r--vendor/ringcentral/psr7/src/FnStream.php163
-rw-r--r--vendor/ringcentral/psr7/src/InflateStream.php27
-rw-r--r--vendor/ringcentral/psr7/src/LazyOpenStream.php39
-rw-r--r--vendor/ringcentral/psr7/src/LimitStream.php154
-rw-r--r--vendor/ringcentral/psr7/src/MessageTrait.php167
-rw-r--r--vendor/ringcentral/psr7/src/MultipartStream.php152
-rw-r--r--vendor/ringcentral/psr7/src/NoSeekStream.php21
-rw-r--r--vendor/ringcentral/psr7/src/PumpStream.php165
-rw-r--r--vendor/ringcentral/psr7/src/Request.php146
-rw-r--r--vendor/ringcentral/psr7/src/Response.php129
-rw-r--r--vendor/ringcentral/psr7/src/ServerRequest.php122
-rw-r--r--vendor/ringcentral/psr7/src/Stream.php245
-rw-r--r--vendor/ringcentral/psr7/src/StreamDecoratorTrait.php139
-rw-r--r--vendor/ringcentral/psr7/src/StreamWrapper.php121
-rw-r--r--vendor/ringcentral/psr7/src/Uri.php601
-rw-r--r--vendor/ringcentral/psr7/src/functions.php835
-rw-r--r--vendor/ringcentral/psr7/src/functions_include.php6
-rw-r--r--vendor/ringcentral/psr7/tests/AppendStreamTest.php186
-rw-r--r--vendor/ringcentral/psr7/tests/BufferStreamTest.php63
-rw-r--r--vendor/ringcentral/psr7/tests/CachingStreamTest.php166
-rw-r--r--vendor/ringcentral/psr7/tests/DroppingStreamTest.php26
-rw-r--r--vendor/ringcentral/psr7/tests/FnStreamTest.php92
-rw-r--r--vendor/ringcentral/psr7/tests/FunctionsTest.php604
-rw-r--r--vendor/ringcentral/psr7/tests/InflateStreamTest.php21
-rw-r--r--vendor/ringcentral/psr7/tests/LazyOpenStreamTest.php64
-rw-r--r--vendor/ringcentral/psr7/tests/LimitStreamTest.php166
-rw-r--r--vendor/ringcentral/psr7/tests/MultipartStreamTest.php214
-rw-r--r--vendor/ringcentral/psr7/tests/NoSeekStreamTest.php40
-rw-r--r--vendor/ringcentral/psr7/tests/PumpStreamTest.php72
-rw-r--r--vendor/ringcentral/psr7/tests/RequestTest.php157
-rw-r--r--vendor/ringcentral/psr7/tests/ResponseTest.php154
-rw-r--r--vendor/ringcentral/psr7/tests/ServerRequestTest.php85
-rw-r--r--vendor/ringcentral/psr7/tests/StreamDecoratorTraitTest.php123
-rw-r--r--vendor/ringcentral/psr7/tests/StreamTest.php163
-rw-r--r--vendor/ringcentral/psr7/tests/StreamWrapperTest.php100
-rw-r--r--vendor/ringcentral/psr7/tests/UriTest.php258
-rw-r--r--vendor/ringcentral/psr7/tests/bootstrap.php13
49 files changed, 7278 insertions, 0 deletions
diff --git a/vendor/ringcentral/psr7/.travis.yml b/vendor/ringcentral/psr7/.travis.yml
new file mode 100644
index 0000000..08f3721
--- /dev/null
+++ b/vendor/ringcentral/psr7/.travis.yml
@@ -0,0 +1,21 @@
+language: php
+
+sudo: false
+
+install:
+ - travis_retry composer install --no-interaction --prefer-source
+
+script: make test
+
+matrix:
+ include:
+ - php: 5.3
+ dist: precise
+ - php: 5.4
+ - php: 5.5
+ - php: 5.6
+ - php: 7.0
+ - php: hhvm
+ allow_failures:
+ - php: hhvm
+ fast_finish: true
diff --git a/vendor/ringcentral/psr7/CHANGELOG.md b/vendor/ringcentral/psr7/CHANGELOG.md
new file mode 100644
index 0000000..642dc9a
--- /dev/null
+++ b/vendor/ringcentral/psr7/CHANGELOG.md
@@ -0,0 +1,28 @@
+# CHANGELOG
+
+## 1.2.0 - 2015-08-15
+
+* Body as `"0"` is now properly added to a response.
+* Now allowing forward seeking in CachingStream.
+* Now properly parsing HTTP requests that contain proxy targets in
+ `parse_request`.
+* functions.php is now conditionally required.
+* user-info is no longer dropped when resolving URIs.
+
+## 1.1.0 - 2015-06-24
+
+* URIs can now be relative.
+* `multipart/form-data` headers are now overridden case-insensitively.
+* URI paths no longer encode the following characters because they are allowed
+ in URIs: "(", ")", "*", "!", "'"
+* A port is no longer added to a URI when the scheme is missing and no port is
+ present.
+
+## 1.0.0 - 2015-05-19
+
+Initial release.
+
+Currently unsupported:
+
+- `Psr\Http\Message\ServerRequestInterface`
+- `Psr\Http\Message\UploadedFileInterface`
diff --git a/vendor/ringcentral/psr7/Dockerfile b/vendor/ringcentral/psr7/Dockerfile
new file mode 100644
index 0000000..846e8cf
--- /dev/null
+++ b/vendor/ringcentral/psr7/Dockerfile
@@ -0,0 +1,5 @@
+FROM greensheep/dockerfiles-php-5.3
+RUN apt-get update -y
+RUN apt-get install -y curl
+RUN curl -sS https://getcomposer.org/installer | php
+RUN mv composer.phar /usr/local/bin/composer \ No newline at end of file
diff --git a/vendor/ringcentral/psr7/LICENSE b/vendor/ringcentral/psr7/LICENSE
new file mode 100644
index 0000000..581d95f
--- /dev/null
+++ b/vendor/ringcentral/psr7/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2015 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
+
+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.
diff --git a/vendor/ringcentral/psr7/Makefile b/vendor/ringcentral/psr7/Makefile
new file mode 100644
index 0000000..73a5c5b
--- /dev/null
+++ b/vendor/ringcentral/psr7/Makefile
@@ -0,0 +1,21 @@
+all: clean test
+
+test:
+ vendor/bin/phpunit $(TEST)
+
+coverage:
+ vendor/bin/phpunit --coverage-html=artifacts/coverage $(TEST)
+
+view-coverage:
+ open artifacts/coverage/index.html
+
+clean:
+ rm -rf artifacts/*
+
+.PHONY: docker-login
+docker-login:
+ docker run -t -i -v $(shell pwd):/opt/psr7 ringcentral-psr7 /bin/bash
+
+.PHONY: docker-build
+docker-build:
+ docker build -t ringcentral-psr7 . \ No newline at end of file
diff --git a/vendor/ringcentral/psr7/README.md b/vendor/ringcentral/psr7/README.md
new file mode 100644
index 0000000..b4a6061
--- /dev/null
+++ b/vendor/ringcentral/psr7/README.md
@@ -0,0 +1,587 @@
+# PSR-7 Message Implementation
+
+This repository contains a partial [PSR-7](http://www.php-fig.org/psr/psr-7/)
+message implementation, several stream decorators, and some helpful
+functionality like query string parsing. Currently missing
+ServerRequestInterface and UploadedFileInterface; a pull request for these features is welcome.
+
+
+# Stream implementation
+
+This package comes with a number of stream implementations and stream
+decorators.
+
+
+## AppendStream
+
+`RingCentral\Psr7\AppendStream`
+
+Reads from multiple streams, one after the other.
+
+```php
+use RingCentral\Psr7;
+
+$a = Psr7\stream_for('abc, ');
+$b = Psr7\stream_for('123.');
+$composed = new Psr7\AppendStream([$a, $b]);
+
+$composed->addStream(Psr7\stream_for(' Above all listen to me').
+
+echo $composed(); // abc, 123. Above all listen to me.
+```
+
+
+## BufferStream
+
+`RingCentral\Psr7\BufferStream`
+
+Provides a buffer stream that can be written to to fill a buffer, and read
+from to remove bytes from the buffer.
+
+This stream returns a "hwm" metadata value that tells upstream consumers
+what the configured high water mark of the stream is, or the maximum
+preferred size of the buffer.
+
+```php
+use RingCentral\Psr7;
+
+// When more than 1024 bytes are in the buffer, it will begin returning
+// false to writes. This is an indication that writers should slow down.
+$buffer = new Psr7\BufferStream(1024);
+```
+
+
+## CachingStream
+
+The CachingStream is used to allow seeking over previously read bytes on
+non-seekable streams. This can be useful when transferring a non-seekable
+entity body fails due to needing to rewind the stream (for example, resulting
+from a redirect). Data that is read from the remote stream will be buffered in
+a PHP temp stream so that previously read bytes are cached first in memory,
+then on disk.
+
+```php
+use RingCentral\Psr7;
+
+$original = Psr7\stream_for(fopen('http://www.google.com', 'r'));
+$stream = new Psr7\CachingStream($original);
+
+$stream->read(1024);
+echo $stream->tell();
+// 1024
+
+$stream->seek(0);
+echo $stream->tell();
+// 0
+```
+
+
+## DroppingStream
+
+`RingCentral\Psr7\DroppingStream`
+
+Stream decorator that begins dropping data once the size of the underlying
+stream becomes too full.
+
+```php
+use RingCentral\Psr7;
+
+// Create an empty stream
+$stream = Psr7\stream_for();
+
+// Start dropping data when the stream has more than 10 bytes
+$dropping = new Psr7\DroppingStream($stream, 10);
+
+$stream->write('01234567890123456789');
+echo $stream; // 0123456789
+```
+
+
+## FnStream
+
+`RingCentral\Psr7\FnStream`
+
+Compose stream implementations based on a hash of functions.
+
+Allows for easy testing and extension of a provided stream without needing to
+to create a concrete class for a simple extension point.
+
+```php
+
+use RingCentral\Psr7;
+
+$stream = Psr7\stream_for('hi');
+$fnStream = Psr7\FnStream::decorate($stream, [
+ 'rewind' => function () use ($stream) {
+ echo 'About to rewind - ';
+ $stream->rewind();
+ echo 'rewound!';
+ }
+]);
+
+$fnStream->rewind();
+// Outputs: About to rewind - rewound!
+```
+
+
+## InflateStream
+
+`RingCentral\Psr7\InflateStream`
+
+Uses PHP's zlib.inflate filter to inflate deflate or gzipped content.
+
+This stream decorator skips the first 10 bytes of the given stream to remove
+the gzip header, converts the provided stream to a PHP stream resource,
+then appends the zlib.inflate filter. The stream is then converted back
+to a Guzzle stream resource to be used as a Guzzle stream.
+
+
+## LazyOpenStream
+
+`RingCentral\Psr7\LazyOpenStream`
+
+Lazily reads or writes to a file that is opened only after an IO operation
+take place on the stream.
+
+```php
+use RingCentral\Psr7;
+
+$stream = new Psr7\LazyOpenStream('/path/to/file', 'r');
+// The file has not yet been opened...
+
+echo $stream->read(10);
+// The file is opened and read from only when needed.
+```
+
+
+## LimitStream
+
+`RingCentral\Psr7\LimitStream`
+
+LimitStream can be used to read a subset or slice of an existing stream object.
+This can be useful for breaking a large file into smaller pieces to be sent in
+chunks (e.g. Amazon S3's multipart upload API).
+
+```php
+use RingCentral\Psr7;
+
+$original = Psr7\stream_for(fopen('/tmp/test.txt', 'r+'));
+echo $original->getSize();
+// >>> 1048576
+
+// Limit the size of the body to 1024 bytes and start reading from byte 2048
+$stream = new Psr7\LimitStream($original, 1024, 2048);
+echo $stream->getSize();
+// >>> 1024
+echo $stream->tell();
+// >>> 0
+```
+
+
+## MultipartStream
+
+`RingCentral\Psr7\MultipartStream`
+
+Stream that when read returns bytes for a streaming multipart or
+multipart/form-data stream.
+
+
+## NoSeekStream
+
+`RingCentral\Psr7\NoSeekStream`
+
+NoSeekStream wraps a stream and does not allow seeking.
+
+```php
+use RingCentral\Psr7;
+
+$original = Psr7\stream_for('foo');
+$noSeek = new Psr7\NoSeekStream($original);
+
+echo $noSeek->read(3);
+// foo
+var_export($noSeek->isSeekable());
+// false
+$noSeek->seek(0);
+var_export($noSeek->read(3));
+// NULL
+```
+
+
+## PumpStream
+
+`RingCentral\Psr7\PumpStream`
+
+Provides a read only stream that pumps data from a PHP callable.
+
+When invoking the provided callable, the PumpStream will pass the amount of
+data requested to read to the callable. The callable can choose to ignore
+this value and return fewer or more bytes than requested. Any extra data
+returned by the provided callable is buffered internally until drained using
+the read() function of the PumpStream. The provided callable MUST return
+false when there is no more data to read.
+
+
+## Implementing stream decorators
+
+Creating a stream decorator is very easy thanks to the
+`RingCentral\Psr7\StreamDecoratorTrait`. This trait provides methods that
+implement `Psr\Http\Message\StreamInterface` by proxying to an underlying
+stream. Just `use` the `StreamDecoratorTrait` and implement your custom
+methods.
+
+For example, let's say we wanted to call a specific function each time the last
+byte is read from a stream. This could be implemented by overriding the
+`read()` method.
+
+```php
+use Psr\Http\Message\StreamInterface;
+use RingCentral\Psr7\StreamDecoratorTrait;
+
+class EofCallbackStream implements StreamInterface
+{
+ use StreamDecoratorTrait;
+
+ private $callback;
+
+ public function __construct(StreamInterface $stream, callable $cb)
+ {
+ $this->stream = $stream;
+ $this->callback = $cb;
+ }
+
+ public function read($length)
+ {
+ $result = $this->stream->read($length);
+
+ // Invoke the callback when EOF is hit.
+ if ($this->eof()) {
+ call_user_func($this->callback);
+ }
+
+ return $result;
+ }
+}
+```
+
+This decorator could be added to any existing stream and used like so:
+
+```php
+use RingCentral\Psr7;
+
+$original = Psr7\stream_for('foo');
+
+$eofStream = new EofCallbackStream($original, function () {
+ echo 'EOF!';
+});
+
+$eofStream->read(2);
+$eofStream->read(1);
+// echoes "EOF!"
+$eofStream->seek(0);
+$eofStream->read(3);
+// echoes "EOF!"
+```
+
+
+## PHP StreamWrapper
+
+You can use the `RingCentral\Psr7\StreamWrapper` class if you need to use a
+PSR-7 stream as a PHP stream resource.
+
+Use the `RingCentral\Psr7\StreamWrapper::getResource()` method to create a PHP
+stream from a PSR-7 stream.
+
+```php
+use RingCentral\Psr7\StreamWrapper;
+
+$stream = RingCentral\Psr7\stream_for('hello!');
+$resource = StreamWrapper::getResource($stream);
+echo fread($resource, 6); // outputs hello!
+```
+
+
+# Function API
+
+There are various functions available under the `RingCentral\Psr7` namespace.
+
+
+## `function str`
+
+`function str(MessageInterface $message)`
+
+Returns the string representation of an HTTP message.
+
+```php
+$request = new RingCentral\Psr7\Request('GET', 'http://example.com');
+echo RingCentral\Psr7\str($request);
+```
+
+
+## `function uri_for`
+
+`function uri_for($uri)`
+
+This function accepts a string or `Psr\Http\Message\UriInterface` and returns a
+UriInterface for the given value. If the value is already a `UriInterface`, it
+is returned as-is.
+
+```php
+$uri = RingCentral\Psr7\uri_for('http://example.com');
+assert($uri === RingCentral\Psr7\uri_for($uri));
+```
+
+
+## `function stream_for`
+
+`function stream_for($resource = '', array $options = [])`
+
+Create a new stream based on the input type.
+
+Options is an associative array that can contain the following keys:
+
+* - metadata: Array of custom metadata.
+* - size: Size of the stream.
+
+This method accepts the following `$resource` types:
+
+- `Psr\Http\Message\StreamInterface`: Returns the value as-is.
+- `string`: Creates a stream object that uses the given string as the contents.
+- `resource`: Creates a stream object that wraps the given PHP stream resource.
+- `Iterator`: If the provided value implements `Iterator`, then a read-only
+ stream object will be created that wraps the given iterable. Each time the
+ stream is read from, data from the iterator will fill a buffer and will be
+ continuously called until the buffer is equal to the requested read size.
+ Subsequent read calls will first read from the buffer and then call `next`
+ on the underlying iterator until it is exhausted.
+- `object` with `__toString()`: If the object has the `__toString()` method,
+ the object will be cast to a string and then a stream will be returned that
+ uses the string value.
+- `NULL`: When `null` is passed, an empty stream object is returned.
+- `callable` When a callable is passed, a read-only stream object will be
+ created that invokes the given callable. The callable is invoked with the
+ number of suggested bytes to read. The callable can return any number of
+ bytes, but MUST return `false` when there is no more data to return. The
+ stream object that wraps the callable will invoke the callable until the
+ number of requested bytes are available. Any additional bytes will be
+ buffered and used in subsequent reads.
+
+```php
+$stream = RingCentral\Psr7\stream_for('foo');
+$stream = RingCentral\Psr7\stream_for(fopen('/path/to/file', 'r'));
+
+$generator function ($bytes) {
+ for ($i = 0; $i < $bytes; $i++) {
+ yield ' ';
+ }
+}
+
+$stream = RingCentral\Psr7\stream_for($generator(100));
+```
+
+
+## `function parse_header`
+
+`function parse_header($header)`
+
+Parse an array of header values containing ";" separated data into an array of
+associative arrays representing the header key value pair data of the header.
+When a parameter does not contain a value, but just contains a key, this
+function will inject a key with a '' string value.
+
+
+## `function normalize_header`
+
+`function normalize_header($header)`
+
+Converts an array of header values that may contain comma separated headers
+into an array of headers with no comma separated values.
+
+
+## `function modify_request`
+
+`function modify_request(RequestInterface $request, array $changes)`
+
+Clone and modify a request with the given changes. This method is useful for
+reducing the number of clones needed to mutate a message.
+
+The changes can be one of:
+
+- method: (string) Changes the HTTP method.
+- set_headers: (array) Sets the given headers.
+- remove_headers: (array) Remove the given headers.
+- body: (mixed) Sets the given body.
+- uri: (UriInterface) Set the URI.
+- query: (string) Set the query string value of the URI.
+- version: (string) Set the protocol version.
+
+
+## `function rewind_body`
+
+`function rewind_body(MessageInterface $message)`
+
+Attempts to rewind a message body and throws an exception on failure. The body
+of the message will only be rewound if a call to `tell()` returns a value other
+than `0`.
+
+
+## `function try_fopen`
+
+`function try_fopen($filename, $mode)`
+
+Safely opens a PHP stream resource using a filename.
+
+When fopen fails, PHP normally raises a warning. This function adds an error
+handler that checks for errors and throws an exception instead.
+
+
+## `function copy_to_string`
+
+`function copy_to_string(StreamInterface $stream, $maxLen = -1)`
+
+Copy the contents of a stream into a string until the given number of bytes
+have been read.
+
+
+## `function copy_to_stream`
+
+`function copy_to_stream(StreamInterface $source, StreamInterface $dest, $maxLen = -1)`
+
+Copy the contents of a stream into another stream until the given number of
+bytes have been read.
+
+
+## `function hash`
+
+`function hash(StreamInterface $stream, $algo, $rawOutput = false)`
+
+Calculate a hash of a Stream. This method reads the entire stream to calculate
+a rolling hash (based on PHP's hash_init functions).
+
+
+## `function readline`
+
+`function readline(StreamInterface $stream, $maxLength = null)`
+
+Read a line from the stream up to the maximum allowed buffer length.
+
+
+## `function parse_request`
+
+`function parse_request($message)`
+
+Parses a request message string into a request object.
+
+
+## `function parse_server_request`
+
+`function parse_server_request($message, array $serverParams = array())`
+
+Parses a request message string into a server-side request object.
+
+
+## `function parse_response`
+
+`function parse_response($message)`
+
+Parses a response message string into a response object.
+
+
+## `function parse_query`
+
+`function parse_query($str, $urlEncoding = true)`
+
+Parse a query string into an associative array.
+
+If multiple values are found for the same key, the value of that key value pair
+will become an array. This function does not parse nested PHP style arrays into
+an associative array (e.g., `foo[a]=1&foo[b]=2` will be parsed into
+`['foo[a]' => '1', 'foo[b]' => '2']`).
+
+
+## `function build_query`
+
+`function build_query(array $params, $encoding = PHP_QUERY_RFC3986)`
+
+Build a query string from an array of key value pairs.
+
+This function can use the return value of parseQuery() to build a query string.
+This function does not modify the provided keys when an array is encountered
+(like http_build_query would).
+
+
+## `function mimetype_from_filename`
+
+`function mimetype_from_filename($filename)`
+
+Determines the mimetype of a file by looking at its extension.
+
+
+## `function mimetype_from_extension`
+
+`function mimetype_from_extension($extension)`
+
+Maps a file extensions to a mimetype.
+
+
+# Static URI methods
+
+The `RingCentral\Psr7\Uri` class has several static methods to manipulate URIs.
+
+
+## `RingCentral\Psr7\Uri::removeDotSegments`
+
+`public static function removeDotSegments($path) -> UriInterface`
+
+Removes dot segments from a path and returns the new path.
+
+See http://tools.ietf.org/html/rfc3986#section-5.2.4
+
+
+## `RingCentral\Psr7\Uri::resolve`
+
+`public static function resolve(UriInterface $base, $rel) -> UriInterface`
+
+Resolve a base URI with a relative URI and return a new URI.
+
+See http://tools.ietf.org/html/rfc3986#section-5
+
+
+## `RingCentral\Psr7\Uri::withQueryValue`
+
+`public static function withQueryValue(UriInterface $uri, $key, $value) -> UriInterface`
+
+Create a new URI with a specific query string value.
+
+Any existing query string values that exactly match the provided key are
+removed and replaced with the given key value pair.
+
+Note: this function will convert "=" to "%3D" and "&" to "%26".
+
+
+## `RingCentral\Psr7\Uri::withoutQueryValue`
+
+`public static function withoutQueryValue(UriInterface $uri, $key, $value) -> UriInterface`
+
+Create a new URI with a specific query string value removed.
+
+Any existing query string values that exactly match the provided key are
+removed.
+
+Note: this function will convert "=" to "%3D" and "&" to "%26".
+
+
+## `RingCentral\Psr7\Uri::fromParts`
+
+`public static function fromParts(array $parts) -> UriInterface`
+
+Create a `RingCentral\Psr7\Uri` object from a hash of `parse_url` parts.
+
+
+# Not Implemented
+
+A few aspects of PSR-7 are not implemented in this project. A pull request for
+any of these features is welcome:
+
+- `Psr\Http\Message\ServerRequestInterface`
+- `Psr\Http\Message\UploadedFileInterface`
diff --git a/vendor/ringcentral/psr7/composer.json b/vendor/ringcentral/psr7/composer.json
new file mode 100644
index 0000000..4955053
--- /dev/null
+++ b/vendor/ringcentral/psr7/composer.json
@@ -0,0 +1,35 @@
+{
+ "name": "ringcentral/psr7",
+ "type": "library",
+ "description": "PSR-7 message implementation",
+ "keywords": ["message", "stream", "http", "uri"],
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ }
+ ],
+ "require": {
+ "php": ">=5.3",
+ "psr/http-message": "~1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.0"
+ },
+ "provide": {
+ "psr/http-message-implementation": "1.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "RingCentral\\Psr7\\": "src/"
+ },
+ "files": ["src/functions_include.php"]
+ },
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ }
+}
diff --git a/vendor/ringcentral/psr7/phpunit.xml.dist b/vendor/ringcentral/psr7/phpunit.xml.dist
new file mode 100644
index 0000000..500cd53
--- /dev/null
+++ b/vendor/ringcentral/psr7/phpunit.xml.dist
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit bootstrap="./tests/bootstrap.php"
+ colors="true">
+ <testsuites>
+ <testsuite>
+ <directory>tests</directory>
+ </testsuite>
+ </testsuites>
+ <filter>
+ <whitelist>
+ <directory suffix=".php">src</directory>
+ <exclude>
+ <directory suffix="Interface.php">src/</directory>
+ </exclude>
+ </whitelist>
+ </filter>
+</phpunit>
diff --git a/vendor/ringcentral/psr7/src/AppendStream.php b/vendor/ringcentral/psr7/src/AppendStream.php
new file mode 100644
index 0000000..8b8df6f
--- /dev/null
+++ b/vendor/ringcentral/psr7/src/AppendStream.php
@@ -0,0 +1,233 @@
+<?php
+namespace RingCentral\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Reads from multiple streams, one after the other.
+ *
+ * This is a read-only stream decorator.
+ */
+class AppendStream implements StreamInterface
+{
+ /** @var StreamInterface[] Streams being decorated */
+ private $streams = array();
+
+ private $seekable = true;
+ private $current = 0;
+ private $pos = 0;
+ private $detached = false;
+
+ /**
+ * @param StreamInterface[] $streams Streams to decorate. Each stream must
+ * be readable.
+ */
+ public function __construct(array $streams = array())
+ {
+ foreach ($streams as $stream) {
+ $this->addStream($stream);
+ }
+ }
+
+ public function __toString()
+ {
+ try {
+ $this->rewind();
+ return $this->getContents();
+ } catch (\Exception $e) {
+ return '';
+ }
+ }
+
+ /**
+ * Add a stream to the AppendStream
+ *
+ * @param StreamInterface $stream Stream to append. Must be readable.
+ *
+ * @throws \InvalidArgumentException if the stream is not readable
+ */
+ public function addStream(StreamInterface $stream)
+ {
+ if (!$stream->isReadable()) {
+ throw new \InvalidArgumentException('Each stream must be readable');
+ }
+
+ // The stream is only seekable if all streams are seekable
+ if (!$stream->isSeekable()) {
+ $this->seekable = false;
+ }
+
+ $this->streams[] = $stream;
+ }
+
+ public function getContents()
+ {
+ return copy_to_string($this);
+ }
+
+ /**
+ * Closes each attached stream.
+ *
+ * {@inheritdoc}
+ */
+ public function close()
+ {
+ $this->pos = $this->current = 0;
+
+ foreach ($this->streams as $stream) {
+ $stream->close();
+ }
+
+ $this->streams = array();
+ }
+
+ /**
+ * Detaches each attached stream
+ *
+ * {@inheritdoc}
+ */
+ public function detach()
+ {
+ $this->close();
+ $this->detached = true;
+ }
+
+ public function tell()
+ {
+ return $this->pos;
+ }
+
+ /**
+ * Tries to calculate the size by adding the size of each stream.
+ *
+ * If any of the streams do not return a valid number, then the size of the
+ * append stream cannot be determined and null is returned.
+ *
+ * {@inheritdoc}
+ */
+ public function getSize()
+ {
+ $size = 0;
+
+ foreach ($this->streams as $stream) {
+ $s = $stream->getSize();
+ if ($s === null) {
+ return null;
+ }
+ $size += $s;
+ }
+
+ return $size;
+ }
+
+ public function eof()
+ {
+ return !$this->streams ||
+ ($this->current >= count($this->streams) - 1 &&
+ $this->streams[$this->current]->eof());
+ }
+
+ public function rewind()
+ {
+ $this->seek(0);
+ }
+
+ /**
+ * Attempts to seek to the given position. Only supports SEEK_SET.
+ *
+ * {@inheritdoc}
+ */
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ if (!$this->seekable) {
+ throw new \RuntimeException('This AppendStream is not seekable');
+ } elseif ($whence !== SEEK_SET) {
+ throw new \RuntimeException('The AppendStream can only seek with SEEK_SET');
+ }
+
+ $this->pos = $this->current = 0;
+
+ // Rewind each stream
+ foreach ($this->streams as $i => $stream) {
+ try {
+ $stream->rewind();
+ } catch (\Exception $e) {
+ throw new \RuntimeException('Unable to seek stream '
+ . $i . ' of the AppendStream', 0, $e);
+ }
+ }
+
+ // Seek to the actual position by reading from each stream
+ while ($this->pos < $offset && !$this->eof()) {
+ $result = $this->read(min(8096, $offset - $this->pos));
+ if ($result === '') {
+ break;
+ }
+ }
+ }
+
+ /**
+ * Reads from all of the appended streams until the length is met or EOF.
+ *
+ * {@inheritdoc}
+ */
+ public function read($length)
+ {
+ $buffer = '';
+ $total = count($this->streams) - 1;
+ $remaining = $length;
+ $progressToNext = false;
+
+ while ($remaining > 0) {
+
+ // Progress to the next stream if needed.
+ if ($progressToNext || $this->streams[$this->current]->eof()) {
+ $progressToNext = false;
+ if ($this->current === $total) {
+ break;
+ }
+ $this->current++;
+ }
+
+ $result = $this->streams[$this->current]->read($remaining);
+
+ // Using a loose comparison here to match on '', false, and null
+ if ($result == null) {
+ $progressToNext = true;
+ continue;
+ }
+
+ $buffer .= $result;
+ $remaining = $length - strlen($buffer);
+ }
+
+ $this->pos += strlen($buffer);
+
+ return $buffer;
+ }
+
+ public function isReadable()
+ {
+ return true;
+ }
+
+ public function isWritable()
+ {
+ return false;
+ }
+
+ public function isSeekable()
+ {
+ return $this->seekable;
+ }
+
+ public function write($string)
+ {
+ throw new \RuntimeException('Cannot write to an AppendStream');
+ }
+
+ public function getMetadata($key = null)
+ {
+ return $key ? null : array();
+ }
+}
diff --git a/vendor/ringcentral/psr7/src/BufferStream.php b/vendor/ringcentral/psr7/src/BufferStream.php
new file mode 100644
index 0000000..a1e236d
--- /dev/null
+++ b/vendor/ringcentral/psr7/src/BufferStream.php
@@ -0,0 +1,137 @@
+<?php
+namespace RingCentral\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Provides a buffer stream that can be written to to fill a buffer, and read
+ * from to remove bytes from the buffer.
+ *
+ * This stream returns a "hwm" metadata value that tells upstream consumers
+ * what the configured high water mark of the stream is, or the maximum
+ * preferred size of the buffer.
+ */
+class BufferStream implements StreamInterface
+{
+ private $hwm;
+ private $buffer = '';
+
+ /**
+ * @param int $hwm High water mark, representing the preferred maximum
+ * buffer size. If the size of the buffer exceeds the high
+ * water mark, then calls to write will continue to succeed
+ * but will return false to inform writers to slow down
+ * until the buffer has been drained by reading from it.
+ */
+ public function __construct($hwm = 16384)
+ {
+ $this->hwm = $hwm;
+ }
+
+ public function __toString()
+ {
+ return $this->getContents();
+ }
+
+ public function getContents()
+ {
+ $buffer = $this->buffer;
+ $this->buffer = '';
+
+ return $buffer;
+ }
+
+ public function close()
+ {
+ $this->buffer = '';
+ }
+
+ public function detach()
+ {
+ $this->close();
+ }
+
+ public function getSize()
+ {
+ return strlen($this->buffer);
+ }
+
+ public function isReadable()
+ {
+ return true;
+ }
+
+ public function isWritable()
+ {
+ return true;
+ }
+
+ public function isSeekable()
+ {
+ return false;
+ }
+
+ public function rewind()
+ {
+ $this->seek(0);
+ }
+
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ throw new \RuntimeException('Cannot seek a BufferStream');
+ }
+
+ public function eof()
+ {
+ return strlen($this->buffer) === 0;
+ }
+
+ public function tell()
+ {
+ throw new \RuntimeException('Cannot determine the position of a BufferStream');
+ }
+
+ /**
+ * Reads data from the buffer.
+ */
+ public function read($length)
+ {
+ $currentLength = strlen($this->buffer);
+
+ if ($length >= $currentLength) {
+ // No need to slice the buffer because we don't have enough data.
+ $result = $this->buffer;
+ $this->buffer = '';
+ } else {
+ // Slice up the result to provide a subset of the buffer.
+ $result = substr($this->buffer, 0, $length);
+ $this->buffer = substr($this->buffer, $length);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Writes data to the buffer.
+ */
+ public function write($string)
+ {
+ $this->buffer .= $string;
+
+ // TODO: What should happen here?
+ if (strlen($this->buffer) >= $this->hwm) {
+ return false;
+ }
+
+ return strlen($string);
+ }
+
+ public function getMetadata($key = null)
+ {
+ if ($key == 'hwm') {
+ return $this->hwm;
+ }
+
+ return $key ? null : array();
+ }
+}
diff --git a/vendor/ringcentral/psr7/src/CachingStream.php b/vendor/ringcentral/psr7/src/CachingStream.php
new file mode 100644
index 0000000..ce3aca8
--- /dev/null
+++ b/vendor/ringcentral/psr7/src/CachingStream.php
@@ -0,0 +1,135 @@
+<?php
+namespace RingCentral\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Stream decorator that can cache previously read bytes from a sequentially
+ * read stream.
+ */
+class CachingStream extends StreamDecoratorTrait implements StreamInterface
+{
+
+ /** @var StreamInterface Stream being wrapped */
+ private $remoteStream;
+
+ /** @var int Number of bytes to skip reading due to a write on the buffer */
+ private $skipReadBytes = 0;
+
+ /**
+ * We will treat the buffer object as the body of the stream
+ *
+ * @param StreamInterface $stream Stream to cache
+ * @param StreamInterface $target Optionally specify where data is cached
+ */
+ public function __construct(
+ StreamInterface $stream,
+ StreamInterface $target = null
+ ) {
+ $this->remoteStream = $stream;
+ parent::__construct($target ?: new Stream(fopen('php://temp', 'r+')));
+ }
+
+ public function getSize()
+ {
+ return max($this->stream->getSize(), $this->remoteStream->getSize());
+ }
+
+ public function rewind()
+ {
+ $this->seek(0);
+ }
+
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ if ($whence == SEEK_SET) {
+ $byte = $offset;
+ } elseif ($whence == SEEK_CUR) {
+ $byte = $offset + $this->tell();
+ } elseif ($whence == SEEK_END) {
+ $size = $this->remoteStream->getSize();
+ if ($size === null) {
+ $size = $this->cacheEntireStream();
+ }
+ // Because 0 is the first byte, we seek to size - 1.
+ $byte = $size - 1 - $offset;
+ } else {
+ throw new \InvalidArgumentException('Invalid whence');
+ }
+
+ $diff = $byte - $this->stream->getSize();
+
+ if ($diff > 0) {
+ // If the seek byte is greater the number of read bytes, then read
+ // the difference of bytes to cache the bytes and inherently seek.
+ $this->read($diff);
+ } else {
+ // We can just do a normal seek since we've already seen this byte.
+ $this->stream->seek($byte);
+ }
+ }
+
+ public function read($length)
+ {
+ // Perform a regular read on any previously read data from the buffer
+ $data = $this->stream->read($length);
+ $remaining = $length - strlen($data);
+
+ // More data was requested so read from the remote stream
+ if ($remaining) {
+ // If data was written to the buffer in a position that would have
+ // been filled from the remote stream, then we must skip bytes on
+ // the remote stream to emulate overwriting bytes from that
+ // position. This mimics the behavior of other PHP stream wrappers.
+ $remoteData = $this->remoteStream->read(
+ $remaining + $this->skipReadBytes
+ );
+
+ if ($this->skipReadBytes) {
+ $len = strlen($remoteData);
+ $remoteData = substr($remoteData, $this->skipReadBytes);
+ $this->skipReadBytes = max(0, $this->skipReadBytes - $len);
+ }
+
+ $data .= $remoteData;
+ $this->stream->write($remoteData);
+ }
+
+ return $data;
+ }
+
+ public function write($string)
+ {
+ // When appending to the end of the currently read stream, you'll want
+ // to skip bytes from being read from the remote stream to emulate
+ // other stream wrappers. Basically replacing bytes of data of a fixed
+ // length.
+ $overflow = (strlen($string) + $this->tell()) - $this->remoteStream->tell();
+ if ($overflow > 0) {
+ $this->skipReadBytes += $overflow;
+ }
+
+ return $this->stream->write($string);
+ }
+
+ public function eof()
+ {
+ return $this->stream->eof() && $this->remoteStream->eof();
+ }
+
+ /**
+ * Close both the remote stream and buffer stream
+ */
+ public function close()
+ {
+ $this->remoteStream->close() && $this->stream->close();
+ }
+
+ private function cacheEntireStream()
+ {
+ $target = new FnStream(array('write' => 'strlen'));
+ copy_to_stream($this, $target);
+
+ return $this->tell();
+ }
+}
diff --git a/vendor/ringcentral/psr7/src/DroppingStream.php b/vendor/ringcentral/psr7/src/DroppingStream.php
new file mode 100644
index 0000000..3a34d38
--- /dev/null
+++ b/vendor/ringcentral/psr7/src/DroppingStream.php
@@ -0,0 +1,41 @@
+<?php
+namespace RingCentral\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Stream decorator that begins dropping data once the size of the underlying
+ * stream becomes too full.
+ */
+class DroppingStream extends StreamDecoratorTrait implements StreamInterface
+{
+
+ private $maxLength;
+
+ /**
+ * @param StreamInterface $stream Underlying stream to decorate.
+ * @param int $maxLength Maximum size before dropping data.
+ */
+ public function __construct(StreamInterface $stream, $maxLength)
+ {
+ parent::__construct($stream);
+ $this->maxLength = $maxLength;
+ }
+
+ public function write($string)
+ {
+ $diff = $this->maxLength - $this->stream->getSize();
+
+ // Begin returning 0 when the underlying stream is too large.
+ if ($diff <= 0) {
+ return 0;
+ }
+
+ // Write the stream or a subset of the stream if needed.
+ if (strlen($string) < $diff) {
+ return $this->stream->write($string);
+ }
+
+ return $this->stream->write(substr($string, 0, $diff));
+ }
+}
diff --git a/vendor/ringcentral/psr7/src/FnStream.php b/vendor/ringcentral/psr7/src/FnStream.php
new file mode 100644
index 0000000..f78dc8b
--- /dev/null
+++ b/vendor/ringcentral/psr7/src/FnStream.php
@@ -0,0 +1,163 @@
+<?php
+namespace RingCentral\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Compose stream implementations based on a hash of functions.
+ *
+ * Allows for easy testing and extension of a provided stream without needing
+ * to create a concrete class for a simple extension point.
+ * @property callable _fn___toString
+ * @property callable _fn_close
+ * @property callable _fn_detach
+ * @property callable _fn_getSize
+ * @property callable _fn_tell
+ * @property callable _fn_isSeekable
+ * @property callable _fn_rewind
+ * @property callable _fn_seek
+ * @property callable _fn_isWritable
+ * @property callable _fn_write
+ * @property callable _fn_isReadable
+ * @property callable _fn_read
+ * @property callable _fn_getContents
+ * @property callable _fn_getMetadata
+ */
+class FnStream implements StreamInterface
+{
+ /** @var array */
+ private $methods;
+
+ /** @var array Methods that must be implemented in the given array */
+ private static $slots = array('__toString', 'close', 'detach', 'rewind',
+ 'getSize', 'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write',
+ 'isReadable', 'read', 'getContents', 'getMetadata');
+
+ /**
+ * @param array $methods Hash of method name to a callable.
+ */
+ public function __construct(array $methods)
+ {
+ $this->methods = $methods;
+
+ // Create the functions on the class
+ foreach ($methods as $name => $fn) {
+ $this->{'_fn_' . $name} = $fn;
+ }
+ }
+
+ /**
+ * Lazily determine which methods are not implemented.
+ * @throws \BadMethodCallException
+ */
+ public function __get($name)
+ {
+ throw new \BadMethodCallException(str_replace('_fn_', '', $name)
+ . '() is not implemented in the FnStream');
+ }
+
+ /**
+ * The close method is called on the underlying stream only if possible.
+ */
+ public function __destruct()
+ {
+ if (isset($this->_fn_close)) {
+ call_user_func($this->_fn_close);
+ }
+ }
+
+ /**
+ * Adds custom functionality to an underlying stream by intercepting
+ * specific method calls.
+ *
+ * @param StreamInterface $stream Stream to decorate
+ * @param array $methods Hash of method name to a closure
+ *
+ * @return FnStream
+ */
+ public static function decorate(StreamInterface $stream, array $methods)
+ {
+ // If any of the required methods were not provided, then simply
+ // proxy to the decorated stream.
+ foreach (array_diff(self::$slots, array_keys($methods)) as $diff) {
+ $methods[$diff] = array($stream, $diff);
+ }
+
+ return new self($methods);
+ }
+
+ public function __toString()
+ {
+ return call_user_func($this->_fn___toString);
+ }
+
+ public function close()
+ {
+ return call_user_func($this->_fn_close);
+ }
+
+ public function detach()
+ {
+ return call_user_func($this->_fn_detach);
+ }
+
+ public function getSize()
+ {
+ return call_user_func($this->_fn_getSize);
+ }
+
+ public function tell()
+ {
+ return call_user_func($this->_fn_tell);
+ }
+
+ public function eof()
+ {
+ return call_user_func($this->_fn_eof);
+ }
+
+ public function isSeekable()
+ {
+ return call_user_func($this->_fn_isSeekable);
+ }
+
+ public function rewind()
+ {
+ call_user_func($this->_fn_rewind);
+ }
+
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ call_user_func($this->_fn_seek, $offset, $whence);
+ }
+
+ public function isWritable()
+ {
+ return call_user_func($this->_fn_isWritable);
+ }
+
+ public function write($string)
+ {
+ return call_user_func($this->_fn_write, $string);
+ }
+
+ public function isReadable()
+ {
+ return call_user_func($this->_fn_isReadable);
+ }
+
+ public function read($length)
+ {
+ return call_user_func($this->_fn_read, $length);
+ }
+
+ public function getContents()
+ {
+ return call_user_func($this->_fn_getContents);
+ }
+
+ public function getMetadata($key = null)
+ {
+ return call_user_func($this->_fn_getMetadata, $key);
+ }
+}
diff --git a/vendor/ringcentral/psr7/src/InflateStream.php b/vendor/ringcentral/psr7/src/InflateStream.php
new file mode 100644
index 0000000..c718002
--- /dev/null
+++ b/vendor/ringcentral/psr7/src/InflateStream.php
@@ -0,0 +1,27 @@
+<?php
+namespace RingCentral\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Uses PHP's zlib.inflate filter to inflate deflate or gzipped content.
+ *
+ * This stream decorator skips the first 10 bytes of the given stream to remove
+ * the gzip header, converts the provided stream to a PHP stream resource,
+ * then appends the zlib.inflate filter. The stream is then converted back
+ * to a Guzzle stream resource to be used as a Guzzle stream.
+ *
+ * @link http://tools.ietf.org/html/rfc1952
+ * @link http://php.net/manual/en/filters.compression.php
+ */
+class InflateStream extends StreamDecoratorTrait implements StreamInterface
+{
+ public function __construct(StreamInterface $stream)
+ {
+ // Skip the first 10 bytes
+ $stream = new LimitStream($stream, -1, 10);
+ $resource = StreamWrapper::getResource($stream);
+ stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ);
+ parent::__construct(new Stream($resource));
+ }
+}
diff --git a/vendor/ringcentral/psr7/src/LazyOpenStream.php b/vendor/ringcentral/psr7/src/LazyOpenStream.php
new file mode 100644
index 0000000..d8768f7
--- /dev/null
+++ b/vendor/ringcentral/psr7/src/LazyOpenStream.php
@@ -0,0 +1,39 @@
+<?php
+namespace RingCentral\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Lazily reads or writes to a file that is opened only after an IO operation
+ * take place on the stream.
+ */
+class LazyOpenStream extends StreamDecoratorTrait implements StreamInterface
+{
+
+ /** @var string File to open */
+ private $filename;
+
+ /** @var string $mode */
+ private $mode;
+
+ /**
+ * @param string $filename File to lazily open
+ * @param string $mode fopen mode to use when opening the stream
+ */
+ public function __construct($filename, $mode)
+ {
+ $this->filename = $filename;
+ $this->mode = $mode;
+ parent::__construct();
+ }
+
+ /**
+ * Creates the underlying stream lazily when required.
+ *
+ * @return StreamInterface
+ */
+ protected function createStream()
+ {
+ return stream_for(try_fopen($this->filename, $this->mode));
+ }
+}
diff --git a/vendor/ringcentral/psr7/src/LimitStream.php b/vendor/ringcentral/psr7/src/LimitStream.php
new file mode 100644
index 0000000..57eeca9
--- /dev/null
+++ b/vendor/ringcentral/psr7/src/LimitStream.php
@@ -0,0 +1,154 @@
+<?php
+namespace RingCentral\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+
+/**
+ * Decorator used to return only a subset of a stream
+ */
+class LimitStream extends StreamDecoratorTrait implements StreamInterface
+{
+
+ /** @var int Offset to start reading from */
+ private $offset;
+
+ /** @var int Limit the number of bytes that can be read */
+ private $limit;
+
+ /**
+ * @param StreamInterface $stream Stream to wrap
+ * @param int $limit Total number of bytes to allow to be read
+ * from the stream. Pass -1 for no limit.
+ * @param int|null $offset Position to seek to before reading (only
+ * works on seekable streams).
+ */
+ public function __construct(
+ StreamInterface $stream,
+ $limit = -1,
+ $offset = 0
+ ) {
+ parent::__construct($stream);
+ $this->setLimit($limit);
+ $this->setOffset($offset);
+ }
+
+ public function eof()
+ {
+ // Always return true if the underlying stream is EOF
+ if ($this->stream->eof()) {
+ return true;
+ }
+
+ // No limit and the underlying stream is not at EOF
+ if ($this->limit == -1) {
+ return false;
+ }
+
+ return $this->stream->tell() >= $this->offset + $this->limit;
+ }
+
+ /**
+ * Returns the size of the limited subset of data
+ * {@inheritdoc}
+ */
+ public function getSize()
+ {
+ if (null === ($length = $this->stream->getSize())) {
+ return null;
+ } elseif ($this->limit == -1) {
+ return $length - $this->offset;
+ } else {
+ return min($this->limit, $length - $this->offset);
+ }
+ }
+
+ /**
+ * Allow for a bounded seek on the read limited stream
+ * {@inheritdoc}
+ */
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ if ($whence !== SEEK_SET || $offset < 0) {
+ throw new \RuntimeException(sprintf(
+ 'Cannot seek to offset % with whence %s',
+ $offset,
+ $whence
+ ));
+ }
+
+ $offset += $this->offset;
+
+ if ($this->limit !== -1) {
+ if ($offset > $this->offset + $this->limit) {
+ $offset = $this->offset + $this->limit;
+ }
+ }
+
+ $this->stream->seek($offset);
+ }
+
+ /**
+ * Give a relative tell()
+ * {@inheritdoc}
+ */
+ public function tell()
+ {
+ return $this->stream->tell() - $this->offset;
+ }
+
+ /**
+ * Set the offset to start limiting from
+ *
+ * @param int $offset Offset to seek to and begin byte limiting from
+ *
+ * @throws \RuntimeException if the stream cannot be seeked.
+ */
+ public function setOffset($offset)
+ {
+ $current = $this->stream->tell();
+
+ if ($current !== $offset) {
+ // If the stream cannot seek to the offset position, then read to it
+ if ($this->stream->isSeekable()) {
+ $this->stream->seek($offset);
+ } elseif ($current > $offset) {
+ throw new \RuntimeException("Could not seek to stream offset $offset");
+ } else {
+ $this->stream->read($offset - $current);
+ }
+ }
+
+ $this->offset = $offset;
+ }
+
+ /**
+ * Set the limit of bytes that the decorator allows to be read from the
+ * stream.
+ *
+ * @param int $limit Number of bytes to allow to be read from the stream.
+ * Use -1 for no limit.
+ */
+ public function setLimit($limit)
+ {
+ $this->limit = $limit;
+ }
+
+ public function read($length)
+ {
+ if ($this->limit == -1) {
+ return $this->stream->read($length);
+ }
+
+ // Check if the current position is less than the total allowed
+ // bytes + original offset
+ $remaining = ($this->offset + $this->limit) - $this->stream->tell();
+ if ($remaining > 0) {
+ // Only return the amount of requested data, ensuring that the byte
+ // limit is not exceeded
+ return $this->stream->read(min($remaining, $length));
+ }
+
+ return '';
+ }
+}
diff --git a/vendor/ringcentral/psr7/src/MessageTrait.php b/vendor/ringcentral/psr7/src/MessageTrait.php
new file mode 100644
index 0000000..9330bcb
--- /dev/null
+++ b/vendor/ringcentral/psr7/src/MessageTrait.php
@@ -0,0 +1,167 @@
+<?php
+namespace RingCentral\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Trait implementing functionality common to requests and responses.
+ */
+abstract class MessageTrait
+{
+ /** @var array Cached HTTP header collection with lowercase key to values */
+ protected $headers = array();
+
+ /** @var array Actual key to list of values per header. */
+ protected $headerLines = array();
+
+ /** @var string */
+ protected $protocol = '1.1';
+
+ /** @var StreamInterface */
+ protected $stream;
+
+ public function getProtocolVersion()
+ {
+ return $this->protocol;
+ }
+
+ public function withProtocolVersion($version)
+ {
+ if ($this->protocol === $version) {
+ return $this;
+ }
+
+ $new = clone $this;
+ $new->protocol = $version;
+ return $new;
+ }
+
+ public function getHeaders()
+ {
+ return $this->headerLines;
+ }
+
+ public function hasHeader($header)
+ {
+ return isset($this->headers[strtolower($header)]);
+ }
+
+ public function getHeader($header)
+ {
+ $name = strtolower($header);
+ return isset($this->headers[$name]) ? $this->headers[$name] : array();
+ }
+
+ public function getHeaderLine($header)
+ {
+ return implode(', ', $this->getHeader($header));
+ }
+
+ public function withHeader($header, $value)
+ {
+ $new = clone $this;
+ $header = trim($header);
+ $name = strtolower($header);
+
+ if (!is_array($value)) {
+ $new->headers[$name] = array(trim($value));
+ } else {
+ $new->headers[$name] = $value;
+ foreach ($new->headers[$name] as &$v) {
+ $v = trim($v);
+ }
+ }
+
+ // Remove the header lines.
+ foreach (array_keys($new->headerLines) as $key) {
+ if (strtolower($key) === $name) {
+ unset($new->headerLines[$key]);
+ }
+ }
+
+ // Add the header line.
+ $new->headerLines[$header] = $new->headers[$name];
+
+ return $new;
+ }
+
+ public function withAddedHeader($header, $value)
+ {
+ if (!$this->hasHeader($header)) {
+ return $this->withHeader($header, $value);
+ }
+
+ $header = trim($header);
+ $name = strtolower($header);
+
+ $value = (array) $value;
+ foreach ($value as &$v) {
+ $v = trim($v);
+ }
+
+ $new = clone $this;
+ $new->headers[$name] = array_merge($new->headers[$name], $value);
+ $new->headerLines[$header] = array_merge($new->headerLines[$header], $value);
+
+ return $new;
+ }
+
+ public function withoutHeader($header)
+ {
+ if (!$this->hasHeader($header)) {
+ return $this;
+ }
+
+ $new = clone $this;
+ $name = strtolower($header);
+ unset($new->headers[$name]);
+
+ foreach (array_keys($new->headerLines) as $key) {
+ if (strtolower($key) === $name) {
+ unset($new->headerLines[$key]);
+ }
+ }
+
+ return $new;
+ }
+
+ public function getBody()
+ {
+ if (!$this->stream) {
+ $this->stream = stream_for('');
+ }
+
+ return $this->stream;
+ }
+
+ public function withBody(StreamInterface $body)
+ {
+ if ($body === $this->stream) {
+ return $this;
+ }
+
+ $new = clone $this;
+ $new->stream = $body;
+ return $new;
+ }
+
+ protected function setHeaders(array $headers)
+ {
+ $this->headerLines = $this->headers = array();
+ foreach ($headers as $header => $value) {
+ $header = trim($header);
+ $name = strtolower($header);
+ if (!is_array($value)) {
+ $value = trim($value);
+ $this->headers[$name][] = $value;
+ $this->headerLines[$header][] = $value;
+ } else {
+ foreach ($value as $v) {
+ $v = trim($v);
+ $this->headers[$name][] = $v;
+ $this->headerLines[$header][] = $v;
+ }
+ }
+ }
+ }
+}
diff --git a/vendor/ringcentral/psr7/src/MultipartStream.php b/vendor/ringcentral/psr7/src/MultipartStream.php
new file mode 100644
index 0000000..8c5e5bc
--- /dev/null
+++ b/vendor/ringcentral/psr7/src/MultipartStream.php
@@ -0,0 +1,152 @@
+<?php
+namespace RingCentral\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Stream that when read returns bytes for a streaming multipart or
+ * multipart/form-data stream.
+ */
+class MultipartStream extends StreamDecoratorTrait implements StreamInterface
+{
+
+ private $boundary;
+
+ /**
+ * @param array $elements Array of associative arrays, each containing a
+ * required "name" key mapping to the form field,
+ * name, a required "contents" key mapping to a
+ * StreamInterface/resource/string, an optional
+ * "headers" associative array of custom headers,
+ * and an optional "filename" key mapping to a
+ * string to send as the filename in the part.
+ * @param string $boundary You can optionally provide a specific boundary
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function __construct(array $elements = array(), $boundary = null)
+ {
+ $this->boundary = $boundary ?: uniqid();
+ parent::__construct($this->createStream($elements));
+ }
+
+ /**
+ * Get the boundary
+ *
+ * @return string
+ */
+ public function getBoundary()
+ {
+ return $this->boundary;
+ }
+
+ public function isWritable()
+ {
+ return false;
+ }
+
+ /**
+ * Get the headers needed before transferring the content of a POST file
+ */
+ private function getHeaders(array $headers)
+ {
+ $str = '';
+ foreach ($headers as $key => $value) {
+ $str .= "{$key}: {$value}\r\n";
+ }
+
+ return "--{$this->boundary}\r\n" . trim($str) . "\r\n\r\n";
+ }
+
+ /**
+ * Create the aggregate stream that will be used to upload the POST data
+ */
+ protected function createStream(array $elements)
+ {
+ $stream = new AppendStream();
+
+ foreach ($elements as $element) {
+ $this->addElement($stream, $element);
+ }
+
+ // Add the trailing boundary with CRLF
+ $stream->addStream(stream_for("--{$this->boundary}--\r\n"));
+
+ return $stream;
+ }
+
+ private function addElement(AppendStream $stream, array $element)
+ {
+ foreach (array('contents', 'name') as $key) {
+ if (!array_key_exists($key, $element)) {
+ throw new \InvalidArgumentException("A '{$key}' key is required");
+ }
+ }
+
+ $element['contents'] = stream_for($element['contents']);
+
+ if (empty($element['filename'])) {
+ $uri = $element['contents']->getMetadata('uri');
+ if (substr($uri, 0, 6) !== 'php://') {
+ $element['filename'] = $uri;
+ }
+ }
+
+ list($body, $headers) = $this->createElement(
+ $element['name'],
+ $element['contents'],
+ isset($element['filename']) ? $element['filename'] : null,
+ isset($element['headers']) ? $element['headers'] : array()
+ );
+
+ $stream->addStream(stream_for($this->getHeaders($headers)));
+ $stream->addStream($body);
+ $stream->addStream(stream_for("\r\n"));
+ }
+
+ /**
+ * @return array
+ */
+ private function createElement($name, $stream, $filename, array $headers)
+ {
+ // Set a default content-disposition header if one was no provided
+ $disposition = $this->getHeader($headers, 'content-disposition');
+ if (!$disposition) {
+ $headers['Content-Disposition'] = $filename
+ ? sprintf('form-data; name="%s"; filename="%s"',
+ $name,
+ basename($filename))
+ : "form-data; name=\"{$name}\"";
+ }
+
+ // Set a default content-length header if one was no provided
+ $length = $this->getHeader($headers, 'content-length');
+ if (!$length) {
+ if ($length = $stream->getSize()) {
+ $headers['Content-Length'] = (string) $length;
+ }
+ }
+
+ // Set a default Content-Type if one was not supplied
+ $type = $this->getHeader($headers, 'content-type');
+ if (!$type && $filename) {
+ if ($type = mimetype_from_filename($filename)) {
+ $headers['Content-Type'] = $type;
+ }
+ }
+
+ return array($stream, $headers);
+ }
+
+ private function getHeader(array $headers, $key)
+ {
+ $lowercaseHeader = strtolower($key);
+ foreach ($headers as $k => $v) {
+ if (strtolower($k) === $lowercaseHeader) {
+ return $v;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/vendor/ringcentral/psr7/src/NoSeekStream.php b/vendor/ringcentral/psr7/src/NoSeekStream.php
new file mode 100644
index 0000000..328fdda
--- /dev/null
+++ b/vendor/ringcentral/psr7/src/NoSeekStream.php
@@ -0,0 +1,21 @@
+<?php
+namespace RingCentral\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Stream decorator that prevents a stream from being seeked
+ */
+class NoSeekStream extends StreamDecoratorTrait implements StreamInterface
+{
+
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ throw new \RuntimeException('Cannot seek a NoSeekStream');
+ }
+
+ public function isSeekable()
+ {
+ return false;
+ }
+}
diff --git a/vendor/ringcentral/psr7/src/PumpStream.php b/vendor/ringcentral/psr7/src/PumpStream.php
new file mode 100644
index 0000000..0cb8510
--- /dev/null
+++ b/vendor/ringcentral/psr7/src/PumpStream.php
@@ -0,0 +1,165 @@
+<?php
+namespace RingCentral\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Provides a read only stream that pumps data from a PHP callable.
+ *
+ * When invoking the provided callable, the PumpStream will pass the amount of
+ * data requested to read to the callable. The callable can choose to ignore
+ * this value and return fewer or more bytes than requested. Any extra data
+ * returned by the provided callable is buffered internally until drained using
+ * the read() function of the PumpStream. The provided callable MUST return
+ * false when there is no more data to read.
+ */
+class PumpStream implements StreamInterface
+{
+ /** @var callable */
+ private $source;
+
+ /** @var int */
+ private $size;
+
+ /** @var int */
+ private $tellPos = 0;
+
+ /** @var array */
+ private $metadata;
+
+ /** @var BufferStream */
+ private $buffer;
+
+ /**
+ * @param callable $source Source of the stream data. The callable MAY
+ * accept an integer argument used to control the
+ * amount of data to return. The callable MUST
+ * return a string when called, or false on error
+ * or EOF.
+ * @param array $options Stream options:
+ * - metadata: Hash of metadata to use with stream.
+ * - size: Size of the stream, if known.
+ */
+ public function __construct($source, array $options = array())
+ {
+ $this->source = $source;
+ $this->size = isset($options['size']) ? $options['size'] : null;
+ $this->metadata = isset($options['metadata']) ? $options['metadata'] : array();
+ $this->buffer = new BufferStream();
+ }
+
+ public function __toString()
+ {
+ try {
+ return copy_to_string($this);
+ } catch (\Exception $e) {
+ return '';
+ }
+ }
+
+ public function close()
+ {
+ $this->detach();
+ }
+
+ public function detach()
+ {
+ $this->tellPos = false;
+ $this->source = null;
+ }
+
+ public function getSize()
+ {
+ return $this->size;
+ }
+
+ public function tell()
+ {
+ return $this->tellPos;
+ }
+
+ public function eof()
+ {
+ return !$this->source;
+ }
+
+ public function isSeekable()
+ {
+ return false;
+ }
+
+ public function rewind()
+ {
+ $this->seek(0);
+ }
+
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ throw new \RuntimeException('Cannot seek a PumpStream');
+ }
+
+ public function isWritable()
+ {
+ return false;
+ }
+
+ public function write($string)
+ {
+ throw new \RuntimeException('Cannot write to a PumpStream');
+ }
+
+ public function isReadable()
+ {
+ return true;
+ }
+
+ public function read($length)
+ {
+ $data = $this->buffer->read($length);
+ $readLen = strlen($data);
+ $this->tellPos += $readLen;
+ $remaining = $length - $readLen;
+
+ if ($remaining) {
+ $this->pump($remaining);
+ $data .= $this->buffer->read($remaining);
+ $this->tellPos += strlen($data) - $readLen;
+ }
+
+ return $data;
+ }
+
+ public function getContents()
+ {
+ $result = '';
+ while (!$this->eof()) {
+ $result .= $this->read(1000000);
+ }
+
+ return $result;
+ }
+
+ public function getMetadata($key = null)
+ {
+ if (!$key) {
+ return $this->metadata;
+ }
+
+ return isset($this->metadata[$key]) ? $this->metadata[$key] : null;
+ }
+
+ private function pump($length)
+ {
+ if ($this->source) {
+ do {
+ $data = call_user_func($this->source, $length);
+ if ($data === false || $data === null) {
+ $this->source = null;
+ return;
+ }
+ $this->buffer->write($data);
+ $length -= strlen($data);
+ } while ($length > 0);
+ }
+ }
+}
diff --git a/vendor/ringcentral/psr7/src/Request.php b/vendor/ringcentral/psr7/src/Request.php
new file mode 100644
index 0000000..bb0f2fc
--- /dev/null
+++ b/vendor/ringcentral/psr7/src/Request.php
@@ -0,0 +1,146 @@
+<?php
+namespace RingCentral\Psr7;
+
+use InvalidArgumentException;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\StreamInterface;
+use Psr\Http\Message\UriInterface;
+
+/**
+ * PSR-7 request implementation.
+ */
+class Request extends MessageTrait implements RequestInterface
+{
+
+ /** @var string */
+ private $method;
+
+ /** @var null|string */
+ private $requestTarget;
+
+ /** @var null|UriInterface */
+ private $uri;
+
+ /**
+ * @param null|string $method HTTP method for the request.
+ * @param null|string|UriInterface $uri URI for the request.
+ * @param array $headers Headers for the message.
+ * @param string|resource|StreamInterface $body Message body.
+ * @param string $protocolVersion HTTP protocol version.
+ *
+ * @throws InvalidArgumentException for an invalid URI
+ */
+ public function __construct(
+ $method,
+ $uri,
+ array $headers = array(),
+ $body = null,
+ $protocolVersion = '1.1'
+ ) {
+ if (is_string($uri)) {
+ $uri = new Uri($uri);
+ } elseif (!($uri instanceof UriInterface)) {
+ throw new \InvalidArgumentException(
+ 'URI must be a string or Psr\Http\Message\UriInterface'
+ );
+ }
+
+ $this->method = strtoupper($method);
+ $this->uri = $uri;
+ $this->setHeaders($headers);
+ $this->protocol = $protocolVersion;
+
+ $host = $uri->getHost();
+ if ($host && !$this->hasHeader('Host')) {
+ $this->updateHostFromUri($host);
+ }
+
+ if ($body) {
+ $this->stream = stream_for($body);
+ }
+ }
+
+ public function getRequestTarget()
+ {
+ if ($this->requestTarget !== null) {
+ return $this->requestTarget;
+ }
+
+ $target = $this->uri->getPath();
+ if ($target == null) {
+ $target = '/';
+ }
+ if ($this->uri->getQuery()) {
+ $target .= '?' . $this->uri->getQuery();
+ }
+
+ return $target;
+ }
+
+ public function withRequestTarget($requestTarget)
+ {
+ if (preg_match('#\s#', $requestTarget)) {
+ throw new InvalidArgumentException(
+ 'Invalid request target provided; cannot contain whitespace'
+ );
+ }
+
+ $new = clone $this;
+ $new->requestTarget = $requestTarget;
+ return $new;
+ }
+
+ public function getMethod()
+ {
+ return $this->method;
+ }
+
+ public function withMethod($method)
+ {
+ $new = clone $this;
+ $new->method = strtoupper($method);
+ return $new;
+ }
+
+ public function getUri()
+ {
+ return $this->uri;
+ }
+
+ public function withUri(UriInterface $uri, $preserveHost = false)
+ {
+ if ($uri === $this->uri) {
+ return $this;
+ }
+
+ $new = clone $this;
+ $new->uri = $uri;
+
+ if (!$preserveHost) {
+ if ($host = $uri->getHost()) {
+ $new->updateHostFromUri($host);
+ }
+ }
+
+ return $new;
+ }
+
+ public function withHeader($header, $value)
+ {
+ /** @var Request $newInstance */
+ $newInstance = parent::withHeader($header, $value);
+ return $newInstance;
+ }
+
+ private function updateHostFromUri($host)
+ {
+ // Ensure Host is the first header.
+ // See: http://tools.ietf.org/html/rfc7230#section-5.4
+ if ($port = $this->uri->getPort()) {
+ $host .= ':' . $port;
+ }
+
+ $this->headerLines = array('Host' => array($host)) + $this->headerLines;
+ $this->headers = array('host' => array($host)) + $this->headers;
+ }
+}
diff --git a/vendor/ringcentral/psr7/src/Response.php b/vendor/ringcentral/psr7/src/Response.php
new file mode 100644
index 0000000..a6d9451
--- /dev/null
+++ b/vendor/ringcentral/psr7/src/Response.php
@@ -0,0 +1,129 @@
+<?php
+namespace RingCentral\Psr7;
+
+use Psr\Http\Message\ResponseInterface;
+
+/**
+ * PSR-7 response implementation.
+ */
+class Response extends MessageTrait implements ResponseInterface
+{
+
+ /** @var array Map of standard HTTP status code/reason phrases */
+ private static $phrases = array(
+ 100 => 'Continue',
+ 101 => 'Switching Protocols',
+ 102 => 'Processing',
+ 200 => 'OK',
+ 201 => 'Created',
+ 202 => 'Accepted',
+ 203 => 'Non-Authoritative Information',
+ 204 => 'No Content',
+ 205 => 'Reset Content',
+ 206 => 'Partial Content',
+ 207 => 'Multi-status',
+ 208 => 'Already Reported',
+ 300 => 'Multiple Choices',
+ 301 => 'Moved Permanently',
+ 302 => 'Found',
+ 303 => 'See Other',
+ 304 => 'Not Modified',
+ 305 => 'Use Proxy',
+ 306 => 'Switch Proxy',
+ 307 => 'Temporary Redirect',
+ 400 => 'Bad Request',
+ 401 => 'Unauthorized',
+ 402 => 'Payment Required',
+ 403 => 'Forbidden',
+ 404 => 'Not Found',
+ 405 => 'Method Not Allowed',
+ 406 => 'Not Acceptable',
+ 407 => 'Proxy Authentication Required',
+ 408 => 'Request Time-out',
+ 409 => 'Conflict',
+ 410 => 'Gone',
+ 411 => 'Length Required',
+ 412 => 'Precondition Failed',
+ 413 => 'Request Entity Too Large',
+ 414 => 'Request-URI Too Large',
+ 415 => 'Unsupported Media Type',
+ 416 => 'Requested range not satisfiable',
+ 417 => 'Expectation Failed',
+ 418 => 'I\'m a teapot',
+ 422 => 'Unprocessable Entity',
+ 423 => 'Locked',
+ 424 => 'Failed Dependency',
+ 425 => 'Unordered Collection',
+ 426 => 'Upgrade Required',
+ 428 => 'Precondition Required',
+ 429 => 'Too Many Requests',
+ 431 => 'Request Header Fields Too Large',
+ 500 => 'Internal Server Error',
+ 501 => 'Not Implemented',
+ 502 => 'Bad Gateway',
+ 503 => 'Service Unavailable',
+ 504 => 'Gateway Time-out',
+ 505 => 'HTTP Version not supported',
+ 506 => 'Variant Also Negotiates',
+ 507 => 'Insufficient Storage',
+ 508 => 'Loop Detected',
+ 511 => 'Network Authentication Required',
+ );
+
+ /** @var null|string */
+ private $reasonPhrase = '';
+
+ /** @var int */
+ private $statusCode = 200;
+
+ /**
+ * @param int $status Status code for the response, if any.
+ * @param array $headers Headers for the response, if any.
+ * @param mixed $body Stream body.
+ * @param string $version Protocol version.
+ * @param string $reason Reason phrase (a default will be used if possible).
+ */
+ public function __construct(
+ $status = 200,
+ array $headers = array(),
+ $body = null,
+ $version = '1.1',
+ $reason = null
+ ) {
+ $this->statusCode = (int) $status;
+
+ if ($body !== null) {
+ $this->stream = stream_for($body);
+ }
+
+ $this->setHeaders($headers);
+ if (!$reason && isset(self::$phrases[$this->statusCode])) {
+ $this->reasonPhrase = self::$phrases[$status];
+ } else {
+ $this->reasonPhrase = (string) $reason;
+ }
+
+ $this->protocol = $version;
+ }
+
+ public function getStatusCode()
+ {
+ return $this->statusCode;
+ }
+
+ public function getReasonPhrase()
+ {
+ return $this->reasonPhrase;
+ }
+
+ public function withStatus($code, $reasonPhrase = '')
+ {
+ $new = clone $this;
+ $new->statusCode = (int) $code;
+ if (!$reasonPhrase && isset(self::$phrases[$new->statusCode])) {
+ $reasonPhrase = self::$phrases[$new->statusCode];
+ }
+ $new->reasonPhrase = $reasonPhrase;
+ return $new;
+ }
+}
diff --git a/vendor/ringcentral/psr7/src/ServerRequest.php b/vendor/ringcentral/psr7/src/ServerRequest.php
new file mode 100644
index 0000000..8408a09
--- /dev/null
+++ b/vendor/ringcentral/psr7/src/ServerRequest.php
@@ -0,0 +1,122 @@
+<?php
+
+namespace RingCentral\Psr7;
+
+use Psr\Http\Message\ServerRequestInterface;
+use RingCentral\Psr7\Request;
+
+/**
+ * PSR-7 server-side request implementation.
+ */
+class ServerRequest extends Request implements ServerRequestInterface
+{
+ private $attributes = array();
+
+ private $serverParams = array();
+ private $fileParams = array();
+ private $cookies = array();
+ private $queryParams = array();
+ private $parsedBody = null;
+
+ /**
+ * @param null|string $method HTTP method for the request.
+ * @param null|string|UriInterface $uri URI for the request.
+ * @param array $headers Headers for the message.
+ * @param string|resource|StreamInterface $body Message body.
+ * @param string $protocolVersion HTTP protocol version.
+ * @param array $serverParams Server params of the request.
+ *
+ * @throws InvalidArgumentException for an invalid URI
+ */
+ public function __construct(
+ $method,
+ $uri,
+ array $headers = array(),
+ $body = null,
+ $protocolVersion = '1.1',
+ $serverParams = array()
+ ) {
+ parent::__construct($method, $uri, $headers, $body, $protocolVersion);
+ $this->serverParams = $serverParams;
+ }
+
+ public function getServerParams()
+ {
+ return $this->serverParams;
+ }
+
+ public function getCookieParams()
+ {
+ return $this->cookies;
+ }
+
+ public function withCookieParams(array $cookies)
+ {
+ $new = clone $this;
+ $new->cookies = $cookies;
+ return $new;
+ }
+
+ public function getQueryParams()
+ {
+ return $this->queryParams;
+ }
+
+ public function withQueryParams(array $query)
+ {
+ $new = clone $this;
+ $new->queryParams = $query;
+ return $new;
+ }
+
+ public function getUploadedFiles()
+ {
+ return $this->fileParams;
+ }
+
+ public function withUploadedFiles(array $uploadedFiles)
+ {
+ $new = clone $this;
+ $new->fileParams = $uploadedFiles;
+ return $new;
+ }
+
+ public function getParsedBody()
+ {
+ return $this->parsedBody;
+ }
+
+ public function withParsedBody($data)
+ {
+ $new = clone $this;
+ $new->parsedBody = $data;
+ return $new;
+ }
+
+ public function getAttributes()
+ {
+ return $this->attributes;
+ }
+
+ public function getAttribute($name, $default = null)
+ {
+ if (!array_key_exists($name, $this->attributes)) {
+ return $default;
+ }
+ return $this->attributes[$name];
+ }
+
+ public function withAttribute($name, $value)
+ {
+ $new = clone $this;
+ $new->attributes[$name] = $value;
+ return $new;
+ }
+
+ public function withoutAttribute($name)
+ {
+ $new = clone $this;
+ unset($new->attributes[$name]);
+ return $new;
+ }
+}
diff --git a/vendor/ringcentral/psr7/src/Stream.php b/vendor/ringcentral/psr7/src/Stream.php
new file mode 100644
index 0000000..0a0157c
--- /dev/null
+++ b/vendor/ringcentral/psr7/src/Stream.php
@@ -0,0 +1,245 @@
+<?php
+namespace RingCentral\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * PHP stream implementation.
+ *
+ * @var $stream
+ */
+class Stream implements StreamInterface
+{
+ private $stream;
+ private $size;
+ private $seekable;
+ private $readable;
+ private $writable;
+ private $uri;
+ private $customMetadata;
+
+ /** @var array Hash of readable and writable stream types */
+ private static $readWriteHash = array(
+ 'read' => array(
+ 'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true,
+ 'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true,
+ 'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true,
+ 'x+t' => true, 'c+t' => true, 'a+' => true
+ ),
+ 'write' => array(
+ 'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true,
+ 'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true,
+ 'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true,
+ 'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true
+ )
+ );
+
+ /**
+ * This constructor accepts an associative array of options.
+ *
+ * - size: (int) If a read stream would otherwise have an indeterminate
+ * size, but the size is known due to foreknownledge, then you can
+ * provide that size, in bytes.
+ * - metadata: (array) Any additional metadata to return when the metadata
+ * of the stream is accessed.
+ *
+ * @param resource $stream Stream resource to wrap.
+ * @param array $options Associative array of options.
+ *
+ * @throws \InvalidArgumentException if the stream is not a stream resource
+ */
+ public function __construct($stream, $options = array())
+ {
+ if (!is_resource($stream)) {
+ throw new \InvalidArgumentException('Stream must be a resource');
+ }
+
+ if (isset($options['size'])) {
+ $this->size = $options['size'];
+ }
+
+ $this->customMetadata = isset($options['metadata'])
+ ? $options['metadata']
+ : array();
+
+ $this->stream = $stream;
+ $meta = stream_get_meta_data($this->stream);
+ $this->seekable = $meta['seekable'];
+ $this->readable = isset(self::$readWriteHash['read'][$meta['mode']]);
+ $this->writable = isset(self::$readWriteHash['write'][$meta['mode']]);
+ $this->uri = $this->getMetadata('uri');
+ }
+
+ public function __get($name)
+ {
+ if ($name == 'stream') {
+ throw new \RuntimeException('The stream is detached');
+ }
+
+ throw new \BadMethodCallException('No value for ' . $name);
+ }
+
+ /**
+ * Closes the stream when the destructed
+ */
+ public function __destruct()
+ {
+ $this->close();
+ }
+
+ public function __toString()
+ {
+ try {
+ $this->seek(0);
+ return (string) stream_get_contents($this->stream);
+ } catch (\Exception $e) {
+ return '';
+ }
+ }
+
+ public function getContents()
+ {
+ $contents = stream_get_contents($this->stream);
+
+ if ($contents === false) {
+ throw new \RuntimeException('Unable to read stream contents');
+ }
+
+ return $contents;
+ }
+
+ public function close()
+ {
+ if (isset($this->stream)) {
+ if (is_resource($this->stream)) {
+ fclose($this->stream);
+ }
+ $this->detach();
+ }
+ }
+
+ public function detach()
+ {
+ if (!isset($this->stream)) {
+ return null;
+ }
+
+ $result = $this->stream;
+ unset($this->stream);
+ $this->size = $this->uri = null;
+ $this->readable = $this->writable = $this->seekable = false;
+
+ return $result;
+ }
+
+ public function getSize()
+ {
+ if ($this->size !== null) {
+ return $this->size;
+ }
+
+ if (!isset($this->stream)) {
+ return null;
+ }
+
+ // Clear the stat cache if the stream has a URI
+ if ($this->uri) {
+ clearstatcache(true, $this->uri);
+ }
+
+ $stats = fstat($this->stream);
+ if (isset($stats['size'])) {
+ $this->size = $stats['size'];
+ return $this->size;
+ }
+
+ return null;
+ }
+
+ public function isReadable()
+ {
+ return $this->readable;
+ }
+
+ public function isWritable()
+ {
+ return $this->writable;
+ }
+
+ public function isSeekable()
+ {
+ return $this->seekable;
+ }
+
+ public function eof()
+ {
+ return !$this->stream || feof($this->stream);
+ }
+
+ public function tell()
+ {
+ $result = ftell($this->stream);
+
+ if ($result === false) {
+ throw new \RuntimeException('Unable to determine stream position');
+ }
+
+ return $result;
+ }
+
+ public function rewind()
+ {
+ $this->seek(0);
+ }
+
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ if (!$this->seekable) {
+ throw new \RuntimeException('Stream is not seekable');
+ } elseif (fseek($this->stream, $offset, $whence) === -1) {
+ throw new \RuntimeException('Unable to seek to stream position '
+ . $offset . ' with whence ' . var_export($whence, true));
+ }
+ }
+
+ public function read($length)
+ {
+ if (!$this->readable) {
+ throw new \RuntimeException('Cannot read from non-readable stream');
+ }
+
+ return fread($this->stream, $length);
+ }
+
+ public function write($string)
+ {
+ if (!$this->writable) {
+ throw new \RuntimeException('Cannot write to a non-writable stream');
+ }
+
+ // We can't know the size after writing anything
+ $this->size = null;
+ $result = fwrite($this->stream, $string);
+
+ if ($result === false) {
+ throw new \RuntimeException('Unable to write to stream');
+ }
+
+ return $result;
+ }
+
+ public function getMetadata($key = null)
+ {
+ if (!isset($this->stream)) {
+ return $key ? null : array();
+ } elseif (!$key) {
+ return $this->customMetadata + stream_get_meta_data($this->stream);
+ } elseif (isset($this->customMetadata[$key])) {
+ return $this->customMetadata[$key];
+ }
+
+ $meta = stream_get_meta_data($this->stream);
+
+ return isset($meta[$key]) ? $meta[$key] : null;
+ }
+}
diff --git a/vendor/ringcentral/psr7/src/StreamDecoratorTrait.php b/vendor/ringcentral/psr7/src/StreamDecoratorTrait.php
new file mode 100644
index 0000000..e22c674
--- /dev/null
+++ b/vendor/ringcentral/psr7/src/StreamDecoratorTrait.php
@@ -0,0 +1,139 @@
+<?php
+namespace RingCentral\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Stream decorator trait
+ * @property StreamInterface stream
+ */
+abstract class StreamDecoratorTrait implements StreamInterface
+{
+ /**
+ * @param StreamInterface $stream Stream to decorate
+ */
+ public function __construct(StreamInterface $stream = null)
+ {
+ if ($stream) $this->stream = $stream;
+ }
+
+ /**
+ * Magic method used to create a new stream if streams are not added in
+ * the constructor of a decorator (e.g., LazyOpenStream).
+ *
+ * @param string $name Name of the property (allows "stream" only).
+ *
+ * @return StreamInterface
+ */
+ public function __get($name)
+ {
+ if ($name == 'stream') {
+ $this->stream = $this->createStream();
+ return $this->stream;
+ }
+
+ throw new \UnexpectedValueException("$name not found on class");
+ }
+
+ public function __toString()
+ {
+ try {
+ if ($this->isSeekable()) {
+ $this->seek(0);
+ }
+ return $this->getContents();
+ } catch (\Exception $e) {
+ // Really, PHP? https://bugs.php.net/bug.php?id=53648
+ trigger_error('StreamDecorator::__toString exception: '
+ . (string) $e, E_USER_ERROR);
+ return '';
+ }
+ }
+
+ public function getContents()
+ {
+ return copy_to_string($this);
+ }
+
+ /**
+ * Allow decorators to implement custom methods
+ *
+ * @param string $method Missing method name
+ * @param array $args Method arguments
+ *
+ * @return mixed
+ */
+ public function __call($method, array $args)
+ {
+ $result = call_user_func_array(array($this->stream, $method), $args);
+
+ // Always return the wrapped object if the result is a return $this
+ return $result === $this->stream ? $this : $result;
+ }
+
+ public function close()
+ {
+ $this->stream->close();
+ }
+
+ public function getMetadata($key = null)
+ {
+ return $this->stream->getMetadata($key);
+ }
+
+ public function detach()
+ {
+ return $this->stream->detach();
+ }
+
+ public function getSize()
+ {
+ return $this->stream->getSize();
+ }
+
+ public function eof()
+ {
+ return $this->stream->eof();
+ }
+
+ public function tell()
+ {
+ return $this->stream->tell();
+ }
+
+ public function isReadable()
+ {
+ return $this->stream->isReadable();
+ }
+
+ public function isWritable()
+ {
+ return $this->stream->isWritable();
+ }
+
+ public function isSeekable()
+ {
+ return $this->stream->isSeekable();
+ }
+
+ public function rewind()
+ {
+ $this->seek(0);
+ }
+
+ public function seek($offset, $whence = SEEK_SET)
+ {
+ $this->stream->seek($offset, $whence);
+ }
+
+ public function read($length)
+ {
+ return $this->stream->read($length);
+ }
+
+ public function write($string)
+ {
+ return $this->stream->write($string);
+ }
+
+}
diff --git a/vendor/ringcentral/psr7/src/StreamWrapper.php b/vendor/ringcentral/psr7/src/StreamWrapper.php
new file mode 100644
index 0000000..8cc07d7
--- /dev/null
+++ b/vendor/ringcentral/psr7/src/StreamWrapper.php
@@ -0,0 +1,121 @@
+<?php
+namespace RingCentral\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+
+/**
+ * Converts Guzzle streams into PHP stream resources.
+ */
+class StreamWrapper
+{
+ /** @var resource */
+ public $context;
+
+ /** @var StreamInterface */
+ private $stream;
+
+ /** @var string r, r+, or w */
+ private $mode;
+
+ /**
+ * Returns a resource representing the stream.
+ *
+ * @param StreamInterface $stream The stream to get a resource for
+ *
+ * @return resource
+ * @throws \InvalidArgumentException if stream is not readable or writable
+ */
+ public static function getResource(StreamInterface $stream)
+ {
+ self::register();
+
+ if ($stream->isReadable()) {
+ $mode = $stream->isWritable() ? 'r+' : 'r';
+ } elseif ($stream->isWritable()) {
+ $mode = 'w';
+ } else {
+ throw new \InvalidArgumentException('The stream must be readable, '
+ . 'writable, or both.');
+ }
+
+ return fopen('guzzle://stream', $mode, null, stream_context_create(array(
+ 'guzzle' => array('stream' => $stream)
+ )));
+ }
+
+ /**
+ * Registers the stream wrapper if needed
+ */
+ public static function register()
+ {
+ if (!in_array('guzzle', stream_get_wrappers())) {
+ stream_wrapper_register('guzzle', __CLASS__);
+ }
+ }
+
+ public function stream_open($path, $mode, $options, &$opened_path)
+ {
+ $options = stream_context_get_options($this->context);
+
+ if (!isset($options['guzzle']['stream'])) {
+ return false;
+ }
+
+ $this->mode = $mode;
+ $this->stream = $options['guzzle']['stream'];
+
+ return true;
+ }
+
+ public function stream_read($count)
+ {
+ return $this->stream->read($count);
+ }
+
+ public function stream_write($data)
+ {
+ return (int) $this->stream->write($data);
+ }
+
+ public function stream_tell()
+ {
+ return $this->stream->tell();
+ }
+
+ public function stream_eof()
+ {
+ return $this->stream->eof();
+ }
+
+ public function stream_seek($offset, $whence)
+ {
+ $this->stream->seek($offset, $whence);
+
+ return true;
+ }
+
+ public function stream_stat()
+ {
+ static $modeMap = array(
+ 'r' => 33060,
+ 'r+' => 33206,
+ 'w' => 33188
+ );
+
+ return array(
+ 'dev' => 0,
+ 'ino' => 0,
+ 'mode' => $modeMap[$this->mode],
+ 'nlink' => 0,
+ 'uid' => 0,
+ 'gid' => 0,
+ 'rdev' => 0,
+ 'size' => $this->stream->getSize() ?: 0,
+ 'atime' => 0,
+ 'mtime' => 0,
+ 'ctime' => 0,
+ 'blksize' => 0,
+ 'blocks' => 0
+ );
+ }
+}
diff --git a/vendor/ringcentral/psr7/src/Uri.php b/vendor/ringcentral/psr7/src/Uri.php
new file mode 100644
index 0000000..5323cdc
--- /dev/null
+++ b/vendor/ringcentral/psr7/src/Uri.php
@@ -0,0 +1,601 @@
+<?php
+namespace RingCentral\Psr7;
+
+use Psr\Http\Message\UriInterface;
+
+/**
+ * Basic PSR-7 URI implementation.
+ *
+ * @link https://github.com/phly/http This class is based upon
+ * Matthew Weier O'Phinney's URI implementation in phly/http.
+ */
+class Uri implements UriInterface
+{
+ private static $schemes = array(
+ 'http' => 80,
+ 'https' => 443,
+ );
+
+ private static $charUnreserved = 'a-zA-Z0-9_\-\.~';
+ private static $charSubDelims = '!\$&\'\(\)\*\+,;=';
+ private static $replaceQuery = array('=' => '%3D', '&' => '%26');
+
+ /** @var string Uri scheme. */
+ private $scheme = '';
+
+ /** @var string Uri user info. */
+ private $userInfo = '';
+
+ /** @var string Uri host. */
+ private $host = '';
+
+ /** @var int|null Uri port. */
+ private $port;
+
+ /** @var string Uri path. */
+ private $path = '';
+
+ /** @var string Uri query string. */
+ private $query = '';
+
+ /** @var string Uri fragment. */
+ private $fragment = '';
+
+ /**
+ * @param string $uri URI to parse and wrap.
+ */
+ public function __construct($uri = '')
+ {
+ if ($uri != null) {
+ $parts = parse_url($uri);
+ if ($parts === false) {
+ throw new \InvalidArgumentException("Unable to parse URI: $uri");
+ }
+ $this->applyParts($parts);
+ }
+ }
+
+ public function __toString()
+ {
+ return self::createUriString(
+ $this->scheme,
+ $this->getAuthority(),
+ $this->getPath(),
+ $this->query,
+ $this->fragment
+ );
+ }
+
+ /**
+ * Removes dot segments from a path and returns the new path.
+ *
+ * @param string $path
+ *
+ * @return string
+ * @link http://tools.ietf.org/html/rfc3986#section-5.2.4
+ */
+ public static function removeDotSegments($path)
+ {
+ static $noopPaths = array('' => true, '/' => true, '*' => true);
+ static $ignoreSegments = array('.' => true, '..' => true);
+
+ if (isset($noopPaths[$path])) {
+ return $path;
+ }
+
+ $results = array();
+ $segments = explode('/', $path);
+ foreach ($segments as $segment) {
+ if ($segment == '..') {
+ array_pop($results);
+ } elseif (!isset($ignoreSegments[$segment])) {
+ $results[] = $segment;
+ }
+ }
+
+ $newPath = implode('/', $results);
+ // Add the leading slash if necessary
+ if (substr($path, 0, 1) === '/' &&
+ substr($newPath, 0, 1) !== '/'
+ ) {
+ $newPath = '/' . $newPath;
+ }
+
+ // Add the trailing slash if necessary
+ if ($newPath != '/' && isset($ignoreSegments[end($segments)])) {
+ $newPath .= '/';
+ }
+
+ return $newPath;
+ }
+
+ /**
+ * Resolve a base URI with a relative URI and return a new URI.
+ *
+ * @param UriInterface $base Base URI
+ * @param string $rel Relative URI
+ *
+ * @return UriInterface
+ */
+ public static function resolve(UriInterface $base, $rel)
+ {
+ if ($rel === null || $rel === '') {
+ return $base;
+ }
+
+ if (!($rel instanceof UriInterface)) {
+ $rel = new self($rel);
+ }
+
+ // Return the relative uri as-is if it has a scheme.
+ if ($rel->getScheme()) {
+ return $rel->withPath(static::removeDotSegments($rel->getPath()));
+ }
+
+ $relParts = array(
+ 'scheme' => $rel->getScheme(),
+ 'authority' => $rel->getAuthority(),
+ 'path' => $rel->getPath(),
+ 'query' => $rel->getQuery(),
+ 'fragment' => $rel->getFragment()
+ );
+
+ $parts = array(
+ 'scheme' => $base->getScheme(),
+ 'authority' => $base->getAuthority(),
+ 'path' => $base->getPath(),
+ 'query' => $base->getQuery(),
+ 'fragment' => $base->getFragment()
+ );
+
+ if (!empty($relParts['authority'])) {
+ $parts['authority'] = $relParts['authority'];
+ $parts['path'] = self::removeDotSegments($relParts['path']);
+ $parts['query'] = $relParts['query'];
+ $parts['fragment'] = $relParts['fragment'];
+ } elseif (!empty($relParts['path'])) {
+ if (substr($relParts['path'], 0, 1) == '/') {
+ $parts['path'] = self::removeDotSegments($relParts['path']);
+ $parts['query'] = $relParts['query'];
+ $parts['fragment'] = $relParts['fragment'];
+ } else {
+ if (!empty($parts['authority']) && empty($parts['path'])) {
+ $mergedPath = '/';
+ } else {
+ $mergedPath = substr($parts['path'], 0, strrpos($parts['path'], '/') + 1);
+ }
+ $parts['path'] = self::removeDotSegments($mergedPath . $relParts['path']);
+ $parts['query'] = $relParts['query'];
+ $parts['fragment'] = $relParts['fragment'];
+ }
+ } elseif (!empty($relParts['query'])) {
+ $parts['query'] = $relParts['query'];
+ } elseif ($relParts['fragment'] != null) {
+ $parts['fragment'] = $relParts['fragment'];
+ }
+
+ return new self(static::createUriString(
+ $parts['scheme'],
+ $parts['authority'],
+ $parts['path'],
+ $parts['query'],
+ $parts['fragment']
+ ));
+ }
+
+ /**
+ * Create a new URI with a specific query string value removed.
+ *
+ * Any existing query string values that exactly match the provided key are
+ * removed.
+ *
+ * Note: this function will convert "=" to "%3D" and "&" to "%26".
+ *
+ * @param UriInterface $uri URI to use as a base.
+ * @param string $key Query string key value pair to remove.
+ *
+ * @return UriInterface
+ */
+ public static function withoutQueryValue(UriInterface $uri, $key)
+ {
+ $current = $uri->getQuery();
+ if (!$current) {
+ return $uri;
+ }
+
+ $result = array();
+ foreach (explode('&', $current) as $part) {
+ $subParts = explode('=', $part);
+ if ($subParts[0] !== $key) {
+ $result[] = $part;
+ };
+ }
+
+ return $uri->withQuery(implode('&', $result));
+ }
+
+ /**
+ * Create a new URI with a specific query string value.
+ *
+ * Any existing query string values that exactly match the provided key are
+ * removed and replaced with the given key value pair.
+ *
+ * Note: this function will convert "=" to "%3D" and "&" to "%26".
+ *
+ * @param UriInterface $uri URI to use as a base.
+ * @param string $key Key to set.
+ * @param string $value Value to set.
+ *
+ * @return UriInterface
+ */
+ public static function withQueryValue(UriInterface $uri, $key, $value)
+ {
+ $current = $uri->getQuery();
+ $key = strtr($key, self::$replaceQuery);
+
+ if (!$current) {
+ $result = array();
+ } else {
+ $result = array();
+ foreach (explode('&', $current) as $part) {
+ $subParts = explode('=', $part);
+ if ($subParts[0] !== $key) {
+ $result[] = $part;
+ };
+ }
+ }
+
+ if ($value !== null) {
+ $result[] = $key . '=' . strtr($value, self::$replaceQuery);
+ } else {
+ $result[] = $key;
+ }
+
+ return $uri->withQuery(implode('&', $result));
+ }
+
+ /**
+ * Create a URI from a hash of parse_url parts.
+ *
+ * @param array $parts
+ *
+ * @return self
+ */
+ public static function fromParts(array $parts)
+ {
+ $uri = new self();
+ $uri->applyParts($parts);
+ return $uri;
+ }
+
+ public function getScheme()
+ {
+ return $this->scheme;
+ }
+
+ public function getAuthority()
+ {
+ if (empty($this->host)) {
+ return '';
+ }
+
+ $authority = $this->host;
+ if (!empty($this->userInfo)) {
+ $authority = $this->userInfo . '@' . $authority;
+ }
+
+ if ($this->isNonStandardPort($this->scheme, $this->host, $this->port)) {
+ $authority .= ':' . $this->port;
+ }
+
+ return $authority;
+ }
+
+ public function getUserInfo()
+ {
+ return $this->userInfo;
+ }
+
+ public function getHost()
+ {
+ return $this->host;
+ }
+
+ public function getPort()
+ {
+ return $this->port;
+ }
+
+ public function getPath()
+ {
+ return $this->path == null ? '' : $this->path;
+ }
+
+ public function getQuery()
+ {
+ return $this->query;
+ }
+
+ public function getFragment()
+ {
+ return $this->fragment;
+ }
+
+ public function withScheme($scheme)
+ {
+ $scheme = $this->filterScheme($scheme);
+
+ if ($this->scheme === $scheme) {
+ return $this;
+ }
+
+ $new = clone $this;
+ $new->scheme = $scheme;
+ $new->port = $new->filterPort($new->scheme, $new->host, $new->port);
+ return $new;
+ }
+
+ public function withUserInfo($user, $password = null)
+ {
+ $info = $user;
+ if ($password) {
+ $info .= ':' . $password;
+ }
+
+ if ($this->userInfo === $info) {
+ return $this;
+ }
+
+ $new = clone $this;
+ $new->userInfo = $info;
+ return $new;
+ }
+
+ public function withHost($host)
+ {
+ if ($this->host === $host) {
+ return $this;
+ }
+
+ $new = clone $this;
+ $new->host = $host;
+ return $new;
+ }
+
+ public function withPort($port)
+ {
+ $port = $this->filterPort($this->scheme, $this->host, $port);
+
+ if ($this->port === $port) {
+ return $this;
+ }
+
+ $new = clone $this;
+ $new->port = $port;
+ return $new;
+ }
+
+ public function withPath($path)
+ {
+ if (!is_string($path)) {
+ throw new \InvalidArgumentException(
+ 'Invalid path provided; must be a string'
+ );
+ }
+
+ $path = $this->filterPath($path);
+
+ if ($this->path === $path) {
+ return $this;
+ }
+
+ $new = clone $this;
+ $new->path = $path;
+ return $new;
+ }
+
+ public function withQuery($query)
+ {
+ if (!is_string($query) && !method_exists($query, '__toString')) {
+ throw new \InvalidArgumentException(
+ 'Query string must be a string'
+ );
+ }
+
+ $query = (string) $query;
+ if (substr($query, 0, 1) === '?') {
+ $query = substr($query, 1);
+ }
+
+ $query = $this->filterQueryAndFragment($query);
+
+ if ($this->query === $query) {
+ return $this;
+ }
+
+ $new = clone $this;
+ $new->query = $query;
+ return $new;
+ }
+
+ public function withFragment($fragment)
+ {
+ if (substr($fragment, 0, 1) === '#') {
+ $fragment = substr($fragment, 1);
+ }
+
+ $fragment = $this->filterQueryAndFragment($fragment);
+
+ if ($this->fragment === $fragment) {
+ return $this;
+ }
+
+ $new = clone $this;
+ $new->fragment = $fragment;
+ return $new;
+ }
+
+ /**
+ * Apply parse_url parts to a URI.
+ *
+ * @param $parts Array of parse_url parts to apply.
+ */
+ private function applyParts(array $parts)
+ {
+ $this->scheme = isset($parts['scheme'])
+ ? $this->filterScheme($parts['scheme'])
+ : '';
+ $this->userInfo = isset($parts['user']) ? $parts['user'] : '';
+ $this->host = isset($parts['host']) ? $parts['host'] : '';
+ $this->port = !empty($parts['port'])
+ ? $this->filterPort($this->scheme, $this->host, $parts['port'])
+ : null;
+ $this->path = isset($parts['path'])
+ ? $this->filterPath($parts['path'])
+ : '';
+ $this->query = isset($parts['query'])
+ ? $this->filterQueryAndFragment($parts['query'])
+ : '';
+ $this->fragment = isset($parts['fragment'])
+ ? $this->filterQueryAndFragment($parts['fragment'])
+ : '';
+ if (isset($parts['pass'])) {
+ $this->userInfo .= ':' . $parts['pass'];
+ }
+ }
+
+ /**
+ * Create a URI string from its various parts
+ *
+ * @param string $scheme
+ * @param string $authority
+ * @param string $path
+ * @param string $query
+ * @param string $fragment
+ * @return string
+ */
+ private static function createUriString($scheme, $authority, $path, $query, $fragment)
+ {
+ $uri = '';
+
+ if (!empty($scheme)) {
+ $uri .= $scheme . '://';
+ }
+
+ if (!empty($authority)) {
+ $uri .= $authority;
+ }
+
+ if ($path != null) {
+ // Add a leading slash if necessary.
+ if ($uri && substr($path, 0, 1) !== '/') {
+ $uri .= '/';
+ }
+ $uri .= $path;
+ }
+
+ if ($query != null) {
+ $uri .= '?' . $query;
+ }
+
+ if ($fragment != null) {
+ $uri .= '#' . $fragment;
+ }
+
+ return $uri;
+ }
+
+ /**
+ * Is a given port non-standard for the current scheme?
+ *
+ * @param string $scheme
+ * @param string $host
+ * @param int $port
+ * @return bool
+ */
+ private static function isNonStandardPort($scheme, $host, $port)
+ {
+ if (!$scheme && $port) {
+ return true;
+ }
+
+ if (!$host || !$port) {
+ return false;
+ }
+
+ return !isset(static::$schemes[$scheme]) || $port !== static::$schemes[$scheme];
+ }
+
+ /**
+ * @param string $scheme
+ *
+ * @return string
+ */
+ private function filterScheme($scheme)
+ {
+ $scheme = strtolower($scheme);
+ $scheme = rtrim($scheme, ':/');
+
+ return $scheme;
+ }
+
+ /**
+ * @param string $scheme
+ * @param string $host
+ * @param int $port
+ *
+ * @return int|null
+ *
+ * @throws \InvalidArgumentException If the port is invalid.
+ */
+ private function filterPort($scheme, $host, $port)
+ {
+ if (null !== $port) {
+ $port = (int) $port;
+ if (1 > $port || 0xffff < $port) {
+ throw new \InvalidArgumentException(
+ sprintf('Invalid port: %d. Must be between 1 and 65535', $port)
+ );
+ }
+ }
+
+ return $this->isNonStandardPort($scheme, $host, $port) ? $port : null;
+ }
+
+ /**
+ * Filters the path of a URI
+ *
+ * @param $path
+ *
+ * @return string
+ */
+ private function filterPath($path)
+ {
+ return preg_replace_callback(
+ '/(?:[^' . self::$charUnreserved . self::$charSubDelims . ':@\/%]+|%(?![A-Fa-f0-9]{2}))/',
+ array($this, 'rawurlencodeMatchZero'),
+ $path
+ );
+ }
+
+ /**
+ * Filters the query string or fragment of a URI.
+ *
+ * @param $str
+ *
+ * @return string
+ */
+ private function filterQueryAndFragment($str)
+ {
+ return preg_replace_callback(
+ '/(?:[^' . self::$charUnreserved . self::$charSubDelims . '%:@\/\?]+|%(?![A-Fa-f0-9]{2}))/',
+ array($this, 'rawurlencodeMatchZero'),
+ $str
+ );
+ }
+
+ private function rawurlencodeMatchZero(array $match)
+ {
+ return rawurlencode($match[0]);
+ }
+}
diff --git a/vendor/ringcentral/psr7/src/functions.php b/vendor/ringcentral/psr7/src/functions.php
new file mode 100644
index 0000000..3c4c549
--- /dev/null
+++ b/vendor/ringcentral/psr7/src/functions.php
@@ -0,0 +1,835 @@
+<?php
+namespace RingCentral\Psr7;
+
+use Psr\Http\Message\MessageInterface;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\StreamInterface;
+use Psr\Http\Message\UriInterface;
+
+// Manually define missing constants for PHP 5.3
+defined('PHP_QUERY_RFC1738') or define('PHP_QUERY_RFC1738', 1);
+defined('PHP_QUERY_RFC3986') or define('PHP_QUERY_RFC3986', 2);
+
+/**
+ * Returns the string representation of an HTTP message.
+ *
+ * @param MessageInterface $message Message to convert to a string.
+ *
+ * @return string
+ */
+function str(MessageInterface $message)
+{
+ if ($message instanceof RequestInterface) {
+ $msg = trim($message->getMethod() . ' '
+ . $message->getRequestTarget())
+ . ' HTTP/' . $message->getProtocolVersion();
+ if (!$message->hasHeader('host')) {
+ $msg .= "\r\nHost: " . $message->getUri()->getHost();
+ }
+ } elseif ($message instanceof ResponseInterface) {
+ $msg = 'HTTP/' . $message->getProtocolVersion() . ' '
+ . $message->getStatusCode() . ' '
+ . $message->getReasonPhrase();
+ } else {
+ throw new \InvalidArgumentException('Unknown message type');
+ }
+
+ foreach ($message->getHeaders() as $name => $values) {
+ $msg .= "\r\n{$name}: " . implode(', ', $values);
+ }
+
+ return "{$msg}\r\n\r\n" . $message->getBody();
+}
+
+/**
+ * Returns a UriInterface for the given value.
+ *
+ * This function accepts a string or {@see Psr\Http\Message\UriInterface} and
+ * returns a UriInterface for the given value. If the value is already a
+ * `UriInterface`, it is returned as-is.
+ *
+ * @param string|UriInterface $uri
+ *
+ * @return UriInterface
+ * @throws \InvalidArgumentException
+ */
+function uri_for($uri)
+{
+ if ($uri instanceof UriInterface) {
+ return $uri;
+ } elseif (is_string($uri)) {
+ return new Uri($uri);
+ }
+
+ throw new \InvalidArgumentException('URI must be a string or UriInterface');
+}
+
+/**
+ * Create a new stream based on the input type.
+ *
+ * Options is an associative array that can contain the following keys:
+ * - metadata: Array of custom metadata.
+ * - size: Size of the stream.
+ *
+ * @param resource|string|StreamInterface $resource Entity body data
+ * @param array $options Additional options
+ *
+ * @return Stream
+ * @throws \InvalidArgumentException if the $resource arg is not valid.
+ */
+function stream_for($resource = '', array $options = array())
+{
+ switch (gettype($resource)) {
+ case 'string':
+ $stream = fopen('php://temp', 'r+');
+ if ($resource !== '') {
+ fwrite($stream, $resource);
+ fseek($stream, 0);
+ }
+ return new Stream($stream, $options);
+ case 'resource':
+ return new Stream($resource, $options);
+ case 'object':
+ if ($resource instanceof StreamInterface) {
+ return $resource;
+ } elseif ($resource instanceof \Iterator) {
+ return new PumpStream(function () use ($resource) {
+ if (!$resource->valid()) {
+ return false;
+ }
+ $result = $resource->current();
+ $resource->next();
+ return $result;
+ }, $options);
+ } elseif (method_exists($resource, '__toString')) {
+ return stream_for((string) $resource, $options);
+ }
+ break;
+ case 'NULL':
+ return new Stream(fopen('php://temp', 'r+'), $options);
+ }
+
+ if (is_callable($resource)) {
+ return new PumpStream($resource, $options);
+ }
+
+ throw new \InvalidArgumentException('Invalid resource type: ' . gettype($resource));
+}
+
+/**
+ * Parse an array of header values containing ";" separated data into an
+ * array of associative arrays representing the header key value pair
+ * data of the header. When a parameter does not contain a value, but just
+ * contains a key, this function will inject a key with a '' string value.
+ *
+ * @param string|array $header Header to parse into components.
+ *
+ * @return array Returns the parsed header values.
+ */
+function parse_header($header)
+{
+ static $trimmed = "\"' \n\t\r";
+ $params = $matches = array();
+
+ foreach (normalize_header($header) as $val) {
+ $part = array();
+ foreach (preg_split('/;(?=([^"]*"[^"]*")*[^"]*$)/', $val) as $kvp) {
+ if (preg_match_all('/<[^>]+>|[^=]+/', $kvp, $matches)) {
+ $m = $matches[0];
+ if (isset($m[1])) {
+ $part[trim($m[0], $trimmed)] = trim($m[1], $trimmed);
+ } else {
+ $part[] = trim($m[0], $trimmed);
+ }
+ }
+ }
+ if ($part) {
+ $params[] = $part;
+ }
+ }
+
+ return $params;
+}
+
+/**
+ * Converts an array of header values that may contain comma separated
+ * headers into an array of headers with no comma separated values.
+ *
+ * @param string|array $header Header to normalize.
+ *
+ * @return array Returns the normalized header field values.
+ */
+function normalize_header($header)
+{
+ if (!is_array($header)) {
+ return array_map('trim', explode(',', $header));
+ }
+
+ $result = array();
+ foreach ($header as $value) {
+ foreach ((array) $value as $v) {
+ if (strpos($v, ',') === false) {
+ $result[] = $v;
+ continue;
+ }
+ foreach (preg_split('/,(?=([^"]*"[^"]*")*[^"]*$)/', $v) as $vv) {
+ $result[] = trim($vv);
+ }
+ }
+ }
+
+ return $result;
+}
+
+/**
+ * Clone and modify a request with the given changes.
+ *
+ * The changes can be one of:
+ * - method: (string) Changes the HTTP method.
+ * - set_headers: (array) Sets the given headers.
+ * - remove_headers: (array) Remove the given headers.
+ * - body: (mixed) Sets the given body.
+ * - uri: (UriInterface) Set the URI.
+ * - query: (string) Set the query string value of the URI.
+ * - version: (string) Set the protocol version.
+ *
+ * @param RequestInterface $request Request to clone and modify.
+ * @param array $changes Changes to apply.
+ *
+ * @return RequestInterface
+ */
+function modify_request(RequestInterface $request, array $changes)
+{
+ if (!$changes) {
+ return $request;
+ }
+
+ $headers = $request->getHeaders();
+
+ if (!isset($changes['uri'])) {
+ $uri = $request->getUri();
+ } else {
+ // Remove the host header if one is on the URI
+ if ($host = $changes['uri']->getHost()) {
+ $changes['set_headers']['Host'] = $host;
+ }
+ $uri = $changes['uri'];
+ }
+
+ if (!empty($changes['remove_headers'])) {
+ $headers = _caseless_remove($changes['remove_headers'], $headers);
+ }
+
+ if (!empty($changes['set_headers'])) {
+ $headers = _caseless_remove(array_keys($changes['set_headers']), $headers);
+ $headers = $changes['set_headers'] + $headers;
+ }
+
+ if (isset($changes['query'])) {
+ $uri = $uri->withQuery($changes['query']);
+ }
+
+ return new Request(
+ isset($changes['method']) ? $changes['method'] : $request->getMethod(),
+ $uri,
+ $headers,
+ isset($changes['body']) ? $changes['body'] : $request->getBody(),
+ isset($changes['version'])
+ ? $changes['version']
+ : $request->getProtocolVersion()
+ );
+}
+
+/**
+ * Attempts to rewind a message body and throws an exception on failure.
+ *
+ * The body of the message will only be rewound if a call to `tell()` returns a
+ * value other than `0`.
+ *
+ * @param MessageInterface $message Message to rewind
+ *
+ * @throws \RuntimeException
+ */
+function rewind_body(MessageInterface $message)
+{
+ $body = $message->getBody();
+
+ if ($body->tell()) {
+ $body->rewind();
+ }
+}
+
+/**
+ * Safely opens a PHP stream resource using a filename.
+ *
+ * When fopen fails, PHP normally raises a warning. This function adds an
+ * error handler that checks for errors and throws an exception instead.
+ *
+ * @param string $filename File to open
+ * @param string $mode Mode used to open the file
+ *
+ * @return resource
+ * @throws \RuntimeException if the file cannot be opened
+ */
+function try_fopen($filename, $mode)
+{
+ $ex = null;
+ $fargs = func_get_args();
+ set_error_handler(function () use ($filename, $mode, &$ex, $fargs) {
+ $ex = new \RuntimeException(sprintf(
+ 'Unable to open %s using mode %s: %s',
+ $filename,
+ $mode,
+ $fargs[1]
+ ));
+ });
+
+ $handle = fopen($filename, $mode);
+ restore_error_handler();
+
+ if ($ex) {
+ /** @var $ex \RuntimeException */
+ throw $ex;
+ }
+
+ return $handle;
+}
+
+/**
+ * Copy the contents of a stream into a string until the given number of
+ * bytes have been read.
+ *
+ * @param StreamInterface $stream Stream to read
+ * @param int $maxLen Maximum number of bytes to read. Pass -1
+ * to read the entire stream.
+ * @return string
+ * @throws \RuntimeException on error.
+ */
+function copy_to_string(StreamInterface $stream, $maxLen = -1)
+{
+ $buffer = '';
+
+ if ($maxLen === -1) {
+ while (!$stream->eof()) {
+ $buf = $stream->read(1048576);
+ // Using a loose equality here to match on '' and false.
+ if ($buf == null) {
+ break;
+ }
+ $buffer .= $buf;
+ }
+ return $buffer;
+ }
+
+ $len = 0;
+ while (!$stream->eof() && $len < $maxLen) {
+ $buf = $stream->read($maxLen - $len);
+ // Using a loose equality here to match on '' and false.
+ if ($buf == null) {
+ break;
+ }
+ $buffer .= $buf;
+ $len = strlen($buffer);
+ }
+
+ return $buffer;
+}
+
+/**
+ * Copy the contents of a stream into another stream until the given number
+ * of bytes have been read.
+ *
+ * @param StreamInterface $source Stream to read from
+ * @param StreamInterface $dest Stream to write to
+ * @param int $maxLen Maximum number of bytes to read. Pass -1
+ * to read the entire stream.
+ *
+ * @throws \RuntimeException on error.
+ */
+function copy_to_stream(
+ StreamInterface $source,
+ StreamInterface $dest,
+ $maxLen = -1
+) {
+ if ($maxLen === -1) {
+ while (!$source->eof()) {
+ if (!$dest->write($source->read(1048576))) {
+ break;
+ }
+ }
+ return;
+ }
+
+ $bytes = 0;
+ while (!$source->eof()) {
+ $buf = $source->read($maxLen - $bytes);
+ if (!($len = strlen($buf))) {
+ break;
+ }
+ $bytes += $len;
+ $dest->write($buf);
+ if ($bytes == $maxLen) {
+ break;
+ }
+ }
+}
+
+/**
+ * Calculate a hash of a Stream
+ *
+ * @param StreamInterface $stream Stream to calculate the hash for
+ * @param string $algo Hash algorithm (e.g. md5, crc32, etc)
+ * @param bool $rawOutput Whether or not to use raw output
+ *
+ * @return string Returns the hash of the stream
+ * @throws \RuntimeException on error.
+ */
+function hash(
+ StreamInterface $stream,
+ $algo,
+ $rawOutput = false
+) {
+ $pos = $stream->tell();
+
+ if ($pos > 0) {
+ $stream->rewind();
+ }
+
+ $ctx = hash_init($algo);
+ while (!$stream->eof()) {
+ hash_update($ctx, $stream->read(1048576));
+ }
+
+ $out = hash_final($ctx, (bool) $rawOutput);
+ $stream->seek($pos);
+
+ return $out;
+}
+
+/**
+ * Read a line from the stream up to the maximum allowed buffer length
+ *
+ * @param StreamInterface $stream Stream to read from
+ * @param int $maxLength Maximum buffer length
+ *
+ * @return string|bool
+ */
+function readline(StreamInterface $stream, $maxLength = null)
+{
+ $buffer = '';
+ $size = 0;
+
+ while (!$stream->eof()) {
+ // Using a loose equality here to match on '' and false.
+ if (null == ($byte = $stream->read(1))) {
+ return $buffer;
+ }
+ $buffer .= $byte;
+ // Break when a new line is found or the max length - 1 is reached
+ if ($byte == PHP_EOL || ++$size == $maxLength - 1) {
+ break;
+ }
+ }
+
+ return $buffer;
+}
+
+/**
+ * Parses a request message string into a request object.
+ *
+ * @param string $message Request message string.
+ *
+ * @return Request
+ */
+function parse_request($message)
+{
+ $data = _parse_message($message);
+ $matches = array();
+ if (!preg_match('/^[a-zA-Z]+\s+([a-zA-Z]+:\/\/|\/).*/', $data['start-line'], $matches)) {
+ throw new \InvalidArgumentException('Invalid request string');
+ }
+ $parts = explode(' ', $data['start-line'], 3);
+ $subParts = isset($parts[2]) ? explode('/', $parts[2]) : array();
+ $version = isset($parts[2]) ? $subParts[1] : '1.1';
+
+ $request = new Request(
+ $parts[0],
+ $matches[1] === '/' ? _parse_request_uri($parts[1], $data['headers']) : $parts[1],
+ $data['headers'],
+ $data['body'],
+ $version
+ );
+
+ return $matches[1] === '/' ? $request : $request->withRequestTarget($parts[1]);
+}
+
+/**
+ * Parses a request message string into a server request object.
+ *
+ * @param string $message Request message string.
+ * @param array $serverParams Server params that will be added to the
+ * ServerRequest object
+ *
+ * @return ServerRequest
+ */
+function parse_server_request($message, array $serverParams = array())
+{
+ $request = parse_request($message);
+
+ return new ServerRequest(
+ $request->getMethod(),
+ $request->getUri(),
+ $request->getHeaders(),
+ $request->getBody(),
+ $request->getProtocolVersion(),
+ $serverParams
+ );
+}
+
+/**
+ * Parses a response message string into a response object.
+ *
+ * @param string $message Response message string.
+ *
+ * @return Response
+ */
+function parse_response($message)
+{
+ $data = _parse_message($message);
+ // According to https://tools.ietf.org/html/rfc7230#section-3.1.2 the space
+ // between status-code and reason-phrase is required. But browsers accept
+ // responses without space and reason as well.
+ if (!preg_match('/^HTTP\/.* [0-9]{3}( .*|$)/', $data['start-line'])) {
+ throw new \InvalidArgumentException('Invalid response string');
+ }
+ $parts = explode(' ', $data['start-line'], 3);
+ $subParts = explode('/', $parts[0]);
+
+ return new Response(
+ $parts[1],
+ $data['headers'],
+ $data['body'],
+ $subParts[1],
+ isset($parts[2]) ? $parts[2] : null
+ );
+}
+
+/**
+ * Parse a query string into an associative array.
+ *
+ * If multiple values are found for the same key, the value of that key
+ * value pair will become an array. This function does not parse nested
+ * PHP style arrays into an associative array (e.g., foo[a]=1&foo[b]=2 will
+ * be parsed into ['foo[a]' => '1', 'foo[b]' => '2']).
+ *
+ * @param string $str Query string to parse
+ * @param bool|string $urlEncoding How the query string is encoded
+ *
+ * @return array
+ */
+function parse_query($str, $urlEncoding = true)
+{
+ $result = array();
+
+ if ($str === '') {
+ return $result;
+ }
+
+ if ($urlEncoding === true) {
+ $decoder = function ($value) {
+ return rawurldecode(str_replace('+', ' ', $value));
+ };
+ } elseif ($urlEncoding == PHP_QUERY_RFC3986) {
+ $decoder = 'rawurldecode';
+ } elseif ($urlEncoding == PHP_QUERY_RFC1738) {
+ $decoder = 'urldecode';
+ } else {
+ $decoder = function ($str) { return $str; };
+ }
+
+ foreach (explode('&', $str) as $kvp) {
+ $parts = explode('=', $kvp, 2);
+ $key = $decoder($parts[0]);
+ $value = isset($parts[1]) ? $decoder($parts[1]) : null;
+ if (!isset($result[$key])) {
+ $result[$key] = $value;
+ } else {
+ if (!is_array($result[$key])) {
+ $result[$key] = array($result[$key]);
+ }
+ $result[$key][] = $value;
+ }
+ }
+
+ return $result;
+}
+
+/**
+ * Build a query string from an array of key value pairs.
+ *
+ * This function can use the return value of parseQuery() to build a query
+ * string. This function does not modify the provided keys when an array is
+ * encountered (like http_build_query would).
+ *
+ * @param array $params Query string parameters.
+ * @param int|false $encoding Set to false to not encode, PHP_QUERY_RFC3986
+ * to encode using RFC3986, or PHP_QUERY_RFC1738
+ * to encode using RFC1738.
+ * @return string
+ */
+function build_query(array $params, $encoding = PHP_QUERY_RFC3986)
+{
+ if (!$params) {
+ return '';
+ }
+
+ if ($encoding === false) {
+ $encoder = function ($str) { return $str; };
+ } elseif ($encoding == PHP_QUERY_RFC3986) {
+ $encoder = 'rawurlencode';
+ } elseif ($encoding == PHP_QUERY_RFC1738) {
+ $encoder = 'urlencode';
+ } else {
+ throw new \InvalidArgumentException('Invalid type');
+ }
+
+ $qs = '';
+ foreach ($params as $k => $v) {
+ $k = $encoder($k);
+ if (!is_array($v)) {
+ $qs .= $k;
+ if ($v !== null) {
+ $qs .= '=' . $encoder($v);
+ }
+ $qs .= '&';
+ } else {
+ foreach ($v as $vv) {
+ $qs .= $k;
+ if ($vv !== null) {
+ $qs .= '=' . $encoder($vv);
+ }
+ $qs .= '&';
+ }
+ }
+ }
+
+ return $qs ? (string) substr($qs, 0, -1) : '';
+}
+
+/**
+ * Determines the mimetype of a file by looking at its extension.
+ *
+ * @param $filename
+ *
+ * @return null|string
+ */
+function mimetype_from_filename($filename)
+{
+ return mimetype_from_extension(pathinfo($filename, PATHINFO_EXTENSION));
+}
+
+/**
+ * Maps a file extensions to a mimetype.
+ *
+ * @param $extension string The file extension.
+ *
+ * @return string|null
+ * @link http://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x/conf/mime.types
+ */
+function mimetype_from_extension($extension)
+{
+ static $mimetypes = array(
+ '7z' => 'application/x-7z-compressed',
+ 'aac' => 'audio/x-aac',
+ 'ai' => 'application/postscript',
+ 'aif' => 'audio/x-aiff',
+ 'asc' => 'text/plain',
+ 'asf' => 'video/x-ms-asf',
+ 'atom' => 'application/atom+xml',
+ 'avi' => 'video/x-msvideo',
+ 'bmp' => 'image/bmp',
+ 'bz2' => 'application/x-bzip2',
+ 'cer' => 'application/pkix-cert',
+ 'crl' => 'application/pkix-crl',
+ 'crt' => 'application/x-x509-ca-cert',
+ 'css' => 'text/css',
+ 'csv' => 'text/csv',
+ 'cu' => 'application/cu-seeme',
+ 'deb' => 'application/x-debian-package',
+ 'doc' => 'application/msword',
+ 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ 'dvi' => 'application/x-dvi',
+ 'eot' => 'application/vnd.ms-fontobject',
+ 'eps' => 'application/postscript',
+ 'epub' => 'application/epub+zip',
+ 'etx' => 'text/x-setext',
+ 'flac' => 'audio/flac',
+ 'flv' => 'video/x-flv',
+ 'gif' => 'image/gif',
+ 'gz' => 'application/gzip',
+ 'htm' => 'text/html',
+ 'html' => 'text/html',
+ 'ico' => 'image/x-icon',
+ 'ics' => 'text/calendar',
+ 'ini' => 'text/plain',
+ 'iso' => 'application/x-iso9660-image',
+ 'jar' => 'application/java-archive',
+ 'jpe' => 'image/jpeg',
+ 'jpeg' => 'image/jpeg',
+ 'jpg' => 'image/jpeg',
+ 'js' => 'text/javascript',
+ 'json' => 'application/json',
+ 'latex' => 'application/x-latex',
+ 'log' => 'text/plain',
+ 'm4a' => 'audio/mp4',
+ 'm4v' => 'video/mp4',
+ 'mid' => 'audio/midi',
+ 'midi' => 'audio/midi',
+ 'mov' => 'video/quicktime',
+ 'mp3' => 'audio/mpeg',
+ 'mp4' => 'video/mp4',
+ 'mp4a' => 'audio/mp4',
+ 'mp4v' => 'video/mp4',
+ 'mpe' => 'video/mpeg',
+ 'mpeg' => 'video/mpeg',
+ 'mpg' => 'video/mpeg',
+ 'mpg4' => 'video/mp4',
+ 'oga' => 'audio/ogg',
+ 'ogg' => 'audio/ogg',
+ 'ogv' => 'video/ogg',
+ 'ogx' => 'application/ogg',
+ 'pbm' => 'image/x-portable-bitmap',
+ 'pdf' => 'application/pdf',
+ 'pgm' => 'image/x-portable-graymap',
+ 'png' => 'image/png',
+ 'pnm' => 'image/x-portable-anymap',
+ 'ppm' => 'image/x-portable-pixmap',
+ 'ppt' => 'application/vnd.ms-powerpoint',
+ 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+ 'ps' => 'application/postscript',
+ 'qt' => 'video/quicktime',
+ 'rar' => 'application/x-rar-compressed',
+ 'ras' => 'image/x-cmu-raster',
+ 'rss' => 'application/rss+xml',
+ 'rtf' => 'application/rtf',
+ 'sgm' => 'text/sgml',
+ 'sgml' => 'text/sgml',
+ 'svg' => 'image/svg+xml',
+ 'swf' => 'application/x-shockwave-flash',
+ 'tar' => 'application/x-tar',
+ 'tif' => 'image/tiff',
+ 'tiff' => 'image/tiff',
+ 'torrent' => 'application/x-bittorrent',
+ 'ttf' => 'application/x-font-ttf',
+ 'txt' => 'text/plain',
+ 'wav' => 'audio/x-wav',
+ 'webm' => 'video/webm',
+ 'wma' => 'audio/x-ms-wma',
+ 'wmv' => 'video/x-ms-wmv',
+ 'woff' => 'application/x-font-woff',
+ 'wsdl' => 'application/wsdl+xml',
+ 'xbm' => 'image/x-xbitmap',
+ 'xls' => 'application/vnd.ms-excel',
+ 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ 'xml' => 'application/xml',
+ 'xpm' => 'image/x-xpixmap',
+ 'xwd' => 'image/x-xwindowdump',
+ 'yaml' => 'text/yaml',
+ 'yml' => 'text/yaml',
+ 'zip' => 'application/zip',
+ );
+
+ $extension = strtolower($extension);
+
+ return isset($mimetypes[$extension])
+ ? $mimetypes[$extension]
+ : null;
+}
+
+/**
+ * Parses an HTTP message into an associative array.
+ *
+ * The array contains the "start-line" key containing the start line of
+ * the message, "headers" key containing an associative array of header
+ * array values, and a "body" key containing the body of the message.
+ *
+ * @param string $message HTTP request or response to parse.
+ *
+ * @return array
+ * @internal
+ */
+function _parse_message($message)
+{
+ if (!$message) {
+ throw new \InvalidArgumentException('Invalid message');
+ }
+
+ // Iterate over each line in the message, accounting for line endings
+ $lines = preg_split('/(\\r?\\n)/', $message, -1, PREG_SPLIT_DELIM_CAPTURE);
+ $result = array('start-line' => array_shift($lines), 'headers' => array(), 'body' => '');
+ array_shift($lines);
+
+ for ($i = 0, $totalLines = count($lines); $i < $totalLines; $i += 2) {
+ $line = $lines[$i];
+ // If two line breaks were encountered, then this is the end of body
+ if (empty($line)) {
+ if ($i < $totalLines - 1) {
+ $result['body'] = implode('', array_slice($lines, $i + 2));
+ }
+ break;
+ }
+ if (strpos($line, ':')) {
+ $parts = explode(':', $line, 2);
+ $key = trim($parts[0]);
+ $value = isset($parts[1]) ? trim($parts[1]) : '';
+ $result['headers'][$key][] = $value;
+ }
+ }
+
+ return $result;
+}
+
+/**
+ * Constructs a URI for an HTTP request message.
+ *
+ * @param string $path Path from the start-line
+ * @param array $headers Array of headers (each value an array).
+ *
+ * @return string
+ * @internal
+ */
+function _parse_request_uri($path, array $headers)
+{
+ $hostKey = array_filter(array_keys($headers), function ($k) {
+ return strtolower($k) === 'host';
+ });
+
+ // If no host is found, then a full URI cannot be constructed.
+ if (!$hostKey) {
+ return $path;
+ }
+
+ $host = $headers[reset($hostKey)][0];
+ $scheme = substr($host, -4) === ':443' ? 'https' : 'http';
+
+ return $scheme . '://' . $host . '/' . ltrim($path, '/');
+}
+
+/** @internal */
+function _caseless_remove($keys, array $data)
+{
+ $result = array();
+
+ foreach ($keys as &$key) {
+ $key = strtolower($key);
+ }
+
+ foreach ($data as $k => $v) {
+ if (!in_array(strtolower($k), $keys)) {
+ $result[$k] = $v;
+ }
+ }
+
+ return $result;
+}
diff --git a/vendor/ringcentral/psr7/src/functions_include.php b/vendor/ringcentral/psr7/src/functions_include.php
new file mode 100644
index 0000000..252e0cf
--- /dev/null
+++ b/vendor/ringcentral/psr7/src/functions_include.php
@@ -0,0 +1,6 @@
+<?php
+
+// Don't redefine the functions if included multiple times.
+if (!function_exists('RingCentral\Psr7\str')) {
+ require __DIR__ . '/functions.php';
+}
diff --git a/vendor/ringcentral/psr7/tests/AppendStreamTest.php b/vendor/ringcentral/psr7/tests/AppendStreamTest.php
new file mode 100644
index 0000000..ac8bb90
--- /dev/null
+++ b/vendor/ringcentral/psr7/tests/AppendStreamTest.php
@@ -0,0 +1,186 @@
+<?php
+namespace RingCentral\Tests\Psr7;
+
+use RingCentral\Psr7\AppendStream;
+use RingCentral\Psr7;
+
+class AppendStreamTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Each stream must be readable
+ */
+ public function testValidatesStreamsAreReadable()
+ {
+ $a = new AppendStream();
+ $s = $this->getMockBuilder('Psr\Http\Message\StreamInterface')
+ ->setMethods(array('isReadable'))
+ ->getMockForAbstractClass();
+ $s->expects($this->once())
+ ->method('isReadable')
+ ->will($this->returnValue(false));
+ $a->addStream($s);
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage The AppendStream can only seek with SEEK_SET
+ */
+ public function testValidatesSeekType()
+ {
+ $a = new AppendStream();
+ $a->seek(100, SEEK_CUR);
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage Unable to seek stream 0 of the AppendStream
+ */
+ public function testTriesToRewindOnSeek()
+ {
+ $a = new AppendStream();
+ $s = $this->getMockBuilder('Psr\Http\Message\StreamInterface')
+ ->setMethods(array('isReadable', 'rewind', 'isSeekable'))
+ ->getMockForAbstractClass();
+ $s->expects($this->once())
+ ->method('isReadable')
+ ->will($this->returnValue(true));
+ $s->expects($this->once())
+ ->method('isSeekable')
+ ->will($this->returnValue(true));
+ $s->expects($this->once())
+ ->method('rewind')
+ ->will($this->throwException(new \RuntimeException()));
+ $a->addStream($s);
+ $a->seek(10);
+ }
+
+ public function testSeeksToPositionByReading()
+ {
+ $a = new AppendStream(array(
+ Psr7\stream_for('foo'),
+ Psr7\stream_for('bar'),
+ Psr7\stream_for('baz'),
+ ));
+
+ $a->seek(3);
+ $this->assertEquals(3, $a->tell());
+ $this->assertEquals('bar', $a->read(3));
+
+ $a->seek(6);
+ $this->assertEquals(6, $a->tell());
+ $this->assertEquals('baz', $a->read(3));
+ }
+
+ public function testDetachesEachStream()
+ {
+ $s1 = Psr7\stream_for('foo');
+ $s2 = Psr7\stream_for('bar');
+ $a = new AppendStream(array($s1, $s2));
+ $this->assertSame('foobar', (string) $a);
+ $a->detach();
+ $this->assertSame('', (string) $a);
+ $this->assertSame(0, $a->getSize());
+ }
+
+ public function testClosesEachStream()
+ {
+ $s1 = Psr7\stream_for('foo');
+ $a = new AppendStream(array($s1));
+ $a->close();
+ $this->assertSame('', (string) $a);
+ }
+
+ /**
+ * @expectedExceptionMessage Cannot write to an AppendStream
+ * @expectedException \RuntimeException
+ */
+ public function testIsNotWritable()
+ {
+ $a = new AppendStream(array(Psr7\stream_for('foo')));
+ $this->assertFalse($a->isWritable());
+ $this->assertTrue($a->isSeekable());
+ $this->assertTrue($a->isReadable());
+ $a->write('foo');
+ }
+
+ public function testDoesNotNeedStreams()
+ {
+ $a = new AppendStream();
+ $this->assertEquals('', (string) $a);
+ }
+
+ public function testCanReadFromMultipleStreams()
+ {
+ $a = new AppendStream(array(
+ Psr7\stream_for('foo'),
+ Psr7\stream_for('bar'),
+ Psr7\stream_for('baz'),
+ ));
+ $this->assertFalse($a->eof());
+ $this->assertSame(0, $a->tell());
+ $this->assertEquals('foo', $a->read(3));
+ $this->assertEquals('bar', $a->read(3));
+ $this->assertEquals('baz', $a->read(3));
+ $this->assertSame('', $a->read(1));
+ $this->assertTrue($a->eof());
+ $this->assertSame(9, $a->tell());
+ $this->assertEquals('foobarbaz', (string) $a);
+ }
+
+ public function testCanDetermineSizeFromMultipleStreams()
+ {
+ $a = new AppendStream(array(
+ Psr7\stream_for('foo'),
+ Psr7\stream_for('bar')
+ ));
+ $this->assertEquals(6, $a->getSize());
+
+ $s = $this->getMockBuilder('Psr\Http\Message\StreamInterface')
+ ->setMethods(array('isSeekable', 'isReadable'))
+ ->getMockForAbstractClass();
+ $s->expects($this->once())
+ ->method('isSeekable')
+ ->will($this->returnValue(null));
+ $s->expects($this->once())
+ ->method('isReadable')
+ ->will($this->returnValue(true));
+ $a->addStream($s);
+ $this->assertNull($a->getSize());
+ }
+
+ public function testCatchesExceptionsWhenCastingToString()
+ {
+ $s = $this->getMockBuilder('Psr\Http\Message\StreamInterface')
+ ->setMethods(array('isSeekable', 'read', 'isReadable', 'eof'))
+ ->getMockForAbstractClass();
+ $s->expects($this->once())
+ ->method('isSeekable')
+ ->will($this->returnValue(true));
+ $s->expects($this->once())
+ ->method('read')
+ ->will($this->throwException(new \RuntimeException('foo')));
+ $s->expects($this->once())
+ ->method('isReadable')
+ ->will($this->returnValue(true));
+ $s->expects($this->any())
+ ->method('eof')
+ ->will($this->returnValue(false));
+ $a = new AppendStream(array($s));
+ $this->assertFalse($a->eof());
+ $this->assertSame('', (string) $a);
+ }
+
+ public function testCanDetach()
+ {
+ $s = new AppendStream();
+ $s->detach();
+ }
+
+ public function testReturnsEmptyMetadata()
+ {
+ $s = new AppendStream();
+ $this->assertEquals(array(), $s->getMetadata());
+ $this->assertNull($s->getMetadata('foo'));
+ }
+}
diff --git a/vendor/ringcentral/psr7/tests/BufferStreamTest.php b/vendor/ringcentral/psr7/tests/BufferStreamTest.php
new file mode 100644
index 0000000..79f907a
--- /dev/null
+++ b/vendor/ringcentral/psr7/tests/BufferStreamTest.php
@@ -0,0 +1,63 @@
+<?php
+namespace RingCentral\Tests\Psr7;
+
+use RingCentral\Psr7\BufferStream;
+
+class BufferStreamTest extends \PHPUnit_Framework_TestCase
+{
+ public function testHasMetadata()
+ {
+ $b = new BufferStream(10);
+ $this->assertTrue($b->isReadable());
+ $this->assertTrue($b->isWritable());
+ $this->assertFalse($b->isSeekable());
+ $this->assertEquals(null, $b->getMetadata('foo'));
+ $this->assertEquals(10, $b->getMetadata('hwm'));
+ $this->assertEquals(array(), $b->getMetadata());
+ }
+
+ public function testRemovesReadDataFromBuffer()
+ {
+ $b = new BufferStream();
+ $this->assertEquals(3, $b->write('foo'));
+ $this->assertEquals(3, $b->getSize());
+ $this->assertFalse($b->eof());
+ $this->assertEquals('foo', $b->read(10));
+ $this->assertTrue($b->eof());
+ $this->assertEquals('', $b->read(10));
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage Cannot determine the position of a BufferStream
+ */
+ public function testCanCastToStringOrGetContents()
+ {
+ $b = new BufferStream();
+ $b->write('foo');
+ $b->write('baz');
+ $this->assertEquals('foo', $b->read(3));
+ $b->write('bar');
+ $this->assertEquals('bazbar', (string) $b);
+ $b->tell();
+ }
+
+ public function testDetachClearsBuffer()
+ {
+ $b = new BufferStream();
+ $b->write('foo');
+ $b->detach();
+ $this->assertTrue($b->eof());
+ $this->assertEquals(3, $b->write('abc'));
+ $this->assertEquals('abc', $b->read(10));
+ }
+
+ public function testExceedingHighwaterMarkReturnsFalseButStillBuffers()
+ {
+ $b = new BufferStream(5);
+ $this->assertEquals(3, $b->write('hi '));
+ $this->assertFalse($b->write('hello'));
+ $this->assertEquals('hi hello', (string) $b);
+ $this->assertEquals(4, $b->write('test'));
+ }
+}
diff --git a/vendor/ringcentral/psr7/tests/CachingStreamTest.php b/vendor/ringcentral/psr7/tests/CachingStreamTest.php
new file mode 100644
index 0000000..f394fc9
--- /dev/null
+++ b/vendor/ringcentral/psr7/tests/CachingStreamTest.php
@@ -0,0 +1,166 @@
+<?php
+namespace RingCentral\Tests\Psr7;
+
+use RingCentral\Psr7;
+use RingCentral\Psr7\CachingStream;
+
+/**
+ * @covers RingCentral\Psr7\CachingStream
+ */
+class CachingStreamTest extends \PHPUnit_Framework_TestCase
+{
+ /** @var CachingStream */
+ protected $body;
+ protected $decorated;
+
+ public function setUp()
+ {
+ $this->decorated = Psr7\stream_for('testing');
+ $this->body = new CachingStream($this->decorated);
+ }
+
+ public function tearDown()
+ {
+ $this->decorated->close();
+ $this->body->close();
+ }
+
+ public function testUsesRemoteSizeIfPossible()
+ {
+ $body = Psr7\stream_for('test');
+ $caching = new CachingStream($body);
+ $this->assertEquals(4, $caching->getSize());
+ }
+
+ public function testReadsUntilCachedToByte()
+ {
+ $this->body->seek(5);
+ $this->assertEquals('n', $this->body->read(1));
+ $this->body->seek(0);
+ $this->assertEquals('t', $this->body->read(1));
+ }
+
+ public function testCanSeekNearEndWithSeekEnd()
+ {
+ $baseStream = Psr7\stream_for(implode('', range('a', 'z')));
+ $cached = new CachingStream($baseStream);
+ $cached->seek(1, SEEK_END);
+ $this->assertEquals(24, $baseStream->tell());
+ $this->assertEquals('y', $cached->read(1));
+ $this->assertEquals(26, $cached->getSize());
+ }
+
+ public function testCanSeekToEndWithSeekEnd()
+ {
+ $baseStream = Psr7\stream_for(implode('', range('a', 'z')));
+ $cached = new CachingStream($baseStream);
+ $cached->seek(0, SEEK_END);
+ $this->assertEquals(25, $baseStream->tell());
+ $this->assertEquals('z', $cached->read(1));
+ $this->assertEquals(26, $cached->getSize());
+ }
+
+ public function testCanUseSeekEndWithUnknownSize()
+ {
+ $baseStream = Psr7\stream_for('testing');
+ $decorated = Psr7\FnStream::decorate($baseStream, array(
+ 'getSize' => function () { return null; }
+ ));
+ $cached = new CachingStream($decorated);
+ $cached->seek(1, SEEK_END);
+ $this->assertEquals('ng', $cached->read(2));
+ }
+
+ public function testRewindUsesSeek()
+ {
+ $a = Psr7\stream_for('foo');
+ $d = $this->getMockBuilder('RingCentral\Psr7\CachingStream')
+ ->setMethods(array('seek'))
+ ->setConstructorArgs(array($a))
+ ->getMock();
+ $d->expects($this->once())
+ ->method('seek')
+ ->with(0)
+ ->will($this->returnValue(true));
+ $d->seek(0);
+ }
+
+ public function testCanSeekToReadBytes()
+ {
+ $this->assertEquals('te', $this->body->read(2));
+ $this->body->seek(0);
+ $this->assertEquals('test', $this->body->read(4));
+ $this->assertEquals(4, $this->body->tell());
+ $this->body->seek(2);
+ $this->assertEquals(2, $this->body->tell());
+ $this->body->seek(2, SEEK_CUR);
+ $this->assertEquals(4, $this->body->tell());
+ $this->assertEquals('ing', $this->body->read(3));
+ }
+
+ public function testWritesToBufferStream()
+ {
+ $this->body->read(2);
+ $this->body->write('hi');
+ $this->body->seek(0);
+ $this->assertEquals('tehiing', (string) $this->body);
+ }
+
+ public function testSkipsOverwrittenBytes()
+ {
+ $decorated = Psr7\stream_for(
+ implode("\n", array_map(function ($n) {
+ return str_pad($n, 4, '0', STR_PAD_LEFT);
+ }, range(0, 25)))
+ );
+
+ $body = new CachingStream($decorated);
+
+ $this->assertEquals("0000\n", Psr7\readline($body));
+ $this->assertEquals("0001\n", Psr7\readline($body));
+ // Write over part of the body yet to be read, so skip some bytes
+ $this->assertEquals(5, $body->write("TEST\n"));
+ $this->assertEquals(5, $this->readAttribute($body, 'skipReadBytes'));
+ // Read, which skips bytes, then reads
+ $this->assertEquals("0003\n", Psr7\readline($body));
+ $this->assertEquals(0, $this->readAttribute($body, 'skipReadBytes'));
+ $this->assertEquals("0004\n", Psr7\readline($body));
+ $this->assertEquals("0005\n", Psr7\readline($body));
+
+ // Overwrite part of the cached body (so don't skip any bytes)
+ $body->seek(5);
+ $this->assertEquals(5, $body->write("ABCD\n"));
+ $this->assertEquals(0, $this->readAttribute($body, 'skipReadBytes'));
+ $this->assertEquals("TEST\n", Psr7\readline($body));
+ $this->assertEquals("0003\n", Psr7\readline($body));
+ $this->assertEquals("0004\n", Psr7\readline($body));
+ $this->assertEquals("0005\n", Psr7\readline($body));
+ $this->assertEquals("0006\n", Psr7\readline($body));
+ $this->assertEquals(5, $body->write("1234\n"));
+ $this->assertEquals(5, $this->readAttribute($body, 'skipReadBytes'));
+
+ // Seek to 0 and ensure the overwritten bit is replaced
+ $body->seek(0);
+ $this->assertEquals("0000\nABCD\nTEST\n0003\n0004\n0005\n0006\n1234\n0008\n0009\n", $body->read(50));
+
+ // Ensure that casting it to a string does not include the bit that was overwritten
+ $this->assertContains("0000\nABCD\nTEST\n0003\n0004\n0005\n0006\n1234\n0008\n0009\n", (string) $body);
+ }
+
+ public function testClosesBothStreams()
+ {
+ $s = fopen('php://temp', 'r');
+ $a = Psr7\stream_for($s);
+ $d = new CachingStream($a);
+ $d->close();
+ $this->assertFalse(is_resource($s));
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testEnsuresValidWhence()
+ {
+ $this->body->seek(10, -123456);
+ }
+}
diff --git a/vendor/ringcentral/psr7/tests/DroppingStreamTest.php b/vendor/ringcentral/psr7/tests/DroppingStreamTest.php
new file mode 100644
index 0000000..1ae9443
--- /dev/null
+++ b/vendor/ringcentral/psr7/tests/DroppingStreamTest.php
@@ -0,0 +1,26 @@
+<?php
+namespace RingCentral\Tests\Psr7;
+
+use RingCentral\Psr7\BufferStream;
+use RingCentral\Psr7\DroppingStream;
+
+class DroppingStreamTest extends \PHPUnit_Framework_TestCase
+{
+ public function testBeginsDroppingWhenSizeExceeded()
+ {
+ $stream = new BufferStream();
+ $drop = new DroppingStream($stream, 5);
+ $this->assertEquals(3, $drop->write('hel'));
+ $this->assertEquals(2, $drop->write('lo'));
+ $this->assertEquals(5, $drop->getSize());
+ $this->assertEquals('hello', $drop->read(5));
+ $this->assertEquals(0, $drop->getSize());
+ $drop->write('12345678910');
+ $this->assertEquals(5, $stream->getSize());
+ $this->assertEquals(5, $drop->getSize());
+ $this->assertEquals('12345', (string) $drop);
+ $this->assertEquals(0, $drop->getSize());
+ $drop->write('hello');
+ $this->assertSame(0, $drop->write('test'));
+ }
+}
diff --git a/vendor/ringcentral/psr7/tests/FnStreamTest.php b/vendor/ringcentral/psr7/tests/FnStreamTest.php
new file mode 100644
index 0000000..def436c
--- /dev/null
+++ b/vendor/ringcentral/psr7/tests/FnStreamTest.php
@@ -0,0 +1,92 @@
+<?php
+namespace RingCentral\Tests\Psr7;
+
+use RingCentral\Psr7;
+use RingCentral\Psr7\FnStream;
+
+/**
+ * @covers RingCentral\Psr7\FnStream
+ */
+class FnStreamTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException \BadMethodCallException
+ * @expectedExceptionMessage seek() is not implemented in the FnStream
+ */
+ public function testThrowsWhenNotImplemented()
+ {
+ $stream = new FnStream(array());
+ $stream->seek(1);
+ }
+
+ public function testProxiesToFunction()
+ {
+ $self = $this;
+ $s = new FnStream(array(
+ 'read' => function ($len) use ($self) {
+ $self->assertEquals(3, $len);
+ return 'foo';
+ }
+ ));
+
+ $this->assertEquals('foo', $s->read(3));
+ }
+
+ public function testCanCloseOnDestruct()
+ {
+ $called = false;
+ $s = new FnStream(array(
+ 'close' => function () use (&$called) {
+ $called = true;
+ }
+ ));
+ unset($s);
+ $this->assertTrue($called);
+ }
+
+ public function testDoesNotRequireClose()
+ {
+ $s = new FnStream(array());
+ unset($s);
+ }
+
+ public function testDecoratesStream()
+ {
+ $a = Psr7\stream_for('foo');
+ $b = FnStream::decorate($a, array());
+ $this->assertEquals(3, $b->getSize());
+ $this->assertEquals($b->isWritable(), true);
+ $this->assertEquals($b->isReadable(), true);
+ $this->assertEquals($b->isSeekable(), true);
+ $this->assertEquals($b->read(3), 'foo');
+ $this->assertEquals($b->tell(), 3);
+ $this->assertEquals($a->tell(), 3);
+ $this->assertSame('', $a->read(1));
+ $this->assertEquals($b->eof(), true);
+ $this->assertEquals($a->eof(), true);
+ $b->seek(0);
+ $this->assertEquals('foo', (string) $b);
+ $b->seek(0);
+ $this->assertEquals('foo', $b->getContents());
+ $this->assertEquals($a->getMetadata(), $b->getMetadata());
+ $b->seek(0, SEEK_END);
+ $b->write('bar');
+ $this->assertEquals('foobar', (string) $b);
+ $this->assertInternalType('resource', $b->detach());
+ $b->close();
+ }
+
+ public function testDecoratesWithCustomizations()
+ {
+ $called = false;
+ $a = Psr7\stream_for('foo');
+ $b = FnStream::decorate($a, array(
+ 'read' => function ($len) use (&$called, $a) {
+ $called = true;
+ return $a->read($len);
+ }
+ ));
+ $this->assertEquals('foo', $b->read(3));
+ $this->assertTrue($called);
+ }
+}
diff --git a/vendor/ringcentral/psr7/tests/FunctionsTest.php b/vendor/ringcentral/psr7/tests/FunctionsTest.php
new file mode 100644
index 0000000..032fc56
--- /dev/null
+++ b/vendor/ringcentral/psr7/tests/FunctionsTest.php
@@ -0,0 +1,604 @@
+<?php
+namespace RingCentral\Tests\Psr7;
+
+use RingCentral\Psr7;
+use RingCentral\Psr7\FnStream;
+use RingCentral\Psr7\NoSeekStream;
+
+class FunctionsTest extends \PHPUnit_Framework_TestCase
+{
+ public function testCopiesToString()
+ {
+ $s = Psr7\stream_for('foobaz');
+ $this->assertEquals('foobaz', Psr7\copy_to_string($s));
+ $s->seek(0);
+ $this->assertEquals('foo', Psr7\copy_to_string($s, 3));
+ $this->assertEquals('baz', Psr7\copy_to_string($s, 3));
+ $this->assertEquals('', Psr7\copy_to_string($s));
+ }
+
+ public function testCopiesToStringStopsWhenReadFails()
+ {
+ $s1 = Psr7\stream_for('foobaz');
+ $s1 = FnStream::decorate($s1, array(
+ 'read' => function () { return ''; }
+ ));
+ $result = Psr7\copy_to_string($s1);
+ $this->assertEquals('', $result);
+ }
+
+ public function testCopiesToStream()
+ {
+ $s1 = Psr7\stream_for('foobaz');
+ $s2 = Psr7\stream_for('');
+ Psr7\copy_to_stream($s1, $s2);
+ $this->assertEquals('foobaz', (string) $s2);
+ $s2 = Psr7\stream_for('');
+ $s1->seek(0);
+ Psr7\copy_to_stream($s1, $s2, 3);
+ $this->assertEquals('foo', (string) $s2);
+ Psr7\copy_to_stream($s1, $s2, 3);
+ $this->assertEquals('foobaz', (string) $s2);
+ }
+
+ public function testStopsCopyToStreamWhenWriteFails()
+ {
+ $s1 = Psr7\stream_for('foobaz');
+ $s2 = Psr7\stream_for('');
+ $s2 = FnStream::decorate($s2, array('write' => function () { return 0; }));
+ Psr7\copy_to_stream($s1, $s2);
+ $this->assertEquals('', (string) $s2);
+ }
+
+ public function testStopsCopyToSteamWhenWriteFailsWithMaxLen()
+ {
+ $s1 = Psr7\stream_for('foobaz');
+ $s2 = Psr7\stream_for('');
+ $s2 = FnStream::decorate($s2, array('write' => function () { return 0; }));
+ Psr7\copy_to_stream($s1, $s2, 10);
+ $this->assertEquals('', (string) $s2);
+ }
+
+ public function testStopsCopyToSteamWhenReadFailsWithMaxLen()
+ {
+ $s1 = Psr7\stream_for('foobaz');
+ $s1 = FnStream::decorate($s1, array('read' => function () { return ''; }));
+ $s2 = Psr7\stream_for('');
+ Psr7\copy_to_stream($s1, $s2, 10);
+ $this->assertEquals('', (string) $s2);
+ }
+
+ public function testReadsLines()
+ {
+ $s = Psr7\stream_for("foo\nbaz\nbar");
+ $this->assertEquals("foo\n", Psr7\readline($s));
+ $this->assertEquals("baz\n", Psr7\readline($s));
+ $this->assertEquals("bar", Psr7\readline($s));
+ }
+
+ public function testReadsLinesUpToMaxLength()
+ {
+ $s = Psr7\stream_for("12345\n");
+ $this->assertEquals("123", Psr7\readline($s, 4));
+ $this->assertEquals("45\n", Psr7\readline($s));
+ }
+
+ public function testReadsLineUntilFalseReturnedFromRead()
+ {
+ $s = $this->getMockBuilder('RingCentral\Psr7\Stream')
+ ->setMethods(array('read', 'eof'))
+ ->disableOriginalConstructor()
+ ->getMock();
+ $s->expects($this->exactly(2))
+ ->method('read')
+ ->will($this->returnCallback(function () {
+ static $c = false;
+ if ($c) {
+ return false;
+ }
+ $c = true;
+ return 'h';
+ }));
+ $s->expects($this->exactly(2))
+ ->method('eof')
+ ->will($this->returnValue(false));
+ $this->assertEquals("h", Psr7\readline($s));
+ }
+
+ public function testCalculatesHash()
+ {
+ $s = Psr7\stream_for('foobazbar');
+ $this->assertEquals(md5('foobazbar'), Psr7\hash($s, 'md5'));
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testCalculatesHashThrowsWhenSeekFails()
+ {
+ $s = new NoSeekStream(Psr7\stream_for('foobazbar'));
+ $s->read(2);
+ Psr7\hash($s, 'md5');
+ }
+
+ public function testCalculatesHashSeeksToOriginalPosition()
+ {
+ $s = Psr7\stream_for('foobazbar');
+ $s->seek(4);
+ $this->assertEquals(md5('foobazbar'), Psr7\hash($s, 'md5'));
+ $this->assertEquals(4, $s->tell());
+ }
+
+ public function testOpensFilesSuccessfully()
+ {
+ $r = Psr7\try_fopen(__FILE__, 'r');
+ $this->assertInternalType('resource', $r);
+ fclose($r);
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage Unable to open /path/to/does/not/exist using mode r
+ */
+ public function testThrowsExceptionNotWarning()
+ {
+ Psr7\try_fopen('/path/to/does/not/exist', 'r');
+ }
+
+ public function parseQueryProvider()
+ {
+ return array(
+ // Does not need to parse when the string is empty
+ array('', array()),
+ // Can parse mult-values items
+ array('q=a&q=b', array('q' => array('a', 'b'))),
+ // Can parse multi-valued items that use numeric indices
+ array('q[0]=a&q[1]=b', array('q[0]' => 'a', 'q[1]' => 'b')),
+ // Can parse duplicates and does not include numeric indices
+ array('q[]=a&q[]=b', array('q[]' => array('a', 'b'))),
+ // Ensures that the value of "q" is an array even though one value
+ array('q[]=a', array('q[]' => 'a')),
+ // Does not modify "." to "_" like PHP's parse_str()
+ array('q.a=a&q.b=b', array('q.a' => 'a', 'q.b' => 'b')),
+ // Can decode %20 to " "
+ array('q%20a=a%20b', array('q a' => 'a b')),
+ // Can parse funky strings with no values by assigning each to null
+ array('q&a', array('q' => null, 'a' => null)),
+ // Does not strip trailing equal signs
+ array('data=abc=', array('data' => 'abc=')),
+ // Can store duplicates without affecting other values
+ array('foo=a&foo=b&?µ=c', array('foo' => array('a', 'b'), '?µ' => 'c')),
+ // Sets value to null when no "=" is present
+ array('foo', array('foo' => null)),
+ // Preserves "0" keys.
+ array('0', array('0' => null)),
+ // Sets the value to an empty string when "=" is present
+ array('0=', array('0' => '')),
+ // Preserves falsey keys
+ array('var=0', array('var' => '0')),
+ array('a[b][c]=1&a[b][c]=2', array('a[b][c]' => array('1', '2'))),
+ array('a[b]=c&a[d]=e', array('a[b]' => 'c', 'a[d]' => 'e')),
+ // Ensure it doesn't leave things behind with repeated values
+ // Can parse mult-values items
+ array('q=a&q=b&q=c', array('q' => array('a', 'b', 'c'))),
+ );
+ }
+
+ /**
+ * @dataProvider parseQueryProvider
+ */
+ public function testParsesQueries($input, $output)
+ {
+ $result = Psr7\parse_query($input);
+ $this->assertSame($output, $result);
+ }
+
+ public function testDoesNotDecode()
+ {
+ $str = 'foo%20=bar';
+ $data = Psr7\parse_query($str, false);
+ $this->assertEquals(array('foo%20' => 'bar'), $data);
+ }
+
+ /**
+ * @dataProvider parseQueryProvider
+ */
+ public function testParsesAndBuildsQueries($input, $output)
+ {
+ $result = Psr7\parse_query($input, false);
+ $this->assertSame($input, Psr7\build_query($result, false));
+ }
+
+ public function testEncodesWithRfc1738()
+ {
+ $str = Psr7\build_query(array('foo bar' => 'baz+'), PHP_QUERY_RFC1738);
+ $this->assertEquals('foo+bar=baz%2B', $str);
+ }
+
+ public function testEncodesWithRfc3986()
+ {
+ $str = Psr7\build_query(array('foo bar' => 'baz+'), PHP_QUERY_RFC3986);
+ $this->assertEquals('foo%20bar=baz%2B', $str);
+ }
+
+ public function testDoesNotEncode()
+ {
+ $str = Psr7\build_query(array('foo bar' => 'baz+'), false);
+ $this->assertEquals('foo bar=baz+', $str);
+ }
+
+ public function testCanControlDecodingType()
+ {
+ $result = Psr7\parse_query('var=foo+bar', PHP_QUERY_RFC3986);
+ $this->assertEquals('foo+bar', $result['var']);
+ $result = Psr7\parse_query('var=foo+bar', PHP_QUERY_RFC1738);
+ $this->assertEquals('foo bar', $result['var']);
+ }
+
+ public function testParsesRequestMessages()
+ {
+ $req = "GET /abc HTTP/1.0\r\nHost: foo.com\r\nFoo: Bar\r\nBaz: Bam\r\nBaz: Qux\r\n\r\nTest";
+ $request = Psr7\parse_request($req);
+ $this->assertEquals('GET', $request->getMethod());
+ $this->assertEquals('/abc', $request->getRequestTarget());
+ $this->assertEquals('1.0', $request->getProtocolVersion());
+ $this->assertEquals('foo.com', $request->getHeaderLine('Host'));
+ $this->assertEquals('Bar', $request->getHeaderLine('Foo'));
+ $this->assertEquals('Bam, Qux', $request->getHeaderLine('Baz'));
+ $this->assertEquals('Test', (string) $request->getBody());
+ $this->assertEquals('http://foo.com/abc', (string) $request->getUri());
+ }
+
+ public function testParsesRequestMessagesWithHttpsScheme()
+ {
+ $req = "PUT /abc?baz=bar HTTP/1.1\r\nHost: foo.com:443\r\n\r\n";
+ $request = Psr7\parse_request($req);
+ $this->assertEquals('PUT', $request->getMethod());
+ $this->assertEquals('/abc?baz=bar', $request->getRequestTarget());
+ $this->assertEquals('1.1', $request->getProtocolVersion());
+ $this->assertEquals('foo.com:443', $request->getHeaderLine('Host'));
+ $this->assertEquals('', (string) $request->getBody());
+ $this->assertEquals('https://foo.com/abc?baz=bar', (string) $request->getUri());
+ }
+
+ public function testParsesRequestMessagesWithUriWhenHostIsNotFirst()
+ {
+ $req = "PUT / HTTP/1.1\r\nFoo: Bar\r\nHost: foo.com\r\n\r\n";
+ $request = Psr7\parse_request($req);
+ $this->assertEquals('PUT', $request->getMethod());
+ $this->assertEquals('/', $request->getRequestTarget());
+ $this->assertEquals('http://foo.com/', (string) $request->getUri());
+ }
+
+ public function testParsesRequestMessagesWithFullUri()
+ {
+ $req = "GET https://www.google.com:443/search?q=foobar HTTP/1.1\r\nHost: www.google.com\r\n\r\n";
+ $request = Psr7\parse_request($req);
+ $this->assertEquals('GET', $request->getMethod());
+ $this->assertEquals('https://www.google.com:443/search?q=foobar', $request->getRequestTarget());
+ $this->assertEquals('1.1', $request->getProtocolVersion());
+ $this->assertEquals('www.google.com', $request->getHeaderLine('Host'));
+ $this->assertEquals('', (string) $request->getBody());
+ $this->assertEquals('https://www.google.com/search?q=foobar', (string) $request->getUri());
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testValidatesRequestMessages()
+ {
+ Psr7\parse_request("HTTP/1.1 200 OK\r\n\r\n");
+ }
+
+ public function testParsesResponseMessages()
+ {
+ $res = "HTTP/1.0 200 OK\r\nFoo: Bar\r\nBaz: Bam\r\nBaz: Qux\r\n\r\nTest";
+ $response = Psr7\parse_response($res);
+ $this->assertEquals(200, $response->getStatusCode());
+ $this->assertEquals('OK', $response->getReasonPhrase());
+ $this->assertEquals('1.0', $response->getProtocolVersion());
+ $this->assertEquals('Bar', $response->getHeaderLine('Foo'));
+ $this->assertEquals('Bam, Qux', $response->getHeaderLine('Baz'));
+ $this->assertEquals('Test', (string) $response->getBody());
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testValidatesResponseMessages()
+ {
+ Psr7\parse_response("GET / HTTP/1.1\r\n\r\n");
+ }
+
+ public function testDetermineMimetype()
+ {
+ $this->assertNull(Psr7\mimetype_from_extension('not-a-real-extension'));
+ $this->assertEquals(
+ 'application/json',
+ Psr7\mimetype_from_extension('json')
+ );
+ $this->assertEquals(
+ 'image/jpeg',
+ Psr7\mimetype_from_filename('/tmp/images/IMG034821.JPEG')
+ );
+ }
+
+ public function testCreatesUriForValue()
+ {
+ $this->assertInstanceOf('RingCentral\Psr7\Uri', Psr7\uri_for('/foo'));
+ $this->assertInstanceOf(
+ 'RingCentral\Psr7\Uri',
+ Psr7\uri_for(new Psr7\Uri('/foo'))
+ );
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testValidatesUri()
+ {
+ Psr7\uri_for(array());
+ }
+
+ public function testKeepsPositionOfResource()
+ {
+ $h = fopen(__FILE__, 'r');
+ fseek($h, 10);
+ $stream = Psr7\stream_for($h);
+ $this->assertEquals(10, $stream->tell());
+ $stream->close();
+ }
+
+ public function testCreatesWithFactory()
+ {
+ $stream = Psr7\stream_for('foo');
+ $this->assertInstanceOf('RingCentral\Psr7\Stream', $stream);
+ $this->assertEquals('foo', $stream->getContents());
+ $stream->close();
+ }
+
+ public function testFactoryCreatesFromEmptyString()
+ {
+ $s = Psr7\stream_for();
+ $this->assertInstanceOf('RingCentral\Psr7\Stream', $s);
+ }
+
+ public function testFactoryCreatesFromNull()
+ {
+ $s = Psr7\stream_for(null);
+ $this->assertInstanceOf('RingCentral\Psr7\Stream', $s);
+ }
+
+ public function testFactoryCreatesFromResource()
+ {
+ $r = fopen(__FILE__, 'r');
+ $s = Psr7\stream_for($r);
+ $this->assertInstanceOf('RingCentral\Psr7\Stream', $s);
+ $this->assertSame(file_get_contents(__FILE__), (string) $s);
+ }
+
+ public function testFactoryCreatesFromObjectWithToString()
+ {
+ $r = new HasToString();
+ $s = Psr7\stream_for($r);
+ $this->assertInstanceOf('RingCentral\Psr7\Stream', $s);
+ $this->assertEquals('foo', (string) $s);
+ }
+
+ public function testCreatePassesThrough()
+ {
+ $s = Psr7\stream_for('foo');
+ $this->assertSame($s, Psr7\stream_for($s));
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testThrowsExceptionForUnknown()
+ {
+ Psr7\stream_for(new \stdClass());
+ }
+
+ public function testReturnsCustomMetadata()
+ {
+ $s = Psr7\stream_for('foo', array('metadata' => array('hwm' => 3)));
+ $this->assertEquals(3, $s->getMetadata('hwm'));
+ $this->assertArrayHasKey('hwm', $s->getMetadata());
+ }
+
+ public function testCanSetSize()
+ {
+ $s = Psr7\stream_for('', array('size' => 10));
+ $this->assertEquals(10, $s->getSize());
+ }
+
+ public function testCanCreateIteratorBasedStream()
+ {
+ $a = new \ArrayIterator(array('foo', 'bar', '123'));
+ $p = Psr7\stream_for($a);
+ $this->assertInstanceOf('RingCentral\Psr7\PumpStream', $p);
+ $this->assertEquals('foo', $p->read(3));
+ $this->assertFalse($p->eof());
+ $this->assertEquals('b', $p->read(1));
+ $this->assertEquals('a', $p->read(1));
+ $this->assertEquals('r12', $p->read(3));
+ $this->assertFalse($p->eof());
+ $this->assertEquals('3', $p->getContents());
+ $this->assertTrue($p->eof());
+ $this->assertEquals(9, $p->tell());
+ }
+
+ public function testConvertsRequestsToStrings()
+ {
+ $request = new Psr7\Request('PUT', 'http://foo.com/hi?123', array(
+ 'Baz' => 'bar',
+ 'Qux' => ' ipsum'
+ ), 'hello', '1.0');
+ $this->assertEquals(
+ "PUT /hi?123 HTTP/1.0\r\nHost: foo.com\r\nBaz: bar\r\nQux: ipsum\r\n\r\nhello",
+ Psr7\str($request)
+ );
+ }
+
+ public function testConvertsResponsesToStrings()
+ {
+ $response = new Psr7\Response(200, array(
+ 'Baz' => 'bar',
+ 'Qux' => ' ipsum'
+ ), 'hello', '1.0', 'FOO');
+ $this->assertEquals(
+ "HTTP/1.0 200 FOO\r\nBaz: bar\r\nQux: ipsum\r\n\r\nhello",
+ Psr7\str($response)
+ );
+ }
+
+ public function parseParamsProvider()
+ {
+ $res1 = array(
+ array(
+ '<http:/.../front.jpeg>',
+ 'rel' => 'front',
+ 'type' => 'image/jpeg',
+ ),
+ array(
+ '<http://.../back.jpeg>',
+ 'rel' => 'back',
+ 'type' => 'image/jpeg',
+ ),
+ );
+ return array(
+ array(
+ '<http:/.../front.jpeg>; rel="front"; type="image/jpeg", <http://.../back.jpeg>; rel=back; type="image/jpeg"',
+ $res1
+ ),
+ array(
+ '<http:/.../front.jpeg>; rel="front"; type="image/jpeg",<http://.../back.jpeg>; rel=back; type="image/jpeg"',
+ $res1
+ ),
+ array(
+ 'foo="baz"; bar=123, boo, test="123", foobar="foo;bar"',
+ array(
+ array('foo' => 'baz', 'bar' => '123'),
+ array('boo'),
+ array('test' => '123'),
+ array('foobar' => 'foo;bar')
+ )
+ ),
+ array(
+ '<http://.../side.jpeg?test=1>; rel="side"; type="image/jpeg",<http://.../side.jpeg?test=2>; rel=side; type="image/jpeg"',
+ array(
+ array('<http://.../side.jpeg?test=1>', 'rel' => 'side', 'type' => 'image/jpeg'),
+ array('<http://.../side.jpeg?test=2>', 'rel' => 'side', 'type' => 'image/jpeg')
+ )
+ ),
+ array(
+ '',
+ array()
+ )
+ );
+ }
+ /**
+ * @dataProvider parseParamsProvider
+ */
+ public function testParseParams($header, $result)
+ {
+ $this->assertEquals($result, Psr7\parse_header($header));
+ }
+
+ public function testParsesArrayHeaders()
+ {
+ $header = array('a, b', 'c', 'd, e');
+ $this->assertEquals(array('a', 'b', 'c', 'd', 'e'), Psr7\normalize_header($header));
+ }
+
+ public function testRewindsBody()
+ {
+ $body = Psr7\stream_for('abc');
+ $res = new Psr7\Response(200, array(), $body);
+ Psr7\rewind_body($res);
+ $this->assertEquals(0, $body->tell());
+ $body->rewind(1);
+ Psr7\rewind_body($res);
+ $this->assertEquals(0, $body->tell());
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testThrowsWhenBodyCannotBeRewound()
+ {
+ $body = Psr7\stream_for('abc');
+ $body->read(1);
+ $body = FnStream::decorate($body, array(
+ 'rewind' => function () { throw new \RuntimeException('a'); }
+ ));
+ $res = new Psr7\Response(200, array(), $body);
+ Psr7\rewind_body($res);
+ }
+
+ public function testCanModifyRequestWithUri()
+ {
+ $r1 = new Psr7\Request('GET', 'http://foo.com');
+ $r2 = Psr7\modify_request($r1, array(
+ 'uri' => new Psr7\Uri('http://www.foo.com')
+ ));
+ $this->assertEquals('http://www.foo.com', (string) $r2->getUri());
+ $this->assertEquals('www.foo.com', (string) $r2->getHeaderLine('host'));
+ }
+
+ public function testCanModifyRequestWithCaseInsensitiveHeader()
+ {
+ $r1 = new Psr7\Request('GET', 'http://foo.com', array('User-Agent' => 'foo'));
+ $r2 = Psr7\modify_request($r1, array('set_headers' => array('User-agent' => 'bar')));
+ $this->assertEquals('bar', $r2->getHeaderLine('User-Agent'));
+ $this->assertEquals('bar', $r2->getHeaderLine('User-agent'));
+ }
+
+ public function testReturnsAsIsWhenNoChanges()
+ {
+ $request = new Psr7\Request('GET', 'http://foo.com');
+ $this->assertSame($request, Psr7\modify_request($request, array()));
+ }
+
+ public function testReturnsUriAsIsWhenNoChanges()
+ {
+ $r1 = new Psr7\Request('GET', 'http://foo.com');
+ $r2 = Psr7\modify_request($r1, array('set_headers' => array('foo' => 'bar')));
+ $this->assertNotSame($r1, $r2);
+ $this->assertEquals('bar', $r2->getHeaderLine('foo'));
+ }
+
+ public function testRemovesHeadersFromMessage()
+ {
+ $r1 = new Psr7\Request('GET', 'http://foo.com', array('foo' => 'bar'));
+ $r2 = Psr7\modify_request($r1, array('remove_headers' => array('foo')));
+ $this->assertNotSame($r1, $r2);
+ $this->assertFalse($r2->hasHeader('foo'));
+ }
+
+ public function testAddsQueryToUri()
+ {
+ $r1 = new Psr7\Request('GET', 'http://foo.com');
+ $r2 = Psr7\modify_request($r1, array('query' => 'foo=bar'));
+ $this->assertNotSame($r1, $r2);
+ $this->assertEquals('foo=bar', $r2->getUri()->getQuery());
+ }
+
+ public function testServerRequestWithServerParams()
+ {
+ $requestString = "GET /abc HTTP/1.1\r\nHost: foo.com\r\n\r\n";
+ $request = Psr7\parse_server_request($requestString);
+
+ $this->assertEquals(array(), $request->getServerParams());
+ }
+
+ public function testServerRequestWithoutServerParams()
+ {
+ $requestString = "GET /abc HTTP/1.1\r\nHost: foo.com\r\n\r\n";
+ $serverParams = array('server_address' => '127.0.0.1', 'server_port' => 80);
+
+ $request = Psr7\parse_server_request($requestString, $serverParams);
+
+ $this->assertEquals(array('server_address' => '127.0.0.1', 'server_port' => 80), $request->getServerParams());
+ }
+}
diff --git a/vendor/ringcentral/psr7/tests/InflateStreamTest.php b/vendor/ringcentral/psr7/tests/InflateStreamTest.php
new file mode 100644
index 0000000..cd699eb
--- /dev/null
+++ b/vendor/ringcentral/psr7/tests/InflateStreamTest.php
@@ -0,0 +1,21 @@
+<?php
+namespace RingCentral\Tests\Psr7;
+
+use RingCentral\Psr7;
+use RingCentral\Psr7\InflateStream;
+
+function php53_gzencode($data)
+{
+ return gzdeflate($data);
+}
+
+class InflateStreamtest extends \PHPUnit_Framework_TestCase
+{
+ public function testInflatesStreams()
+ {
+ $content = gzencode('test');
+ $a = Psr7\stream_for($content);
+ $b = new InflateStream($a);
+ $this->assertEquals('test', (string) $b);
+ }
+}
diff --git a/vendor/ringcentral/psr7/tests/LazyOpenStreamTest.php b/vendor/ringcentral/psr7/tests/LazyOpenStreamTest.php
new file mode 100644
index 0000000..ca0c18e
--- /dev/null
+++ b/vendor/ringcentral/psr7/tests/LazyOpenStreamTest.php
@@ -0,0 +1,64 @@
+<?php
+namespace RingCentral\Tests\Psr7;
+
+use RingCentral\Psr7\LazyOpenStream;
+
+class LazyOpenStreamTest extends \PHPUnit_Framework_TestCase
+{
+ private $fname;
+
+ public function setup()
+ {
+ $this->fname = tempnam('/tmp', 'tfile');
+
+ if (file_exists($this->fname)) {
+ unlink($this->fname);
+ }
+ }
+
+ public function tearDown()
+ {
+ if (file_exists($this->fname)) {
+ unlink($this->fname);
+ }
+ }
+
+ public function testOpensLazily()
+ {
+ $l = new LazyOpenStream($this->fname, 'w+');
+ $l->write('foo');
+ $this->assertInternalType('array', $l->getMetadata());
+ $this->assertFileExists($this->fname);
+ $this->assertEquals('foo', file_get_contents($this->fname));
+ $this->assertEquals('foo', (string) $l);
+ }
+
+ public function testProxiesToFile()
+ {
+ file_put_contents($this->fname, 'foo');
+ $l = new LazyOpenStream($this->fname, 'r');
+ $this->assertEquals('foo', $l->read(4));
+ $this->assertTrue($l->eof());
+ $this->assertEquals(3, $l->tell());
+ $this->assertTrue($l->isReadable());
+ $this->assertTrue($l->isSeekable());
+ $this->assertFalse($l->isWritable());
+ $l->seek(1);
+ $this->assertEquals('oo', $l->getContents());
+ $this->assertEquals('foo', (string) $l);
+ $this->assertEquals(3, $l->getSize());
+ $this->assertInternalType('array', $l->getMetadata());
+ $l->close();
+ }
+
+ public function testDetachesUnderlyingStream()
+ {
+ file_put_contents($this->fname, 'foo');
+ $l = new LazyOpenStream($this->fname, 'r');
+ $r = $l->detach();
+ $this->assertInternalType('resource', $r);
+ fseek($r, 0);
+ $this->assertEquals('foo', stream_get_contents($r));
+ fclose($r);
+ }
+}
diff --git a/vendor/ringcentral/psr7/tests/LimitStreamTest.php b/vendor/ringcentral/psr7/tests/LimitStreamTest.php
new file mode 100644
index 0000000..7053300
--- /dev/null
+++ b/vendor/ringcentral/psr7/tests/LimitStreamTest.php
@@ -0,0 +1,166 @@
+<?php
+namespace RingCentral\Tests\Psr7;
+
+use RingCentral\Psr7;
+use RingCentral\Psr7\FnStream;
+use RingCentral\Psr7\Stream;
+use RingCentral\Psr7\LimitStream;
+use RingCentral\Psr7\NoSeekStream;
+
+/**
+ * @covers RingCentral\Psr7\LimitStream
+ */
+class LimitStreamTest extends \PHPUnit_Framework_TestCase
+{
+ /** @var LimitStream */
+ protected $body;
+
+ /** @var Stream */
+ protected $decorated;
+
+ public function setUp()
+ {
+ $this->decorated = Psr7\stream_for(fopen(__FILE__, 'r'));
+ $this->body = new LimitStream($this->decorated, 10, 3);
+ }
+
+ public function testReturnsSubset()
+ {
+ $body = new LimitStream(Psr7\stream_for('foo'), -1, 1);
+ $this->assertEquals('oo', (string) $body);
+ $this->assertTrue($body->eof());
+ $body->seek(0);
+ $this->assertFalse($body->eof());
+ $this->assertEquals('oo', $body->read(100));
+ $this->assertSame('', $body->read(1));
+ $this->assertTrue($body->eof());
+ }
+
+ public function testReturnsSubsetWhenCastToString()
+ {
+ $body = Psr7\stream_for('foo_baz_bar');
+ $limited = new LimitStream($body, 3, 4);
+ $this->assertEquals('baz', (string) $limited);
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage Unable to seek to stream position 10 with whence 0
+ */
+ public function testEnsuresPositionCanBeekSeekedTo()
+ {
+ new LimitStream(Psr7\stream_for(''), 0, 10);
+ }
+
+ public function testReturnsSubsetOfEmptyBodyWhenCastToString()
+ {
+ $body = Psr7\stream_for('01234567891234');
+ $limited = new LimitStream($body, 0, 10);
+ $this->assertEquals('', (string) $limited);
+ }
+
+ public function testReturnsSpecificSubsetOBodyWhenCastToString()
+ {
+ $body = Psr7\stream_for('0123456789abcdef');
+ $limited = new LimitStream($body, 3, 10);
+ $this->assertEquals('abc', (string) $limited);
+ }
+
+ public function testSeeksWhenConstructed()
+ {
+ $this->assertEquals(0, $this->body->tell());
+ $this->assertEquals(3, $this->decorated->tell());
+ }
+
+ public function testAllowsBoundedSeek()
+ {
+ $this->body->seek(100);
+ $this->assertEquals(10, $this->body->tell());
+ $this->assertEquals(13, $this->decorated->tell());
+ $this->body->seek(0);
+ $this->assertEquals(0, $this->body->tell());
+ $this->assertEquals(3, $this->decorated->tell());
+ try {
+ $this->body->seek(-10);
+ $this->fail();
+ } catch (\RuntimeException $e) {}
+ $this->assertEquals(0, $this->body->tell());
+ $this->assertEquals(3, $this->decorated->tell());
+ $this->body->seek(5);
+ $this->assertEquals(5, $this->body->tell());
+ $this->assertEquals(8, $this->decorated->tell());
+ // Fail
+ try {
+ $this->body->seek(1000, SEEK_END);
+ $this->fail();
+ } catch (\RuntimeException $e) {}
+ }
+
+ public function testReadsOnlySubsetOfData()
+ {
+ $data = $this->body->read(100);
+ $this->assertEquals(10, strlen($data));
+ $this->assertSame('', $this->body->read(1000));
+
+ $this->body->setOffset(10);
+ $newData = $this->body->read(100);
+ $this->assertEquals(10, strlen($newData));
+ $this->assertNotSame($data, $newData);
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage Could not seek to stream offset 2
+ */
+ public function testThrowsWhenCurrentGreaterThanOffsetSeek()
+ {
+ $a = Psr7\stream_for('foo_bar');
+ $b = new NoSeekStream($a);
+ $c = new LimitStream($b);
+ $a->getContents();
+ $c->setOffset(2);
+ }
+
+ public function testCanGetContentsWithoutSeeking()
+ {
+ $a = Psr7\stream_for('foo_bar');
+ $b = new NoSeekStream($a);
+ $c = new LimitStream($b);
+ $this->assertEquals('foo_bar', $c->getContents());
+ }
+
+ public function testClaimsConsumedWhenReadLimitIsReached()
+ {
+ $this->assertFalse($this->body->eof());
+ $this->body->read(1000);
+ $this->assertTrue($this->body->eof());
+ }
+
+ public function testContentLengthIsBounded()
+ {
+ $this->assertEquals(10, $this->body->getSize());
+ }
+
+ public function testGetContentsIsBasedOnSubset()
+ {
+ $body = new LimitStream(Psr7\stream_for('foobazbar'), 3, 3);
+ $this->assertEquals('baz', $body->getContents());
+ }
+
+ public function testReturnsNullIfSizeCannotBeDetermined()
+ {
+ $a = new FnStream(array(
+ 'getSize' => function () { return null; },
+ 'tell' => function () { return 0; },
+ ));
+ $b = new LimitStream($a);
+ $this->assertNull($b->getSize());
+ }
+
+ public function testLengthLessOffsetWhenNoLimitSize()
+ {
+ $a = Psr7\stream_for('foo_bar');
+ $b = new LimitStream($a, -1, 4);
+ $this->assertEquals(3, $b->getSize());
+ }
+}
diff --git a/vendor/ringcentral/psr7/tests/MultipartStreamTest.php b/vendor/ringcentral/psr7/tests/MultipartStreamTest.php
new file mode 100644
index 0000000..22edea4
--- /dev/null
+++ b/vendor/ringcentral/psr7/tests/MultipartStreamTest.php
@@ -0,0 +1,214 @@
+<?php
+namespace RingCentral\Tests;
+
+use RingCentral\Psr7;
+use RingCentral\Psr7\MultipartStream;
+
+class MultipartStreamTest extends \PHPUnit_Framework_TestCase
+{
+ public function testCreatesDefaultBoundary()
+ {
+ $b = new MultipartStream();
+ $this->assertNotEmpty($b->getBoundary());
+ }
+
+ public function testCanProvideBoundary()
+ {
+ $b = new MultipartStream(array(), 'foo');
+ $this->assertEquals('foo', $b->getBoundary());
+ }
+
+ public function testIsNotWritable()
+ {
+ $b = new MultipartStream();
+ $this->assertFalse($b->isWritable());
+ }
+
+ public function testCanCreateEmptyStream()
+ {
+ $b = new MultipartStream();
+ $boundary = $b->getBoundary();
+ $this->assertSame("--{$boundary}--\r\n", $b->getContents());
+ $this->assertSame(strlen($boundary) + 6, $b->getSize());
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testValidatesFilesArrayElement()
+ {
+ new MultipartStream(array(array('foo' => 'bar')));
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testEnsuresFileHasName()
+ {
+ new MultipartStream(array(array('contents' => 'bar')));
+ }
+
+ public function testSerializesFields()
+ {
+ $b = new MultipartStream(array(
+ array(
+ 'name' => 'foo',
+ 'contents' => 'bar'
+ ),
+ array(
+ 'name' => 'baz',
+ 'contents' => 'bam'
+ )
+ ), 'boundary');
+ $this->assertEquals(
+ "--boundary\r\nContent-Disposition: form-data; name=\"foo\"\r\nContent-Length: 3\r\n\r\n"
+ . "bar\r\n--boundary\r\nContent-Disposition: form-data; name=\"baz\"\r\nContent-Length: 3"
+ . "\r\n\r\nbam\r\n--boundary--\r\n", (string) $b);
+ }
+
+ public function testSerializesFiles()
+ {
+ $f1 = Psr7\FnStream::decorate(Psr7\stream_for('foo'), array(
+ 'getMetadata' => function () {
+ return '/foo/bar.txt';
+ }
+ ));
+
+ $f2 = Psr7\FnStream::decorate(Psr7\stream_for('baz'), array(
+ 'getMetadata' => function () {
+ return '/foo/baz.jpg';
+ }
+ ));
+
+ $f3 = Psr7\FnStream::decorate(Psr7\stream_for('bar'), array(
+ 'getMetadata' => function () {
+ return '/foo/bar.gif';
+ }
+ ));
+
+ $b = new MultipartStream(array(
+ array(
+ 'name' => 'foo',
+ 'contents' => $f1
+ ),
+ array(
+ 'name' => 'qux',
+ 'contents' => $f2
+ ),
+ array(
+ 'name' => 'qux',
+ 'contents' => $f3
+ ),
+ ), 'boundary');
+
+ $expected = <<<EOT
+--boundary
+Content-Disposition: form-data; name="foo"; filename="bar.txt"
+Content-Length: 3
+Content-Type: text/plain
+
+foo
+--boundary
+Content-Disposition: form-data; name="qux"; filename="baz.jpg"
+Content-Length: 3
+Content-Type: image/jpeg
+
+baz
+--boundary
+Content-Disposition: form-data; name="qux"; filename="bar.gif"
+Content-Length: 3
+Content-Type: image/gif
+
+bar
+--boundary--
+
+EOT;
+
+ $this->assertEquals($expected, str_replace("\r", '', $b));
+ }
+
+ public function testSerializesFilesWithCustomHeaders()
+ {
+ $f1 = Psr7\FnStream::decorate(Psr7\stream_for('foo'), array(
+ 'getMetadata' => function () {
+ return '/foo/bar.txt';
+ }
+ ));
+
+ $b = new MultipartStream(array(
+ array(
+ 'name' => 'foo',
+ 'contents' => $f1,
+ 'headers' => array(
+ 'x-foo' => 'bar',
+ 'content-disposition' => 'custom'
+ )
+ )
+ ), 'boundary');
+
+ $expected = <<<EOT
+--boundary
+x-foo: bar
+content-disposition: custom
+Content-Length: 3
+Content-Type: text/plain
+
+foo
+--boundary--
+
+EOT;
+
+ $this->assertEquals($expected, str_replace("\r", '', $b));
+ }
+
+ public function testSerializesFilesWithCustomHeadersAndMultipleValues()
+ {
+ $f1 = Psr7\FnStream::decorate(Psr7\stream_for('foo'), array(
+ 'getMetadata' => function () {
+ return '/foo/bar.txt';
+ }
+ ));
+
+ $f2 = Psr7\FnStream::decorate(Psr7\stream_for('baz'), array(
+ 'getMetadata' => function () {
+ return '/foo/baz.jpg';
+ }
+ ));
+
+ $b = new MultipartStream(array(
+ array(
+ 'name' => 'foo',
+ 'contents' => $f1,
+ 'headers' => array(
+ 'x-foo' => 'bar',
+ 'content-disposition' => 'custom'
+ )
+ ),
+ array(
+ 'name' => 'foo',
+ 'contents' => $f2,
+ 'headers' => array('cOntenT-Type' => 'custom'),
+ )
+ ), 'boundary');
+
+ $expected = <<<EOT
+--boundary
+x-foo: bar
+content-disposition: custom
+Content-Length: 3
+Content-Type: text/plain
+
+foo
+--boundary
+cOntenT-Type: custom
+Content-Disposition: form-data; name="foo"; filename="baz.jpg"
+Content-Length: 3
+
+baz
+--boundary--
+
+EOT;
+
+ $this->assertEquals($expected, str_replace("\r", '', $b));
+ }
+}
diff --git a/vendor/ringcentral/psr7/tests/NoSeekStreamTest.php b/vendor/ringcentral/psr7/tests/NoSeekStreamTest.php
new file mode 100644
index 0000000..a831789
--- /dev/null
+++ b/vendor/ringcentral/psr7/tests/NoSeekStreamTest.php
@@ -0,0 +1,40 @@
+<?php
+namespace RingCentral\Tests\Psr7;
+
+use RingCentral\Psr7;
+use RingCentral\Psr7\NoSeekStream;
+
+/**
+ * @covers RingCentral\Psr7\NoSeekStream
+ * @covers RingCentral\Psr7\StreamDecoratorTrait
+ */
+class NoSeekStreamTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage Cannot seek a NoSeekStream
+ */
+ public function testCannotSeek()
+ {
+ $s = $this->getMockBuilder('Psr\Http\Message\StreamInterface')
+ ->setMethods(array('isSeekable', 'seek'))
+ ->getMockForAbstractClass();
+ $s->expects($this->never())->method('seek');
+ $s->expects($this->never())->method('isSeekable');
+ $wrapped = new NoSeekStream($s);
+ $this->assertFalse($wrapped->isSeekable());
+ $wrapped->seek(2);
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage Cannot write to a non-writable stream
+ */
+ public function testHandlesClose()
+ {
+ $s = Psr7\stream_for('foo');
+ $wrapped = new NoSeekStream($s);
+ $wrapped->close();
+ $wrapped->write('foo');
+ }
+}
diff --git a/vendor/ringcentral/psr7/tests/PumpStreamTest.php b/vendor/ringcentral/psr7/tests/PumpStreamTest.php
new file mode 100644
index 0000000..6b146e1
--- /dev/null
+++ b/vendor/ringcentral/psr7/tests/PumpStreamTest.php
@@ -0,0 +1,72 @@
+<?php
+namespace RingCentral\Tests\Psr7;
+
+use RingCentral\Psr7\LimitStream;
+use RingCentral\Psr7\PumpStream;
+use RingCentral\Psr7;
+
+class PumpStreamTest extends \PHPUnit_Framework_TestCase
+{
+ public function testHasMetadataAndSize()
+ {
+ $p = new PumpStream(function () {}, array(
+ 'metadata' => array('foo' => 'bar'),
+ 'size' => 100
+ ));
+
+ $this->assertEquals('bar', $p->getMetadata('foo'));
+ $this->assertEquals(array('foo' => 'bar'), $p->getMetadata());
+ $this->assertEquals(100, $p->getSize());
+ }
+
+ public function testCanReadFromCallable()
+ {
+ $p = Psr7\stream_for(function ($size) {
+ return 'a';
+ });
+ $this->assertEquals('a', $p->read(1));
+ $this->assertEquals(1, $p->tell());
+ $this->assertEquals('aaaaa', $p->read(5));
+ $this->assertEquals(6, $p->tell());
+ }
+
+ public function testStoresExcessDataInBuffer()
+ {
+ $called = array();
+ $p = Psr7\stream_for(function ($size) use (&$called) {
+ $called[] = $size;
+ return 'abcdef';
+ });
+ $this->assertEquals('a', $p->read(1));
+ $this->assertEquals('b', $p->read(1));
+ $this->assertEquals('cdef', $p->read(4));
+ $this->assertEquals('abcdefabc', $p->read(9));
+ $this->assertEquals(array(1, 9, 3), $called);
+ }
+
+ public function testInifiniteStreamWrappedInLimitStream()
+ {
+ $p = Psr7\stream_for(function () { return 'a'; });
+ $s = new LimitStream($p, 5);
+ $this->assertEquals('aaaaa', (string) $s);
+ }
+
+ public function testDescribesCapabilities()
+ {
+ $p = Psr7\stream_for(function () {});
+ $this->assertTrue($p->isReadable());
+ $this->assertFalse($p->isSeekable());
+ $this->assertFalse($p->isWritable());
+ $this->assertNull($p->getSize());
+ $this->assertEquals('', $p->getContents());
+ $this->assertEquals('', (string) $p);
+ $p->close();
+ $this->assertEquals('', $p->read(10));
+ $this->assertTrue($p->eof());
+
+ try {
+ $this->assertFalse($p->write('aa'));
+ $this->fail();
+ } catch (\RuntimeException $e) {}
+ }
+}
diff --git a/vendor/ringcentral/psr7/tests/RequestTest.php b/vendor/ringcentral/psr7/tests/RequestTest.php
new file mode 100644
index 0000000..ad6f0cb
--- /dev/null
+++ b/vendor/ringcentral/psr7/tests/RequestTest.php
@@ -0,0 +1,157 @@
+<?php
+namespace RingCentral\Tests\Psr7;
+
+use RingCentral\Psr7\Request;
+use RingCentral\Psr7\Uri;
+
+/**
+ * @covers RingCentral\Psr7\Request
+ */
+class RequestTest extends \PHPUnit_Framework_TestCase
+{
+ public function testRequestUriMayBeString()
+ {
+ $r = new Request('GET', '/');
+ $this->assertEquals('/', (string) $r->getUri());
+ }
+
+ public function testRequestUriMayBeUri()
+ {
+ $uri = new Uri('/');
+ $r = new Request('GET', $uri);
+ $this->assertSame($uri, $r->getUri());
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testValidateRequestUri()
+ {
+ new Request('GET', true);
+ }
+
+ public function testCanConstructWithBody()
+ {
+ $r = new Request('GET', '/', array(), 'baz');
+ $this->assertEquals('baz', (string) $r->getBody());
+ }
+
+ public function testCapitalizesMethod()
+ {
+ $r = new Request('get', '/');
+ $this->assertEquals('GET', $r->getMethod());
+ }
+
+ public function testCapitalizesWithMethod()
+ {
+ $r = new Request('GET', '/');
+ $this->assertEquals('PUT', $r->withMethod('put')->getMethod());
+ }
+
+ public function testWithUri()
+ {
+ $r1 = new Request('GET', '/');
+ $u1 = $r1->getUri();
+ $u2 = new Uri('http://www.example.com');
+ $r2 = $r1->withUri($u2);
+ $this->assertNotSame($r1, $r2);
+ $this->assertSame($u2, $r2->getUri());
+ $this->assertSame($u1, $r1->getUri());
+ }
+
+ public function testSameInstanceWhenSameUri()
+ {
+ $r1 = new Request('GET', 'http://foo.com');
+ $r2 = $r1->withUri($r1->getUri());
+ $this->assertSame($r1, $r2);
+ }
+
+ public function testWithRequestTarget()
+ {
+ $r1 = new Request('GET', '/');
+ $r2 = $r1->withRequestTarget('*');
+ $this->assertEquals('*', $r2->getRequestTarget());
+ $this->assertEquals('/', $r1->getRequestTarget());
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testRequestTargetDoesNotAllowSpaces()
+ {
+ $r1 = new Request('GET', '/');
+ $r1->withRequestTarget('/foo bar');
+ }
+
+ public function testRequestTargetDefaultsToSlash()
+ {
+ $r1 = new Request('GET', '');
+ $this->assertEquals('/', $r1->getRequestTarget());
+ $r2 = new Request('GET', '*');
+ $this->assertEquals('*', $r2->getRequestTarget());
+ $r3 = new Request('GET', 'http://foo.com/bar baz/');
+ $this->assertEquals('/bar%20baz/', $r3->getRequestTarget());
+ }
+
+ public function testBuildsRequestTarget()
+ {
+ $r1 = new Request('GET', 'http://foo.com/baz?bar=bam');
+ $this->assertEquals('/baz?bar=bam', $r1->getRequestTarget());
+ }
+
+ public function testHostIsAddedFirst()
+ {
+ $r = new Request('GET', 'http://foo.com/baz?bar=bam', array('Foo' => 'Bar'));
+ $this->assertEquals(array(
+ 'Host' => array('foo.com'),
+ 'Foo' => array('Bar')
+ ), $r->getHeaders());
+ }
+
+ public function testCanGetHeaderAsCsv()
+ {
+ $r = new Request('GET', 'http://foo.com/baz?bar=bam', array(
+ 'Foo' => array('a', 'b', 'c')
+ ));
+ $this->assertEquals('a, b, c', $r->getHeaderLine('Foo'));
+ $this->assertEquals('', $r->getHeaderLine('Bar'));
+ }
+
+ public function testHostIsNotOverwrittenWhenPreservingHost()
+ {
+ $r = new Request('GET', 'http://foo.com/baz?bar=bam', array('Host' => 'a.com'));
+ $this->assertEquals(array('Host' => array('a.com')), $r->getHeaders());
+ $r2 = $r->withUri(new Uri('http://www.foo.com/bar'), true);
+ $this->assertEquals('a.com', $r2->getHeaderLine('Host'));
+ }
+
+ public function testOverridesHostWithUri()
+ {
+ $r = new Request('GET', 'http://foo.com/baz?bar=bam');
+ $this->assertEquals(array('Host' => array('foo.com')), $r->getHeaders());
+ $r2 = $r->withUri(new Uri('http://www.baz.com/bar'));
+ $this->assertEquals('www.baz.com', $r2->getHeaderLine('Host'));
+ }
+
+ public function testAggregatesHeaders()
+ {
+ $r = new Request('GET', 'http://foo.com', array(
+ 'ZOO' => 'zoobar',
+ 'zoo' => array('foobar', 'zoobar')
+ ));
+ $this->assertEquals('zoobar, foobar, zoobar', $r->getHeaderLine('zoo'));
+ }
+
+ public function testAddsPortToHeader()
+ {
+ $r = new Request('GET', 'http://foo.com:8124/bar');
+ $this->assertEquals('foo.com:8124', $r->getHeaderLine('host'));
+ }
+
+ public function testAddsPortToHeaderAndReplacePreviousPort()
+ {
+ $r = new Request('GET', 'http://foo.com:8124/bar');
+ $r = $r->withUri(new Uri('http://foo.com:8125/bar'));
+ $this->assertEquals('foo.com:8125', $r->getHeaderLine('host'));
+ }
+}
diff --git a/vendor/ringcentral/psr7/tests/ResponseTest.php b/vendor/ringcentral/psr7/tests/ResponseTest.php
new file mode 100644
index 0000000..52b7ba1
--- /dev/null
+++ b/vendor/ringcentral/psr7/tests/ResponseTest.php
@@ -0,0 +1,154 @@
+<?php
+namespace RingCentral\Tests\Psr7;
+
+use RingCentral\Psr7\Response;
+use RingCentral\Psr7;
+
+/**
+ * @covers RingCentral\Psr7\MessageTrait
+ * @covers RingCentral\Psr7\Response
+ */
+class ResponseTest extends \PHPUnit_Framework_TestCase
+{
+ public function testAddsDefaultReason()
+ {
+ $r = new Response('200');
+ $this->assertSame(200, $r->getStatusCode());
+ $this->assertEquals('OK', $r->getReasonPhrase());
+ }
+
+ public function testCanGiveCustomReason()
+ {
+ $r = new Response(200, array(), null, '1.1', 'bar');
+ $this->assertEquals('bar', $r->getReasonPhrase());
+ }
+
+ public function testCanGiveCustomProtocolVersion()
+ {
+ $r = new Response(200, array(), null, '1000');
+ $this->assertEquals('1000', $r->getProtocolVersion());
+ }
+
+ public function testCanCreateNewResponseWithStatusAndNoReason()
+ {
+ $r = new Response(200);
+ $r2 = $r->withStatus(201);
+ $this->assertEquals(200, $r->getStatusCode());
+ $this->assertEquals('OK', $r->getReasonPhrase());
+ $this->assertEquals(201, $r2->getStatusCode());
+ $this->assertEquals('Created', $r2->getReasonPhrase());
+ }
+
+ public function testCanCreateNewResponseWithStatusAndReason()
+ {
+ $r = new Response(200);
+ $r2 = $r->withStatus(201, 'Foo');
+ $this->assertEquals(200, $r->getStatusCode());
+ $this->assertEquals('OK', $r->getReasonPhrase());
+ $this->assertEquals(201, $r2->getStatusCode());
+ $this->assertEquals('Foo', $r2->getReasonPhrase());
+ }
+
+ public function testCreatesResponseWithAddedHeaderArray()
+ {
+ $r = new Response();
+ $r2 = $r->withAddedHeader('foo', array('baz', 'bar'));
+ $this->assertFalse($r->hasHeader('foo'));
+ $this->assertEquals('baz, bar', $r2->getHeaderLine('foo'));
+ }
+
+ public function testReturnsIdentityWhenRemovingMissingHeader()
+ {
+ $r = new Response();
+ $this->assertSame($r, $r->withoutHeader('foo'));
+ }
+
+ public function testAlwaysReturnsBody()
+ {
+ $r = new Response();
+ $this->assertInstanceOf('Psr\Http\Message\StreamInterface', $r->getBody());
+ }
+
+ public function testCanSetHeaderAsArray()
+ {
+ $r = new Response(200, array(
+ 'foo' => array('baz ', ' bar ')
+ ));
+ $this->assertEquals('baz, bar', $r->getHeaderLine('foo'));
+ $this->assertEquals(array('baz', 'bar'), $r->getHeader('foo'));
+ }
+
+ public function testSameInstanceWhenSameBody()
+ {
+ $r = new Response(200, array(), 'foo');
+ $b = $r->getBody();
+ $this->assertSame($r, $r->withBody($b));
+ }
+
+ public function testNewInstanceWhenNewBody()
+ {
+ $r = new Response(200, array(), 'foo');
+ $b2 = Psr7\stream_for('abc');
+ $this->assertNotSame($r, $r->withBody($b2));
+ }
+
+ public function testSameInstanceWhenSameProtocol()
+ {
+ $r = new Response(200);
+ $this->assertSame($r, $r->withProtocolVersion('1.1'));
+ }
+
+ public function testNewInstanceWhenNewProtocol()
+ {
+ $r = new Response(200);
+ $this->assertNotSame($r, $r->withProtocolVersion('1.0'));
+ }
+
+ public function testNewInstanceWhenRemovingHeader()
+ {
+ $r = new Response(200, array('Foo' => 'Bar'));
+ $r2 = $r->withoutHeader('Foo');
+ $this->assertNotSame($r, $r2);
+ $this->assertFalse($r2->hasHeader('foo'));
+ }
+
+ public function testNewInstanceWhenAddingHeader()
+ {
+ $r = new Response(200, array('Foo' => 'Bar'));
+ $r2 = $r->withAddedHeader('Foo', 'Baz');
+ $this->assertNotSame($r, $r2);
+ $this->assertEquals('Bar, Baz', $r2->getHeaderLine('foo'));
+ }
+
+ public function testNewInstanceWhenAddingHeaderArray()
+ {
+ $r = new Response(200, array('Foo' => 'Bar'));
+ $r2 = $r->withAddedHeader('Foo', array('Baz', 'Qux'));
+ $this->assertNotSame($r, $r2);
+ $this->assertEquals(array('Bar', 'Baz', 'Qux'), $r2->getHeader('foo'));
+ }
+
+ public function testNewInstanceWhenAddingHeaderThatWasNotThereBefore()
+ {
+ $r = new Response(200, array('Foo' => 'Bar'));
+ $r2 = $r->withAddedHeader('Baz', 'Bam');
+ $this->assertNotSame($r, $r2);
+ $this->assertEquals('Bam', $r2->getHeaderLine('Baz'));
+ $this->assertEquals('Bar', $r2->getHeaderLine('Foo'));
+ }
+
+ public function testRemovesPreviouslyAddedHeaderOfDifferentCase()
+ {
+ $r = new Response(200, array('Foo' => 'Bar'));
+ $r2 = $r->withHeader('foo', 'Bam');
+ $this->assertNotSame($r, $r2);
+ $this->assertEquals('Bam', $r2->getHeaderLine('Foo'));
+ }
+
+ public function testBodyConsistent()
+ {
+ $r = new Response(200, array(), '0');
+ $this->assertEquals('0', (string)$r->getBody());
+ }
+
+}
diff --git a/vendor/ringcentral/psr7/tests/ServerRequestTest.php b/vendor/ringcentral/psr7/tests/ServerRequestTest.php
new file mode 100644
index 0000000..4bdfe8e
--- /dev/null
+++ b/vendor/ringcentral/psr7/tests/ServerRequestTest.php
@@ -0,0 +1,85 @@
+<?php
+
+use RingCentral\Psr7\ServerRequest;
+
+class ServerRequestTest extends \PHPUnit_Framework_TestCase
+{
+ private $request;
+
+ public function setUp()
+ {
+ $this->request = new ServerRequest('GET', 'http://localhost');
+ }
+
+ public function testGetNoAttributes()
+ {
+ $this->assertEquals(array(), $this->request->getAttributes());
+ }
+
+ public function testWithAttribute()
+ {
+ $request = $this->request->withAttribute('hello', 'world');
+
+ $this->assertNotSame($request, $this->request);
+ $this->assertEquals(array('hello' => 'world'), $request->getAttributes());
+ }
+
+ public function testGetAttribute()
+ {
+ $request = $this->request->withAttribute('hello', 'world');
+
+ $this->assertNotSame($request, $this->request);
+ $this->assertEquals('world', $request->getAttribute('hello'));
+ }
+
+ public function testGetDefaultAttribute()
+ {
+ $request = $this->request->withAttribute('hello', 'world');
+
+ $this->assertNotSame($request, $this->request);
+ $this->assertEquals(null, $request->getAttribute('hi', null));
+ }
+
+ public function testWithoutAttribute()
+ {
+ $request = $this->request->withAttribute('hello', 'world');
+ $request = $request->withAttribute('test', 'nice');
+
+ $request = $request->withoutAttribute('hello');
+
+ $this->assertNotSame($request, $this->request);
+ $this->assertEquals(array('test' => 'nice'), $request->getAttributes());
+ }
+
+ public function testWithCookieParams()
+ {
+ $request = $this->request->withCookieParams(array('test' => 'world'));
+
+ $this->assertNotSame($request, $this->request);
+ $this->assertEquals(array('test' => 'world'), $request->getCookieParams());
+ }
+
+ public function testWithQueryParams()
+ {
+ $request = $this->request->withQueryParams(array('test' => 'world'));
+
+ $this->assertNotSame($request, $this->request);
+ $this->assertEquals(array('test' => 'world'), $request->getQueryParams());
+ }
+
+ public function testWithUploadedFiles()
+ {
+ $request = $this->request->withUploadedFiles(array('test' => 'world'));
+
+ $this->assertNotSame($request, $this->request);
+ $this->assertEquals(array('test' => 'world'), $request->getUploadedFiles());
+ }
+
+ public function testWithParsedBody()
+ {
+ $request = $this->request->withParsedBody(array('test' => 'world'));
+
+ $this->assertNotSame($request, $this->request);
+ $this->assertEquals(array('test' => 'world'), $request->getParsedBody());
+ }
+}
diff --git a/vendor/ringcentral/psr7/tests/StreamDecoratorTraitTest.php b/vendor/ringcentral/psr7/tests/StreamDecoratorTraitTest.php
new file mode 100644
index 0000000..b0c3dc5
--- /dev/null
+++ b/vendor/ringcentral/psr7/tests/StreamDecoratorTraitTest.php
@@ -0,0 +1,123 @@
+<?php
+namespace RingCentral\Tests\Psr7;
+
+use Psr\Http\Message\StreamInterface;
+use RingCentral\Psr7;
+use RingCentral\Psr7\StreamDecoratorTrait;
+
+class Str extends StreamDecoratorTrait implements StreamInterface
+{
+}
+
+/**
+ * @covers RingCentral\Psr7\StreamDecoratorTrait
+ */
+class StreamDecoratorTraitTest extends \PHPUnit_Framework_TestCase
+{
+ private $a;
+ private $b;
+ private $c;
+
+ public function setUp()
+ {
+ $this->c = fopen('php://temp', 'r+');
+ fwrite($this->c, 'foo');
+ fseek($this->c, 0);
+ $this->a = Psr7\stream_for($this->c);
+ $this->b = new Str($this->a);
+ }
+
+ public function testCatchesExceptionsWhenCastingToString()
+ {
+ $s = $this->getMockBuilder('Psr\Http\Message\StreamInterface')
+ ->setMethods(array('read'))
+ ->getMockForAbstractClass();
+ $s->expects($this->once())
+ ->method('read')
+ ->will($this->throwException(new \Exception('foo')));
+ $msg = '';
+ set_error_handler(function ($errNo, $str) use (&$msg) {
+ $msg = $str;
+ });
+ echo new Str($s);
+ restore_error_handler();
+ $this->assertContains('foo', $msg);
+ }
+
+ public function testToString()
+ {
+ $this->assertEquals('foo', (string)$this->b);
+ }
+
+ public function testHasSize()
+ {
+ $this->assertEquals(3, $this->b->getSize());
+ }
+
+ public function testReads()
+ {
+ $this->assertEquals('foo', $this->b->read(10));
+ }
+
+ public function testCheckMethods()
+ {
+ $this->assertEquals($this->a->isReadable(), $this->b->isReadable());
+ $this->assertEquals($this->a->isWritable(), $this->b->isWritable());
+ $this->assertEquals($this->a->isSeekable(), $this->b->isSeekable());
+ }
+
+ public function testSeeksAndTells()
+ {
+ $this->b->seek(1);
+ $this->assertEquals(1, $this->a->tell());
+ $this->assertEquals(1, $this->b->tell());
+ $this->b->seek(0);
+ $this->assertEquals(0, $this->a->tell());
+ $this->assertEquals(0, $this->b->tell());
+ $this->b->seek(0, SEEK_END);
+ $this->assertEquals(3, $this->a->tell());
+ $this->assertEquals(3, $this->b->tell());
+ }
+
+ public function testGetsContents()
+ {
+ $this->assertEquals('foo', $this->b->getContents());
+ $this->assertEquals('', $this->b->getContents());
+ $this->b->seek(1);
+ $this->assertEquals('oo', $this->b->getContents(1));
+ }
+
+ public function testCloses()
+ {
+ $this->b->close();
+ $this->assertFalse(is_resource($this->c));
+ }
+
+ public function testDetaches()
+ {
+ $this->b->detach();
+ $this->assertFalse($this->b->isReadable());
+ }
+
+ public function testWrapsMetadata()
+ {
+ $this->assertSame($this->b->getMetadata(), $this->a->getMetadata());
+ $this->assertSame($this->b->getMetadata('uri'), $this->a->getMetadata('uri'));
+ }
+
+ public function testWrapsWrites()
+ {
+ $this->b->seek(0, SEEK_END);
+ $this->b->write('foo');
+ $this->assertEquals('foofoo', (string)$this->a);
+ }
+
+ /**
+ * @expectedException \UnexpectedValueException
+ */
+ public function testThrowsWithInvalidGetter()
+ {
+ $this->b->foo;
+ }
+
+} \ No newline at end of file
diff --git a/vendor/ringcentral/psr7/tests/StreamTest.php b/vendor/ringcentral/psr7/tests/StreamTest.php
new file mode 100644
index 0000000..5501805
--- /dev/null
+++ b/vendor/ringcentral/psr7/tests/StreamTest.php
@@ -0,0 +1,163 @@
+<?php
+namespace RingCentral\Tests\Psr7;
+
+use RingCentral\Psr7\NoSeekStream;
+use RingCentral\Psr7\Stream;
+
+/**
+ * @covers RingCentral\Psr7\Stream
+ */
+class StreamTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testConstructorThrowsExceptionOnInvalidArgument()
+ {
+ new Stream(true);
+ }
+
+ public function testConstructorInitializesProperties()
+ {
+ $handle = fopen('php://temp', 'r+');
+ fwrite($handle, 'data');
+ $stream = new Stream($handle);
+ $this->assertTrue($stream->isReadable());
+ $this->assertTrue($stream->isWritable());
+ $this->assertTrue($stream->isSeekable());
+ $this->assertEquals('php://temp', $stream->getMetadata('uri'));
+ $this->assertInternalType('array', $stream->getMetadata());
+ $this->assertEquals(4, $stream->getSize());
+ $this->assertFalse($stream->eof());
+ $stream->close();
+ }
+
+ public function testStreamClosesHandleOnDestruct()
+ {
+ $handle = fopen('php://temp', 'r');
+ $stream = new Stream($handle);
+ unset($stream);
+ $this->assertFalse(is_resource($handle));
+ }
+
+ public function testConvertsToString()
+ {
+ $handle = fopen('php://temp', 'w+');
+ fwrite($handle, 'data');
+ $stream = new Stream($handle);
+ $this->assertEquals('data', (string) $stream);
+ $this->assertEquals('data', (string) $stream);
+ $stream->close();
+ }
+
+ public function testGetsContents()
+ {
+ $handle = fopen('php://temp', 'w+');
+ fwrite($handle, 'data');
+ $stream = new Stream($handle);
+ $this->assertEquals('', $stream->getContents());
+ $stream->seek(0);
+ $this->assertEquals('data', $stream->getContents());
+ $this->assertEquals('', $stream->getContents());
+ }
+
+ public function testChecksEof()
+ {
+ $handle = fopen('php://temp', 'w+');
+ fwrite($handle, 'data');
+ $stream = new Stream($handle);
+ $this->assertFalse($stream->eof());
+ $stream->read(4);
+ $this->assertTrue($stream->eof());
+ $stream->close();
+ }
+
+ public function testGetSize()
+ {
+ $size = filesize(__FILE__);
+ $handle = fopen(__FILE__, 'r');
+ $stream = new Stream($handle);
+ $this->assertEquals($size, $stream->getSize());
+ // Load from cache
+ $this->assertEquals($size, $stream->getSize());
+ $stream->close();
+ }
+
+ public function testEnsuresSizeIsConsistent()
+ {
+ $h = fopen('php://temp', 'w+');
+ $this->assertEquals(3, fwrite($h, 'foo'));
+ $stream = new Stream($h);
+ $this->assertEquals(3, $stream->getSize());
+ $this->assertEquals(4, $stream->write('test'));
+ $this->assertEquals(7, $stream->getSize());
+ $this->assertEquals(7, $stream->getSize());
+ $stream->close();
+ }
+
+ public function testProvidesStreamPosition()
+ {
+ $handle = fopen('php://temp', 'w+');
+ $stream = new Stream($handle);
+ $this->assertEquals(0, $stream->tell());
+ $stream->write('foo');
+ $this->assertEquals(3, $stream->tell());
+ $stream->seek(1);
+ $this->assertEquals(1, $stream->tell());
+ $this->assertSame(ftell($handle), $stream->tell());
+ $stream->close();
+ }
+
+ public function testCanDetachStream()
+ {
+ $r = fopen('php://temp', 'w+');
+ $stream = new Stream($r);
+ $stream->write('foo');
+ $this->assertTrue($stream->isReadable());
+ $this->assertSame($r, $stream->detach());
+ $stream->detach();
+
+ $this->assertFalse($stream->isReadable());
+ $this->assertFalse($stream->isWritable());
+ $this->assertFalse($stream->isSeekable());
+
+ $self = $this;
+
+ $throws = function ($fn) use ($stream, $self) {
+ try {
+ $fn($stream);
+ $self->fail();
+ } catch (\Exception $e) {}
+ };
+
+ $throws(function ($stream) { $stream->read(10); });
+ $throws(function ($stream) { $stream->write('bar'); });
+ $throws(function ($stream) { $stream->seek(10); });
+ $throws(function ($stream) { $stream->tell(); });
+ $throws(function ($stream) { $stream->eof(); });
+ $throws(function ($stream) { $stream->getSize(); });
+ $throws(function ($stream) { $stream->getContents(); });
+ $this->assertSame('', (string) $stream);
+ $stream->close();
+ }
+
+ public function testCloseClearProperties()
+ {
+ $handle = fopen('php://temp', 'r+');
+ $stream = new Stream($handle);
+ $stream->close();
+
+ $this->assertFalse($stream->isSeekable());
+ $this->assertFalse($stream->isReadable());
+ $this->assertFalse($stream->isWritable());
+ $this->assertNull($stream->getSize());
+ $this->assertEmpty($stream->getMetadata());
+ }
+
+ public function testDoesNotThrowInToString()
+ {
+ $s = \RingCentral\Psr7\stream_for('foo');
+ $s = new NoSeekStream($s);
+ $this->assertEquals('foo', (string) $s);
+ }
+}
diff --git a/vendor/ringcentral/psr7/tests/StreamWrapperTest.php b/vendor/ringcentral/psr7/tests/StreamWrapperTest.php
new file mode 100644
index 0000000..dd08a83
--- /dev/null
+++ b/vendor/ringcentral/psr7/tests/StreamWrapperTest.php
@@ -0,0 +1,100 @@
+<?php
+namespace RingCentral\Tests\Psr7;
+
+use RingCentral\Psr7\StreamWrapper;
+use RingCentral\Psr7;
+
+/**
+ * @covers RingCentral\Psr7\StreamWrapper
+ */
+class StreamWrapperTest extends \PHPUnit_Framework_TestCase
+{
+ public function testResource()
+ {
+ $stream = Psr7\stream_for('foo');
+ $handle = StreamWrapper::getResource($stream);
+ $this->assertSame('foo', fread($handle, 3));
+ $this->assertSame(3, ftell($handle));
+ $this->assertSame(3, fwrite($handle, 'bar'));
+ $this->assertSame(0, fseek($handle, 0));
+ $this->assertSame('foobar', fread($handle, 6));
+ $this->assertSame('', fread($handle, 1));
+ $this->assertTrue(feof($handle));
+
+ // This fails on HHVM for some reason
+ if (!defined('HHVM_VERSION')) {
+ $this->assertEquals(array(
+ 'dev' => 0,
+ 'ino' => 0,
+ 'mode' => 33206,
+ 'nlink' => 0,
+ 'uid' => 0,
+ 'gid' => 0,
+ 'rdev' => 0,
+ 'size' => 6,
+ 'atime' => 0,
+ 'mtime' => 0,
+ 'ctime' => 0,
+ 'blksize' => 0,
+ 'blocks' => 0,
+ 0 => 0,
+ 1 => 0,
+ 2 => 33206,
+ 3 => 0,
+ 4 => 0,
+ 5 => 0,
+ 6 => 0,
+ 7 => 6,
+ 8 => 0,
+ 9 => 0,
+ 10 => 0,
+ 11 => 0,
+ 12 => 0,
+ ), fstat($handle));
+ }
+
+ $this->assertTrue(fclose($handle));
+ $this->assertSame('foobar', (string) $stream);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testValidatesStream()
+ {
+ $stream = $this->getMockBuilder('Psr\Http\Message\StreamInterface')
+ ->setMethods(array('isReadable', 'isWritable'))
+ ->getMockForAbstractClass();
+ $stream->expects($this->once())
+ ->method('isReadable')
+ ->will($this->returnValue(false));
+ $stream->expects($this->once())
+ ->method('isWritable')
+ ->will($this->returnValue(false));
+ StreamWrapper::getResource($stream);
+ }
+
+ /**
+ * @expectedException \PHPUnit_Framework_Error_Warning
+ */
+ public function testReturnsFalseWhenStreamDoesNotExist()
+ {
+ fopen('guzzle://foo', 'r');
+ }
+
+ public function testCanOpenReadonlyStream()
+ {
+ $stream = $this->getMockBuilder('Psr\Http\Message\StreamInterface')
+ ->setMethods(array('isReadable', 'isWritable'))
+ ->getMockForAbstractClass();
+ $stream->expects($this->once())
+ ->method('isReadable')
+ ->will($this->returnValue(false));
+ $stream->expects($this->once())
+ ->method('isWritable')
+ ->will($this->returnValue(true));
+ $r = StreamWrapper::getResource($stream);
+ $this->assertInternalType('resource', $r);
+ fclose($r);
+ }
+}
diff --git a/vendor/ringcentral/psr7/tests/UriTest.php b/vendor/ringcentral/psr7/tests/UriTest.php
new file mode 100644
index 0000000..b53c97e
--- /dev/null
+++ b/vendor/ringcentral/psr7/tests/UriTest.php
@@ -0,0 +1,258 @@
+<?php
+namespace RingCentral\Tests\Psr7;
+
+use RingCentral\Psr7\Uri;
+
+/**
+ * @covers RingCentral\Psr7\Uri
+ */
+class UriTest extends \PHPUnit_Framework_TestCase
+{
+ const RFC3986_BASE = "http://a/b/c/d;p?q";
+
+ public function testParsesProvidedUrl()
+ {
+ $uri = new Uri('https://michael:test@test.com:443/path/123?q=abc#test');
+
+ // Standard port 443 for https gets ignored.
+ $this->assertEquals(
+ 'https://michael:test@test.com/path/123?q=abc#test',
+ (string) $uri
+ );
+
+ $this->assertEquals('test', $uri->getFragment());
+ $this->assertEquals('test.com', $uri->getHost());
+ $this->assertEquals('/path/123', $uri->getPath());
+ $this->assertEquals(null, $uri->getPort());
+ $this->assertEquals('q=abc', $uri->getQuery());
+ $this->assertEquals('https', $uri->getScheme());
+ $this->assertEquals('michael:test', $uri->getUserInfo());
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Unable to parse URI
+ */
+ public function testValidatesUriCanBeParsed()
+ {
+ // Due to 5.4.7 "Fixed host recognition when scheme is omitted and a leading component separator is present" this does not work in 5.3
+ //new Uri('///');
+ throw new \InvalidArgumentException('Unable to parse URI');
+ }
+
+ public function testCanTransformAndRetrievePartsIndividually()
+ {
+ $uri = new Uri('');
+ $uri = $uri->withFragment('#test')
+ ->withHost('example.com')
+ ->withPath('path/123')
+ ->withPort(8080)
+ ->withQuery('?q=abc')
+ ->withScheme('http')
+ ->withUserInfo('user', 'pass');
+
+ // Test getters.
+ $this->assertEquals('user:pass@example.com:8080', $uri->getAuthority());
+ $this->assertEquals('test', $uri->getFragment());
+ $this->assertEquals('example.com', $uri->getHost());
+ $this->assertEquals('path/123', $uri->getPath());
+ $this->assertEquals(8080, $uri->getPort());
+ $this->assertEquals('q=abc', $uri->getQuery());
+ $this->assertEquals('http', $uri->getScheme());
+ $this->assertEquals('user:pass', $uri->getUserInfo());
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testPortMustBeValid()
+ {
+ $uri = new Uri('');
+ $uri->withPort(100000);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testPathMustBeValid()
+ {
+ $uri = new Uri('');
+ $uri->withPath(array());
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testQueryMustBeValid()
+ {
+ $uri = new Uri('');
+ $uri->withQuery(new \stdClass);
+ }
+
+ public function testAllowsFalseyUrlParts()
+ {
+ $url = new Uri('http://a:1/0?0#0');
+ $this->assertSame('a', $url->getHost());
+ $this->assertEquals(1, $url->getPort());
+ $this->assertSame('/0', $url->getPath());
+ $this->assertEquals('0', (string) $url->getQuery());
+ $this->assertSame('0', $url->getFragment());
+ $this->assertEquals('http://a:1/0?0#0', (string) $url);
+ $url = new Uri('');
+ $this->assertSame('', (string) $url);
+ $url = new Uri('0');
+ $this->assertSame('0', (string) $url);
+ $url = new Uri('/');
+ $this->assertSame('/', (string) $url);
+ }
+
+ /**
+ * @dataProvider getResolveTestCases
+ */
+ public function testResolvesUris($base, $rel, $expected)
+ {
+ $uri = new Uri($base);
+ $actual = Uri::resolve($uri, $rel);
+ $this->assertEquals($expected, (string) $actual);
+ }
+
+ public function getResolveTestCases()
+ {
+ return array(
+ //[self::RFC3986_BASE, 'g:h', 'g:h'],
+ array(self::RFC3986_BASE, 'g', 'http://a/b/c/g'),
+ array(self::RFC3986_BASE, './g', 'http://a/b/c/g'),
+ array(self::RFC3986_BASE, 'g/', 'http://a/b/c/g/'),
+ array(self::RFC3986_BASE, '/g', 'http://a/g'),
+ // Due to 5.4.7 "Fixed host recognition when scheme is omitted and a leading component separator is present" this does not work in 5.3
+ //array(self::RFC3986_BASE, '//g', 'http://g'),
+ array(self::RFC3986_BASE, '?y', 'http://a/b/c/d;p?y'),
+ array(self::RFC3986_BASE, 'g?y', 'http://a/b/c/g?y'),
+ array(self::RFC3986_BASE, '#s', 'http://a/b/c/d;p?q#s'),
+ array(self::RFC3986_BASE, 'g#s', 'http://a/b/c/g#s'),
+ array(self::RFC3986_BASE, 'g?y#s', 'http://a/b/c/g?y#s'),
+ array(self::RFC3986_BASE, ';x', 'http://a/b/c/;x'),
+ array(self::RFC3986_BASE, 'g;x', 'http://a/b/c/g;x'),
+ array(self::RFC3986_BASE, 'g;x?y#s', 'http://a/b/c/g;x?y#s'),
+ array(self::RFC3986_BASE, '', self::RFC3986_BASE),
+ array(self::RFC3986_BASE, '.', 'http://a/b/c/'),
+ array(self::RFC3986_BASE, './', 'http://a/b/c/'),
+ array(self::RFC3986_BASE, '..', 'http://a/b/'),
+ array(self::RFC3986_BASE, '../', 'http://a/b/'),
+ array(self::RFC3986_BASE, '../g', 'http://a/b/g'),
+ array(self::RFC3986_BASE, '../..', 'http://a/'),
+ array(self::RFC3986_BASE, '../../', 'http://a/'),
+ array(self::RFC3986_BASE, '../../g', 'http://a/g'),
+ array(self::RFC3986_BASE, '../../../g', 'http://a/g'),
+ array(self::RFC3986_BASE, '../../../../g', 'http://a/g'),
+ array(self::RFC3986_BASE, '/./g', 'http://a/g'),
+ array(self::RFC3986_BASE, '/../g', 'http://a/g'),
+ array(self::RFC3986_BASE, 'g.', 'http://a/b/c/g.'),
+ array(self::RFC3986_BASE, '.g', 'http://a/b/c/.g'),
+ array(self::RFC3986_BASE, 'g..', 'http://a/b/c/g..'),
+ array(self::RFC3986_BASE, '..g', 'http://a/b/c/..g'),
+ array(self::RFC3986_BASE, './../g', 'http://a/b/g'),
+ array(self::RFC3986_BASE, 'foo////g', 'http://a/b/c/foo////g'),
+ array(self::RFC3986_BASE, './g/.', 'http://a/b/c/g/'),
+ array(self::RFC3986_BASE, 'g/./h', 'http://a/b/c/g/h'),
+ array(self::RFC3986_BASE, 'g/../h', 'http://a/b/c/h'),
+ array(self::RFC3986_BASE, 'g;x=1/./y', 'http://a/b/c/g;x=1/y'),
+ array(self::RFC3986_BASE, 'g;x=1/../y', 'http://a/b/c/y'),
+ array('http://u@a/b/c/d;p?q', '.', 'http://u@a/b/c/'),
+ array('http://u:p@a/b/c/d;p?q', '.', 'http://u:p@a/b/c/'),
+ //[self::RFC3986_BASE, 'http:g', 'http:g'],
+ );
+ }
+
+ public function testAddAndRemoveQueryValues()
+ {
+ $uri = new Uri('http://foo.com/bar');
+ $uri = Uri::withQueryValue($uri, 'a', 'b');
+ $uri = Uri::withQueryValue($uri, 'c', 'd');
+ $uri = Uri::withQueryValue($uri, 'e', null);
+ $this->assertEquals('a=b&c=d&e', $uri->getQuery());
+
+ $uri = Uri::withoutQueryValue($uri, 'c');
+ $uri = Uri::withoutQueryValue($uri, 'e');
+ $this->assertEquals('a=b', $uri->getQuery());
+ $uri = Uri::withoutQueryValue($uri, 'a');
+ $uri = Uri::withoutQueryValue($uri, 'a');
+ $this->assertEquals('', $uri->getQuery());
+ }
+
+ public function testGetAuthorityReturnsCorrectPort()
+ {
+ // HTTPS non-standard port
+ $uri = new Uri('https://foo.co:99');
+ $this->assertEquals('foo.co:99', $uri->getAuthority());
+
+ // HTTP non-standard port
+ $uri = new Uri('http://foo.co:99');
+ $this->assertEquals('foo.co:99', $uri->getAuthority());
+
+ // No scheme
+ $uri = new Uri('foo.co:99');
+ $this->assertEquals('foo.co:99', $uri->getAuthority());
+
+ // No host or port
+ $uri = new Uri('http:');
+ $this->assertEquals('', $uri->getAuthority());
+
+ // No host or port
+ $uri = new Uri('http://foo.co');
+ $this->assertEquals('foo.co', $uri->getAuthority());
+ }
+
+ public function pathTestProvider()
+ {
+ return array(
+ // Percent encode spaces.
+ array('http://foo.com/baz bar', 'http://foo.com/baz%20bar'),
+ // Don't encoding something that's already encoded.
+ array('http://foo.com/baz%20bar', 'http://foo.com/baz%20bar'),
+ // Percent encode invalid percent encodings
+ array('http://foo.com/baz%2-bar', 'http://foo.com/baz%252-bar'),
+ // Don't encode path segments
+ array('http://foo.com/baz/bar/bam?a', 'http://foo.com/baz/bar/bam?a'),
+ array('http://foo.com/baz+bar', 'http://foo.com/baz+bar'),
+ array('http://foo.com/baz:bar', 'http://foo.com/baz:bar'),
+ array('http://foo.com/baz@bar', 'http://foo.com/baz@bar'),
+ array('http://foo.com/baz(bar);bam/', 'http://foo.com/baz(bar);bam/'),
+ array('http://foo.com/a-zA-Z0-9.-_~!$&\'()*+,;=:@', 'http://foo.com/a-zA-Z0-9.-_~!$&\'()*+,;=:@'),
+ );
+ }
+
+ /**
+ * @dataProvider pathTestProvider
+ */
+ public function testUriEncodesPathProperly($input, $output)
+ {
+ $uri = new Uri($input);
+ $this->assertEquals((string) $uri, $output);
+ }
+
+ public function testDoesNotAddPortWhenNoPort()
+ {
+ // Due to 5.4.7 "Fixed host recognition when scheme is omitted and a leading component separator is present" this does not work in 5.3
+ //$uri = new Uri('//bar');
+ //$this->assertEquals('bar', (string) $uri);
+ //$uri = new Uri('//barx');
+ //$this->assertEquals('barx', $uri->getHost());
+ }
+
+ public function testAllowsForRelativeUri()
+ {
+ $uri = new Uri();
+ $uri = $uri->withPath('foo');
+ $this->assertEquals('foo', $uri->getPath());
+ $this->assertEquals('foo', (string) $uri);
+ }
+
+ public function testAddsSlashForRelativeUriStringWithHost()
+ {
+ $uri = new Uri();
+ $uri = $uri->withPath('foo')->withHost('bar.com');
+ $this->assertEquals('foo', $uri->getPath());
+ $this->assertEquals('bar.com/foo', (string) $uri);
+ }
+}
diff --git a/vendor/ringcentral/psr7/tests/bootstrap.php b/vendor/ringcentral/psr7/tests/bootstrap.php
new file mode 100644
index 0000000..ea6a079
--- /dev/null
+++ b/vendor/ringcentral/psr7/tests/bootstrap.php
@@ -0,0 +1,13 @@
+<?php
+namespace RingCentral\Tests\Psr7;
+
+error_reporting(E_ALL);
+
+require __DIR__ . '/../vendor/autoload.php';
+
+class HasToString
+{
+ public function __toString() {
+ return 'foo';
+ }
+}